about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock135
-rw-r--r--compiler/rustc/Cargo.toml3
-rw-r--r--compiler/rustc_ast/src/ast.rs6
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs42
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs2
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs16
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs5
-rw-r--r--compiler/rustc_attr/src/builtin.rs33
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs22
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/assert.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs307
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs13
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs10
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs17
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs99
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/glue.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs52
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/intrinsic.rs8
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs157
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs39
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs137
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs12
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs4
-rw-r--r--compiler/rustc_const_eval/src/lib.rs13
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs3
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs33
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs10
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs14
-rw-r--r--compiler/rustc_driver/Cargo.toml6
-rw-r--r--compiler/rustc_error_messages/src/lib.rs3
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs8
-rw-r--r--compiler/rustc_errors/src/lib.rs23
-rw-r--r--compiler/rustc_expand/src/base.rs2
-rw-r--r--compiler/rustc_expand/src/expand.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs4
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs8
-rw-r--r--compiler/rustc_feature/src/removed.rs3
-rw-r--r--compiler/rustc_hir/Cargo.toml1
-rw-r--r--compiler/rustc_hir/src/hir.rs16
-rw-r--r--compiler/rustc_hir/src/intravisit.rs15
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs14
-rw-r--r--compiler/rustc_incremental/src/persist/load.rs6
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs4
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs2
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs10
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs18
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs10
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs2
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs2
-rw-r--r--compiler/rustc_infer/src/infer/fudge.rs2
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs33
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs79
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs2
-rw-r--r--compiler/rustc_interface/Cargo.toml4
-rw-r--r--compiler/rustc_interface/src/passes.rs2
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lint/src/array_into_iter.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs27
-rw-r--r--compiler/rustc_lint/src/context.rs8
-rw-r--r--compiler/rustc_lint/src/internal.rs146
-rw-r--r--compiler/rustc_lint/src/levels.rs6
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/redundant_semicolon.rs4
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp10
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs13
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs6
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs10
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs2
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs2
-rw-r--r--compiler/rustc_middle/src/mir/graph_cyclic_cache.rs10
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs62
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs270
-rw-r--r--compiler/rustc_middle/src/mir/predecessors.rs6
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs23
-rw-r--r--compiler/rustc_middle/src/mir/query.rs4
-rw-r--r--compiler/rustc_middle/src/mir/switch_sources.rs6
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs3
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs6
-rw-r--r--compiler/rustc_middle/src/query/mod.rs22
-rw-r--r--compiler/rustc_middle/src/traits/chalk.rs3
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs65
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs83
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs59
-rw-r--r--compiler/rustc_middle/src/ty/context.rs16
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs2
-rw-r--r--compiler/rustc_middle/src/ty/error.rs2
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs6
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs2
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs14
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs1
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs41
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs119
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs82
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs8
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs2
-rw-r--r--compiler/rustc_middle/src/ty/util.rs6
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs63
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs130
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs99
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs9
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml1
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir_transform/Cargo.toml1
-rw-r--r--compiler/rustc_mir_transform/src/const_debuginfo.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs19
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs2
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs2
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs2
-rw-r--r--compiler/rustc_mir_transform/src/instcombine.rs8
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs2
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs4
-rw-r--r--compiler/rustc_mir_transform/src/required_consts.rs2
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs4
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml1
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs28
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs4
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs8
-rw-r--r--compiler/rustc_parse/src/lexer/unicode_chars.rs2
-rw-r--r--compiler/rustc_parse/src/lib.rs2
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs7
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs70
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs185
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs2
-rw-r--r--compiler/rustc_parse/src/parser/item.rs41
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs18
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs42
-rw-r--r--compiler/rustc_parse/src/parser/path.rs32
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs30
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs8
-rw-r--r--compiler/rustc_passes/Cargo.toml1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs47
-rw-r--r--compiler/rustc_passes/src/liveness.rs6
-rw-r--r--compiler/rustc_passes/src/loops.rs12
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs4
-rw-r--r--compiler/rustc_passes/src/reachable.rs2
-rw-r--r--compiler/rustc_passes/src/stability.rs2
-rw-r--r--compiler/rustc_passes/src/upvars.rs2
-rw-r--r--compiler/rustc_plugin_impl/Cargo.toml2
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/Cargo.toml1
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs12
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs3
-rw-r--r--compiler/rustc_query_system/Cargo.toml1
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs6
-rw-r--r--compiler/rustc_query_system/src/ich/hcx.rs11
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs35
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs28
-rw-r--r--compiler/rustc_resolve/src/ident.rs2
-rw-r--r--compiler/rustc_resolve/src/imports.rs29
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs38
-rw-r--r--compiler/rustc_resolve/src/lib.rs10
-rw-r--r--compiler/rustc_resolve/src/macros.rs4
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs6
-rw-r--r--compiler/rustc_serialize/src/opaque.rs52
-rw-r--r--compiler/rustc_serialize/tests/opaque.rs10
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/options.rs9
-rw-r--r--compiler/rustc_session/src/parse.rs2
-rw-r--r--compiler/rustc_session/src/session.rs16
-rw-r--r--compiler/rustc_smir/.gitignore1
-rw-r--r--compiler/rustc_smir/Cargo.toml28
-rw-r--r--compiler/rustc_smir/README.md75
-rw-r--r--compiler/rustc_smir/rust-toolchain.toml3
-rw-r--r--compiler/rustc_smir/src/lib.rs17
-rw-r--r--compiler/rustc_smir/src/mir.rs10
-rw-r--r--compiler/rustc_smir/src/very_unstable.rs27
-rw-r--r--compiler/rustc_span/src/lib.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs13
-rw-r--r--compiler/rustc_symbol_mangling/Cargo.toml1
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs13
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs7
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs111
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs38
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs9
-rw-r--r--compiler/rustc_target/src/spec/apple_sdk_base.rs8
-rw-r--r--compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs28
-rw-r--r--compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs3
-rw-r--r--compiler/rustc_target/src/spec/armv7k_apple_watchos.rs28
-rw-r--r--compiler/rustc_target/src/spec/mod.rs5
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs35
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs41
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs30
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs8
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs6
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs1
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs2
-rw-r--r--compiler/rustc_type_ir/src/sty.rs72
-rw-r--r--compiler/rustc_typeck/src/astconv/errors.rs2
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs12
-rw-r--r--compiler/rustc_typeck/src/check/_match.rs2
-rw-r--r--compiler/rustc_typeck/src/check/callee.rs12
-rw-r--r--compiler/rustc_typeck/src/check/check.rs4
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs4
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs6
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs2
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs20
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs10
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs8
-rw-r--r--compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs4
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs25
-rw-r--r--compiler/rustc_typeck/src/check/op.rs6
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs71
-rw-r--r--compiler/rustc_typeck/src/check/region.rs2
-rw-r--r--compiler/rustc_typeck/src/check/regionck.rs13
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs4
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs11
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs2
-rw-r--r--compiler/rustc_typeck/src/check_unused.rs2
-rw-r--r--compiler/rustc_typeck/src/coherence/builtin.rs14
-rw-r--r--compiler/rustc_typeck/src/collect.rs25
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs6
-rw-r--r--compiler/rustc_typeck/src/constrained_generic_params.rs2
-rw-r--r--compiler/rustc_typeck/src/expr_use_visitor.rs2
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs4
-rw-r--r--compiler/rustc_typeck/src/mem_categorization.rs2
-rw-r--r--compiler/rustc_typeck/src/outlives/utils.rs11
-rw-r--r--compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs6
-rw-r--r--compiler/rustc_typeck/src/variance/constraints.rs6
-rw-r--r--library/alloc/src/collections/btree/fix.rs4
-rw-r--r--library/alloc/src/collections/btree/map/entry.rs9
-rw-r--r--library/core/src/ffi/mod.rs3
-rw-r--r--library/core/src/str/mod.rs1
-rw-r--r--library/proc_macro/src/bridge/handle.rs22
-rw-r--r--library/std/build.rs1
-rw-r--r--library/std/src/collections/hash/map.rs2
-rw-r--r--library/std/src/ffi/os_str.rs34
-rw-r--r--library/std/src/os/fd/mod.rs2
-rw-r--r--library/std/src/os/fd/owned.rs62
-rw-r--r--library/std/src/os/horizon/fs.rs95
-rw-r--r--library/std/src/os/horizon/mod.rs6
-rw-r--r--library/std/src/os/horizon/raw.rs70
-rw-r--r--library/std/src/os/mod.rs2
-rw-r--r--library/std/src/os/unix/io/fd.rs3
-rw-r--r--library/std/src/os/unix/io/mod.rs2
-rw-r--r--library/std/src/os/unix/mod.rs2
-rw-r--r--library/std/src/os/unix/net/datagram.rs6
-rw-r--r--library/std/src/os/unix/net/listener.rs6
-rw-r--r--library/std/src/os/unix/net/stream.rs6
-rw-r--r--library/std/src/os/unix/process.rs60
-rw-r--r--library/std/src/os/windows/io/handle.rs72
-rw-r--r--library/std/src/os/windows/io/mod.rs4
-rw-r--r--library/std/src/os/windows/io/socket.rs35
-rw-r--r--library/std/src/os/windows/process.rs6
-rw-r--r--library/std/src/sys/unix/alloc.rs3
-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.rs41
-rw-r--r--library/std/src/sys/unix/fs.rs25
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs13
-rw-r--r--library/std/src/sys/unix/mod.rs6
-rw-r--r--library/std/src/sys/unix/os.rs8
-rw-r--r--library/std/src/sys/unix/process/mod.rs3
-rw-r--r--library/std/src/sys/unix/process/process_unsupported.rs13
-rw-r--r--library/std/src/sys/unix/rand.rs16
-rw-r--r--library/std/src/sys/unix/stdio.rs12
-rw-r--r--library/std/src/sys/unix/thread_local_dtor.rs2
-rw-r--r--library/std/src/sys/unix/thread_parker.rs2
-rw-r--r--library/std/src/sys/unix/time.rs5
-rw-r--r--library/std/src/sys/windows/compat.rs18
-rw-r--r--library/std/src/sys_common/net.rs14
-rw-r--r--src/bootstrap/native.rs21
-rw-r--r--src/doc/rustc/src/SUMMARY.md2
-rw-r--r--src/doc/rustc/src/platform-support.md6
-rw-r--r--src/doc/rustc/src/platform-support/apple-watchos.md55
-rw-r--r--src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md130
-rw-r--r--src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md39
-rw-r--r--src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md44
-rw-r--r--src/librustdoc/clean/utils.rs14
-rw-r--r--src/librustdoc/html/format.rs29
-rw-r--r--src/librustdoc/json/mod.rs53
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs2
-rw-r--r--src/librustdoc/scrape_examples.rs4
-rw-r--r--src/test/codegen/issue-96497-slice-size-nowrap.rs29
-rw-r--r--src/test/codegen/virtual-function-elimination-32bit.rs35
-rw-r--r--src/test/codegen/virtual-function-elimination.rs100
-rw-r--r--src/test/debuginfo/function-names.rs4
-rw-r--r--src/test/incremental/issue-54242.rs2
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir30
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir32
-rw-r--r--src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff4
-rw-r--r--src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff4
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir4
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir4
-rw-r--r--src/test/rustdoc-json/generic_impl.rs24
-rw-r--r--src/test/rustdoc/slice-links.link_box_u32.html2
-rw-r--r--src/test/rustdoc/slice-links.link_slice_generic.html2
-rw-r--r--src/test/rustdoc/slice-links.link_slice_u32.html2
-rw-r--r--src/test/ui-fulldeps/deriving-encodable-decodable-box.rs6
-rw-r--r--src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs6
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics.rs73
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics.stderr44
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.rs15
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.stderr17
-rw-r--r--src/test/ui-fulldeps/issue-14021.rs6
-rw-r--r--src/test/ui/associated-consts/defaults-cyclic-fail.rs2
-rw-r--r--src/test/ui/associated-consts/defaults-cyclic-fail.stderr34
-rw-r--r--src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr23
-rw-r--r--src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr23
-rw-r--r--src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr23
-rw-r--r--src/test/ui/borrowck/issue-81899.rs2
-rw-r--r--src/test/ui/borrowck/issue-81899.stderr18
-rw-r--r--src/test/ui/borrowck/issue-88434-minimal-example.rs2
-rw-r--r--src/test/ui/borrowck/issue-88434-minimal-example.stderr18
-rw-r--r--src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs2
-rw-r--r--src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr18
-rw-r--r--src/test/ui/check-cfg/well-known-values.stderr2
-rw-r--r--src/test/ui/const-generics/different_generic_args_array.stderr2
-rw-r--r--src/test/ui/const-generics/issue-97007.rs88
-rw-r--r--src/test/ui/const-generics/issues/issue-67945-3.full.stderr16
-rw-r--r--src/test/ui/const-generics/issues/issue-67945-3.min.stderr21
-rw-r--r--src/test/ui/const-generics/issues/issue-67945-3.rs17
-rw-r--r--src/test/ui/const-generics/issues/issue-67945-4.full.stderr16
-rw-r--r--src/test/ui/const-generics/issues/issue-67945-4.min.stderr21
-rw-r--r--src/test/ui/const-generics/issues/issue-67945-4.rs16
-rw-r--r--src/test/ui/const-generics/issues/issue-83765.stderr6
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.32bit.stderr4
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.64bit.stderr4
-rw-r--r--src/test/ui/const-ptr/out_of_bounds_read.stderr6
-rw-r--r--src/test/ui/consts/const-eval/const-eval-query-stack.rs3
-rw-r--r--src/test/ui/consts/const-eval/const-eval-query-stack.stderr24
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr65
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr65
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.rs6
-rw-r--r--src/test/ui/consts/const-float-bits-reject-conv.rs16
-rw-r--r--src/test/ui/consts/const-float-bits-reject-conv.stderr107
-rw-r--r--src/test/ui/consts/const-integer-bool-ops.rs10
-rw-r--r--src/test/ui/consts/const-integer-bool-ops.stderr95
-rw-r--r--src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr12
-rw-r--r--src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr12
-rw-r--r--src/test/ui/consts/const-mut-refs/issue-76510.rs1
-rw-r--r--src/test/ui/consts/const-size_of-cycle.stderr6
-rw-r--r--src/test/ui/consts/const-tup-index-span.rs1
-rw-r--r--src/test/ui/consts/const-tup-index-span.stderr11
-rw-r--r--src/test/ui/consts/invalid-union.32bit.stderr2
-rw-r--r--src/test/ui/consts/invalid-union.64bit.stderr2
-rw-r--r--src/test/ui/consts/issue-36163.stderr40
-rw-r--r--src/test/ui/consts/issue-39974.rs (renamed from src/test/ui/issues/issue-39974.rs)0
-rw-r--r--src/test/ui/consts/issue-39974.stderr (renamed from src/test/ui/issues/issue-39974.stderr)0
-rw-r--r--src/test/ui/consts/issue-44415.rs2
-rw-r--r--src/test/ui/consts/issue-44415.stderr6
-rw-r--r--src/test/ui/consts/offset_from_ub.rs12
-rw-r--r--src/test/ui/consts/offset_from_ub.stderr14
-rw-r--r--src/test/ui/deprecation/rustc_deprecated.rs13
-rw-r--r--src/test/ui/deprecation/rustc_deprecated.stderr21
-rw-r--r--src/test/ui/destructure-trait-ref.stderr12
-rw-r--r--src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr10
-rw-r--r--src/test/ui/expr/if/if-without-block.rs4
-rw-r--r--src/test/ui/expr/if/if-without-block.stderr15
-rw-r--r--src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.rs12
-rw-r--r--src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr19
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs1
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr326
-rw-r--r--src/test/ui/issues/issue-17252.stderr15
-rw-r--r--src/test/ui/issues/issue-23302-1.stderr17
-rw-r--r--src/test/ui/issues/issue-23302-2.stderr17
-rw-r--r--src/test/ui/issues/issue-23302-3.stderr30
-rw-r--r--src/test/ui/issues/issue-39848.stderr12
-rw-r--r--src/test/ui/issues/issue-41394.rs1
-rw-r--r--src/test/ui/issues/issue-41394.stderr11
-rw-r--r--src/test/ui/issues/issue-54954.rs2
-rw-r--r--src/test/ui/issues/issue-54954.stderr18
-rw-r--r--src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs1
-rw-r--r--src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr10
-rw-r--r--src/test/ui/lifetimes/issue-17728.rs (renamed from src/test/ui/issues/issue-17728.rs)0
-rw-r--r--src/test/ui/lifetimes/issue-17728.stderr (renamed from src/test/ui/issues/issue-17728.stderr)0
-rw-r--r--src/test/ui/lifetimes/issue-55796.rs (renamed from src/test/ui/issues/issue-55796.rs)0
-rw-r--r--src/test/ui/lifetimes/issue-55796.stderr (renamed from src/test/ui/issues/issue-55796.stderr)0
-rw-r--r--src/test/ui/lto/issue-11154.rs (renamed from src/test/ui/issues/issue-11154.rs)0
-rw-r--r--src/test/ui/lto/issue-11154.stderr (renamed from src/test/ui/issues/issue-11154.stderr)0
-rw-r--r--src/test/ui/macros/assert-trailing-junk.rs3
-rw-r--r--src/test/ui/macros/assert-trailing-junk.with-generic-asset.stderr (renamed from src/test/ui/macros/assert-trailing-junk.stderr)14
-rw-r--r--src/test/ui/macros/assert-trailing-junk.without-generic-asset.stderr54
-rw-r--r--src/test/ui/macros/assert.rs3
-rw-r--r--src/test/ui/macros/assert.with-generic-asset.stderr (renamed from src/test/ui/macros/assert.stderr)8
-rw-r--r--src/test/ui/macros/assert.without-generic-asset.stderr28
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs143
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs43
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs13
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs14
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs25
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs9
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout29
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs (renamed from src/test/ui/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs)8
-rw-r--r--src/test/ui/mismatched_types/issue-38371-unfixable.rs5
-rw-r--r--src/test/ui/mismatched_types/issue-38371-unfixable.stderr21
-rw-r--r--src/test/ui/mismatched_types/issue-38371.fixed18
-rw-r--r--src/test/ui/mismatched_types/issue-38371.rs29
-rw-r--r--src/test/ui/mismatched_types/issue-38371.stderr47
-rw-r--r--src/test/ui/mismatched_types/ref-pat-suggestions.fixed24
-rw-r--r--src/test/ui/mismatched_types/ref-pat-suggestions.rs24
-rw-r--r--src/test/ui/mismatched_types/ref-pat-suggestions.stderr297
-rw-r--r--src/test/ui/missing/missing-block-hint.stderr17
-rw-r--r--src/test/ui/nll/issue-46023.rs (renamed from src/test/ui/issues/issue-46023.rs)0
-rw-r--r--src/test/ui/nll/issue-46023.stderr (renamed from src/test/ui/issues/issue-46023.stderr)0
-rw-r--r--src/test/ui/parser/bad-if-statements.rs38
-rw-r--r--src/test/ui/parser/bad-if-statements.stderr86
-rw-r--r--src/test/ui/parser/can-begin-expr-check.rs2
-rw-r--r--src/test/ui/parser/can-begin-expr-check.stderr4
-rw-r--r--src/test/ui/parser/duplicate-visibility.rs4
-rw-r--r--src/test/ui/parser/duplicate-visibility.stderr4
-rw-r--r--src/test/ui/parser/if-block-unreachable-expr.rs8
-rw-r--r--src/test/ui/parser/issue-61858.stderr10
-rw-r--r--src/test/ui/parser/issue-68091-unicode-ident-after-if.rs5
-rw-r--r--src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr18
-rw-r--r--src/test/ui/parser/issue-91421.rs5
-rw-r--r--src/test/ui/parser/issue-91421.stderr17
-rw-r--r--src/test/ui/parser/issues/issue-13483.rs8
-rw-r--r--src/test/ui/parser/issues/issue-13483.stderr29
-rw-r--r--src/test/ui/parser/issues/issue-20616-2.rs2
-rw-r--r--src/test/ui/parser/issues/issue-20616-2.stderr4
-rw-r--r--src/test/ui/parser/issues/issue-51602.stderr10
-rw-r--r--src/test/ui/parser/issues/issue-62554.stderr9
-rw-r--r--src/test/ui/parser/issues/issue-62660.rs2
-rw-r--r--src/test/ui/parser/issues/issue-62660.stderr4
-rw-r--r--src/test/ui/parser/issues/issue-84117.rs2
-rw-r--r--src/test/ui/parser/issues/issue-84117.stderr4
-rw-r--r--src/test/ui/parser/issues/issue-93282.stderr4
-rw-r--r--src/test/ui/parser/issues/issue-93867.rs10
-rw-r--r--src/test/ui/parser/issues/issue-93867.stderr13
-rw-r--r--src/test/ui/parser/lifetime-semicolon.fixed2
-rw-r--r--src/test/ui/parser/lifetime-semicolon.rs2
-rw-r--r--src/test/ui/parser/lifetime-semicolon.stderr4
-rw-r--r--src/test/ui/parser/require-parens-for-chained-comparison.stderr4
-rw-r--r--src/test/ui/pattern/for-loop-bad-item.stderr6
-rw-r--r--src/test/ui/privacy/macro-private-reexport.rs17
-rw-r--r--src/test/ui/privacy/macro-private-reexport.stderr29
-rw-r--r--src/test/ui/resolve/filter-intrinsics.rs10
-rw-r--r--src/test/ui/resolve/filter-intrinsics.stderr25
-rw-r--r--src/test/ui/resolve/issue-50599.rs1
-rw-r--r--src/test/ui/resolve/issue-50599.stderr11
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs4
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr4
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/infer-static.rs12
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/infer-static.stderr12
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs6
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr36
-rw-r--r--src/test/ui/rust-2018/uniform-paths/macro-rules.stderr8
-rw-r--r--src/test/ui/suggestions/match-ergonomics.stderr26
-rw-r--r--src/test/ui/traits/issue-18400.rs (renamed from src/test/ui/issues/issue-18400.rs)0
-rw-r--r--src/test/ui/traits/issue-18400.stderr (renamed from src/test/ui/issues/issue-18400.stderr)0
-rw-r--r--src/test/ui/traits/issue-18412.rs (renamed from src/test/ui/issues/issue-18412.rs)0
-rw-r--r--src/test/ui/traits/issue-35869.rs (renamed from src/test/ui/issues/issue-35869.rs)0
-rw-r--r--src/test/ui/traits/issue-35869.stderr (renamed from src/test/ui/issues/issue-35869.stderr)0
-rw-r--r--src/test/ui/type/type-dependent-def-issue-49241.rs1
-rw-r--r--src/test/ui/type/type-dependent-def-issue-49241.stderr11
-rw-r--r--src/test/ui/typeck/issue-29124.rs (renamed from src/test/ui/issues/issue-29124.rs)0
-rw-r--r--src/test/ui/typeck/issue-29124.stderr (renamed from src/test/ui/issues/issue-29124.stderr)0
-rw-r--r--src/test/ui/typeck/issue-74086.rs1
-rw-r--r--src/test/ui/typeck/issue-74086.stderr8
-rw-r--r--src/test/ui/typeck/issue-81885.rs3
-rw-r--r--src/test/ui/typeck/issue-81885.stderr16
-rw-r--r--src/test/ui/typeck/issue-88643.rs19
-rw-r--r--src/test/ui/typeck/issue-88643.stderr21
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item_help.rs1
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item_help.stderr12
-rw-r--r--src/test/ui/variance/variance-object-types.rs4
-rw-r--r--src/test/ui/variance/variance-object-types.stderr2
-rw-r--r--src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/as_underscore.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/bytecount.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_ok_or.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/map_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/map_err_ignore.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/map_unit_fn.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/search_is_some.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_for_each.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_late_init.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/attrs.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs23
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs2
-rw-r--r--src/tools/compiletest/src/raise_fd_limit.rs2
-rw-r--r--src/tools/compiletest/src/util.rs1
m---------src/tools/miri20
m---------src/tools/rust-analyzer16
-rw-r--r--src/tools/rustc-workspace-hack/Cargo.toml1
-rw-r--r--src/tools/rustfmt/.github/workflows/integration.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/linux.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/mac.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/rustdoc_check.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/upload-assets.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/windows.yml2
-rw-r--r--src/tools/rustfmt/CHANGELOG.md77
-rw-r--r--src/tools/rustfmt/Cargo.lock415
-rw-r--r--src/tools/rustfmt/Cargo.toml45
-rw-r--r--src/tools/rustfmt/Configurations.md61
-rw-r--r--src/tools/rustfmt/rust-toolchain2
-rw-r--r--src/tools/rustfmt/src/cargo-fmt/main.rs34
-rw-r--r--src/tools/rustfmt/src/cargo-fmt/test/mod.rs42
-rw-r--r--src/tools/rustfmt/src/comment.rs2
-rw-r--r--src/tools/rustfmt/src/config/config_type.rs22
-rw-r--r--src/tools/rustfmt/src/config/license.rs265
-rw-r--r--src/tools/rustfmt/src/config/mod.rs38
-rw-r--r--src/tools/rustfmt/src/expr.rs51
-rw-r--r--src/tools/rustfmt/src/format-diff/main.rs45
-rw-r--r--src/tools/rustfmt/src/format_report_formatter.rs3
-rw-r--r--src/tools/rustfmt/src/formatting.rs64
-rw-r--r--src/tools/rustfmt/src/imports.rs87
-rw-r--r--src/tools/rustfmt/src/issues.rs309
-rw-r--r--src/tools/rustfmt/src/items.rs2
-rw-r--r--src/tools/rustfmt/src/lib.rs14
-rw-r--r--src/tools/rustfmt/src/overflow.rs12
-rw-r--r--src/tools/rustfmt/src/parse/session.rs2
-rw-r--r--src/tools/rustfmt/src/reorder.rs17
-rw-r--r--src/tools/rustfmt/src/rewrite.rs13
-rw-r--r--src/tools/rustfmt/src/shape.rs4
-rw-r--r--src/tools/rustfmt/src/string.rs45
-rw-r--r--src/tools/rustfmt/src/test/mod.rs39
-rw-r--r--src/tools/rustfmt/src/visitor.rs7
-rw-r--r--src/tools/rustfmt/tests/config/issue-3802.toml2
-rw-r--r--src/tools/rustfmt/tests/config/small_tabs.toml2
-rw-r--r--src/tools/rustfmt/tests/license-template/lt.txt2
-rw-r--r--src/tools/rustfmt/tests/rustfmt/main.rs2
-rw-r--r--src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs27
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports-impl-only-use.rs (renamed from src/tools/rustfmt/tests/source/imports-impl-only-use.rs)0
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports-reorder-lines-and-items.rs (renamed from src/tools/rustfmt/tests/source/imports-reorder-lines-and-items.rs)0
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports-reorder-lines.rs (renamed from src/tools/rustfmt/tests/source/imports-reorder-lines.rs)0
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports-reorder.rs (renamed from src/tools/rustfmt/tests/source/imports-reorder.rs)0
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports.rs (renamed from src/tools/rustfmt/tests/source/imports.rs)0
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports_block_indent.rs (renamed from src/tools/rustfmt/tests/source/imports_block_indent.rs)0
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports_granularity_crate.rs (renamed from src/tools/rustfmt/tests/source/imports_granularity_crate.rs)28
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports_granularity_default-with-dups.rs6
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs13
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups.rs11
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports_granularity_item.rs34
-rw-r--r--src/tools/rustfmt/tests/source/imports/imports_granularity_module.rs47
-rw-r--r--src/tools/rustfmt/tests/source/imports_granularity_item.rs6
-rw-r--r--src/tools/rustfmt/tests/source/imports_granularity_module.rs19
-rw-r--r--src/tools/rustfmt/tests/source/imports_granularity_one.rs28
-rw-r--r--src/tools/rustfmt/tests/source/issue-5030.rs22
-rw-r--r--src/tools/rustfmt/tests/source/issue-5260.rs14
-rw-r--r--src/tools/rustfmt/tests/source/license-templates/empty_license_path.rs5
-rw-r--r--src/tools/rustfmt/tests/source/license-templates/license.rs6
-rw-r--r--src/tools/rustfmt/tests/source/performance/issue-4476.rs638
-rw-r--r--src/tools/rustfmt/tests/source/performance/issue-5128.rs5127
-rw-r--r--src/tools/rustfmt/tests/source/struct_field_doc_comment.rs72
-rw-r--r--src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs18
-rw-r--r--src/tools/rustfmt/tests/target/imports/import-fencepost-length.rs (renamed from src/tools/rustfmt/tests/target/import-fencepost-length.rs)0
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports-impl-only-use.rs (renamed from src/tools/rustfmt/tests/target/imports-impl-only-use.rs)0
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports-reorder-lines-and-items.rs (renamed from src/tools/rustfmt/tests/target/imports-reorder-lines-and-items.rs)0
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports-reorder-lines.rs (renamed from src/tools/rustfmt/tests/target/imports-reorder-lines.rs)0
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports-reorder.rs (renamed from src/tools/rustfmt/tests/target/imports-reorder.rs)0
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports.rs (renamed from src/tools/rustfmt/tests/target/imports.rs)0
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports_2021_edition.rs (renamed from src/tools/rustfmt/tests/target/imports_2021_edition.rs)0
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports_block_indent.rs (renamed from src/tools/rustfmt/tests/target/imports_block_indent.rs)0
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports_granularity_crate.rs (renamed from src/tools/rustfmt/tests/target/imports_granularity_crate.rs)31
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports_granularity_default-with-dups.rs6
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs7
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups.rs5
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports_granularity_item.rs45
-rw-r--r--src/tools/rustfmt/tests/target/imports/imports_granularity_module.rs55
-rw-r--r--src/tools/rustfmt/tests/target/imports_granularity_item.rs13
-rw-r--r--src/tools/rustfmt/tests/target/imports_granularity_module.rs22
-rw-r--r--src/tools/rustfmt/tests/target/imports_granularity_one.rs46
-rw-r--r--src/tools/rustfmt/tests/target/issue-5030.rs21
-rw-r--r--src/tools/rustfmt/tests/target/issue-5260.rs13
-rw-r--r--src/tools/rustfmt/tests/target/issue_3937.rs13
-rw-r--r--src/tools/rustfmt/tests/target/issue_4573.rs245
-rw-r--r--src/tools/rustfmt/tests/target/license-templates/empty_license_path.rs5
-rw-r--r--src/tools/rustfmt/tests/target/license-templates/license.rs6
-rw-r--r--src/tools/rustfmt/tests/target/performance/issue-4476.rs705
-rw-r--r--src/tools/rustfmt/tests/target/performance/issue-4867.rs13
-rw-r--r--src/tools/rustfmt/tests/target/performance/issue-5128.rs4898
-rw-r--r--src/tools/rustfmt/tests/target/struct_field_doc_comment.rs69
-rw-r--r--src/tools/tidy/src/ui_tests.rs4
670 files changed, 19709 insertions, 4370 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 51b0da65b31..b47e8147404 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -72,7 +72,14 @@ name = "annotate-snippets"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5"
+
+[[package]]
+name = "annotate-snippets"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36"
 dependencies = [
+ "unicode-width",
  "yansi-term",
 ]
 
@@ -614,6 +621,7 @@ checksum = "6d76c22c9b9b215eeb8d016ad3a90417bd13cb24cf8142756e6472445876cab7"
 dependencies = [
  "atty",
  "bitflags",
+ "clap_derive",
  "indexmap",
  "lazy_static",
  "os_str_bytes",
@@ -632,6 +640,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "clap_derive"
+version = "3.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c"
+dependencies = [
+ "heck 0.4.0",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "clippy"
 version = "0.1.63"
 dependencies = [
@@ -1099,11 +1120,10 @@ dependencies = [
 
 [[package]]
 name = "dirs"
-version = "2.0.2"
+version = "4.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
 dependencies = [
- "cfg-if 0.1.10",
  "dirs-sys",
 ]
 
@@ -1221,19 +1241,6 @@ dependencies = [
 
 [[package]]
 name = "env_logger"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
-dependencies = [
- "atty",
- "humantime 2.0.1",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
-name = "env_logger"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
@@ -1709,6 +1716,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "heck"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+
+[[package]]
 name = "hermit-abi"
 version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3290,7 +3303,7 @@ dependencies = [
  "difference",
  "env_logger 0.9.0",
  "futures 0.3.19",
- "heck",
+ "heck 0.3.1",
  "home",
  "itertools",
  "jsonrpc-core",
@@ -3440,6 +3453,7 @@ dependencies = [
  "jemalloc-sys",
  "rustc_codegen_ssa",
  "rustc_driver",
+ "rustc_smir",
 ]
 
 [[package]]
@@ -3499,6 +3513,7 @@ version = "1.0.0"
 dependencies = [
  "bstr",
  "byteorder",
+ "clap 3.1.1",
  "crossbeam-utils",
  "libc",
  "libz-sys",
@@ -3663,7 +3678,6 @@ dependencies = [
  "libloading",
  "measureme 10.0.0",
  "rustc-demangle",
- "rustc_arena",
  "rustc_ast",
  "rustc_attr",
  "rustc_codegen_ssa",
@@ -3680,6 +3694,7 @@ dependencies = [
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
+ "rustc_symbol_mangling",
  "rustc_target",
  "smallvec",
  "tracing",
@@ -3785,7 +3800,6 @@ dependencies = [
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_codegen_ssa",
- "rustc_const_eval",
  "rustc_data_structures",
  "rustc_error_codes",
  "rustc_errors",
@@ -3800,7 +3814,6 @@ dependencies = [
  "rustc_parse",
  "rustc_plugin_impl",
  "rustc_save_analysis",
- "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -3833,7 +3846,7 @@ dependencies = [
 name = "rustc_errors"
 version = "0.0.0"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.8.0",
  "atty",
  "rustc_data_structures",
  "rustc_error_messages",
@@ -3896,7 +3909,6 @@ dependencies = [
  "rustc_ast",
  "rustc_data_structures",
  "rustc_error_messages",
- "rustc_feature",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
@@ -3957,7 +3969,6 @@ dependencies = [
  "rustc_macros",
  "rustc_middle",
  "rustc_serialize",
- "rustc_session",
  "rustc_span",
  "rustc_target",
  "smallvec",
@@ -4084,7 +4095,7 @@ dependencies = [
 name = "rustc_macros"
 version = "0.1.0"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.8.0",
  "fluent-bundle",
  "fluent-syntax",
  "proc-macro2",
@@ -4191,7 +4202,6 @@ dependencies = [
  "rustc_index",
  "rustc_middle",
  "rustc_serialize",
- "rustc_session",
  "rustc_span",
  "rustc_target",
  "smallvec",
@@ -4213,7 +4223,6 @@ dependencies = [
  "rustc_index",
  "rustc_middle",
  "rustc_mir_dataflow",
- "rustc_query_system",
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
@@ -4228,7 +4237,6 @@ name = "rustc_monomorphize"
 version = "0.0.0"
 dependencies = [
  "rustc_data_structures",
- "rustc_errors",
  "rustc_hir",
  "rustc_index",
  "rustc_middle",
@@ -4280,7 +4288,6 @@ dependencies = [
  "rustc_index",
  "rustc_lexer",
  "rustc_middle",
- "rustc_parse",
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
@@ -4295,10 +4302,8 @@ dependencies = [
  "libloading",
  "rustc_ast",
  "rustc_errors",
- "rustc_hir",
  "rustc_lint",
  "rustc_metadata",
- "rustc_middle",
  "rustc_session",
  "rustc_span",
 ]
@@ -4337,7 +4342,6 @@ dependencies = [
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
- "rustc_type_ir",
  "tracing",
 ]
 
@@ -4359,7 +4363,6 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
- "rustc_type_ir",
  "smallvec",
  "tracing",
 ]
@@ -4438,6 +4441,21 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_smir"
+version = "0.0.0"
+dependencies = [
+ "rustc_borrowck",
+ "rustc_driver",
+ "rustc_hir",
+ "rustc_interface",
+ "rustc_middle",
+ "rustc_mir_dataflow",
+ "rustc_mir_transform",
+ "rustc_serialize",
+ "rustc_trait_selection",
+]
+
+[[package]]
 name = "rustc_span"
 version = "0.0.0"
 dependencies = [
@@ -4464,7 +4482,6 @@ dependencies = [
  "rustc_data_structures",
  "rustc_hir",
  "rustc_middle",
- "rustc_query_system",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -4671,16 +4688,17 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.38"
+version = "1.5.0"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.9.1",
  "anyhow",
  "bytecount",
  "cargo_metadata",
+ "clap 3.1.1",
  "derive-new",
  "diff",
  "dirs",
- "env_logger 0.8.4",
+ "env_logger 0.9.0",
  "getopts",
  "ignore",
  "itertools",
@@ -4691,8 +4709,7 @@ dependencies = [
  "rustfmt-config_proc_macro",
  "serde",
  "serde_json",
- "structopt",
- "term 0.6.1",
+ "term",
  "thiserror",
  "toml",
  "unicode-segmentation",
@@ -5081,30 +5098,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
-name = "structopt"
-version = "0.3.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c"
-dependencies = [
- "clap 2.34.0",
- "lazy_static",
- "structopt-derive",
-]
-
-[[package]]
-name = "structopt-derive"
-version = "0.4.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "strum"
 version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5116,7 +5109,7 @@ version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
 dependencies = [
- "heck",
+ "heck 0.3.1",
  "proc-macro2",
  "quote",
  "syn",
@@ -5198,16 +5191,6 @@ dependencies = [
 
 [[package]]
 name = "term"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
-dependencies = [
- "dirs",
- "winapi",
-]
-
-[[package]]
-name = "term"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
@@ -5260,7 +5243,7 @@ dependencies = [
  "getopts",
  "libc",
  "num_cpus",
- "term 0.7.0",
+ "term",
 ]
 
 [[package]]
@@ -5689,9 +5672,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.6.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
+checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
 
 [[package]]
 name = "unicode-width"
diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml
index 5e0bb1a7f95..27ee3dd2aea 100644
--- a/compiler/rustc/Cargo.toml
+++ b/compiler/rustc/Cargo.toml
@@ -9,6 +9,9 @@ rustc_driver = { path = "../rustc_driver" }
 # Make sure rustc_codegen_ssa ends up in the sysroot, because this
 # crate is intended to be used by codegen backends, which may not be in-tree.
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
+# Make sure rustc_smir ends up in the sysroot, because this
+# crate is intended to be used by stable MIR consumers, which are not in-tree
+rustc_smir = { path = "../rustc_smir" }
 
 [dependencies.jemalloc-sys]
 version = "0.5.0"
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 4e2495ab14c..e5b61d7000a 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -31,7 +31,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_macros::HashStable_Generic;
-use rustc_serialize::{self, Decoder, Encoder};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -2488,11 +2488,11 @@ rustc_index::newtype_index! {
     }
 }
 
-impl<S: Encoder> rustc_serialize::Encodable<S> for AttrId {
+impl<S: Encoder> Encodable<S> for AttrId {
     fn encode(&self, _s: &mut S) {}
 }
 
-impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId {
+impl<D: Decoder> Decodable<D> for AttrId {
     fn decode(_: &mut D) -> AttrId {
         crate::attr::mk_attr_id()
     }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 539e33702aa..0786ae330e0 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -577,7 +577,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
 
         // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
-        let decl = self.arena.alloc(hir::FnDecl {
+        let fn_decl = self.arena.alloc(hir::FnDecl {
             inputs: arena_vec![self; input_ty],
             output,
             c_variadic: false,
@@ -598,7 +598,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
         let params = arena_vec![self; param];
 
-        let body_id = self.lower_body(move |this| {
+        let body = self.lower_body(move |this| {
             this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
 
             let old_ctx = this.task_context;
@@ -609,13 +609,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         });
 
         // `static |_task_context| -> <ret_ty> { body }`:
-        let generator_kind = hir::ExprKind::Closure(
+        let generator_kind = hir::ExprKind::Closure {
             capture_clause,
-            decl,
-            body_id,
-            self.lower_span(span),
-            Some(hir::Movability::Static),
-        );
+            fn_decl,
+            body,
+            fn_decl_span: self.lower_span(span),
+            movability: Some(hir::Movability::Static),
+        };
         let generator = hir::Expr {
             hir_id: self.lower_node_id(closure_node_id),
             kind: generator_kind,
@@ -840,7 +840,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         body: &Expr,
         fn_decl_span: Span,
     ) -> hir::ExprKind<'hir> {
-        let (body_id, generator_option) = self.with_new_scopes(move |this| {
+        let (body, generator_option) = self.with_new_scopes(move |this| {
             let prev = this.current_item;
             this.current_item = Some(fn_decl_span);
             let mut generator_kind = None;
@@ -858,13 +858,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // Lower outside new scope to preserve `is_in_loop_condition`.
         let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
 
-        hir::ExprKind::Closure(
+        hir::ExprKind::Closure {
             capture_clause,
             fn_decl,
-            body_id,
-            self.lower_span(fn_decl_span),
-            generator_option,
-        )
+            body,
+            fn_decl_span: self.lower_span(fn_decl_span),
+            movability: generator_option,
+        }
     }
 
     fn generator_movability_for_fn(
@@ -911,7 +911,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let outer_decl =
             FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
 
-        let body_id = self.with_new_scopes(|this| {
+        let body = self.with_new_scopes(|this| {
             // FIXME(cramertj): allow `async` non-`move` closures with arguments.
             if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
                 struct_span_err!(
@@ -950,13 +950,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // closure argument types.
         let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
 
-        hir::ExprKind::Closure(
+        hir::ExprKind::Closure {
             capture_clause,
             fn_decl,
-            body_id,
-            self.lower_span(fn_decl_span),
-            None,
-        )
+            body,
+            fn_decl_span: self.lower_span(fn_decl_span),
+            movability: None,
+        }
     }
 
     /// Destructure the LHS of complex assignments.
@@ -1168,7 +1168,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             .span_suggestion(
                                 e.span,
                                 "consider removing the trailing pattern",
-                                String::new(),
+                                "",
                                 rustc_errors::Applicability::MachineApplicable,
                             )
                             .emit();
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 6fe95a21fa4..cb7804ca375 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -871,7 +871,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
                 }
                 GenericArgs::Parenthesized(ref data) => {
-                    self.assoc_ty_contraint_param_error_emit(data);
+                    self.emit_bad_parenthesized_trait_in_assoc_ty(data);
                     self.lower_angle_bracketed_parameter_data(
                         &data.as_angle_bracketed_args(),
                         ParamMode::Explicit,
@@ -982,7 +982,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn assoc_ty_contraint_param_error_emit(&self, data: &ParenthesizedArgs) -> () {
+    fn emit_bad_parenthesized_trait_in_assoc_ty(&self, data: &ParenthesizedArgs) {
         let mut err = self.sess.struct_span_err(
             data.span,
             "parenthesized generic arguments cannot be used in associated type constraints",
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index e27bc7a0f47..95bf947854f 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -139,7 +139,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         .span_suggestion_verbose(
                             sp,
                             &format!("if you don't need to use the contents of {}, discard the tuple's remaining fields", ident),
-                            "..".to_string(),
+                            "..",
                             Applicability::MaybeIncorrect,
                         )
                         .emit();
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 21db7d0eebc..503bdbad258 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -488,7 +488,7 @@ impl<'a> AstValidator<'a> {
             .span_suggestion(
                 replace_span,
                 &format!("provide a definition for the {}", ctx),
-                sugg.to_string(),
+                sugg,
                 Applicability::HasPlaceholders,
             )
             .emit();
@@ -522,7 +522,7 @@ impl<'a> AstValidator<'a> {
                 .span_suggestion(
                     span,
                     &format!("remove the {}", remove_descr),
-                    String::new(),
+                    "",
                     Applicability::MaybeIncorrect,
                 )
                 .span_label(self.current_extern_span(), "`extern` block begins here")
@@ -570,7 +570,7 @@ impl<'a> AstValidator<'a> {
             .span_suggestion(
                 body.span,
                 "remove the invalid body",
-                ";".to_string(),
+                ";",
                 Applicability::MaybeIncorrect,
             )
             .help(
@@ -599,7 +599,7 @@ impl<'a> AstValidator<'a> {
                 .span_suggestion_verbose(
                     span.until(ident.span.shrink_to_lo()),
                     "remove the qualifiers",
-                    "fn ".to_string(),
+                    "fn ",
                     Applicability::MaybeIncorrect,
                 )
                 .emit();
@@ -703,7 +703,7 @@ impl<'a> AstValidator<'a> {
             .span_suggestion(
                 generics.span,
                 "remove the parameters",
-                String::new(),
+                "",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -721,7 +721,7 @@ impl<'a> AstValidator<'a> {
         .span_suggestion(
             span,
             "remove the super traits or lifetime bounds",
-            String::new(),
+            "",
             Applicability::MachineApplicable,
         )
         .emit();
@@ -753,7 +753,7 @@ impl<'a> AstValidator<'a> {
             .span_suggestion(
                 total_span,
                 "remove these associated items",
-                String::new(),
+                "",
                 Applicability::MachineApplicable,
             )
             .span_label(ident_span, "auto trait cannot have associated items")
@@ -993,7 +993,7 @@ fn validate_generic_param_order(
             err.span_suggestion(
                 span,
                 "reorder the parameters: lifetimes, then consts and types",
-                ordered_params.clone(),
+                &ordered_params,
                 Applicability::MachineApplicable,
             );
             err.emit();
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 77dd4ccd64e..4024f883f37 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -406,8 +406,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
         // Emit errors for non-staged-api crates.
         if !self.features.staged_api {
-            if attr.has_name(sym::rustc_deprecated)
-                || attr.has_name(sym::unstable)
+            if attr.has_name(sym::unstable)
                 || attr.has_name(sym::stable)
                 || attr.has_name(sym::rustc_const_unstable)
                 || attr.has_name(sym::rustc_const_stable)
@@ -823,7 +822,7 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
                 err.span_suggestion(
                     attr.span,
                     "remove the attribute",
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 );
             }
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index c8f1e1dbb01..ce7c0eb72cd 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -59,7 +59,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
                     err.span_suggestion(
                         span,
                         "consider removing the prefix",
-                        lint_str[1..].to_string(),
+                        &lint_str[1..],
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -720,18 +720,10 @@ where
     let is_rustc = sess.features_untracked().staged_api;
 
     'outer: for attr in attrs_iter {
-        if !(attr.has_name(sym::deprecated) || attr.has_name(sym::rustc_deprecated)) {
+        if !attr.has_name(sym::deprecated) {
             continue;
         }
 
-        // FIXME(jhpratt) remove this eventually
-        if attr.has_name(sym::rustc_deprecated) {
-            diagnostic
-                .struct_span_err(attr.span, "`#[rustc_deprecated]` has been removed")
-                .help("use `#[deprecated]` instead")
-                .emit();
-        }
-
         let Some(meta) = attr.meta() else {
             continue;
         };
@@ -787,25 +779,6 @@ where
                                     continue 'outer;
                                 }
                             }
-                            // FIXME(jhpratt) remove this eventually
-                            sym::reason if attr.has_name(sym::rustc_deprecated) => {
-                                if !get(mi, &mut note) {
-                                    continue 'outer;
-                                }
-
-                                let mut diag = diagnostic
-                                    .struct_span_err(mi.span, "`reason` has been renamed");
-                                match note {
-                                    Some(note) => diag.span_suggestion(
-                                        mi.span,
-                                        "use `note` instead",
-                                        format!("note = \"{note}\""),
-                                        Applicability::MachineApplicable,
-                                    ),
-                                    None => diag.span_help(mi.span, "use `note` instead"),
-                                };
-                                diag.emit();
-                            }
                             sym::suggestion => {
                                 if !sess.features_untracked().deprecated_suggestion {
                                     let mut diag = sess.struct_span_err(
@@ -942,7 +915,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                         err.span_suggestion(
                             item.span(),
                             "supply an argument here",
-                            "align(...)".to_string(),
+                            "align(...)",
                             Applicability::HasPlaceholders,
                         );
                         err.emit();
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 191574d7a8f..73c0bf16a1f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -225,7 +225,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                     .map(|n| format!("`{}`", n))
                                     .unwrap_or_else(|| "the value".to_string())
                             ),
-                            "ref ".to_string(),
+                            "ref ",
                             Applicability::MachineApplicable,
                         );
                         in_pattern = true;
@@ -276,7 +276,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 .map(|n| format!("`{}`", n))
                                 .unwrap_or_else(|| "the mutable reference".to_string()),
                         ),
-                        "&mut *".to_string(),
+                        "&mut *",
                         Applicability::MachineApplicable,
                     );
                 }
@@ -1519,15 +1519,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             Ok(string) => {
                 if string.starts_with("async ") {
                     let pos = args_span.lo() + BytePos(6);
-                    (args_span.with_lo(pos).with_hi(pos), "move ".to_string())
+                    (args_span.with_lo(pos).with_hi(pos), "move ")
                 } else if string.starts_with("async|") {
                     let pos = args_span.lo() + BytePos(5);
-                    (args_span.with_lo(pos).with_hi(pos), " move".to_string())
+                    (args_span.with_lo(pos).with_hi(pos), " move")
                 } else {
-                    (args_span.shrink_to_lo(), "move ".to_string())
+                    (args_span.shrink_to_lo(), "move ")
                 }
             }
-            Err(_) => (args_span, "move |<args>| <body>".to_string()),
+            Err(_) => (args_span, "move |<args>| <body>"),
         };
         let kind = match use_span.generator_kind() {
             Some(generator_kind) => match generator_kind {
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 5d9e5907dff..230ccf51990 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -212,7 +212,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
                                         "consider adding semicolon after the expression so its \
                                         temporaries are dropped sooner, before the local variables \
                                         declared by the block are dropped",
-                                        ";".to_string(),
+                                        ";",
                                         Applicability::MaybeIncorrect,
                                     );
                                 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 9581bb65236..fbc3a8cc088 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -896,7 +896,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(local_did);
         let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
         debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
-        if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr {
+        if let hir::ExprKind::Closure { body, fn_decl_span, .. } = expr {
             for (captured_place, place) in self
                 .infcx
                 .tcx
@@ -909,11 +909,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         if target_place == place.as_ref() =>
                     {
                         debug!("closure_span: found captured local {:?}", place);
-                        let body = self.infcx.tcx.hir().body(*body_id);
+                        let body = self.infcx.tcx.hir().body(*body);
                         let generator_kind = body.generator_kind();
 
                         return Some((
-                            *args_span,
+                            *fn_decl_span,
                             generator_kind,
                             captured_place.get_capture_kind_span(self.infcx.tcx),
                             captured_place.get_path_span(self.infcx.tcx),
@@ -1023,7 +1023,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                      avoid moving into the `for` loop",
                                     ty,
                                 ),
-                                "&".to_string(),
+                                "&",
                                 Applicability::MaybeIncorrect,
                             );
                         }
@@ -1049,7 +1049,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                             .map(|n| format!("`{}`", n))
                                             .unwrap_or_else(|| "the mutable reference".to_string()),
                                     ),
-                                    "&mut *".to_string(),
+                                    "&mut *",
                                     Applicability::MachineApplicable,
                                 );
                             }
@@ -1067,7 +1067,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         err.span_suggestion_verbose(
                             fn_call_span.shrink_to_lo(),
                             "consider calling `.as_ref()` to borrow the type's contents",
-                            "as_ref().".to_string(),
+                            "as_ref().",
                             Applicability::MachineApplicable,
                         );
                     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index e7fd89c140f..eb5e61fa064 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -417,7 +417,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             err.span_suggestion_verbose(
                 span.shrink_to_hi(),
                 &format!("consider borrowing the `{}`'s content", diag_name.unwrap()),
-                ".as_ref()".to_string(),
+                ".as_ref()",
                 Applicability::MaybeIncorrect,
             );
         } else if let Some(use_spans) = use_spans {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index fe5e3c5a81b..861c5e973f1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -295,7 +295,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                             err.span_suggestion_verbose(
                                 source_info.span.with_hi(source_info.span.lo() + BytePos(5)),
                                 "try removing `&mut` here",
-                                String::new(),
+                                "",
                                 Applicability::MachineApplicable,
                             );
                         } else {
@@ -316,7 +316,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     err.span_suggestion_verbose(
                         decl.source_info.span.shrink_to_lo(),
                         "consider making the binding mutable",
-                        "mut ".to_string(),
+                        "mut ",
                         Applicability::MachineApplicable,
                     );
                 }
@@ -402,7 +402,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 err.span_suggestion(
                     span,
                     "try removing `&mut` here",
-                    String::new(),
+                    "",
                     Applicability::MaybeIncorrect,
                 );
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 35f805ce76e..e0f8da1c872 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -860,7 +860,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 err.span_suggestion_verbose(
                     span.shrink_to_hi(),
                     "consider relaxing the implicit `'static` requirement",
-                    " + '_".to_string(),
+                    " + '_",
                     Applicability::MaybeIncorrect,
                 );
                 suggested = true;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index fcb6ae438fe..d6b5089712a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -311,8 +311,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                         // Can't have BrEnv in functions, constants or generators.
                         bug!("BrEnv outside of closure.");
                     };
-                    let hir::ExprKind::Closure(_, _, _, args_span, _) =
-                        tcx.hir().expect_expr(self.mir_hir_id()).kind else {
+                    let hir::ExprKind::Closure { fn_decl_span, .. }
+                        = tcx.hir().expect_expr(self.mir_hir_id()).kind
+                    else {
                         bug!("Closure is not defined by a closure expr");
                     };
                     let region_name = self.synthesize_region_name();
@@ -336,7 +337,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                     Some(RegionName {
                         name: region_name,
                         source: RegionNameSource::SynthesizedFreeEnvRegion(
-                            args_span,
+                            fn_decl_span,
                             note.to_string(),
                         ),
                     })
@@ -683,16 +684,16 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
 
         let (return_span, mir_description, hir_ty) = match hir.get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_, return_ty, body_id, span, _),
+                kind: hir::ExprKind::Closure { fn_decl, body, fn_decl_span, .. },
                 ..
             }) => {
-                let (mut span, mut hir_ty) = match return_ty.output {
+                let (mut span, mut hir_ty) = match fn_decl.output {
                     hir::FnRetTy::DefaultReturn(_) => {
-                        (tcx.sess.source_map().end_point(*span), None)
+                        (tcx.sess.source_map().end_point(*fn_decl_span), None)
                     }
-                    hir::FnRetTy::Return(hir_ty) => (return_ty.output.span(), Some(hir_ty)),
+                    hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
                 };
-                let mir_description = match hir.body(*body_id).generator_kind {
+                let mir_description = match hir.body(*body).generator_kind {
                     Some(hir::GeneratorKind::Async(gen)) => match gen {
                         hir::AsyncGeneratorKind::Block => " of async block",
                         hir::AsyncGeneratorKind::Closure => " of async closure",
@@ -822,8 +823,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
 
         let yield_span = match tcx.hir().get(self.mir_hir_id()) {
             hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_, _, _, span, _), ..
-            }) => (tcx.sess.source_map().end_point(*span)),
+                kind: hir::ExprKind::Closure { fn_decl_span, .. },
+                ..
+            }) => (tcx.sess.source_map().end_point(*fn_decl_span)),
             _ => self.body.span,
         };
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index bf38ca19484..8ef2974c372 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -426,7 +426,7 @@ fn do_mir_borrowck<'a, 'tcx>(
                 .span_suggestion_short(
                     mut_span,
                     "remove this `mut`",
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 )
                 .emit();
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index e405baf7575..ae6b8e0ae30 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -378,7 +378,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
         } else {
             let tcx = self.tcx();
             let maybe_uneval = match constant.literal {
-                ConstantKind::Ty(ct) => match ct.val() {
+                ConstantKind::Ty(ct) => match ct.kind() {
                     ty::ConstKind::Unevaluated(uv) => Some(uv),
                     _ => None,
                 },
@@ -1841,7 +1841,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
         if let Operand::Constant(constant) = op {
             let maybe_uneval = match constant.literal {
-                ConstantKind::Ty(ct) => match ct.val() {
+                ConstantKind::Ty(ct) => match ct.kind() {
                     ty::ConstKind::Unevaluated(uv) => Some(uv),
                     _ => None,
                 },
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index c95d7147176..42bddd1b6ed 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -363,7 +363,7 @@ fn err_duplicate_option<'a>(p: &mut Parser<'a>, symbol: Symbol, span: Span) {
     err.tool_only_span_suggestion(
         full_span,
         "remove this option",
-        String::new(),
+        "",
         Applicability::MachineApplicable,
     );
 
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index 0c75187193c..925c36edb51 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -132,7 +132,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
         err.span_suggestion(
             parser.token.span,
             "try removing semicolon",
-            String::new(),
+            "",
             Applicability::MaybeIncorrect,
         );
         err.emit();
@@ -153,7 +153,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
             err.span_suggestion_short(
                 comma_span,
                 "try adding a comma",
-                ", ".to_string(),
+                ", ",
                 Applicability::MaybeIncorrect,
             );
             err.emit();
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 8d187a4be8a..37a4bf5fdca 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -1,44 +1,299 @@
-use rustc_ast::{ptr::P, Expr, Path};
+use crate::assert::expr_if_not;
+use rustc_ast::{
+    attr,
+    ptr::P,
+    token,
+    tokenstream::{DelimSpan, TokenStream, TokenTree},
+    BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability, Path,
+    PathSegment, Stmt, UseTree, UseTreeKind, DUMMY_NODE_ID,
+};
+use rustc_ast_pretty::pprust;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_expand::base::ExtCtxt;
-use rustc_span::Span;
+use rustc_span::{
+    symbol::{sym, Ident, Symbol},
+    Span,
+};
 
 pub(super) struct Context<'cx, 'a> {
+    // Top-level `let captureN = Capture::new()` statements
+    capture_decls: Vec<Capture>,
     cx: &'cx ExtCtxt<'a>,
+    // Formatting string used for debugging
+    fmt_string: String,
+    // Top-level `let __local_bindN = &expr` statements
+    local_bind_decls: Vec<Stmt>,
+    // Used to avoid capturing duplicated paths
+    //
+    // ```rust
+    // let a = 1i32;
+    // assert!(add(a, a) == 3);
+    // ```
+    paths: FxHashSet<Ident>,
     span: Span,
 }
 
 impl<'cx, 'a> Context<'cx, 'a> {
     pub(super) fn new(cx: &'cx ExtCtxt<'a>, span: Span) -> Self {
-        Self { cx, span }
+        Self {
+            capture_decls: <_>::default(),
+            cx,
+            fmt_string: <_>::default(),
+            local_bind_decls: <_>::default(),
+            paths: <_>::default(),
+            span,
+        }
     }
 
-    /// Builds the whole `assert!` expression.
+    /// Builds the whole `assert!` expression. For example, `let elem = 1; assert!(elem == 1);` expands to:
     ///
+    /// ```rust
+    /// let elem = 1;
     /// {
-    ///    use ::core::asserting::{ ... };
+    ///   #[allow(unused_imports)]
+    ///   use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+    ///   let mut __capture0 = ::core::asserting::Capture::new();
+    ///   let __local_bind0 = &elem;
+    ///   if !(
+    ///     *{
+    ///       (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+    ///       __local_bind0
+    ///     } == 1
+    ///   ) {
+    ///     panic!("Assertion failed: elem == 1\nWith captures:\n  elem = {}", __capture0)
+    ///   }
+    /// }
+    /// ```
+    pub(super) fn build(mut self, mut cond_expr: P<Expr>, panic_path: Path) -> P<Expr> {
+        let expr_str = pprust::expr_to_string(&cond_expr);
+        self.manage_cond_expr(&mut cond_expr);
+        let initial_imports = self.build_initial_imports();
+        let panic = self.build_panic(&expr_str, panic_path);
+
+        let Self { capture_decls, cx, local_bind_decls, span, .. } = self;
+
+        let mut stmts = Vec::with_capacity(4);
+        stmts.push(initial_imports);
+        stmts.extend(capture_decls.into_iter().map(|c| c.decl));
+        stmts.extend(local_bind_decls);
+        stmts.push(cx.stmt_expr(expr_if_not(cx, span, cond_expr, panic, None)));
+        cx.expr_block(cx.block(span, stmts))
+    }
+
+    /// Initial **trait** imports
+    ///
+    /// use ::core::asserting::{ ... };
+    fn build_initial_imports(&self) -> Stmt {
+        let nested_tree = |this: &Self, sym| {
+            (
+                UseTree {
+                    prefix: this.cx.path(this.span, vec![Ident::with_dummy_span(sym)]),
+                    kind: UseTreeKind::Simple(None, DUMMY_NODE_ID, DUMMY_NODE_ID),
+                    span: this.span,
+                },
+                DUMMY_NODE_ID,
+            )
+        };
+        self.cx.stmt_item(
+            self.span,
+            self.cx.item(
+                self.span,
+                Ident::empty(),
+                vec![self.cx.attribute(attr::mk_list_item(
+                    Ident::new(sym::allow, self.span),
+                    vec![attr::mk_nested_word_item(Ident::new(sym::unused_imports, self.span))],
+                ))],
+                ItemKind::Use(UseTree {
+                    prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
+                    kind: UseTreeKind::Nested(vec![
+                        nested_tree(self, sym::TryCaptureGeneric),
+                        nested_tree(self, sym::TryCapturePrintable),
+                    ]),
+                    span: self.span,
+                }),
+            ),
+        )
+    }
+
+    /// The necessary custom `panic!(...)` expression.
+    ///
+    /// panic!(
+    ///     "Assertion failed: ... \n With expansion: ...",
+    ///     __capture0,
+    ///     ...
+    /// );
+    fn build_panic(&self, expr_str: &str, panic_path: Path) -> P<Expr> {
+        let escaped_expr_str = escape_to_fmt(expr_str);
+        let initial = [
+            TokenTree::token(
+                token::Literal(token::Lit {
+                    kind: token::LitKind::Str,
+                    symbol: Symbol::intern(&if self.fmt_string.is_empty() {
+                        format!("Assertion failed: {escaped_expr_str}")
+                    } else {
+                        format!(
+                            "Assertion failed: {escaped_expr_str}\nWith captures:\n{}",
+                            &self.fmt_string
+                        )
+                    }),
+                    suffix: None,
+                }),
+                self.span,
+            ),
+            TokenTree::token(token::Comma, self.span),
+        ];
+        let captures = self.capture_decls.iter().flat_map(|cap| {
+            [
+                TokenTree::token(token::Ident(cap.ident.name, false), cap.ident.span),
+                TokenTree::token(token::Comma, self.span),
+            ]
+        });
+        self.cx.expr(
+            self.span,
+            ExprKind::MacCall(MacCall {
+                path: panic_path,
+                args: P(MacArgs::Delimited(
+                    DelimSpan::from_single(self.span),
+                    MacDelimiter::Parenthesis,
+                    initial.into_iter().chain(captures).collect::<TokenStream>(),
+                )),
+                prior_type_ascription: None,
+            }),
+        )
+    }
+
+    /// Recursive function called until `cond_expr` and `fmt_str` are fully modified.
+    ///
+    /// See [Self::manage_initial_capture] and [Self::manage_try_capture]
+    fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
+        match (*expr).kind {
+            ExprKind::Binary(_, ref mut lhs, ref mut rhs) => {
+                self.manage_cond_expr(lhs);
+                self.manage_cond_expr(rhs);
+            }
+            ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => {
+                let path_ident = path_segment.ident;
+                self.manage_initial_capture(expr, path_ident);
+            }
+            _ => {}
+        }
+    }
+
+    /// Pushes the top-level declarations and modifies `expr` to try capturing variables.
     ///
-    ///    let mut __capture0 = Capture::new();
-    ///    ...
-    ///    ...
-    ///    ...
+    /// `fmt_str`, the formatting string used for debugging, is constructed to show possible
+    /// captured variables.
+    fn manage_initial_capture(&mut self, expr: &mut P<Expr>, path_ident: Ident) {
+        if self.paths.contains(&path_ident) {
+            return;
+        } else {
+            self.fmt_string.push_str("  ");
+            self.fmt_string.push_str(path_ident.as_str());
+            self.fmt_string.push_str(" = {:?}\n");
+            let _ = self.paths.insert(path_ident);
+        }
+        let curr_capture_idx = self.capture_decls.len();
+        let capture_string = format!("__capture{curr_capture_idx}");
+        let ident = Ident::new(Symbol::intern(&capture_string), self.span);
+        let init_std_path = self.cx.std_path(&[sym::asserting, sym::Capture, sym::new]);
+        let init = self.cx.expr_call(
+            self.span,
+            self.cx.expr_path(self.cx.path(self.span, init_std_path)),
+            vec![],
+        );
+        let capture = Capture { decl: self.cx.stmt_let(self.span, true, ident, init), ident };
+        self.capture_decls.push(capture);
+        self.manage_try_capture(ident, curr_capture_idx, expr);
+    }
+
+    /// Tries to copy `__local_bindN` into `__captureN`.
     ///
-    ///    if !{
-    ///       ...
-    ///       ...
-    ///       ...
-    ///    } {
-    ///        panic!(
-    ///            "Assertion failed: ... \n With expansion: ...",
-    ///            __capture0,
-    ///            ...
-    ///            ...
-    ///            ...
-    ///        );
-    ///    }
+    /// *{
+    ///    (&Wrapper(__local_bindN)).try_capture(&mut __captureN);
+    ///    __local_bindN
     /// }
-    pub(super) fn build(self, _cond_expr: P<Expr>, _panic_path: Path) -> P<Expr> {
-        let Self { cx, span, .. } = self;
-        let stmts = Vec::new();
-        cx.expr_block(cx.block(span, stmts))
+    fn manage_try_capture(&mut self, capture: Ident, curr_capture_idx: usize, expr: &mut P<Expr>) {
+        let local_bind_string = format!("__local_bind{curr_capture_idx}");
+        let local_bind = Ident::new(Symbol::intern(&local_bind_string), self.span);
+        self.local_bind_decls.push(self.cx.stmt_let(
+            self.span,
+            false,
+            local_bind,
+            self.cx.expr_addr_of(self.span, expr.clone()),
+        ));
+        let wrapper = self.cx.expr_call(
+            self.span,
+            self.cx.expr_path(
+                self.cx.path(self.span, self.cx.std_path(&[sym::asserting, sym::Wrapper])),
+            ),
+            vec![self.cx.expr_path(Path::from_ident(local_bind))],
+        );
+        let try_capture_call = self
+            .cx
+            .stmt_expr(expr_method_call(
+                self.cx,
+                PathSegment {
+                    args: None,
+                    id: DUMMY_NODE_ID,
+                    ident: Ident::new(sym::try_capture, self.span),
+                },
+                vec![
+                    expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)),
+                    expr_addr_of_mut(
+                        self.cx,
+                        self.span,
+                        self.cx.expr_path(Path::from_ident(capture)),
+                    ),
+                ],
+                self.span,
+            ))
+            .add_trailing_semicolon();
+        let local_bind_path = self.cx.expr_path(Path::from_ident(local_bind));
+        let ret = self.cx.stmt_expr(local_bind_path);
+        let block = self.cx.expr_block(self.cx.block(self.span, vec![try_capture_call, ret]));
+        *expr = self.cx.expr_deref(self.span, block);
+    }
+}
+
+/// Information about a captured element.
+#[derive(Debug)]
+struct Capture {
+    // Generated indexed `Capture` statement.
+    //
+    // `let __capture{} = Capture::new();`
+    decl: Stmt,
+    // The name of the generated indexed `Capture` variable.
+    //
+    // `__capture{}`
+    ident: Ident,
+}
+
+/// Escapes to use as a formatting string.
+fn escape_to_fmt(s: &str) -> String {
+    let mut rslt = String::with_capacity(s.len());
+    for c in s.chars() {
+        rslt.extend(c.escape_debug());
+        match c {
+            '{' | '}' => rslt.push(c),
+            _ => {}
+        }
     }
+    rslt
+}
+
+fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
+    cx.expr(sp, ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, e))
+}
+
+fn expr_method_call(
+    cx: &ExtCtxt<'_>,
+    path: PathSegment,
+    args: Vec<P<Expr>>,
+    span: Span,
+) -> P<Expr> {
+    cx.expr(span, ExprKind::MethodCall(path, args, span))
+}
+
+fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
+    cx.expr(sp, ExprKind::Paren(e))
 }
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index 7f25b23734b..d3de10ca4a2 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -142,7 +142,7 @@ fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
     let report_error = |title, action| {
         let span = meta.span.with_lo(meta.path.span.hi());
         sess.struct_span_err(span, title)
-            .span_suggestion(span, action, String::new(), Applicability::MachineApplicable)
+            .span_suggestion(span, action, "", Applicability::MachineApplicable)
             .emit();
     };
     match meta.kind {
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 60b96399b5e..10348c4967c 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -330,7 +330,7 @@ impl<'a, 'b> Context<'a, 'b> {
                                 err.tool_only_span_suggestion(
                                     sp,
                                     &format!("use the `{}` trait", name),
-                                    (*fmt).to_string(),
+                                    *fmt,
                                     Applicability::MaybeIncorrect,
                                 );
                             }
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 124d0d18cdb..11565ba72d7 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(array_windows)]
 #![feature(box_patterns)]
 #![feature(decl_macro)]
+#![feature(if_let_guard)]
 #![feature(is_sorted)]
 #![feature(let_chains)]
 #![feature(let_else)]
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 0c2d20b8f2d..e20375689f3 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -118,7 +118,7 @@ pub fn expand_test_or_bench(
         };
         err.span_label(attr_sp, "the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions")
             .span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr()))
-            .span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", String::from("#[cfg(test)]"), Applicability::MaybeIncorrect)
+            .span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", "#[cfg(test)]", Applicability::MaybeIncorrect)
             .emit();
 
         return vec![Annotatable::Item(item)];
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 07136e1b76a..fbe830b2b10 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -710,7 +710,7 @@ fn codegen_stmt<'tcx>(
                     let times = fx
                         .monomorphize(times)
                         .eval(fx.tcx, ParamEnv::reveal_all())
-                        .val()
+                        .kind()
                         .try_to_bits(fx.tcx.data_layout.pointer_size)
                         .unwrap();
                     if operand.layout().size.bytes() == 0 {
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 7d2e3e52f34..ef72e6efb94 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -45,7 +45,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
             ConstantKind::Ty(ct) => ct,
             ConstantKind::Val(..) => continue,
         };
-        match const_.val() {
+        match const_.kind() {
             ConstKind::Value(_) => {}
             ConstKind::Unevaluated(unevaluated) => {
                 if let Err(err) =
@@ -126,8 +126,8 @@ pub(crate) fn codegen_constant<'tcx>(
         ConstantKind::Ty(ct) => ct,
         ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty),
     };
-    let const_val = match const_.val() {
-        ConstKind::Value(const_val) => const_val,
+    let const_val = match const_.kind() {
+        ConstKind::Value(valtree) => fx.tcx.valtree_to_const_val((const_.ty(), valtree)),
         ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
             if fx.tcx.is_static(def.did) =>
         {
@@ -468,9 +468,10 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
 ) -> Option<ConstValue<'tcx>> {
     match operand {
         Operand::Constant(const_) => match const_.literal {
-            ConstantKind::Ty(const_) => {
-                fx.monomorphize(const_).eval(fx.tcx, ParamEnv::reveal_all()).val().try_to_value()
-            }
+            ConstantKind::Ty(const_) => fx
+                .monomorphize(const_)
+                .eval_for_mir(fx.tcx, ParamEnv::reveal_all())
+                .try_to_value(fx.tcx),
             ConstantKind::Val(val, _) => Some(val),
         },
         // FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index c6681de68e2..5fbdedac0c4 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -356,6 +356,16 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.context.new_rvalue_from_int(self.int_type, 0)
     }
 
+    fn type_checked_load(
+        &mut self,
+        _llvtable: Self::Value,
+        _vtable_byte_offset: u64,
+        _typeid: Self::Value,
+    ) -> Self::Value {
+        // Unsupported.
+        self.context.new_rvalue_from_int(self.int_type, 0)
+    }
+
     fn va_start(&mut self, _va_list: RValue<'gcc>) -> RValue<'gcc> {
         unimplemented!();
     }
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 67183ff5887..b486af13376 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -16,9 +16,9 @@ measureme = "10.0.0"
 tracing = "0.1"
 rustc_middle = { path = "../rustc_middle" }
 rustc-demangle = "0.1.21"
-rustc_arena = { path = "../rustc_arena" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
+rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fs_util = { path = "../rustc_fs_util" }
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index c7497bfd355..38402e04313 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -586,9 +586,21 @@ pub(crate) fn run_pass_manager(
     // LTO-specific optimization passes that LLVM provides.
     //
     // This code is based off the code found in llvm's LTO code generator:
-    //      tools/lto/LTOCodeGenerator.cpp
+    //      llvm/lib/LTO/LTOCodeGenerator.cpp
     debug!("running the pass manager");
     unsafe {
+        if !llvm::LLVMRustHasModuleFlag(
+            module.module_llvm.llmod(),
+            "LTOPostLink".as_ptr().cast(),
+            11,
+        ) {
+            llvm::LLVMRustAddModuleFlag(
+                module.module_llvm.llmod(),
+                llvm::LLVMModFlagBehavior::Error,
+                "LTOPostLink\0".as_ptr().cast(),
+                1,
+            );
+        }
         if llvm_util::should_use_new_llvm_pass_manager(
             &config.new_llvm_pass_manager,
             &cgcx.target_arch,
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 3864db9ffc1..d05d09a11ea 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -1036,7 +1036,8 @@ unsafe fn embed_bitcode(
     // reason (see issue #90326 for historical background).
     let is_apple = cgcx.opts.target_triple.triple().contains("-ios")
         || cgcx.opts.target_triple.triple().contains("-darwin")
-        || cgcx.opts.target_triple.triple().contains("-tvos");
+        || cgcx.opts.target_triple.triple().contains("-tvos")
+        || cgcx.opts.target_triple.triple().contains("-watchos");
     if is_apple
         || cgcx.opts.target_triple.triple().starts_with("wasm")
         || cgcx.opts.target_triple.triple().starts_with("asmjs")
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 5544f0d3f60..b5c31fcebe0 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -326,6 +326,15 @@ pub unsafe fn create_module<'ll>(
         )
     }
 
+    if sess.opts.debugging_opts.virtual_function_elimination {
+        llvm::LLVMRustAddModuleFlag(
+            llmod,
+            llvm::LLVMModFlagBehavior::Error,
+            "Virtual Function Elim\0".as_ptr().cast(),
+            1,
+        );
+    }
+
     llmod
 }
 
@@ -656,6 +665,7 @@ impl<'ll> CodegenCx<'ll, '_> {
         let t_isize = self.type_isize();
         let t_f32 = self.type_f32();
         let t_f64 = self.type_f64();
+        let t_metadata = self.type_metadata();
 
         ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32);
         ifn!("llvm.wasm.trunc.unsigned.i32.f64", fn(t_f64) -> t_i32);
@@ -881,11 +891,12 @@ impl<'ll> CodegenCx<'ll, '_> {
             ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void);
         }
 
-        ifn!("llvm.type.test", fn(i8p, self.type_metadata()) -> i1);
+        ifn!("llvm.type.test", fn(i8p, t_metadata) -> i1);
+        ifn!("llvm.type.checked.load", fn(i8p, t_i32, t_metadata) -> mk_struct! {i8p, i1});
 
         if self.sess().opts.debuginfo != DebugInfo::None {
-            ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void);
-            ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void);
+            ifn!("llvm.dbg.declare", fn(t_metadata, t_metadata) -> void);
+            ifn!("llvm.dbg.value", fn(t_metadata, t_i64, t_metadata) -> void);
         }
         None
     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index f5cbbc7ca91..d5f39a45670 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -30,20 +30,21 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::bug;
 use rustc_middle::mir::{self, GeneratorLayout};
-use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, AdtKind, Instance, ParamEnv, Ty, TyCtxt};
-use rustc_session::config::{self, DebugInfo};
+use rustc_middle::ty::{
+    self, AdtKind, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
+};
+use rustc_session::config::{self, DebugInfo, Lto};
 use rustc_span::symbol::Symbol;
 use rustc_span::FileName;
-use rustc_span::FileNameDisplayPreference;
-use rustc_span::{self, SourceFile};
+use rustc_span::{self, FileNameDisplayPreference, SourceFile};
+use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::abi::{Align, Size};
 use smallvec::smallvec;
 use tracing::debug;
 
-use libc::{c_longlong, c_uint};
+use libc::{c_char, c_longlong, c_uint};
 use std::borrow::Cow;
 use std::fmt::{self, Write};
 use std::hash::{Hash, Hasher};
@@ -1468,6 +1469,84 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
     .di_node
 }
 
+fn vcall_visibility_metadata<'ll, 'tcx>(
+    cx: &CodegenCx<'ll, 'tcx>,
+    ty: Ty<'tcx>,
+    trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
+    vtable: &'ll Value,
+) {
+    enum VCallVisibility {
+        Public = 0,
+        LinkageUnit = 1,
+        TranslationUnit = 2,
+    }
+
+    let Some(trait_ref) = trait_ref else { return };
+
+    let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty);
+    let trait_ref_self = cx.tcx.erase_regions(trait_ref_self);
+    let trait_def_id = trait_ref_self.def_id();
+    let trait_vis = cx.tcx.visibility(trait_def_id);
+
+    let cgus = cx.sess().codegen_units();
+    let single_cgu = cgus == 1;
+
+    let lto = cx.sess().lto();
+
+    // Since LLVM requires full LTO for the virtual function elimination optimization to apply,
+    // only the `Lto::Fat` cases are relevant currently.
+    let vcall_visibility = match (lto, trait_vis, single_cgu) {
+        // If there is not LTO and the visibility in public, we have to assume that the vtable can
+        // be seen from anywhere. With multiple CGUs, the vtable is quasi-public.
+        (Lto::No | Lto::ThinLocal, Visibility::Public, _)
+        | (Lto::No, Visibility::Restricted(_) | Visibility::Invisible, false) => {
+            VCallVisibility::Public
+        }
+        // With LTO and a quasi-public visibility, the usages of the functions of the vtable are
+        // all known by the `LinkageUnit`.
+        // FIXME: LLVM only supports this optimization for `Lto::Fat` currently. Once it also
+        // supports `Lto::Thin` the `VCallVisibility` may have to be adjusted for those.
+        (Lto::Fat | Lto::Thin, Visibility::Public, _)
+        | (
+            Lto::ThinLocal | Lto::Thin | Lto::Fat,
+            Visibility::Restricted(_) | Visibility::Invisible,
+            false,
+        ) => VCallVisibility::LinkageUnit,
+        // If there is only one CGU, private vtables can only be seen by that CGU/translation unit
+        // and therefore we know of all usages of functions in the vtable.
+        (_, Visibility::Restricted(_) | Visibility::Invisible, true) => {
+            VCallVisibility::TranslationUnit
+        }
+    };
+
+    let trait_ref_typeid = typeid_for_trait_ref(cx.tcx, trait_ref);
+
+    unsafe {
+        let typeid = llvm::LLVMMDStringInContext(
+            cx.llcx,
+            trait_ref_typeid.as_ptr() as *const c_char,
+            trait_ref_typeid.as_bytes().len() as c_uint,
+        );
+        let v = [cx.const_usize(0), typeid];
+        llvm::LLVMRustGlobalAddMetadata(
+            vtable,
+            llvm::MD_type as c_uint,
+            llvm::LLVMValueAsMetadata(llvm::LLVMMDNodeInContext(
+                cx.llcx,
+                v.as_ptr(),
+                v.len() as c_uint,
+            )),
+        );
+        let vcall_visibility = llvm::LLVMValueAsMetadata(cx.const_u64(vcall_visibility as u64));
+        let vcall_visibility_metadata = llvm::LLVMMDNodeInContext2(cx.llcx, &vcall_visibility, 1);
+        llvm::LLVMGlobalSetMetadata(
+            vtable,
+            llvm::MetadataType::MD_vcall_visibility as c_uint,
+            vcall_visibility_metadata,
+        );
+    }
+}
+
 /// Creates debug information for the given vtable, which is for the
 /// given type.
 ///
@@ -1478,6 +1557,12 @@ pub fn create_vtable_di_node<'ll, 'tcx>(
     poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
     vtable: &'ll Value,
 ) {
+    // FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
+    // LLVM at the moment.
+    if cx.sess().opts.debugging_opts.virtual_function_elimination && cx.sess().lto() == Lto::Fat {
+        vcall_visibility_metadata(cx, ty, poly_trait_ref, vtable);
+    }
+
     if cx.dbg_cx.is_none() {
         return;
     }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 9927f5f399b..a18f5b9dd7f 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -406,6 +406,16 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         self.call_intrinsic("llvm.type.test", &[bitcast, typeid])
     }
 
+    fn type_checked_load(
+        &mut self,
+        llvtable: &'ll Value,
+        vtable_byte_offset: u64,
+        typeid: &'ll Value,
+    ) -> Self::Value {
+        let vtable_byte_offset = self.const_i32(vtable_byte_offset as i32);
+        self.call_intrinsic("llvm.type.checked.load", &[llvtable, vtable_byte_offset, typeid])
+    }
+
     fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value {
         self.call_intrinsic("llvm.va_start", &[va_list])
     }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 1d9a4655db6..b831423994f 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -442,6 +442,7 @@ pub enum MetadataType {
     MD_nonnull = 11,
     MD_align = 17,
     MD_type = 19,
+    MD_vcall_visibility = 28,
     MD_noundef = 29,
 }
 
@@ -1067,6 +1068,7 @@ extern "C" {
     pub fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value);
     pub fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Node: &'a Value);
     pub fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
+    pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
     pub fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
 
     // Operations on constants of any type
@@ -1080,6 +1082,11 @@ extern "C" {
         Vals: *const &'a Value,
         Count: c_uint,
     ) -> &'a Value;
+    pub fn LLVMMDNodeInContext2<'a>(
+        C: &'a Context,
+        Vals: *const &'a Metadata,
+        Count: size_t,
+    ) -> &'a Metadata;
     pub fn LLVMAddNamedMetadataOperand<'a>(M: &'a Module, Name: *const c_char, Val: &'a Value);
 
     // Operations on scalar constants
@@ -1936,6 +1943,7 @@ extern "C" {
         name: *const c_char,
         value: u32,
     );
+    pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool;
 
     pub fn LLVMRustMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 82213e7d748..e70509f3ecc 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2606,7 +2606,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
     let os = &sess.target.os;
     let llvm_target = &sess.target.llvm_target;
     if sess.target.vendor != "apple"
-        || !matches!(os.as_ref(), "ios" | "tvos")
+        || !matches!(os.as_ref(), "ios" | "tvos" | "watchos")
         || flavor != LinkerFlavor::Gcc
     {
         return;
@@ -2616,11 +2616,16 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
         ("x86_64", "tvos") => "appletvsimulator",
         ("arm", "ios") => "iphoneos",
         ("aarch64", "ios") if llvm_target.contains("macabi") => "macosx",
-        ("aarch64", "ios") if llvm_target.contains("sim") => "iphonesimulator",
+        ("aarch64", "ios") if llvm_target.ends_with("-simulator") => "iphonesimulator",
         ("aarch64", "ios") => "iphoneos",
         ("x86", "ios") => "iphonesimulator",
         ("x86_64", "ios") if llvm_target.contains("macabi") => "macosx",
         ("x86_64", "ios") => "iphonesimulator",
+        ("x86_64", "watchos") => "watchsimulator",
+        ("arm64_32", "watchos") => "watchos",
+        ("aarch64", "watchos") if llvm_target.ends_with("-simulator") => "watchsimulator",
+        ("aarch64", "watchos") => "watchos",
+        ("arm", "watchos") => "watchos",
         _ => {
             sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os));
             return;
@@ -2667,6 +2672,11 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> {
             "macosx10.15"
                 if sdkroot.contains("iPhoneOS.platform")
                     || sdkroot.contains("iPhoneSimulator.platform") => {}
+            "watchos"
+                if sdkroot.contains("WatchSimulator.platform")
+                    || sdkroot.contains("MacOSX.platform") => {}
+            "watchsimulator"
+                if sdkroot.contains("WatchOS.platform") || sdkroot.contains("MacOSX.platform") => {}
             // Ignore `SDKROOT` if it's not a valid path.
             _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
             _ => return Ok(sdkroot),
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index ae43464791d..8755d91818d 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -180,7 +180,7 @@ fn push_debuginfo_type_name<'tcx>(
             if cpp_like_debuginfo {
                 output.push_str("array$<");
                 push_debuginfo_type_name(tcx, inner_type, true, output, visited);
-                match len.val() {
+                match len.kind() {
                     ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(),
                     _ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
                         .unwrap(),
@@ -188,7 +188,7 @@ fn push_debuginfo_type_name<'tcx>(
             } else {
                 output.push('[');
                 push_debuginfo_type_name(tcx, inner_type, true, output, visited);
-                match len.val() {
+                match len.kind() {
                     ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(),
                     _ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
                         .unwrap(),
@@ -679,7 +679,7 @@ fn push_generic_params_internal<'tcx>(
 }
 
 fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut String) {
-    match ct.val() {
+    match ct.kind() {
         ty::ConstKind::Param(param) => {
             write!(output, "{}", param.name)
         }
@@ -703,15 +703,19 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
                 // but we get a deterministic, virtually unique value for the constant.
                 let hcx = &mut tcx.create_stable_hashing_context();
                 let mut hasher = StableHasher::new();
-                hcx.while_hashing_spans(false, |hcx| ct.val().hash_stable(hcx, &mut hasher));
+                let ct = ct.eval(tcx, ty::ParamEnv::reveal_all());
+                hcx.while_hashing_spans(false, |hcx| ct.to_valtree().hash_stable(hcx, &mut hasher));
                 // Let's only emit 64 bits of the hash value. That should be plenty for
                 // avoiding collisions and will make the emitted type names shorter.
-                let hash: u64 = hasher.finish();
+                // Note: Don't use `StableHashResult` impl of `u64` here directly, since that
+                // would lead to endianness problems.
+                let hash: u128 = hasher.finish();
+                let hash_short = (hash.to_le() as u64).to_le();
 
                 if cpp_like_debuginfo(tcx) {
-                    write!(output, "CONST${:x}", hash)
+                    write!(output, "CONST${:x}", hash_short)
                 } else {
-                    write!(output, "{{CONST#{:x}}}", hash)
+                    write!(output, "{{CONST#{:x}}}", hash_short)
                 }
             }
         },
diff --git a/compiler/rustc_codegen_ssa/src/glue.rs b/compiler/rustc_codegen_ssa/src/glue.rs
index 694f5434e9a..e6f402ef19d 100644
--- a/compiler/rustc_codegen_ssa/src/glue.rs
+++ b/compiler/rustc_codegen_ssa/src/glue.rs
@@ -39,7 +39,12 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             // The info in this case is the length of the str, so the size is that
             // times the unit size.
             (
-                bx.mul(info.unwrap(), bx.const_usize(unit.size.bytes())),
+                // All slice sizes must fit into `isize`, so this multiplication cannot (signed) wrap.
+                // NOTE: ideally, we want the effects of both `unchecked_smul` and `unchecked_umul`
+                // (resulting in `mul nsw nuw` in LLVM IR), since we know that the multiplication
+                // cannot signed wrap, and that both operands are non-negative. But at the time of writing,
+                // `BuilderMethods` can't do this, and it doesn't seem to enable any further optimizations.
+                bx.unchecked_smul(info.unwrap(), bx.const_usize(unit.size.bytes())),
                 bx.const_usize(unit.align.abi.bytes()),
             )
         }
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 771157dcad9..750432b0b26 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -29,7 +29,8 @@ use rustc_middle::dep_graph::WorkProduct;
 use rustc_middle::middle::dependency_format::Dependencies;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_middle::ty::query::{ExternProviders, Providers};
-use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
+use rustc_serialize::opaque::{MemDecoder, MemEncoder};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::cstore::{self, CrateSource};
 use rustc_session::utils::NativeLibKind;
@@ -203,7 +204,7 @@ const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
 
 impl CodegenResults {
     pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> {
-        let mut encoder = opaque::Encoder::new();
+        let mut encoder = MemEncoder::new();
         encoder.emit_raw_bytes(RLINK_MAGIC);
         // `emit_raw_bytes` is used to make sure that the version representation does not depend on
         // Encoder's inner representation of `u32`.
@@ -230,7 +231,7 @@ impl CodegenResults {
             return Err(".rlink file was produced with encoding version {version_array}, but the current version is {RLINK_VERSION}".to_string());
         }
 
-        let mut decoder = opaque::Decoder::new(&data[4..], 0);
+        let mut decoder = MemDecoder::new(&data[4..], 0);
         let rustc_version = decoder.read_str();
         let current_version = RUSTC_VERSION.unwrap();
         if rustc_version != current_version {
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index 00f101595f2..5203ebfad75 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -1,6 +1,8 @@
 use crate::traits::*;
 
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, subst::GenericArgKind, ExistentialPredicate, Ty, TyCtxt};
+use rustc_session::config::Lto;
+use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::abi::call::FnAbi;
 
 #[derive(Copy, Clone, Debug)]
@@ -15,20 +17,32 @@ impl<'a, 'tcx> VirtualIndex {
         self,
         bx: &mut Bx,
         llvtable: Bx::Value,
+        ty: Ty<'tcx>,
         fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
     ) -> Bx::Value {
         // Load the data pointer from the object.
-        debug!("get_fn({:?}, {:?})", llvtable, self);
-
+        debug!("get_fn({llvtable:?}, {ty:?}, {self:?})");
         let llty = bx.fn_ptr_backend_type(fn_abi);
         let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
-        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        let gep = bx.inbounds_gep(llty, llvtable, &[bx.const_usize(self.0)]);
-        let ptr = bx.load(llty, gep, ptr_align);
-        bx.nonnull_metadata(ptr);
-        // Vtable loads are invariant.
-        bx.set_invariant_load(ptr);
-        ptr
+
+        if bx.cx().sess().opts.debugging_opts.virtual_function_elimination
+            && bx.cx().sess().lto() == Lto::Fat
+        {
+            let typeid =
+                bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), get_trait_ref(bx.tcx(), ty)));
+            let vtable_byte_offset = self.0 * bx.data_layout().pointer_size.bytes();
+            let type_checked_load = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
+            let func = bx.extract_value(type_checked_load, 0);
+            bx.pointercast(func, llty)
+        } else {
+            let ptr_align = bx.tcx().data_layout.pointer_align.abi;
+            let gep = bx.inbounds_gep(llty, llvtable, &[bx.const_usize(self.0)]);
+            let ptr = bx.load(llty, gep, ptr_align);
+            bx.nonnull_metadata(ptr);
+            // Vtable loads are invariant.
+            bx.set_invariant_load(ptr);
+            ptr
+        }
     }
 
     pub fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
@@ -50,6 +64,24 @@ impl<'a, 'tcx> VirtualIndex {
     }
 }
 
+fn get_trait_ref<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::PolyExistentialTraitRef<'tcx> {
+    for arg in ty.peel_refs().walk() {
+        if let GenericArgKind::Type(ty) = arg.unpack() {
+            if let ty::Dynamic(trait_refs, _) = ty.kind() {
+                return trait_refs[0].map_bound(|trait_ref| match trait_ref {
+                    ExistentialPredicate::Trait(tr) => tr,
+                    ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
+                    ExistentialPredicate::AutoTrait(_) => {
+                        bug!("auto traits don't have functions")
+                    }
+                });
+            }
+        }
+    }
+
+    bug!("expected a `dyn Trait` ty, found {ty:?}")
+}
+
 /// Creates a dynamic vtable for the given type and vtable origin.
 /// This is used only for objects.
 ///
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 03ef6d50d44..db348f2bdd5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -401,7 +401,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 args = &args[..1];
                 (
                     meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
-                        .get_fn(&mut bx, vtable, &fn_abi),
+                        .get_fn(&mut bx, vtable, ty, &fn_abi),
                     fn_abi,
                 )
             }
@@ -819,9 +819,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     // the data pointer as the first argument
                     match op.val {
                         Pair(data_ptr, meta) => {
-                            llfn = Some(
-                                meth::VirtualIndex::from_index(idx).get_fn(&mut bx, meta, &fn_abi),
-                            );
+                            llfn = Some(meth::VirtualIndex::from_index(idx).get_fn(
+                                &mut bx,
+                                meta,
+                                op.layout.ty,
+                                &fn_abi,
+                            ));
                             llargs.push(data_ptr);
                             continue 'make_args;
                         }
@@ -829,7 +832,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                 } else if let Ref(data_ptr, Some(meta), _) = op.val {
                     // by-value dynamic dispatch
-                    llfn = Some(meth::VirtualIndex::from_index(idx).get_fn(&mut bx, meta, &fn_abi));
+                    llfn = Some(meth::VirtualIndex::from_index(idx).get_fn(
+                        &mut bx,
+                        meta,
+                        op.layout.ty,
+                        &fn_abi,
+                    ));
                     llargs.push(data_ptr);
                     continue;
                 } else {
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 479b2b05f43..9a995fbf65c 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -29,7 +29,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             mir::ConstantKind::Ty(ct) => ct,
             mir::ConstantKind::Val(val, _) => return Ok(val),
         };
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Unevaluated(ct) => self
                 .cx
                 .tcx()
@@ -38,7 +38,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
                     err
                 }),
-            ty::ConstKind::Value(value) => Ok(value),
+            ty::ConstKind::Value(val) => Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val))),
             err => span_bug!(
                 constant.span,
                 "encountered bad ConstKind after monomorphizing: {:?}",
@@ -58,14 +58,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         constant
             .map(|val| {
                 let field_ty = ty.builtin_index().unwrap();
-                let c = ty::Const::from_value(bx.tcx(), val, ty);
+                let c = mir::ConstantKind::from_value(val, ty);
                 let values: Vec<_> = bx
                     .tcx()
-                    .destructure_const(ty::ParamEnv::reveal_all().and(c))
+                    .destructure_mir_constant(ty::ParamEnv::reveal_all(), c)
                     .fields
                     .iter()
                     .map(|field| {
-                        if let Some(prim) = field.val().try_to_scalar() {
+                        if let Some(prim) = field.try_to_scalar() {
                             let layout = bx.layout_of(field_ty);
                             let Abi::Scalar(scalar) = layout.abi else {
                                 bug!("from_const: invalid ByVal layout: {:#?}", layout);
diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
index 02be6cd360c..7755e67938c 100644
--- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
@@ -22,6 +22,14 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
     fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;
     /// Trait method used to test whether a given pointer is associated with a type identifier.
     fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value;
+    /// Trait method used to load a function while testing if it is associated with a type
+    /// identifier.
+    fn type_checked_load(
+        &mut self,
+        llvtable: Self::Value,
+        vtable_byte_offset: u64,
+        typeid: Self::Value,
+    ) -> Self::Value;
     /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in
     /// Rust defined C-variadic functions.
     fn va_start(&mut self, val: Self::Value) -> Self::Value;
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 3bd092263c1..3eeb0138b37 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -140,6 +140,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
     ///
     /// If `lint_root.is_some()` report it as a lint, else report it as a hard error.
     /// (Except that for some errors, we ignore all that -- see `must_error` below.)
+    #[instrument(skip(self, tcx, decorate, lint_root), level = "debug")]
     fn struct_generic(
         &self,
         tcx: TyCtxtAt<'tcx>,
@@ -190,6 +191,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
             decorate(err);
         };
 
+        debug!("self.error: {:?}", self.error);
         // Special handling for certain errors
         match &self.error {
             // Don't emit a new diagnostic for these errors
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 0c20324e452..b7e5e7aea49 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -196,7 +196,7 @@ pub(super) fn op_to_const<'tcx>(
 }
 
 #[instrument(skip(tcx), level = "debug")]
-fn turn_into_const_value<'tcx>(
+pub(crate) fn turn_into_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     constant: ConstAlloc<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
@@ -222,6 +222,7 @@ fn turn_into_const_value<'tcx>(
     const_val
 }
 
+#[instrument(skip(tcx), level = "debug")]
 pub fn eval_to_const_value_raw_provider<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
@@ -256,6 +257,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
     tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
 }
 
+#[instrument(skip(tcx), level = "debug")]
 pub fn eval_to_allocation_raw_provider<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index db43f7a425c..a1d2e5cf3ef 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -1,12 +1,11 @@
 // Not in interpret to make sure we do not use private implementation details
 
-use std::convert::TryFrom;
-
 use rustc_hir::Mutability;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
+use rustc_target::abi::VariantIdx;
 
 use crate::interpret::{
     intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
@@ -40,7 +39,7 @@ pub(crate) fn const_caller_location(
 }
 
 // We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
-const VALTREE_MAX_NODES: usize = 1000;
+const VALTREE_MAX_NODES: usize = 100000;
 
 pub(crate) enum ValTreeCreationError {
     NodesOverflow,
@@ -56,6 +55,8 @@ pub(crate) fn eval_to_valtree<'tcx>(
     cid: GlobalId<'tcx>,
 ) -> EvalToValTreeResult<'tcx> {
     let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
+
+    // FIXME Need to provide a span to `eval_to_valtree`
     let ecx = mk_eval_cx(
         tcx, DUMMY_SP, param_env,
         // It is absolutely crucial for soundness that
@@ -90,40 +91,81 @@ pub(crate) fn eval_to_valtree<'tcx>(
     }
 }
 
-/// This function should never fail for validated constants. However, it is also invoked from the
-/// pretty printer which might attempt to format invalid constants and in that case it might fail.
+/// Tries to destructure constants of type Array or Adt into the constants
+/// of its fields.
 pub(crate) fn try_destructure_const<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    val: ty::Const<'tcx>,
-) -> InterpResult<'tcx, mir::DestructuredConst<'tcx>> {
-    trace!("destructure_const: {:?}", val);
-    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
-    let op = ecx.const_to_op(val, None)?;
-    // We go to `usize` as we cannot allocate anything bigger anyway.
-    let (field_count, variant, down) = match val.ty().kind() {
-        ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
-        // Checks if we have any variants, to avoid downcasting to a non-existing variant (when
-        // there are no variants `read_discriminant` successfully returns a non-existing variant
-        // index).
-        ty::Adt(def, _) if def.variants().is_empty() => throw_ub!(Unreachable),
-        ty::Adt(def, _) => {
-            let variant = ecx.read_discriminant(&op)?.1;
-            let down = ecx.operand_downcast(&op, variant)?;
-            (def.variant(variant).fields.len(), Some(variant), down)
-        }
-        ty::Tuple(substs) => (substs.len(), None, op),
-        _ => bug!("cannot destructure constant {:?}", val),
-    };
-    let fields = (0..field_count)
-        .map(|i| {
-            let field_op = ecx.operand_field(&down, i)?;
-            let val = op_to_const(&ecx, &field_op);
-            Ok(ty::Const::from_value(tcx, val, field_op.layout.ty))
-        })
-        .collect::<InterpResult<'tcx, Vec<_>>>()?;
-    let fields = tcx.arena.alloc_from_iter(fields);
-    Ok(mir::DestructuredConst { variant, fields })
+    const_: ty::Const<'tcx>,
+) -> Option<ty::DestructuredConst<'tcx>> {
+    if let ty::ConstKind::Value(valtree) = const_.kind() {
+        let branches = match valtree {
+            ty::ValTree::Branch(b) => b,
+            _ => return None,
+        };
+
+        let (fields, variant) = match const_.ty().kind() {
+            ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
+                // construct the consts for the elements of the array/slice
+                let field_consts = branches
+                    .iter()
+                    .map(|b| {
+                        tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty })
+                    })
+                    .collect::<Vec<_>>();
+                debug!(?field_consts);
+
+                (field_consts, None)
+            }
+            ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"),
+            ty::Adt(def, substs) => {
+                let variant_idx = if def.is_enum() {
+                    VariantIdx::from_u32(branches[0].unwrap_leaf().try_to_u32().ok()?)
+                } else {
+                    VariantIdx::from_u32(0)
+                };
+                let fields = &def.variant(variant_idx).fields;
+                let mut field_consts = Vec::with_capacity(fields.len());
+
+                // Note: First element inValTree corresponds to variant of enum
+                let mut valtree_idx = if def.is_enum() { 1 } else { 0 };
+                for field in fields {
+                    let field_ty = field.ty(tcx, substs);
+                    let field_valtree = branches[valtree_idx]; // first element of branches is variant
+                    let field_const = tcx.mk_const(ty::ConstS {
+                        kind: ty::ConstKind::Value(field_valtree),
+                        ty: field_ty,
+                    });
+                    field_consts.push(field_const);
+                    valtree_idx += 1;
+                }
+                debug!(?field_consts);
+
+                (field_consts, Some(variant_idx))
+            }
+            ty::Tuple(elem_tys) => {
+                let fields = elem_tys
+                    .iter()
+                    .enumerate()
+                    .map(|(i, elem_ty)| {
+                        let elem_valtree = branches[i];
+                        tcx.mk_const(ty::ConstS {
+                            kind: ty::ConstKind::Value(elem_valtree),
+                            ty: elem_ty,
+                        })
+                    })
+                    .collect::<Vec<_>>();
+
+                (fields, None)
+            }
+            _ => bug!("cannot destructure constant {:?}", const_),
+        };
+
+        let fields = tcx.arena.alloc_from_iter(fields.into_iter());
+
+        Some(ty::DestructuredConst { variant, fields })
+    } else {
+        None
+    }
 }
 
 #[instrument(skip(tcx), level = "debug")]
@@ -143,8 +185,8 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
             throw_ub!(Unreachable)
         }
         ty::Adt(def, _) => {
-            let variant = ecx.read_discriminant(&op).unwrap().1;
-            let down = ecx.operand_downcast(&op, variant).unwrap();
+            let variant = ecx.read_discriminant(&op)?.1;
+            let down = ecx.operand_downcast(&op, variant)?;
             (def.variants()[variant].fields.len(), Some(variant), down)
         }
         ty::Tuple(substs) => (substs.len(), None, op),
@@ -164,43 +206,6 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
 }
 
 #[instrument(skip(tcx), level = "debug")]
-pub(crate) fn deref_const<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    val: ty::Const<'tcx>,
-) -> ty::Const<'tcx> {
-    trace!("deref_const: {:?}", val);
-    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
-    let op = ecx.const_to_op(val, None).unwrap();
-    let mplace = ecx.deref_operand(&op).unwrap();
-    if let Some(alloc_id) = mplace.ptr.provenance {
-        assert_eq!(
-            tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().inner().mutability,
-            Mutability::Not,
-            "deref_const cannot be used with mutable allocations as \
-            that could allow pattern matching to observe mutable statics",
-        );
-    }
-
-    let ty = match mplace.meta {
-        MemPlaceMeta::None => mplace.layout.ty,
-        MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
-        // In case of unsized types, figure out the real type behind.
-        MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
-            ty::Str => bug!("there's no sized equivalent of a `str`"),
-            ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
-            _ => bug!(
-                "type {} should not have metadata, but had {:?}",
-                mplace.layout.ty,
-                mplace.meta
-            ),
-        },
-    };
-
-    tcx.mk_const(ty::ConstS { val: ty::ConstKind::Value(op_to_const(&ecx, &mplace.into())), ty })
-}
-
-#[instrument(skip(tcx), level = "debug")]
 pub(crate) fn deref_mir_constant<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -213,14 +218,14 @@ pub(crate) fn deref_mir_constant<'tcx>(
         assert_eq!(
             tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().0.0.mutability,
             Mutability::Not,
-            "deref_const cannot be used with mutable allocations as \
+            "deref_mir_constant cannot be used with mutable allocations as \
             that could allow pattern matching to observe mutable statics",
         );
     }
 
     let ty = match mplace.meta {
         MemPlaceMeta::None => mplace.layout.ty,
-        MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
+        MemPlaceMeta::Poison => bug!("poison metadata in `deref_mir_constant`: {:#?}", mplace),
         // In case of unsized types, figure out the real type behind.
         MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
             ty::Str => bug!("there's no sized equivalent of a `str`"),
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 7346d69bb5d..4849a07e3b4 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -5,13 +5,11 @@ use crate::interpret::{
     intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta,
     MemoryKind, PlaceTy, Scalar, ScalarMaybeUninit,
 };
+use crate::interpret::{MPlaceTy, Value};
+use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_target::abi::{Align, VariantIdx};
 
-use crate::interpret::MPlaceTy;
-use crate::interpret::Value;
-use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
-
 #[instrument(skip(ecx), level = "debug")]
 fn branches<'tcx>(
     ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
@@ -76,13 +74,13 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
     place: &MPlaceTy<'tcx>,
     num_nodes: &mut usize,
 ) -> ValTreeCreationResult<'tcx> {
+    let ty = place.layout.ty;
+    debug!("ty kind: {:?}", ty.kind());
+
     if *num_nodes >= VALTREE_MAX_NODES {
         return Err(ValTreeCreationError::NodesOverflow);
     }
 
-    let ty = place.layout.ty;
-    debug!("ty kind: {:?}", ty.kind());
-
     match ty.kind() {
         ty::FnDef(..) => {
             *num_nodes += 1;
@@ -234,19 +232,15 @@ fn create_pointee_place<'tcx>(
         // Get the size of the memory behind the DST
         let dst_size = unsized_inner_ty_size.checked_mul(num_elems as u64, &tcx).unwrap();
 
-        let ptr = ecx
-            .allocate_ptr(
-                size_of_sized_part.checked_add(dst_size, &tcx).unwrap(),
-                Align::from_bytes(1).unwrap(),
-                MemoryKind::Stack,
-            )
-            .unwrap();
+        let size = size_of_sized_part.checked_add(dst_size, &tcx).unwrap();
+        let align = Align::from_bytes(size.bytes().next_power_of_two()).unwrap();
+        let ptr = ecx.allocate_ptr(size, align, MemoryKind::Stack).unwrap();
         debug!(?ptr);
 
         let place = MPlaceTy::from_aligned_ptr_with_meta(
             ptr.into(),
             layout,
-            MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64)),
+            MemPlaceMeta::Meta(Scalar::from_machine_usize(num_elems as u64, &tcx)),
         );
         debug!(?place);
 
@@ -262,7 +256,7 @@ fn create_pointee_place<'tcx>(
 #[instrument(skip(tcx), level = "debug")]
 pub fn valtree_to_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
+    param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
     valtree: ty::ValTree<'tcx>,
 ) -> ConstValue<'tcx> {
     // Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
@@ -272,8 +266,8 @@ pub fn valtree_to_const_value<'tcx>(
     // create inner `MPlace`s which are filled recursively.
     // FIXME Does this need an example?
 
-    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::empty(), false);
-    let param_env_ty = ty::ParamEnv::empty().and(ty);
+    let (param_env, ty) = param_env_ty.into_parts();
+    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
 
     match ty.kind() {
         ty::FnDef(..) => {
@@ -336,7 +330,6 @@ pub fn valtree_to_const_value<'tcx>(
     }
 }
 
-// FIXME Needs a better/correct name
 #[instrument(skip(ecx), level = "debug")]
 fn valtree_into_mplace<'tcx>(
     ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
@@ -377,7 +370,8 @@ fn valtree_into_mplace<'tcx>(
             let imm = match inner_ty.kind() {
                 ty::Slice(_) | ty::Str => {
                     let len = valtree.unwrap_branch().len();
-                    let len_scalar = ScalarMaybeUninit::Scalar(Scalar::from_u64(len as u64));
+                    let len_scalar =
+                        ScalarMaybeUninit::Scalar(Scalar::from_machine_usize(len as u64, &tcx));
 
                     Immediate::ScalarPair(
                         ScalarMaybeUninit::from_maybe_pointer((*pointee_place).ptr, &tcx),
@@ -448,7 +442,10 @@ fn valtree_into_mplace<'tcx>(
                         place
                             .offset(
                                 offset,
-                                MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64)),
+                                MemPlaceMeta::Meta(Scalar::from_machine_usize(
+                                    num_elems as u64,
+                                    &tcx,
+                                )),
                                 inner_layout,
                                 &tcx,
                             )
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index c5770f50526..e51c51cf45e 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -313,78 +313,82 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let a = self.read_pointer(&args[0])?;
                 let b = self.read_pointer(&args[1])?;
 
-                // Special case: if both scalars are *equal integers*
-                // and not null, we pretend there is an allocation of size 0 right there,
-                // and their offset is 0. (There's never a valid object at null, making it an
-                // exception from the exception.)
-                // This is the dual to the special exception for offset-by-0
-                // in the inbounds pointer offset operation (see `ptr_offset_inbounds` below).
-                match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) {
-                    (Err(a), Err(b)) if a == b && a != 0 => {
-                        // Both are the same non-null integer.
-                        self.write_scalar(Scalar::from_machine_isize(0, self), dest)?;
-                    }
-                    (Err(offset), _) | (_, Err(offset)) => {
-                        throw_ub!(DanglingIntPointer(offset, CheckInAllocMsg::OffsetFromTest));
-                    }
-                    (Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _))) => {
-                        // Both are pointers. They must be into the same allocation.
-                        if a_alloc_id != b_alloc_id {
-                            throw_ub_format!(
-                                "{} cannot compute offset of pointers into different allocations.",
-                                intrinsic_name,
-                            );
+                let usize_layout = self.layout_of(self.tcx.types.usize)?;
+                let isize_layout = self.layout_of(self.tcx.types.isize)?;
+
+                // Get offsets for both that are at least relative to the same base.
+                let (a_offset, b_offset) =
+                    match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) {
+                        (Err(a), Err(b)) => {
+                            // Neither poiner points to an allocation.
+                            // If these are inequal or null, this *will* fail the deref check below.
+                            (a, b)
                         }
-                        // And they must both be valid for zero-sized accesses ("in-bounds or one past the end").
-                        self.check_ptr_access_align(
-                            a,
-                            Size::ZERO,
-                            Align::ONE,
-                            CheckInAllocMsg::OffsetFromTest,
-                        )?;
-                        self.check_ptr_access_align(
-                            b,
-                            Size::ZERO,
-                            Align::ONE,
-                            CheckInAllocMsg::OffsetFromTest,
-                        )?;
-
-                        if intrinsic_name == sym::ptr_offset_from_unsigned && a_offset < b_offset {
+                        (Err(_), _) | (_, Err(_)) => {
+                            // We managed to find a valid allocation for one pointer, but not the other.
+                            // That means they are definitely not pointing to the same allocation.
                             throw_ub_format!(
-                                "{} cannot compute a negative offset, but {} < {}",
-                                intrinsic_name,
-                                a_offset.bytes(),
-                                b_offset.bytes(),
+                                "{} called on pointers into different allocations",
+                                intrinsic_name
                             );
                         }
-
-                        // Compute offset.
-                        let usize_layout = self.layout_of(self.tcx.types.usize)?;
-                        let isize_layout = self.layout_of(self.tcx.types.isize)?;
-                        let ret_layout = if intrinsic_name == sym::ptr_offset_from {
-                            isize_layout
-                        } else {
-                            usize_layout
-                        };
-
-                        // The subtraction is always done in `isize` to enforce
-                        // the "no more than `isize::MAX` apart" requirement.
-                        let a_offset = ImmTy::from_uint(a_offset.bytes(), isize_layout);
-                        let b_offset = ImmTy::from_uint(b_offset.bytes(), isize_layout);
-                        let (val, overflowed, _ty) =
-                            self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
-                        if overflowed {
-                            throw_ub_format!("Pointers were too far apart for {}", intrinsic_name);
+                        (Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _))) => {
+                            // Found allocation for both. They must be into the same allocation.
+                            if a_alloc_id != b_alloc_id {
+                                throw_ub_format!(
+                                    "{} called on pointers into different allocations",
+                                    intrinsic_name
+                                );
+                            }
+                            // Use these offsets for distance calculation.
+                            (a_offset.bytes(), b_offset.bytes())
                         }
-
-                        let pointee_layout = self.layout_of(substs.type_at(0))?;
-                        // This re-interprets an isize at ret_layout, but we already checked
-                        // that if ret_layout is usize, then the result must be non-negative.
-                        let val = ImmTy::from_scalar(val, ret_layout);
-                        let size = ImmTy::from_int(pointee_layout.size.bytes(), ret_layout);
-                        self.exact_div(&val, &size, dest)?;
+                    };
+
+                // Compute distance.
+                let distance = {
+                    // The subtraction is always done in `isize` to enforce
+                    // the "no more than `isize::MAX` apart" requirement.
+                    let a_offset = ImmTy::from_uint(a_offset, isize_layout);
+                    let b_offset = ImmTy::from_uint(b_offset, isize_layout);
+                    let (val, overflowed, _ty) =
+                        self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
+                    if overflowed {
+                        throw_ub_format!("pointers were too far apart for {}", intrinsic_name);
                     }
+                    val.to_machine_isize(self)?
+                };
+
+                // Check that the range between them is dereferenceable ("in-bounds or one past the
+                // end of the same allocation"). This is like the check in ptr_offset_inbounds.
+                let min_ptr = if distance >= 0 { b } else { a };
+                self.check_ptr_access_align(
+                    min_ptr,
+                    Size::from_bytes(distance.unsigned_abs()),
+                    Align::ONE,
+                    CheckInAllocMsg::OffsetFromTest,
+                )?;
+
+                if intrinsic_name == sym::ptr_offset_from_unsigned && distance < 0 {
+                    throw_ub_format!(
+                        "{} called when first pointer has smaller offset than second: {} < {}",
+                        intrinsic_name,
+                        a_offset,
+                        b_offset,
+                    );
                 }
+
+                // Perform division by size to compute return value.
+                let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
+                    usize_layout
+                } else {
+                    isize_layout
+                };
+                let pointee_layout = self.layout_of(substs.type_at(0))?;
+                // If ret_layout is unsigned, we checked that so is the distance, so we are good.
+                let val = ImmTy::from_int(distance, ret_layout);
+                let size = ImmTy::from_int(pointee_layout.size.bytes(), ret_layout);
+                self.exact_div(&val, &size, dest)?;
             }
 
             sym::transmute => {
@@ -575,11 +579,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // memory between these pointers must be accessible. Note that we do not require the
         // pointers to be properly aligned (unlike a read/write operation).
         let min_ptr = if offset_bytes >= 0 { ptr } else { offset_ptr };
-        let size = offset_bytes.unsigned_abs();
         // This call handles checking for integer/null pointers.
         self.check_ptr_access_align(
             min_ptr,
-            Size::from_bytes(size),
+            Size::from_bytes(offset_bytes.unsigned_abs()),
             Align::ONE,
             CheckInAllocMsg::PointerArithmeticTest,
         )?;
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 6338e08380f..6b05a49575f 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -622,10 +622,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// "universe" (param_env).
     pub fn const_to_op(
         &self,
-        val: ty::Const<'tcx>,
+        c: ty::Const<'tcx>,
         layout: Option<TyAndLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        match val.val() {
+        match c.kind() {
             ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
             ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => {
                 throw_inval!(AlreadyReported(reported))
@@ -635,9 +635,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
             }
             ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
-                span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", val)
+                span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
+            }
+            ty::ConstKind::Value(valtree) => {
+                let ty = c.ty();
+                let const_val = self.tcx.valtree_to_const_val((ty, valtree));
+                self.const_val_to_op(const_val, ty, layout)
             }
-            ty::ConstKind::Value(val_val) => self.const_val_to_op(val_val, val.ty(), layout),
         }
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index 0fddafbee79..b9866995e9f 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -55,7 +55,7 @@ where
                                     assert!(matches!(ty.kind(), ty::Param(_)))
                                 }
                                 ty::subst::GenericArgKind::Const(ct) => {
-                                    assert!(matches!(ct.val(), ty::ConstKind::Param(_)))
+                                    assert!(matches!(ct.kind(), ty::ConstKind::Param(_)))
                                 }
                                 ty::subst::GenericArgKind::Lifetime(..) => (),
                             },
@@ -69,7 +69,7 @@ where
         }
 
         fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-            match c.val() {
+            match c.kind() {
                 ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
                 _ => c.super_visit_with(self),
             }
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 04410ca3828..64a74e9d7e2 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -34,6 +34,7 @@ pub mod interpret;
 pub mod transform;
 pub mod util;
 
+use rustc_middle::ty;
 use rustc_middle::ty::query::Providers;
 
 pub fn provide(providers: &mut Providers) {
@@ -41,10 +42,7 @@ pub fn provide(providers: &mut Providers) {
     providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
     providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
     providers.const_caller_location = const_eval::const_caller_location;
-    providers.try_destructure_const = |tcx, param_env_and_val| {
-        let (param_env, c) = param_env_and_val.into_parts();
-        const_eval::try_destructure_const(tcx, param_env, c).ok()
-    };
+    providers.try_destructure_const = |tcx, val| const_eval::try_destructure_const(tcx, val);
     providers.eval_to_valtree = |tcx, param_env_and_value| {
         let (param_env, raw) = param_env_and_value.into_parts();
         const_eval::eval_to_valtree(tcx, param_env, raw)
@@ -53,11 +51,8 @@ pub fn provide(providers: &mut Providers) {
         let (param_env, value) = param_env_and_value.into_parts();
         const_eval::try_destructure_mir_constant(tcx, param_env, value).ok()
     };
-    providers.valtree_to_const_val =
-        |tcx, (ty, valtree)| const_eval::valtree_to_const_value(tcx, ty, valtree);
-    providers.deref_const = |tcx, param_env_and_value| {
-        let (param_env, value) = param_env_and_value.into_parts();
-        const_eval::deref_const(tcx, param_env, value)
+    providers.valtree_to_const_val = |tcx, (ty, valtree)| {
+        const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree)
     };
     providers.deref_mir_constant = |tcx, param_env_and_value| {
         let (param_env, value) = param_env_and_value.into_parts();
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 4b98e19376d..b8a14e37a09 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -1035,7 +1035,7 @@ fn emit_unstable_in_stable_error(ccx: &ConstCx<'_, '_>, span: Span, gate: Symbol
         .span_suggestion(
             attr_span,
             "if it is not part of the public API, make this function unstably const",
-            concat!(r#"#[rustc_const_unstable(feature = "...", issue = "...")]"#, '\n').to_owned(),
+            concat!(r#"#[rustc_const_unstable(feature = "...", issue = "...")]"#, '\n'),
             Applicability::HasPlaceholders,
         )
         .span_suggestion(
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 9fd94dc334f..6e5a0c813ac 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -353,7 +353,8 @@ where
 
     // Check the qualifs of the value of `const` items.
     if let Some(ct) = constant.literal.const_for_ty() {
-        if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val() {
+        if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.kind()
+        {
             // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
             // only for `NeedsNonConstDrop` with precise drop checking. This is the only const
             // check performed after the promotion. Verify that with an assertion.
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index d1e776854b2..3595a488d0c 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -765,7 +765,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                         let unit = Rvalue::Use(Operand::Constant(Box::new(Constant {
                             span: statement.source_info.span,
                             user_ty: None,
-                            literal: ty::Const::zero_sized(self.tcx, self.tcx.types.unit).into(),
+                            literal: ConstantKind::zero_sized(self.tcx.types.unit),
                         })));
                         mem::replace(rhs, unit)
                     },
@@ -835,26 +835,25 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
             let mut promoted_operand = |ty, span| {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
+                let _const = tcx.mk_const(ty::ConstS {
+                    ty,
+                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                        def,
+                        substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
+                            if let ty::GenericParamDefKind::Lifetime = param.kind {
+                                tcx.lifetimes.re_erased.into()
+                            } else {
+                                tcx.mk_param_from_def(param)
+                            }
+                        }),
+                        promoted: Some(promoted_id),
+                    }),
+                });
 
                 Operand::Constant(Box::new(Constant {
                     span,
                     user_ty: None,
-                    literal: tcx
-                        .mk_const(ty::ConstS {
-                            ty,
-                            val: ty::ConstKind::Unevaluated(ty::Unevaluated {
-                                def,
-                                substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
-                                    if let ty::GenericParamDefKind::Lifetime = param.kind {
-                                        tcx.lifetimes.re_erased.into()
-                                    } else {
-                                        tcx.mk_param_from_def(param)
-                                    }
-                                }),
-                                promoted: Some(promoted_id),
-                            }),
-                        })
-                        .into(),
+                    literal: ConstantKind::from_const(_const, tcx),
                 }))
             };
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index a032b039f34..5ff2d18dd2b 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -1,5 +1,5 @@
 use crate::stable_hasher;
-use rustc_serialize::{Decodable, Encodable};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::convert::TryInto;
 use std::hash::{Hash, Hasher};
 
@@ -142,14 +142,14 @@ impl stable_hasher::StableHasherResult for Fingerprint {
 
 impl_stable_hash_via_hash!(Fingerprint);
 
-impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint {
+impl<E: Encoder> Encodable<E> for Fingerprint {
     #[inline]
     fn encode(&self, s: &mut E) {
         s.emit_raw_bytes(&self.to_le_bytes());
     }
 }
 
-impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint {
+impl<D: Decoder> Decodable<D> for Fingerprint {
     #[inline]
     fn decode(d: &mut D) -> Self {
         Fingerprint::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap())
@@ -184,7 +184,7 @@ impl std::fmt::Display for PackedFingerprint {
     }
 }
 
-impl<E: rustc_serialize::Encoder> Encodable<E> for PackedFingerprint {
+impl<E: Encoder> Encodable<E> for PackedFingerprint {
     #[inline]
     fn encode(&self, s: &mut E) {
         // Copy to avoid taking reference to packed field.
@@ -193,7 +193,7 @@ impl<E: rustc_serialize::Encoder> Encodable<E> for PackedFingerprint {
     }
 }
 
-impl<D: rustc_serialize::Decoder> Decodable<D> for PackedFingerprint {
+impl<D: Decoder> Decodable<D> for PackedFingerprint {
     #[inline]
     fn decode(d: &mut D) -> Self {
         Self(Fingerprint::decode(d))
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index bf7924a81ff..a1f42d8d3c0 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -550,14 +550,20 @@ impl SelfProfiler {
     pub fn new(
         output_directory: &Path,
         crate_name: Option<&str>,
-        event_filters: &Option<Vec<String>>,
+        event_filters: Option<&[String]>,
+        counter_name: &str,
     ) -> Result<SelfProfiler, Box<dyn Error + Send + Sync>> {
         fs::create_dir_all(output_directory)?;
 
         let crate_name = crate_name.unwrap_or("unknown-crate");
-        let filename = format!("{}-{}.rustc_profile", crate_name, process::id());
+        // HACK(eddyb) we need to pad the PID, strange as it may seem, as its
+        // length can behave as a source of entropy for heap addresses, when
+        // ASLR is disabled and the heap is otherwise determinic.
+        let pid: u32 = process::id();
+        let filename = format!("{}-{:07}.rustc_profile", crate_name, pid);
         let path = output_directory.join(&filename);
-        let profiler = Profiler::new(&path)?;
+        let profiler =
+            Profiler::with_counter(&path, measureme::counters::Counter::by_name(counter_name)?)?;
 
         let query_event_kind = profiler.alloc_string("Query");
         let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
@@ -570,7 +576,7 @@ impl SelfProfiler {
 
         let mut event_filter_mask = EventFilter::empty();
 
-        if let Some(ref event_filters) = *event_filters {
+        if let Some(event_filters) = event_filters {
             let mut unknown_events = vec![];
             for item in event_filters {
                 if let Some(&(_, mask)) =
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index a2cbd9abc90..08d5d4f343c 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2021"
 crate-type = ["dylib"]
 
 [dependencies]
-libc = "0.2"
 tracing = { version = "0.1.28" }
 serde_json = "1.0.59"
 rustc_log = { path = "../rustc_log" }
@@ -21,7 +20,6 @@ rustc_feature = { path = "../rustc_feature" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_metadata = { path = "../rustc_metadata" }
-rustc_const_eval = { path = "../rustc_const_eval" }
 rustc_parse = { path = "../rustc_parse" }
 rustc_plugin_impl = { path = "../rustc_plugin_impl" }
 rustc_save_analysis = { path = "../rustc_save_analysis" }
@@ -29,11 +27,13 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_session = { path = "../rustc_session" }
 rustc_error_codes = { path = "../rustc_error_codes" }
 rustc_interface = { path = "../rustc_interface" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
 rustc_typeck = { path = "../rustc_typeck" }
 
+[target.'cfg(unix)'.dependencies]
+libc = "0.2"
+
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
 
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 02d076c95ca..fd4b2daae9c 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -1,6 +1,7 @@
 #![feature(let_chains)]
 #![feature(once_cell)]
 #![feature(path_try_exists)]
+#![feature(rustc_attrs)]
 #![feature(type_alias_impl_trait)]
 
 use fluent_bundle::FluentResource;
@@ -241,6 +242,7 @@ type FluentId = Cow<'static, str>;
 /// message so messages of this type must be combined with a `DiagnosticMessage` (using
 /// `DiagnosticMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from
 /// the `SessionSubdiagnostic` derive refer to Fluent identifiers directly.
+#[rustc_diagnostic_item = "SubdiagnosticMessage"]
 pub enum SubdiagnosticMessage {
     /// Non-translatable diagnostic message.
     // FIXME(davidtwco): can a `Cow<'static, str>` be used here?
@@ -281,6 +283,7 @@ impl<S: Into<String>> From<S> for SubdiagnosticMessage {
 ///
 /// Intended to be removed once diagnostics are entirely translatable.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
+#[rustc_diagnostic_item = "DiagnosticMessage"]
 pub enum DiagnosticMessage {
     /// Non-translatable diagnostic message.
     // FIXME(davidtwco): can a `Cow<'static, str>` be used here?
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index eaceecc1667..00c0ff8bcaf 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -80,6 +80,7 @@ impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
 
 /// Trait implemented by error types. This should not be implemented manually. Instead, use
 /// `#[derive(SessionSubdiagnostic)]` -- see [rustc_macros::SessionSubdiagnostic].
+#[rustc_diagnostic_item = "AddSubdiagnostic"]
 pub trait AddSubdiagnostic {
     /// Add a subdiagnostic to an existing diagnostic.
     fn add_to_diagnostic(self, diag: &mut Diagnostic);
@@ -283,6 +284,7 @@ impl Diagnostic {
     ///
     /// This span is *not* considered a ["primary span"][`MultiSpan`]; only
     /// the `Span` supplied when creating the diagnostic is primary.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagnosticMessage>) -> &mut Self {
         self.span.push_span_label(span, self.subdiagnostic_message_to_diagnostic_message(label));
         self
@@ -401,6 +403,7 @@ impl Diagnostic {
     }
 
     /// Add a note attached to this diagnostic.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
         self.sub(Level::Note, msg, MultiSpan::new(), None);
         self
@@ -423,6 +426,7 @@ impl Diagnostic {
 
     /// Prints the span with a note above it.
     /// This is like [`Diagnostic::note()`], but it gets its own span.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_note<S: Into<MultiSpan>>(
         &mut self,
         sp: S,
@@ -444,6 +448,7 @@ impl Diagnostic {
     }
 
     /// Add a warning attached to this diagnostic.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
         self.sub(Level::Warning, msg, MultiSpan::new(), None);
         self
@@ -451,6 +456,7 @@ impl Diagnostic {
 
     /// Prints the span with a warning above it.
     /// This is like [`Diagnostic::warn()`], but it gets its own span.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_warn<S: Into<MultiSpan>>(
         &mut self,
         sp: S,
@@ -461,6 +467,7 @@ impl Diagnostic {
     }
 
     /// Add a help message attached to this diagnostic.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
         self.sub(Level::Help, msg, MultiSpan::new(), None);
         self
@@ -474,6 +481,7 @@ impl Diagnostic {
 
     /// Prints the span with some help above it.
     /// This is like [`Diagnostic::help()`], but it gets its own span.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_help<S: Into<MultiSpan>>(
         &mut self,
         sp: S,
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 83fe2a2df89..8b6eba122f8 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -9,6 +9,7 @@
 #![feature(let_else)]
 #![feature(never_type)]
 #![feature(adt_const_params)]
+#![feature(rustc_attrs)]
 #![allow(incomplete_features)]
 #![allow(rustc::potential_query_instability)]
 
@@ -648,6 +649,7 @@ impl Handler {
     /// Attempting to `.emit()` the builder will only emit if either:
     /// * `can_emit_warnings` is `true`
     /// * `is_force_warn` was set in `DiagnosticId::Lint`
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_warn(
         &self,
         span: impl Into<MultiSpan>,
@@ -659,6 +661,7 @@ impl Handler {
     }
 
     /// Construct a builder at the `Allow` level at the given `span` and with the `msg`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_allow(
         &self,
         span: impl Into<MultiSpan>,
@@ -671,6 +674,7 @@ impl Handler {
 
     /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
     /// Also include a code.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_warn_with_code(
         &self,
         span: impl Into<MultiSpan>,
@@ -687,16 +691,19 @@ impl Handler {
     /// Attempting to `.emit()` the builder will only emit if either:
     /// * `can_emit_warnings` is `true`
     /// * `is_force_warn` was set in `DiagnosticId::Lint`
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         DiagnosticBuilder::new(self, Level::Warning, msg)
     }
 
     /// Construct a builder at the `Allow` level with the `msg`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         DiagnosticBuilder::new(self, Level::Allow, msg)
     }
 
     /// Construct a builder at the `Expect` level with the `msg`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_expect(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -706,6 +713,7 @@ impl Handler {
     }
 
     /// Construct a builder at the `Error` level at the given `span` and with the `msg`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err(
         &self,
         span: impl Into<MultiSpan>,
@@ -717,6 +725,7 @@ impl Handler {
     }
 
     /// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err_with_code(
         &self,
         span: impl Into<MultiSpan>,
@@ -730,6 +739,7 @@ impl Handler {
 
     /// Construct a builder at the `Error` level with the `msg`.
     // FIXME: This method should be removed (every error should have an associated error code).
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_err(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -744,6 +754,7 @@ impl Handler {
     }
 
     /// Construct a builder at the `Error` level with the `msg` and the `code`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_err_with_code(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -755,6 +766,7 @@ impl Handler {
     }
 
     /// Construct a builder at the `Warn` level with the `msg` and the `code`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_warn_with_code(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -766,6 +778,7 @@ impl Handler {
     }
 
     /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_fatal(
         &self,
         span: impl Into<MultiSpan>,
@@ -777,6 +790,7 @@ impl Handler {
     }
 
     /// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_fatal_with_code(
         &self,
         span: impl Into<MultiSpan>,
@@ -789,16 +803,19 @@ impl Handler {
     }
 
     /// Construct a builder at the `Error` level with the `msg`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
         DiagnosticBuilder::new_fatal(self, msg)
     }
 
     /// Construct a builder at the `Help` level with the `msg`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_help(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         DiagnosticBuilder::new(self, Level::Help, msg)
     }
 
     /// Construct a builder at the `Note` level with the `msg`.
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_note_without_error(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -806,11 +823,13 @@ impl Handler {
         DiagnosticBuilder::new(self, Level::Note, msg)
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
         self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span);
         FatalError.raise()
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_fatal_with_code(
         &self,
         span: impl Into<MultiSpan>,
@@ -821,6 +840,7 @@ impl Handler {
         FatalError.raise()
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err(
         &self,
         span: impl Into<MultiSpan>,
@@ -829,6 +849,7 @@ impl Handler {
         self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span).unwrap()
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_err_with_code(
         &self,
         span: impl Into<MultiSpan>,
@@ -841,10 +862,12 @@ impl Handler {
         );
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
         self.emit_diag_at_span(Diagnostic::new(Warning, msg), span);
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn span_warn_with_code(
         &self,
         span: impl Into<MultiSpan>,
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index bb671b8705e..75b6b1cc919 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1194,7 +1194,7 @@ pub fn expr_to_spanned_string<'a>(
                 err.span_suggestion(
                     expr.span.shrink_to_lo(),
                     "consider removing the leading `b`",
-                    String::new(),
+                    "",
                     Applicability::MaybeIncorrect,
                 );
                 Some((err, true))
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 5af6b777abe..978f87b1d13 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -945,7 +945,7 @@ pub fn ensure_complete_parse<'a>(
                 err.span_suggestion(
                     semi_span,
                     "you might be missing a semicolon here",
-                    ";".to_owned(),
+                    ";",
                     Applicability::MaybeIncorrect,
                 );
             }
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index a66d36aaf72..f40c365cbcc 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -102,7 +102,7 @@ fn emit_frag_parse_err(
                 e.span_suggestion_verbose(
                     site_span.shrink_to_hi(),
                     "add `;` to interpret the expansion as a statement",
-                    ";".to_string(),
+                    ";",
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -357,7 +357,7 @@ fn expand_macro<'cx>(
                     err.span_suggestion_short(
                         comma_span,
                         "missing comma here",
-                        ", ".to_string(),
+                        ", ",
                         Applicability::MachineApplicable,
                     );
                 }
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index ccc1c2b2ca0..45c462bc425 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -52,7 +52,7 @@ impl MetaVarExpr {
                 err.span_suggestion(
                     ident.span,
                     "supported expressions are count, ignore, index and length",
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 );
                 return Err(err);
@@ -142,7 +142,7 @@ fn parse_ident<'sess>(
         err.span_suggestion(
             token.span,
             &format!("try removing `{}`", &token_str),
-            String::new(),
+            "",
             Applicability::MaybeIncorrect,
         );
         return Err(err);
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 35473b6e97a..b54f0ef361a 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -409,8 +409,6 @@ declare_features! (
     (active, if_let_guard, "1.47.0", Some(51114), None),
     /// Allows using imported `main` function
     (active, imported_main, "1.53.0", Some(28937), None),
-    /// Allows inferring `'static` outlives requirements (RFC 2093).
-    (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None),
     /// Allows associated types in inherent impls.
     (incomplete, inherent_associated_types, "1.52.0", Some(8995), None),
     /// Allow anonymous constants from an inline `const` block
@@ -523,7 +521,7 @@ declare_features! (
     (active, type_ascription, "1.6.0", Some(23416), None),
     /// Allows creation of instances of a struct by moving fields that have
     /// not changed from prior instances of the same struct (RFC #2528)
-    (incomplete, type_changing_struct_update, "1.58.0", Some(86555), None),
+    (active, type_changing_struct_update, "1.58.0", Some(86555), None),
     /// Allows unsized fn parameters.
     (active, unsized_fn_params, "1.49.0", Some(48055), None),
     /// Allows unsized rvalues at arguments and parameters.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 5eb2be97f8b..d4452a79dfb 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -489,11 +489,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // ==========================================================================
 
     ungated!(feature, CrateLevel, template!(List: "name1, name2, ..."), DuplicatesOk),
-    // FIXME(jhpratt) remove this eventually
-    ungated!(
-        rustc_deprecated, Normal,
-        template!(List: r#"since = "version", note = "...""#), ErrorFollowing
-    ),
     // DuplicatesOk since it has its own validation
     ungated!(
         stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk,
@@ -615,6 +610,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Used by the `rustc::potential_query_instability` lint to warn methods which
     // might not be stable during incremental compilation.
     rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
+    // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints
+    // to assist in changes to diagnostic APIs.
+    rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
 
     // ==========================================================================
     // Internal attributes, Const related:
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 7194416cd1d..54626caaf53 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -109,6 +109,9 @@ declare_features! (
     /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`).
     (removed, in_band_lifetimes, "1.23.0", Some(44524), None,
      Some("removed due to unsolved ergonomic questions and added lifetime resolution complexity")),
+    /// Allows inferring `'static` outlives requirements (RFC 2093).
+    (removed, infer_static_outlives_requirements, "1.63.0", Some(54185), None,
+     Some("removed as it caused some confusion and discussion was inactive for years")),
     /// Lazily evaluate constants. This allows constants to depend on type parameters.
     (removed, lazy_normalization_consts, "1.46.0", Some(72219), None, Some("superseded by `generic_const_exprs`")),
     /// Allows using the `#[link_args]` attribute.
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index 34d366f4013..47ace7ca3a7 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -8,7 +8,6 @@ doctest = false
 
 [dependencies]
 rustc_target = { path = "../rustc_target" }
-rustc_feature = { path = "../rustc_feature" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_messages = { path = "../rustc_error_messages" }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index bd5973f31cf..5a06f8eab7e 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1652,7 +1652,7 @@ impl Expr<'_> {
             ExprKind::Let(..) => ExprPrecedence::Let,
             ExprKind::Loop(..) => ExprPrecedence::Loop,
             ExprKind::Match(..) => ExprPrecedence::Match,
-            ExprKind::Closure(..) => ExprPrecedence::Closure,
+            ExprKind::Closure { .. } => ExprPrecedence::Closure,
             ExprKind::Block(..) => ExprPrecedence::Block,
             ExprKind::Assign(..) => ExprPrecedence::Assign,
             ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
@@ -1712,7 +1712,7 @@ impl Expr<'_> {
             | ExprKind::Tup(..)
             | ExprKind::If(..)
             | ExprKind::Match(..)
-            | ExprKind::Closure(..)
+            | ExprKind::Closure { .. }
             | ExprKind::Block(..)
             | ExprKind::Repeat(..)
             | ExprKind::Array(..)
@@ -1795,7 +1795,7 @@ impl Expr<'_> {
             | ExprKind::Match(..)
             | ExprKind::MethodCall(..)
             | ExprKind::Call(..)
-            | ExprKind::Closure(..)
+            | ExprKind::Closure { .. }
             | ExprKind::Block(..)
             | ExprKind::Repeat(..)
             | ExprKind::Break(..)
@@ -1930,7 +1930,13 @@ pub enum ExprKind<'hir> {
     ///
     /// This may also be a generator literal or an `async block` as indicated by the
     /// `Option<Movability>`.
-    Closure(CaptureBy, &'hir FnDecl<'hir>, BodyId, Span, Option<Movability>),
+    Closure {
+        capture_clause: CaptureBy,
+        fn_decl: &'hir FnDecl<'hir>,
+        body: BodyId,
+        fn_decl_span: Span,
+        movability: Option<Movability>,
+    },
     /// A block (e.g., `'label: { ... }`).
     Block(&'hir Block<'hir>, Option<Label>),
 
@@ -3456,7 +3462,7 @@ impl<'hir> Node<'hir> {
                 _ => None,
             },
             Node::Expr(e) => match e.kind {
-                ExprKind::Closure(..) => Some(FnKind::Closure),
+                ExprKind::Closure { .. } => Some(FnKind::Closure),
                 _ => None,
             },
             _ => None,
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index bd8587f1106..d1da2519bad 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -1168,14 +1168,13 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             visitor.visit_expr(subexpression);
             walk_list!(visitor, visit_arm, arms);
         }
-        ExprKind::Closure(_, ref function_declaration, body, _fn_decl_span, _gen) => visitor
-            .visit_fn(
-                FnKind::Closure,
-                function_declaration,
-                body,
-                expression.span,
-                expression.hir_id,
-            ),
+        ExprKind::Closure {
+            ref fn_decl,
+            body,
+            capture_clause: _,
+            fn_decl_span: _,
+            movability: _,
+        } => visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id),
         ExprKind::Block(ref block, ref opt_label) => {
             walk_list!(visitor, visit_label, opt_label);
             visitor.visit_block(block);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index fb40008d60b..7317ce7335a 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1078,7 +1078,9 @@ impl<'a> State<'a> {
     // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
     fn cond_needs_par(expr: &hir::Expr<'_>) -> bool {
         match expr.kind {
-            hir::ExprKind::Break(..) | hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) => true,
+            hir::ExprKind::Break(..) | hir::ExprKind::Closure { .. } | hir::ExprKind::Ret(..) => {
+                true
+            }
             _ => contains_exterior_struct_lit(expr),
         }
     }
@@ -1455,10 +1457,16 @@ impl<'a> State<'a> {
                 }
                 self.bclose(expr.span);
             }
-            hir::ExprKind::Closure(capture_clause, ref decl, body, _fn_decl_span, _gen) => {
+            hir::ExprKind::Closure {
+                capture_clause,
+                ref fn_decl,
+                body,
+                fn_decl_span: _,
+                movability: _,
+            } => {
                 self.print_capture_clause(capture_clause);
 
-                self.print_closure_params(&decl, body);
+                self.print_closure_params(&fn_decl, body);
                 self.space();
 
                 // This is a bare expression.
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index 9de14950aa8..9c325faae80 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::memmap::Mmap;
 use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
 use rustc_middle::ty::OnDiskCache;
-use rustc_serialize::opaque::Decoder;
+use rustc_serialize::opaque::MemDecoder;
 use rustc_serialize::Decodable;
 use rustc_session::config::IncrementalStateAssertion;
 use rustc_session::Session;
@@ -156,7 +156,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
 
         if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
             // Decode the list of work_products
-            let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos);
+            let mut work_product_decoder = MemDecoder::new(&work_products_data[..], start_pos);
             let work_products: Vec<SerializedWorkProduct> =
                 Decodable::decode(&mut work_product_decoder);
 
@@ -193,7 +193,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
             LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
             LoadResult::Error { message } => LoadResult::Error { message },
             LoadResult::Ok { data: (bytes, start_pos) } => {
-                let mut decoder = Decoder::new(&bytes, start_pos);
+                let mut decoder = MemDecoder::new(&bytes, start_pos);
                 let prev_commandline_args_hash = u64::decode(&mut decoder);
 
                 if prev_commandline_args_hash != expected_hash {
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index f87ea43b1a7..bbc2b767734 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -14,7 +14,6 @@ rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
-rustc_session = { path = "../rustc_session" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 07682577197..9c30c81123b 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -476,7 +476,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Infer(InferConst::Var(vid)) => {
                 debug!("canonical: const var found with vid {:?}", vid);
                 match self.infcx.probe_const_var(vid) {
@@ -778,7 +778,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         } else {
             let var = self.canonical_var(info, const_var.into());
             self.tcx().mk_const(ty::ConstS {
-                val: ty::ConstKind::Bound(self.binder_index, var),
+                kind: ty::ConstKind::Bound(self.binder_index, var),
                 ty: self.fold_ty(const_var.ty()),
             })
         }
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index c7fa2527eb2..f251d561c60 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -149,7 +149,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                 let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, name };
                 self.tcx
                     .mk_const(ty::ConstS {
-                        val: ty::ConstKind::Placeholder(placeholder_mapped),
+                        kind: ty::ConstKind::Placeholder(placeholder_mapped),
                         ty: name.ty,
                     })
                     .into()
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index ec468f42852..8938ed78a94 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -458,7 +458,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                     }
                 }
                 GenericArgKind::Const(result_value) => {
-                    if let ty::ConstKind::Bound(debrujin, b) = result_value.val() {
+                    if let ty::ConstKind::Bound(debrujin, b) = result_value.kind() {
                         // ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
 
                         // We only allow a `ty::INNERMOST` index in substitutions.
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 120e57ecebd..67dcb6e708b 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -142,7 +142,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
 
         let a_is_expected = relation.a_is_expected();
 
-        match (a.val(), b.val()) {
+        match (a.kind(), b.kind()) {
             (
                 ty::ConstKind::Infer(InferConst::Var(a_vid)),
                 ty::ConstKind::Infer(InferConst::Var(b_vid)),
@@ -726,7 +726,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
         assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
 
-        match c.val() {
+        match c.kind() {
             ty::ConstKind::Infer(InferConst::Var(vid)) => {
                 let mut inner = self.infcx.inner.borrow_mut();
                 let variable_table = &mut inner.const_unification_table();
@@ -761,7 +761,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 )?;
                 Ok(self.tcx().mk_const(ty::ConstS {
                     ty: c.ty(),
-                    val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
+                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
                 }))
             }
             _ => relate::super_relate_consts(self, c, c),
@@ -941,7 +941,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
         debug_assert_eq!(c, _c);
         debug!("ConstInferUnifier: c={:?}", c);
 
-        match c.val() {
+        match c.kind() {
             ty::ConstKind::Infer(InferConst::Var(vid)) => {
                 // Check if the current unification would end up
                 // unifying `target_vid` with a const which contains
@@ -992,7 +992,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
                 )?;
                 Ok(self.tcx().mk_const(ty::ConstS {
                     ty: c.ty(),
-                    val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
+                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
                 }))
             }
             _ => relate::super_relate_consts(self, c, c),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 3eeea7fdb13..b94d205488d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -670,7 +670,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                                 err.span_suggestion(
                                     source_map.end_point(cause.span),
                                     "try removing this `?`",
-                                    "".to_string(),
+                                    "",
                                     Applicability::MachineApplicable,
                                 );
                             }
@@ -726,14 +726,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                             err.span_suggestion_short(
                                 sp,
                                 "consider removing this semicolon and boxing the expressions",
-                                String::new(),
+                                "",
                                 Applicability::MachineApplicable,
                             );
                         } else {
                             err.span_suggestion_short(
                                 sp,
                                 "consider removing this semicolon",
-                                String::new(),
+                                "",
                                 Applicability::MachineApplicable,
                             );
                         }
@@ -776,7 +776,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         err.span_suggestion_short(
                             sp,
                             "consider removing this semicolon",
-                            String::new(),
+                            "",
                             Applicability::MachineApplicable,
                         );
                     }
@@ -1935,7 +1935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 diag.span_suggestion_verbose(
                     exp_span.shrink_to_hi(),
                     "consider `await`ing on the `Future`",
-                    ".await".to_string(),
+                    ".await",
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -1945,7 +1945,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     diag.span_suggestion_verbose(
                         span.shrink_to_hi(),
                         "consider `await`ing on the `Future`",
-                        ".await".to_string(),
+                        ".await",
                         Applicability::MaybeIncorrect,
                     );
                 }
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 4c734b1589b..20b9ed9cd73 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
@@ -247,7 +247,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 }
             }
             GenericArgKind::Const(ct) => {
-                if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val() {
+                if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
                     let origin =
                         self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
                     if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
@@ -673,7 +673,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
             }
             (GenericArgKind::Const(inner_ct), GenericArgKind::Const(target_ct)) => {
                 use ty::InferConst::*;
-                match (inner_ct.val(), target_ct.val()) {
+                match (inner_ct.kind(), target_ct.kind()) {
                     (ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => self
                         .infcx
                         .inner
@@ -713,7 +713,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                     }
                 }
                 GenericArgKind::Const(ct) => {
-                    if matches!(ct.val(), ty::ConstKind::Unevaluated(..)) {
+                    if matches!(ct.kind(), ty::ConstKind::Unevaluated(..)) {
                         // You can't write the generic arguments for
                         // unevaluated constants.
                         walker.skip_current_subtree();
@@ -988,22 +988,24 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
         }
 
         if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
-            if let (&ExprKind::Closure(_, decl, body_id, span, _), ty::Closure(_, substs)) =
-                (&expr.kind, node_ty.kind())
+            if let (
+                &ExprKind::Closure { fn_decl, body, fn_decl_span, .. },
+                ty::Closure(_, substs),
+            ) = (&expr.kind, node_ty.kind())
             {
                 let output = substs.as_closure().sig().output().skip_binder();
                 if self.generic_arg_contains_target(output.into()) {
-                    let body = self.infcx.tcx.hir().body(body_id);
+                    let body = self.infcx.tcx.hir().body(body);
                     let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) {
                         None
                     } else {
                         Some(body.value.span.shrink_to_hi())
                     };
                     self.update_infer_source(InferSource {
-                        span,
+                        span: fn_decl_span,
                         kind: InferSourceKind::ClosureReturn {
                             ty: output,
-                            data: &decl.output,
+                            data: &fn_decl.output,
                             should_wrap_expr,
                         },
                     })
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
index 80500f3fe65..43d5c9fdf33 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -85,7 +85,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                     err.span_suggestion_verbose(
                         span.shrink_to_hi(),
                         "consider relaxing the implicit `'static` requirement",
-                        " + '_".to_string(),
+                        " + '_",
                         Applicability::MaybeIncorrect,
                     );
                 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 375ad8d3736..76cb76d9ff4 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -107,7 +107,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         diag.span_suggestion(
             new_ty_span,
             &format!("add explicit lifetime `{}` to {}", named, span_label_var),
-            new_ty.to_string(),
+            new_ty,
             Applicability::Unspecified,
         );
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index b856198cf3f..6935ce9710b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -328,7 +328,7 @@ pub fn suggest_new_region_bound(
                         err.span_suggestion_verbose(
                             span,
                             &format!("{} `impl Trait`'s {}", consider, explicit_static),
-                            lifetime_name.clone(),
+                            &lifetime_name,
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -363,7 +363,7 @@ pub fn suggest_new_region_bound(
                             captures = captures,
                             explicit = explicit,
                         ),
-                        plus_lt.clone(),
+                        &plus_lt,
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -378,7 +378,7 @@ pub fn suggest_new_region_bound(
                             captures = captures,
                             explicit = explicit,
                         ),
-                        plus_lt.clone(),
+                        &plus_lt,
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -391,7 +391,7 @@ pub fn suggest_new_region_bound(
                         err.span_suggestion_verbose(
                             lt.span,
                             &format!("{} trait object's {}", consider, explicit_static),
-                            lifetime_name.clone(),
+                            &lifetime_name,
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -535,7 +535,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 err.span_suggestion_verbose(
                     span.shrink_to_hi(),
                     "consider relaxing the implicit `'static` requirement",
-                    " + '_".to_string(),
+                    " + '_",
                     Applicability::MaybeIncorrect,
                 );
                 suggested = true;
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 96b57b6cd20..b9596cd10ed 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
@@ -55,7 +55,7 @@ pub fn find_param_with_region<'tcx>(
 
     // Don't perform this on closures
     match hir.get(hir_id) {
-        hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
+        hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
             return None;
         }
         _ => {}
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index edafee2df57..024f7409947 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -218,7 +218,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
                 let opt_ct = self
                     .infcx
diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs
index 1e6995db269..2f0eadce631 100644
--- a/compiler/rustc_infer/src/infer/fudge.rs
+++ b/compiler/rustc_infer/src/infer/fudge.rs
@@ -229,7 +229,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.val() {
+        if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
             if self.const_vars.0.contains(&vid) {
                 // This variable was created during the fudging.
                 // Recreate it with a fresh variable here.
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index bb3b410b2bd..c82685d1b70 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -99,7 +99,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         let fld_c = |bound_var: ty::BoundVar, ty| {
             self.tcx.mk_const(ty::ConstS {
-                val: ty::ConstKind::Placeholder(ty::PlaceholderConst {
+                kind: ty::ConstKind::Placeholder(ty::PlaceholderConst {
                     universe: next_universe,
                     name: ty::BoundConst { var: bound_var, ty },
                 }),
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 44cf9b6611e..7975b946ee5 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -7,7 +7,6 @@ use crate::infer::region_constraints::VarInfos;
 use crate::infer::region_constraints::VerifyBound;
 use crate::infer::RegionRelations;
 use crate::infer::RegionVariableOrigin;
-use crate::infer::RegionckMode;
 use crate::infer::SubregionOrigin;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::implementation::{
@@ -33,32 +32,23 @@ pub(crate) fn resolve<'tcx>(
     region_rels: &RegionRelations<'_, 'tcx>,
     var_infos: VarInfos,
     data: RegionConstraintData<'tcx>,
-    mode: RegionckMode,
 ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
     let mut errors = vec![];
     let mut resolver = LexicalResolver { region_rels, var_infos, data };
-    match mode {
-        RegionckMode::Solve => {
-            let values = resolver.infer_variable_values(&mut errors);
-            (values, errors)
-        }
-        RegionckMode::Erase => {
-            // Skip region inference entirely.
-            (resolver.erased_data(region_rels.tcx), Vec::new())
-        }
-    }
+    let values = resolver.infer_variable_values(&mut errors);
+    (values, errors)
 }
 
 /// Contains the result of lexical region resolution. Offers methods
 /// to lookup up the final value of a region variable.
 #[derive(Clone)]
 pub struct LexicalRegionResolutions<'tcx> {
-    values: IndexVec<RegionVid, VarValue<'tcx>>,
-    error_region: ty::Region<'tcx>,
+    pub(crate) values: IndexVec<RegionVid, VarValue<'tcx>>,
+    pub(crate) error_region: ty::Region<'tcx>,
 }
 
 #[derive(Copy, Clone, Debug)]
-enum VarValue<'tcx> {
+pub(crate) enum VarValue<'tcx> {
     Value(Region<'tcx>),
     ErrorValue,
 }
@@ -162,19 +152,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
     }
 
-    /// An erased version of the lexical region resolutions. Used when we're
-    /// erasing regions and suppressing errors: in item bodies with
-    /// `-Zborrowck=mir`.
-    fn erased_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
-        LexicalRegionResolutions {
-            error_region: tcx.lifetimes.re_static,
-            values: IndexVec::from_elem_n(
-                VarValue::Value(tcx.lifetimes.re_erased),
-                self.num_vars(),
-            ),
-        }
-    }
-
     fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) {
         debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context);
         for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 0e30b136622..93a067cb516 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -20,7 +20,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
-use rustc_middle::mir::interpret::{ErrorHandled, EvalToConstValueResult};
+use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::traits::select;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -84,20 +84,6 @@ pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable<
     ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut InferCtxtUndoLogs<'tcx>>,
 >;
 
-/// How we should handle region solving.
-///
-/// This is used so that the region values inferred by HIR region solving are
-/// not exposed, and so that we can avoid doing work in HIR typeck that MIR
-/// typeck will also do.
-#[derive(Copy, Clone, Debug, Default)]
-pub enum RegionckMode {
-    /// The default mode: report region errors, don't erase regions.
-    #[default]
-    Solve,
-    /// Erase the results of region after solving.
-    Erase,
-}
-
 /// This type contains all the things within `InferCtxt` that sit within a
 /// `RefCell` and are involved with taking/rolling back snapshots. Snapshot
 /// operations are hot enough that we want only one call to `borrow_mut` per
@@ -1248,6 +1234,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         self.tainted_by_errors_flag.set(true)
     }
 
+    pub fn skip_region_resolution(&self) {
+        let (var_infos, _) = {
+            let mut inner = self.inner.borrow_mut();
+            let inner = &mut *inner;
+            // Note: `inner.region_obligations` may not be empty, because we
+            // didn't necessarily call `process_registered_region_obligations`.
+            // This is okay, because that doesn't introduce new vars.
+            inner
+                .region_constraint_storage
+                .take()
+                .expect("regions already resolved")
+                .with_log(&mut inner.undo_log)
+                .into_infos_and_data()
+        };
+
+        let lexical_region_resolutions = LexicalRegionResolutions {
+            error_region: self.tcx.lifetimes.re_static,
+            values: rustc_index::vec::IndexVec::from_elem_n(
+                crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
+                var_infos.len(),
+            ),
+        };
+
+        let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
+        assert!(old_value.is_none());
+    }
+
     /// Process the region constraints and return any any errors that
     /// result. After this, no more unification operations should be
     /// done -- or the compiler will panic -- but it is legal to use
@@ -1256,7 +1269,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         &self,
         region_context: DefId,
         outlives_env: &OutlivesEnvironment<'tcx>,
-        mode: RegionckMode,
     ) -> Vec<RegionResolutionError<'tcx>> {
         let (var_infos, data) = {
             let mut inner = self.inner.borrow_mut();
@@ -1278,7 +1290,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             &RegionRelations::new(self.tcx, region_context, outlives_env.free_region_map());
 
         let (lexical_region_resolutions, errors) =
-            lexical_region_resolve::resolve(region_rels, var_infos, data, mode);
+            lexical_region_resolve::resolve(region_rels, var_infos, data);
 
         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
         assert!(old_value.is_none());
@@ -1294,9 +1306,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         &self,
         region_context: DefId,
         outlives_env: &OutlivesEnvironment<'tcx>,
-        mode: RegionckMode,
     ) {
-        let errors = self.resolve_regions(region_context, outlives_env, mode);
+        let errors = self.resolve_regions(region_context, outlives_env);
 
         if !self.is_tainted_by_errors() {
             // As a heuristic, just skip reporting region errors
@@ -1605,6 +1616,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         u
     }
 
+    pub fn try_const_eval_resolve(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        unevaluated: ty::Unevaluated<'tcx>,
+        ty: Ty<'tcx>,
+        span: Option<Span>,
+    ) -> Result<ty::Const<'tcx>, ErrorHandled> {
+        match self.const_eval_resolve(param_env, unevaluated, span) {
+            Ok(Some(val)) => Ok(ty::Const::from_value(self.tcx, val, ty)),
+            Ok(None) => {
+                let tcx = self.tcx;
+                let def_id = unevaluated.def.did;
+                span_bug!(
+                    tcx.def_span(def_id),
+                    "unable to construct a constant value for the unevaluated constant {:?}",
+                    unevaluated
+                );
+            }
+            Err(err) => Err(err),
+        }
+    }
+
     /// Resolves and evaluates a constant.
     ///
     /// The constant can be located on a trait like `<A as B>::C`, in which case the given
@@ -1623,7 +1656,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         unevaluated: ty::Unevaluated<'tcx>,
         span: Option<Span>,
-    ) -> EvalToConstValueResult<'tcx> {
+    ) -> EvalToValTreeResult<'tcx> {
         let substs = self.resolve_vars_if_possible(unevaluated.substs);
         debug!(?substs);
 
@@ -1647,7 +1680,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         // The return value is the evaluated value which doesn't contain any reference to inference
         // variables, thus we don't need to substitute back the original values.
-        self.tcx.const_eval_resolve(param_env_erased, unevaluated, span)
+        self.tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span)
     }
 
     /// `ty_or_const_infer_var_changed` is equivalent to one of these two:
@@ -1743,7 +1776,7 @@ impl<'tcx> TyOrConstInferVar<'tcx> {
     /// Tries to extract an inference variable from a constant, returns `None`
     /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
     pub fn maybe_from_const(ct: ty::Const<'tcx>) -> Option<Self> {
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
             _ => None,
         }
@@ -1822,7 +1855,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val() {
+        if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
             self.infcx
                 .inner
                 .borrow_mut()
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 9b6e5c8a347..ebe156d081d 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -659,7 +659,7 @@ where
             b = self.infcx.shallow_resolve(b);
         }
 
-        match b.val() {
+        match b.kind() {
             ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
                 // Forbid inference variables in the RHS.
                 bug!("unexpected inference var {:?}", b)
@@ -1034,7 +1034,7 @@ where
         a: ty::Const<'tcx>,
         _: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        match a.val() {
+        match a.kind() {
             ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
                 bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
             }
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index ce3c7328e2d..d830000b65f 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -223,7 +223,7 @@ impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
             Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
             let c = self.infcx.shallow_resolve(c);
-            match c.val() {
+            match c.kind() {
                 ty::ConstKind::Infer(InferConst::Var(vid)) => {
                     return Err(FixupError::UnresolvedConst(vid));
                 }
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index 47dc5f2ef86..26b1b9948a0 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2021"
 doctest = false
 
 [dependencies]
-libc = "0.2"
 libloading = "0.7.1"
 tracing = "0.1"
 rustc-rayon-core = { version = "0.4.0", optional = true }
@@ -49,6 +48,9 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
 tempfile = "3.2"
 
+[target.'cfg(unix)'.dependencies]
+libc = "0.2"
+
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["libloaderapi"] }
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 3c867e308c4..389e6483f30 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -449,7 +449,7 @@ pub fn configure_and_expand(
                     .span_suggestion(
                         first_span,
                         "try using their name instead",
-                        "ferris".to_string(),
+                        "ferris",
                         Applicability::MaybeIncorrect,
                     )
                     .emit();
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 3747fb5eca0..30a29ed6ed3 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -797,6 +797,7 @@ fn test_debugging_options_tracking_hash() {
     tracked!(unleash_the_miri_inside_of_you, true);
     tracked!(use_ctors_section, Some(true));
     tracked!(verify_llvm_ir, true);
+    tracked!(virtual_function_elimination, true);
     tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
 
     macro_rules! tracked_no_crate_hash {
diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs
index dff2e31c607..b33ab40eb39 100644
--- a/compiler/rustc_lint/src/array_into_iter.rs
+++ b/compiler/rustc_lint/src/array_into_iter.rs
@@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
                     diag.span_suggestion(
                         receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
                         "or remove `.into_iter()` to iterate by value",
-                        String::new(),
+                        "",
                         Applicability::MaybeIncorrect,
                     );
                 } else if receiver_ty.is_array() {
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 205ca72aae8..7cf447a1419 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -993,7 +993,7 @@ fn lint_deprecated_attr(
             .span_suggestion_short(
                 attr.span,
                 suggestion.unwrap_or("remove this attribute"),
-                String::new(),
+                "",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -1182,7 +1182,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
                                 .span_suggestion_short(
                                     no_mangle_attr.span,
                                     "remove this attribute",
-                                    String::new(),
+                                    "",
                                     // Use of `#[no_mangle]` suggests FFI intent; correct
                                     // fix may be to monomorphize source by hand
                                     Applicability::MaybeIncorrect,
@@ -1221,7 +1221,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
                         err.span_suggestion(
                             const_span,
                             "try a static value",
-                            "pub static".to_owned(),
+                            "pub static",
                             Applicability::MachineApplicable,
                         );
                         err.emit();
@@ -1405,7 +1405,7 @@ impl UnreachablePub {
                 err.span_suggestion(
                     vis_span,
                     "consider restricting its visibility",
-                    "pub(crate)".to_owned(),
+                    "pub(crate)",
                     applicability,
                 );
                 if exportable {
@@ -1566,7 +1566,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
                 err.span_suggestion(
                     type_alias_generics.where_clause_span,
                     "the clause will not be checked when the type alias is used, and should be removed",
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 );
                 if !suggested_changing_assoc_types {
@@ -1830,7 +1830,7 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
                     });
                 }
             } else {
-                let replace = "..=".to_owned();
+                let replace = "..=";
                 if join.edition() >= Edition::Edition2021 {
                     let mut err =
                         rustc_errors::struct_span_err!(cx.sess(), pat.span, E0783, "{}", msg,);
@@ -2113,7 +2113,6 @@ impl ExplicitOutlivesRequirements {
         tcx: TyCtxt<'tcx>,
         bounds: &hir::GenericBounds<'_>,
         inferred_outlives: &[ty::Region<'tcx>],
-        infer_static: bool,
     ) -> Vec<(usize, Span)> {
         use rustc_middle::middle::resolve_lifetime::Region;
 
@@ -2123,9 +2122,6 @@ impl ExplicitOutlivesRequirements {
             .filter_map(|(i, bound)| {
                 if let hir::GenericBound::Outlives(lifetime) = bound {
                     let is_inferred = match tcx.named_region(lifetime.hir_id) {
-                        Some(Region::Static) if infer_static => {
-                            inferred_outlives.iter().any(|r| matches!(**r, ty::ReStatic))
-                        }
                         Some(Region::EarlyBound(index, ..)) => inferred_outlives.iter().any(|r| {
                             if let ty::ReEarlyBound(ebr) = **r { ebr.index == index } else { false }
                         }),
@@ -2201,7 +2197,6 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
         use rustc_middle::middle::resolve_lifetime::Region;
 
-        let infer_static = cx.tcx.features().infer_static_outlives_requirements;
         let def_id = item.def_id;
         if let hir::ItemKind::Struct(_, ref hir_generics)
         | hir::ItemKind::Enum(_, ref hir_generics)
@@ -2262,12 +2257,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                     continue;
                 }
 
-                let bound_spans = self.collect_outlives_bound_spans(
-                    cx.tcx,
-                    bounds,
-                    &relevant_lifetimes,
-                    infer_static,
-                );
+                let bound_spans =
+                    self.collect_outlives_bound_spans(cx.tcx, bounds, &relevant_lifetimes);
                 bound_count += bound_spans.len();
 
                 let drop_predicate = bound_spans.len() == bounds.len();
@@ -2882,7 +2873,7 @@ impl ClashingExternDeclarations {
                         }
                         (Array(a_ty, a_const), Array(b_ty, b_const)) => {
                             // For arrays, we also check the constness of the type.
-                            a_const.val() == b_const.val()
+                            a_const.kind() == b_const.kind()
                                 && structurally_same_type_impl(seen_types, cx, *a_ty, *b_ty, ckind)
                         }
                         (Slice(a_ty), Slice(b_ty)) => {
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 2c6bdef361a..2084494f771 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -718,7 +718,7 @@ pub trait LintContext: Sized {
                                   the macro must produce the documentation as part of its expansion");
                 }
                 BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident) => {
-                    db.span_suggestion(span, "remove `mut` from the parameter", ident.to_string(), Applicability::MachineApplicable);
+                    db.span_suggestion(span, "remove `mut` from the parameter", ident, Applicability::MachineApplicable);
                 }
                 BuiltinLintDiagnostics::MissingAbi(span, default_abi) => {
                     db.span_label(span, "ABI should be specified here");
@@ -778,7 +778,7 @@ pub trait LintContext: Sized {
 
                     // Suggest the most probable if we found one
                     if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) {
-                        db.span_suggestion(name_span, "did you mean", format!("{best_match}"), Applicability::MaybeIncorrect);
+                        db.span_suggestion(name_span, "did you mean", best_match, Applicability::MaybeIncorrect);
                     }
                 },
                 BuiltinLintDiagnostics::UnexpectedCfg((name, name_span), Some((value, value_span))) => {
@@ -805,7 +805,7 @@ pub trait LintContext: Sized {
                     } else {
                         db.note(&format!("no expected value for `{name}`"));
                         if name != sym::feature {
-                            db.span_suggestion(name_span.shrink_to_hi().to(value_span), "remove the value", String::new(), Applicability::MaybeIncorrect);
+                            db.span_suggestion(name_span.shrink_to_hi().to(value_span), "remove the value", "", Applicability::MaybeIncorrect);
                         }
                     }
                 },
@@ -852,7 +852,7 @@ pub trait LintContext: Sized {
                     db.span_suggestion(
                         deletion_span,
                         "elide the unused lifetime",
-                        String::new(),
+                        "",
                         Applicability::MachineApplicable,
                     );
                 },
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index b83d63e0da0..fadb1c87933 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -5,12 +5,14 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}
 use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::{Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
-use rustc_hir::{HirId, Item, ItemKind, Node, Pat, Ty, TyKind};
+use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
+use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::Span;
+use tracing::debug;
 
 declare_tool_lint! {
     pub rustc::DEFAULT_HASH_TYPES,
@@ -46,6 +48,41 @@ impl LateLintPass<'_> for DefaultHashTypes {
     }
 }
 
+/// Helper function for lints that check for expressions with calls and use typeck results to
+/// get the `DefId` and `SubstsRef` of the function.
+fn typeck_results_of_method_fn<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &Expr<'_>,
+) -> Option<(Span, DefId, ty::subst::SubstsRef<'tcx>)> {
+    // FIXME(rustdoc): Lints which use this function use typecheck results which can cause
+    // `rustdoc` to error if there are resolution failures.
+    //
+    // As internal lints are currently always run if there are `unstable_options`, they are added
+    // to the lint store of rustdoc. Internal lints are also not used via the `lint_mod` query.
+    // Crate lints run outside of a query so rustdoc currently doesn't disable them.
+    //
+    // Instead of relying on this, either change crate lints to a query disabled by rustdoc, only
+    // run internal lints if the user is explicitly opting in or figure out a different way to
+    // avoid running lints for rustdoc.
+    if cx.tcx.sess.opts.actually_rustdoc {
+        return None;
+    }
+
+    match expr.kind {
+        ExprKind::MethodCall(segment, _, _)
+            if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
+        {
+            Some((segment.ident.span, def_id, cx.typeck_results().node_substs(expr.hir_id)))
+        },
+        _ => {
+            match cx.typeck_results().node_type(expr.hir_id).kind() {
+                &ty::FnDef(def_id, substs) => Some((expr.span, def_id, substs)),
+                _ => None,
+            }
+        }
+    }
+}
+
 declare_tool_lint! {
     pub rustc::POTENTIAL_QUERY_INSTABILITY,
     Allow,
@@ -57,35 +94,7 @@ declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY]);
 
 impl LateLintPass<'_> for QueryStability {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        // FIXME(rustdoc): This lint uses typecheck results, causing rustdoc to
-        // error if there are resolution failures.
-        //
-        // As internal lints are currently always run if there are `unstable_options`,
-        // they are added to the lint store of rustdoc. Internal lints are also
-        // not used via the `lint_mod` query. Crate lints run outside of a query
-        // so rustdoc currently doesn't disable them.
-        //
-        // Instead of relying on this, either change crate lints to a query disabled by
-        // rustdoc, only run internal lints if the user is explicitly opting in
-        // or figure out a different way to avoid running lints for rustdoc.
-        if cx.tcx.sess.opts.actually_rustdoc {
-            return;
-        }
-
-        let (span, def_id, substs) = match expr.kind {
-            ExprKind::MethodCall(segment, _, _)
-                if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
-            {
-                (segment.ident.span, def_id, cx.typeck_results().node_substs(expr.hir_id))
-            },
-            _ => {
-                let &ty::FnDef(def_id, substs) =
-                    cx.typeck_results()
-                        .node_type(expr.hir_id)
-                        .kind() else { return };
-                (expr.span, def_id, substs)
-            }
-        };
+        let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return };
         if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) {
             let def_id = instance.def_id();
             if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
@@ -141,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
                     .span_suggestion(
                         span,
                         "try using `ty::<kind>` directly",
-                        "ty".to_string(),
+                        "ty",
                         Applicability::MaybeIncorrect, // ty maybe needs an import
                     )
                     .emit();
@@ -170,7 +179,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
                                         .span_suggestion(
                                             path.span,
                                             "try using `ty::<kind>` directly",
-                                            "ty".to_string(),
+                                            "ty",
                                             Applicability::MaybeIncorrect, // ty maybe needs an import
                                         )
                                         .emit();
@@ -188,7 +197,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
                                         .span_suggestion(
                                             path.span,
                                             "try using `ty::<kind>` directly",
-                                            "ty".to_string(),
+                                            "ty",
                                             Applicability::MaybeIncorrect, // ty maybe needs an import
                                         )
                                         .emit();
@@ -208,7 +217,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
                                         .span_suggestion(
                                             path.span,
                                             "try using `ty::<kind>` directly",
-                                            "ty".to_string(),
+                                            "ty",
                                             Applicability::MaybeIncorrect, // ty maybe needs an import
                                         )
                                         .emit();
@@ -376,3 +385,70 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
         }
     }
 }
+
+declare_tool_lint! {
+    pub rustc::UNTRANSLATABLE_DIAGNOSTIC,
+    Allow,
+    "prevent creation of diagnostics which cannot be translated",
+    report_in_external_macro: true
+}
+
+declare_tool_lint! {
+    pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL,
+    Allow,
+    "prevent creation of diagnostics outside of `SessionDiagnostic`/`AddSubdiagnostic` impls",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(Diagnostics => [ UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL ]);
+
+impl LateLintPass<'_> for Diagnostics {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return };
+        debug!(?span, ?def_id, ?substs);
+        if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) &&
+            !cx.tcx.has_attr(instance.def_id(), sym::rustc_lint_diagnostics)
+        {
+            return;
+        }
+
+        let mut found_impl = false;
+        for (_, parent) in cx.tcx.hir().parent_iter(expr.hir_id) {
+            debug!(?parent);
+            if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent &&
+                let Impl { of_trait: Some(of_trait), .. } = impl_ &&
+                let Some(def_id) = of_trait.trait_def_id() &&
+                let Some(name) = cx.tcx.get_diagnostic_name(def_id) &&
+                matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic)
+            {
+                found_impl = true;
+                break;
+            }
+        }
+        debug!(?found_impl);
+        if !found_impl {
+            cx.struct_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, |lint| {
+                lint.build("diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls")
+                    .emit();
+            })
+        }
+
+        let mut found_diagnostic_message = false;
+        for ty in substs.types() {
+            debug!(?ty);
+            if let Some(adt_def) = ty.ty_adt_def() &&
+                let Some(name) =  cx.tcx.get_diagnostic_name(adt_def.did()) &&
+                matches!(name, sym::DiagnosticMessage | sym::SubdiagnosticMessage)
+            {
+                found_diagnostic_message = true;
+                break;
+            }
+        }
+        debug!(?found_diagnostic_message);
+        if !found_diagnostic_message {
+            cx.struct_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, |lint| {
+                lint.build("diagnostics should be created using translatable messages").emit();
+            })
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 54f2c725279..7faac5b5296 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -443,7 +443,7 @@ impl<'s> LintLevelsBuilder<'s> {
                                             .span_suggestion(
                                                 sp,
                                                 "change it to",
-                                                new_lint_name.to_string(),
+                                                new_lint_name,
                                                 Applicability::MachineApplicable,
                                             )
                                             .emit();
@@ -516,7 +516,7 @@ impl<'s> LintLevelsBuilder<'s> {
                                     err.span_suggestion(
                                         sp,
                                         "use the new name",
-                                        new_name.to_string(),
+                                        new_name,
                                         Applicability::MachineApplicable,
                                     );
                                 }
@@ -543,7 +543,7 @@ impl<'s> LintLevelsBuilder<'s> {
                                 db.span_suggestion(
                                     sp,
                                     "did you mean",
-                                    suggestion.to_string(),
+                                    suggestion,
                                     Applicability::MachineApplicable,
                                 );
                             }
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index ff4ed94fab3..f0182883d2b 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -508,6 +508,8 @@ fn register_internals(store: &mut LintStore) {
     store.register_late_pass(|| Box::new(ExistingDocKeyword));
     store.register_lints(&TyTyKind::get_lints());
     store.register_late_pass(|| Box::new(TyTyKind));
+    store.register_lints(&Diagnostics::get_lints());
+    store.register_late_pass(|| Box::new(Diagnostics));
     store.register_lints(&PassByValue::get_lints());
     store.register_late_pass(|| Box::new(PassByValue));
     store.register_group(
diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs
index 0fe6564880f..f06a8b8f4b0 100644
--- a/compiler/rustc_lint/src/redundant_semicolon.rs
+++ b/compiler/rustc_lint/src/redundant_semicolon.rs
@@ -54,9 +54,7 @@ fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, boo
             } else {
                 ("unnecessary trailing semicolon", "remove this semicolon")
             };
-            lint.build(msg)
-                .span_suggestion(span, rem, String::new(), Applicability::MaybeIncorrect)
-                .emit();
+            lint.build(msg).span_suggestion(span, rem, "", Applicability::MaybeIncorrect).emit();
         });
     }
 }
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 8cae95f46dc..73f353e62c1 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -160,7 +160,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 lint.span_suggestion_verbose(
                     expr.span.shrink_to_lo(),
                     "use `let _ = ...` to ignore the resulting value",
-                    "let _ = ".to_string(),
+                    "let _ = ",
                     Applicability::MachineApplicable,
                 );
                 lint.emit();
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index f90bb7f2368..a52d5340242 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -672,10 +672,20 @@ extern "C" void LLVMRustAddModuleFlag(
   unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
 }
 
+extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
+                                      size_t Len) {
+  return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
+}
+
 extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
   return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
 }
 
+extern "C" void LLVMRustGlobalAddMetadata(
+    LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
+  unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
+}
+
 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
   return new DIBuilder(*unwrap(M));
 }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 186031d4586..c1ded99a25a 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -26,7 +26,8 @@ use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::GeneratorDiagnosticData;
 use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility};
-use rustc_serialize::{opaque, Decodable, Decoder};
+use rustc_serialize::opaque::MemDecoder;
+use rustc_serialize::{Decodable, Decoder};
 use rustc_session::cstore::{
     CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib,
 };
@@ -154,7 +155,7 @@ struct ImportedSourceFile {
 }
 
 pub(super) struct DecodeContext<'a, 'tcx> {
-    opaque: opaque::Decoder<'a>,
+    opaque: MemDecoder<'a>,
     cdata: Option<CrateMetadataRef<'a>>,
     blob: &'a MetadataBlob,
     sess: Option<&'tcx Session>,
@@ -186,7 +187,7 @@ pub(super) trait Metadata<'a, 'tcx>: Copy {
     fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
         let tcx = self.tcx();
         DecodeContext {
-            opaque: opaque::Decoder::new(self.blob(), pos),
+            opaque: MemDecoder::new(self.blob(), pos),
             cdata: self.cdata(),
             blob: self.blob(),
             sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
@@ -418,7 +419,7 @@ impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> {
     where
         F: FnOnce(&mut Self) -> R,
     {
-        let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
+        let new_opaque = MemDecoder::new(self.opaque.data, pos);
         let old_opaque = mem::replace(&mut self.opaque, new_opaque);
         let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
         let r = f(self);
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 50c09aaf8d4..91ca4ecf3e1 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -27,7 +27,8 @@ use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
-use rustc_serialize::{opaque, Encodable, Encoder};
+use rustc_serialize::opaque::MemEncoder;
+use rustc_serialize::{Encodable, Encoder};
 use rustc_session::config::CrateType;
 use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
 use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
@@ -43,7 +44,7 @@ use std::num::NonZeroUsize;
 use tracing::{debug, trace};
 
 pub(super) struct EncodeContext<'a, 'tcx> {
-    opaque: opaque::Encoder,
+    opaque: MemEncoder,
     tcx: TyCtxt<'tcx>,
     feat: &'tcx rustc_feature::Features,
 
@@ -93,8 +94,8 @@ macro_rules! encoder_methods {
 }
 
 impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
-    type Ok = <opaque::Encoder as Encoder>::Ok;
-    type Err = <opaque::Encoder as Encoder>::Err;
+    type Ok = <MemEncoder as Encoder>::Ok;
+    type Err = <MemEncoder as Encoder>::Err;
 
     encoder_methods! {
         emit_usize(usize);
@@ -2026,7 +2027,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     }
 
     fn encode_info_for_expr(&mut self, expr: &hir::Expr<'_>) {
-        if let hir::ExprKind::Closure(..) = expr.kind {
+        if let hir::ExprKind::Closure { .. } = expr.kind {
             self.encode_info_for_closure(expr.hir_id);
         }
     }
@@ -2180,7 +2181,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
 }
 
 fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
-    let mut encoder = opaque::Encoder::new();
+    let mut encoder = MemEncoder::new();
     encoder.emit_raw_bytes(METADATA_HEADER);
 
     // Will be filled with the root position after encoding everything.
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index fb2ffe1d73d..04f0847f5cc 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -22,7 +22,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, ReprOptions, Ty};
 use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
-use rustc_serialize::opaque::Encoder;
+use rustc_serialize::opaque::MemEncoder;
 use rustc_session::config::SymbolManglingVersion;
 use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
 use rustc_span::edition::Edition;
@@ -323,7 +323,7 @@ macro_rules! define_tables {
         }
 
         impl TableBuilders {
-            fn encode(&self, buf: &mut Encoder) -> LazyTables {
+            fn encode(&self, buf: &mut MemEncoder) -> LazyTables {
                 LazyTables {
                     $($name: self.$name.encode(buf)),+
                 }
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 8baa67a8f9f..5ab4269ae99 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -4,8 +4,8 @@ use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_hir::def::{CtorKind, CtorOf};
 use rustc_index::vec::Idx;
 use rustc_middle::ty::ParameterizedOverTcx;
-use rustc_serialize::opaque::Encoder;
-use rustc_serialize::Encoder as _;
+use rustc_serialize::opaque::MemEncoder;
+use rustc_serialize::Encoder;
 use rustc_span::hygiene::MacroKind;
 use std::convert::TryInto;
 use std::marker::PhantomData;
@@ -281,7 +281,7 @@ where
         Some(value).write_to_bytes(&mut self.blocks[i]);
     }
 
-    pub(crate) fn encode<const N: usize>(&self, buf: &mut Encoder) -> LazyTable<I, T>
+    pub(crate) fn encode<const N: usize>(&self, buf: &mut MemEncoder) -> LazyTable<I, T>
     where
         Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
     {
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 0f1597e66e7..0826cd79375 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -22,7 +22,7 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
         Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
         | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })
         | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl),
-        Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. })
+        Node::Expr(Expr { kind: ExprKind::Closure { fn_decl, .. }, .. })
         | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, ..), .. }) => {
             Some(fn_decl)
         }
@@ -54,7 +54,7 @@ pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
             kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
             ..
         })
-        | Node::Expr(Expr { kind: ExprKind::Closure(.., body, _, _), .. }) => Some(*body),
+        | Node::Expr(Expr { kind: ExprKind::Closure { body, .. }, .. }) => Some(*body),
 
         Node::AnonConst(constant) => Some(constant.body),
 
@@ -285,8 +285,8 @@ impl<'hir> Map<'hir> {
             }
             Node::Field(_) => DefKind::Field,
             Node::Expr(expr) => match expr.kind {
-                ExprKind::Closure(.., None) => DefKind::Closure,
-                ExprKind::Closure(.., Some(_)) => DefKind::Generator,
+                ExprKind::Closure { movability: None, .. } => DefKind::Closure,
+                ExprKind::Closure { movability: Some(_), .. } => DefKind::Generator,
                 _ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
             },
             Node::GenericParam(param) => match param.kind {
@@ -758,7 +758,7 @@ impl<'hir> Map<'hir> {
                 Node::Item(_)
                 | Node::ForeignItem(_)
                 | Node::TraitItem(_)
-                | Node::Expr(Expr { kind: ExprKind::Closure(..), .. })
+                | Node::Expr(Expr { kind: ExprKind::Closure { .. }, .. })
                 | Node::ImplItem(_) => return Some(hir_id),
                 // Ignore `return`s on the first iteration
                 Node::Expr(Expr { kind: ExprKind::Loop(..) | ExprKind::Ret(..), .. })
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 6b7ac883f5c..79f94802d20 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -336,7 +336,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
                     GenericArgKind::Const(ct) => tcx
                         .mk_const(ty::ConstS {
                             ty: ct.ty(),
-                            val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
+                            kind: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
                         })
                         .into(),
                 })
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 62e0fec0661..d23707a9d31 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -153,7 +153,7 @@ pub fn deprecation_suggestion(
         diag.span_suggestion(
             span,
             &format!("replace the use of the deprecated {}", kind),
-            suggestion.to_string(),
+            suggestion,
             Applicability::MachineApplicable,
         );
     }
diff --git a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
index 096bf8cbc15..1279f5aee36 100644
--- a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
+++ b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::graph::{
 };
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::OnceCell;
-use rustc_serialize as serialize;
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
 /// Helper type to cache the result of `graph::is_cyclic`.
 #[derive(Clone, Debug)]
@@ -36,17 +36,17 @@ impl GraphIsCyclicCache {
     }
 }
 
-impl<S: serialize::Encoder> serialize::Encodable<S> for GraphIsCyclicCache {
+impl<S: Encoder> Encodable<S> for GraphIsCyclicCache {
     #[inline]
     fn encode(&self, s: &mut S) {
-        serialize::Encodable::encode(&(), s);
+        Encodable::encode(&(), s);
     }
 }
 
-impl<D: serialize::Decoder> serialize::Decodable<D> for GraphIsCyclicCache {
+impl<D: Decoder> Decodable<D> for GraphIsCyclicCache {
     #[inline]
     fn decode(d: &mut D) -> Self {
-        let () = serialize::Decodable::decode(d);
+        let () = Decodable::decode(d);
         Self::new()
     }
 }
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 8fc957cf49c..5f32f0d5e89 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -1,4 +1,4 @@
-use super::{ErrorHandled, EvalToConstValueResult, GlobalId};
+use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
 
 use crate::mir;
 use crate::ty::fold::TypeFoldable;
@@ -11,6 +11,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
     /// that can't take any generic arguments like statics, const items or enum discriminants. If a
     /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
+    #[instrument(skip(self), level = "debug")]
     pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
         // In some situations def_id will have substitutions within scope, but they aren't allowed
         // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
@@ -22,7 +23,6 @@ impl<'tcx> TyCtxt<'tcx> {
         let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
         self.const_eval_global_id(param_env, cid, None)
     }
-
     /// Resolves and evaluates a constant.
     ///
     /// The constant can be located on a trait like `<A as B>::C`, in which case the given
@@ -59,6 +59,33 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
+    pub fn const_eval_resolve_for_typeck(
+        self,
+        param_env: ty::ParamEnv<'tcx>,
+        ct: ty::Unevaluated<'tcx>,
+        span: Option<Span>,
+    ) -> EvalToValTreeResult<'tcx> {
+        // Cannot resolve `Unevaluated` constants that contain inference
+        // variables. We reject those here since `resolve_opt_const_arg`
+        // would fail otherwise.
+        //
+        // When trying to evaluate constants containing inference variables,
+        // use `Infcx::const_eval_resolve` instead.
+        if ct.substs.has_infer_types_or_consts() {
+            bug!("did not expect inference variables here");
+        }
+
+        match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
+            Ok(Some(instance)) => {
+                let cid = GlobalId { instance, promoted: ct.promoted };
+                self.const_eval_global_id_for_typeck(param_env, cid, span)
+            }
+            Ok(None) => Err(ErrorHandled::TooGeneric),
+            Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
+        }
+    }
+
     pub fn const_eval_instance(
         self,
         param_env: ty::ParamEnv<'tcx>,
@@ -68,7 +95,8 @@ impl<'tcx> TyCtxt<'tcx> {
         self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span)
     }
 
-    /// Evaluate a constant.
+    /// Evaluate a constant to a `ConstValue`.
+    #[instrument(skip(self), level = "debug")]
     pub fn const_eval_global_id(
         self,
         param_env: ty::ParamEnv<'tcx>,
@@ -86,6 +114,27 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
+    /// Evaluate a constant to a type-level constant.
+    #[instrument(skip(self), level = "debug")]
+    pub fn const_eval_global_id_for_typeck(
+        self,
+        param_env: ty::ParamEnv<'tcx>,
+        cid: GlobalId<'tcx>,
+        span: Option<Span>,
+    ) -> EvalToValTreeResult<'tcx> {
+        let param_env = param_env.with_const();
+        debug!(?param_env);
+        // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
+        // improve caching of queries.
+        let inputs = self.erase_regions(param_env.and(cid));
+        debug!(?inputs);
+        if let Some(span) = span {
+            self.at(span).eval_to_valtree(inputs)
+        } else {
+            self.eval_to_valtree(inputs)
+        }
+    }
+
     /// Evaluate a static's initializer, returning the allocation of the initializer's memory.
     #[inline(always)]
     pub fn eval_static_initializer(
@@ -125,11 +174,8 @@ impl<'tcx> TyCtxtAt<'tcx> {
 impl<'tcx> TyCtxt<'tcx> {
     /// Destructure a type-level constant ADT or array into its variant index and its field values.
     /// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
-    pub fn destructure_const(
-        self,
-        param_env_and_val: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>,
-    ) -> mir::DestructuredConst<'tcx> {
-        self.try_destructure_const(param_env_and_val).unwrap()
+    pub fn destructure_const(self, const_: ty::Const<'tcx>) -> ty::DestructuredConst<'tcx> {
+        self.try_destructure_const(const_).unwrap()
     }
 
     /// Destructure a mir constant ADT or array into its variant index and its field values.
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 146ae45e468..e80918d5e5d 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -111,6 +111,10 @@ impl<'tcx> ConstValue<'tcx> {
     pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
         ConstValue::Scalar(Scalar::from_machine_usize(i, cx))
     }
+
+    pub fn zst() -> Self {
+        Self::Scalar(Scalar::ZST)
+    }
 }
 
 /// A `Scalar` represents an immediate, primitive value existing outside of a
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 6823dfc6933..c173d453041 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -3,7 +3,9 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 
 use crate::mir::coverage::{CodeRegion, CoverageKind};
-use crate::mir::interpret::{ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar};
+use crate::mir::interpret::{
+    AllocRange, ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar,
+};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -2399,7 +2401,7 @@ impl<'tcx> Operand<'tcx> {
         Operand::Constant(Box::new(Constant {
             span,
             user_ty: None,
-            literal: ConstantKind::Ty(ty::Const::zero_sized(tcx, ty)),
+            literal: ConstantKind::Val(ConstValue::zst(), ty),
         }))
     }
 
@@ -2953,22 +2955,9 @@ impl<'tcx> Constant<'tcx> {
     }
 }
 
-impl<'tcx> From<ty::Const<'tcx>> for ConstantKind<'tcx> {
-    #[inline]
-    fn from(ct: ty::Const<'tcx>) -> Self {
-        match ct.val() {
-            ty::ConstKind::Value(cv) => {
-                // FIXME Once valtrees are introduced we need to convert those
-                // into `ConstValue` instances here
-                Self::Val(cv, ct.ty())
-            }
-            _ => Self::Ty(ct),
-        }
-    }
-}
-
 impl<'tcx> ConstantKind<'tcx> {
     /// Returns `None` if the constant is not trivially safe for use in the type system.
+    #[inline]
     pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> {
         match self {
             ConstantKind::Ty(c) => Some(*c),
@@ -2976,6 +2965,7 @@ impl<'tcx> ConstantKind<'tcx> {
         }
     }
 
+    #[inline(always)]
     pub fn ty(&self) -> Ty<'tcx> {
         match self {
             ConstantKind::Ty(c) => c.ty(),
@@ -2983,32 +2973,34 @@ impl<'tcx> ConstantKind<'tcx> {
         }
     }
 
-    pub fn try_val(&self) -> Option<ConstValue<'tcx>> {
+    #[inline]
+    pub fn try_to_value(self, tcx: TyCtxt<'tcx>) -> Option<interpret::ConstValue<'tcx>> {
         match self {
-            ConstantKind::Ty(c) => match c.val() {
-                ty::ConstKind::Value(v) => Some(v),
+            ConstantKind::Ty(c) => match c.kind() {
+                ty::ConstKind::Value(valtree) => Some(tcx.valtree_to_const_val((c.ty(), valtree))),
                 _ => None,
             },
-            ConstantKind::Val(v, _) => Some(*v),
-        }
-    }
-
-    #[inline]
-    pub fn try_to_value(self) -> Option<interpret::ConstValue<'tcx>> {
-        match self {
-            ConstantKind::Ty(c) => c.val().try_to_value(),
             ConstantKind::Val(val, _) => Some(val),
         }
     }
 
     #[inline]
     pub fn try_to_scalar(self) -> Option<Scalar> {
-        self.try_to_value()?.try_to_scalar()
+        match self {
+            ConstantKind::Ty(c) => match c.kind() {
+                ty::ConstKind::Value(valtree) => match valtree {
+                    ty::ValTree::Leaf(scalar_int) => Some(Scalar::Int(scalar_int)),
+                    ty::ValTree::Branch(_) => None,
+                },
+                _ => None,
+            },
+            ConstantKind::Val(val, _) => val.try_to_scalar(),
+        }
     }
 
     #[inline]
     pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
-        Some(self.try_to_value()?.try_to_scalar()?.assert_int())
+        Some(self.try_to_scalar()?.assert_int())
     }
 
     #[inline]
@@ -3025,9 +3017,7 @@ impl<'tcx> ConstantKind<'tcx> {
     pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
         match self {
             Self::Ty(c) => {
-                // FIXME Need to use a different evaluation function that directly returns a `ConstValue`
-                // if evaluation succeeds and does not create a ValTree first
-                if let Some(val) = c.val().try_eval(tcx, param_env) {
+                if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
                     match val {
                         Ok(val) => Self::Val(val, c.ty()),
                         Err(_) => Self::Ty(tcx.const_error(self.ty())),
@@ -3081,6 +3071,11 @@ impl<'tcx> ConstantKind<'tcx> {
         }
     }
 
+    #[inline]
+    pub fn from_value(val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self {
+        Self::Val(val, ty)
+    }
+
     pub fn from_bits(
         tcx: TyCtxt<'tcx>,
         bits: u128,
@@ -3097,11 +3092,13 @@ impl<'tcx> ConstantKind<'tcx> {
         Self::Val(cv, param_env_ty.value)
     }
 
+    #[inline]
     pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
         let cv = ConstValue::from_bool(v);
         Self::Val(cv, tcx.types.bool)
     }
 
+    #[inline]
     pub fn zero_sized(ty: Ty<'tcx>) -> Self {
         let cv = ConstValue::Scalar(Scalar::ZST);
         Self::Val(cv, ty)
@@ -3112,6 +3109,12 @@ impl<'tcx> ConstantKind<'tcx> {
         Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty))
     }
 
+    #[inline]
+    pub fn from_scalar(_tcx: TyCtxt<'tcx>, s: Scalar, ty: Ty<'tcx>) -> Self {
+        let val = ConstValue::Scalar(s);
+        Self::Val(val, ty)
+    }
+
     /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
     /// converted to a constant, everything else becomes `Unevaluated`.
     pub fn from_anon_const(
@@ -3161,7 +3164,7 @@ impl<'tcx> ConstantKind<'tcx> {
             ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
                 .substs;
         let uneval_const = tcx.mk_const(ty::ConstS {
-            val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+            kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                 def: ty::WithOptConstParam::unknown(def_id).to_global(),
                 substs,
                 promoted: None,
@@ -3199,8 +3202,10 @@ impl<'tcx> ConstantKind<'tcx> {
             }
             _ => expr,
         };
+        debug!("expr.kind: {:?}", expr.kind);
 
         let ty = tcx.type_of(def.def_id_for_type_of());
+        debug!(?ty);
 
         // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
         // does not provide the parents generics to anonymous constants. We still allow generic const
@@ -3221,9 +3226,10 @@ impl<'tcx> ConstantKind<'tcx> {
                 let index = generics.param_def_id_to_index[&def_id];
                 let name = tcx.hir().name(hir_id);
                 let ty_const = tcx.mk_const(ty::ConstS {
-                    val: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
+                    kind: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
                     ty,
                 });
+                debug!(?ty_const);
 
                 return Self::Ty(ty_const);
             }
@@ -3253,23 +3259,38 @@ impl<'tcx> ConstantKind<'tcx> {
         debug!(?span, ?param_env);
 
         match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
-            Ok(val) => Self::Val(val, ty),
+            Ok(val) => {
+                debug!("evaluated const value: {:?}", val);
+                Self::Val(val, ty)
+            }
             Err(_) => {
+                debug!("error encountered during evaluation");
                 // Error was handled in `const_eval_resolve`. Here we just create a
                 // new unevaluated const and error hard later in codegen
                 let ty_const = tcx.mk_const(ty::ConstS {
-                    val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                         def: def.to_global(),
                         substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
                         promoted: None,
                     }),
                     ty,
                 });
+                debug!(?ty_const);
 
                 Self::Ty(ty_const)
             }
         }
     }
+
+    pub fn from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
+        match c.kind() {
+            ty::ConstKind::Value(valtree) => {
+                let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
+                Self::Val(const_val, c.ty())
+            }
+            _ => Self::Ty(c),
+        }
+    }
 }
 
 /// A collection of projections into user types.
@@ -3485,20 +3506,183 @@ fn pretty_print_const<'tcx>(
     })
 }
 
+fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Result {
+    fmt.write_str("b\"")?;
+    for &c in byte_str {
+        for e in std::ascii::escape_default(c) {
+            fmt.write_char(e as char)?;
+        }
+    }
+    fmt.write_str("\"")?;
+
+    Ok(())
+}
+
+fn comma_sep<'tcx>(fmt: &mut Formatter<'_>, elems: Vec<ConstantKind<'tcx>>) -> fmt::Result {
+    let mut first = true;
+    for elem in elems {
+        if !first {
+            fmt.write_str(", ")?;
+        }
+        fmt.write_str(&format!("{}", elem))?;
+        first = false;
+    }
+    Ok(())
+}
+
+// FIXME: Move that into `mir/pretty.rs`.
 fn pretty_print_const_value<'tcx>(
-    val: interpret::ConstValue<'tcx>,
+    ct: ConstValue<'tcx>,
     ty: Ty<'tcx>,
     fmt: &mut Formatter<'_>,
-    print_types: bool,
+    print_ty: bool,
 ) -> fmt::Result {
     use crate::ty::print::PrettyPrinter;
+
     ty::tls::with(|tcx| {
-        let val = tcx.lift(val).unwrap();
+        let ct = tcx.lift(ct).unwrap();
         let ty = tcx.lift(ty).unwrap();
-        let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
-        cx.print_alloc_ids = true;
-        let cx = cx.pretty_print_const_value(val, ty, print_types)?;
-        fmt.write_str(&cx.into_buffer())?;
+
+        if tcx.sess.verbose() {
+            fmt.write_str(&format!("ConstValue({:?}: {})", ct, ty))?;
+            return Ok(());
+        }
+
+        let u8_type = tcx.types.u8;
+        match (ct, ty.kind()) {
+            // Byte/string slices, printed as (byte) string literals.
+            (ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => {
+                match inner.kind() {
+                    ty::Slice(t) => {
+                        if *t == u8_type {
+                            // The `inspect` here is okay since we checked the bounds, and there are
+                            // no relocations (we have an active slice reference here). We don't use
+                            // this result to affect interpreter execution.
+                            let byte_str = data
+                                .inner()
+                                .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
+                            pretty_print_byte_str(fmt, byte_str)?;
+                            return Ok(());
+                        }
+                    }
+                    ty::Str => {
+                        // The `inspect` here is okay since we checked the bounds, and there are no
+                        // relocations (we have an active `str` reference here). We don't use this
+                        // result to affect interpreter execution.
+                        let slice = data
+                            .inner()
+                            .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
+                        fmt.write_str(&format!("{:?}", String::from_utf8_lossy(slice)))?;
+                        return Ok(());
+                    }
+                    _ => {}
+                }
+            }
+            (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
+                let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap();
+                // cast is ok because we already checked for pointer size (32 or 64 bit) above
+                let range = AllocRange { start: offset, size: Size::from_bytes(n) };
+                let byte_str = alloc.inner().get_bytes(&tcx, range).unwrap();
+                fmt.write_str("*")?;
+                pretty_print_byte_str(fmt, byte_str)?;
+                return Ok(());
+            }
+            // Aggregates, printed as array/tuple/struct/variant construction syntax.
+            //
+            // NB: the `has_param_types_or_consts` check ensures that we can use
+            // 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)
+            //
+            // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
+            // correct `ty::ParamEnv` to allow printing *all* constant values.
+            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
+                let ct = tcx.lift(ct).unwrap();
+                let ty = tcx.lift(ty).unwrap();
+                if let Some(contents) = tcx.try_destructure_mir_constant(
+                    ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)),
+                ) {
+                    let fields = contents.fields.iter().copied().collect::<Vec<_>>();
+                    match *ty.kind() {
+                        ty::Array(..) => {
+                            fmt.write_str("[")?;
+                            comma_sep(fmt, fields)?;
+                            fmt.write_str("]")?;
+                        }
+                        ty::Tuple(..) => {
+                            fmt.write_str("(")?;
+                            comma_sep(fmt, fields)?;
+                            if contents.fields.len() == 1 {
+                                fmt.write_str(",")?;
+                            }
+                            fmt.write_str(")")?;
+                        }
+                        ty::Adt(def, _) if def.variants().is_empty() => {
+                            fmt.write_str(&format!("{{unreachable(): {}}}", ty))?;
+                        }
+                        ty::Adt(def, substs) => {
+                            let variant_idx = contents
+                                .variant
+                                .expect("destructed mir constant of adt without variant idx");
+                            let variant_def = &def.variant(variant_idx);
+                            let substs = tcx.lift(substs).unwrap();
+                            let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
+                            cx.print_alloc_ids = true;
+                            let cx = cx.print_value_path(variant_def.def_id, substs)?;
+                            fmt.write_str(&cx.into_buffer())?;
+
+                            match variant_def.ctor_kind {
+                                CtorKind::Const => {}
+                                CtorKind::Fn => {
+                                    fmt.write_str("(")?;
+                                    comma_sep(fmt, fields)?;
+                                    fmt.write_str(")")?;
+                                }
+                                CtorKind::Fictive => {
+                                    fmt.write_str(" {{ ")?;
+                                    let mut first = true;
+                                    for (field_def, field) in iter::zip(&variant_def.fields, fields)
+                                    {
+                                        if !first {
+                                            fmt.write_str(", ")?;
+                                        }
+                                        fmt.write_str(&format!("{}: {}", field_def.name, field))?;
+                                        first = false;
+                                    }
+                                    fmt.write_str(" }}")?;
+                                }
+                            }
+                        }
+                        _ => unreachable!(),
+                    }
+                    return Ok(());
+                } else {
+                    // Fall back to debug pretty printing for invalid constants.
+                    fmt.write_str(&format!("{:?}", ct))?;
+                    if print_ty {
+                        fmt.write_str(&format!(": {}", ty))?;
+                    }
+                    return Ok(());
+                };
+            }
+            (ConstValue::Scalar(scalar), _) => {
+                let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
+                cx.print_alloc_ids = true;
+                let ty = tcx.lift(ty).unwrap();
+                cx = cx.pretty_print_const_scalar(scalar, ty, print_ty)?;
+                fmt.write_str(&cx.into_buffer())?;
+                return Ok(());
+            }
+            // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
+            // their fields instead of just dumping the memory.
+            _ => {}
+        }
+        // fallback
+        fmt.write_str(&format!("{:?}", ct))?;
+        if print_ty {
+            fmt.write_str(&format!(": {}", ty))?;
+        }
         Ok(())
     })
 }
diff --git a/compiler/rustc_middle/src/mir/predecessors.rs b/compiler/rustc_middle/src/mir/predecessors.rs
index 9bc0cb1138f..620cf7e336b 100644
--- a/compiler/rustc_middle/src/mir/predecessors.rs
+++ b/compiler/rustc_middle/src/mir/predecessors.rs
@@ -3,7 +3,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::OnceCell;
 use rustc_index::vec::IndexVec;
-use rustc_serialize as serialize;
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use smallvec::SmallVec;
 
 use crate::mir::{BasicBlock, BasicBlockData};
@@ -54,12 +54,12 @@ impl PredecessorCache {
     }
 }
 
-impl<S: serialize::Encoder> serialize::Encodable<S> for PredecessorCache {
+impl<S: Encoder> Encodable<S> for PredecessorCache {
     #[inline]
     fn encode(&self, _s: &mut S) {}
 }
 
-impl<D: serialize::Decoder> serialize::Decodable<D> for PredecessorCache {
+impl<D: Decoder> Decodable<D> for PredecessorCache {
     #[inline]
     fn decode(_: &mut D) -> Self {
         Self::new()
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index eaa68bf1b38..462c0ada3cf 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -454,8 +454,13 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                 ConstValue::ByRef { .. } => format!("ByRef(..)"),
             };
 
+            let fmt_valtree = |valtree: &ty::ValTree<'tcx>| match valtree {
+                ty::ValTree::Leaf(leaf) => format!("ValTree::Leaf({:?})", leaf),
+                ty::ValTree::Branch(_) => format!("ValTree::Branch(..)"),
+            };
+
             let val = match literal {
-                ConstantKind::Ty(ct) => match ct.val() {
+                ConstantKind::Ty(ct) => match ct.kind() {
                     ty::ConstKind::Param(p) => format!("Param({})", p),
                     ty::ConstKind::Unevaluated(uv) => format!(
                         "Unevaluated({}, {:?}, {:?})",
@@ -463,7 +468,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                         uv.substs,
                         uv.promoted,
                     ),
-                    ty::ConstKind::Value(val) => format!("Value({})", fmt_val(&val)),
+                    ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
                     ty::ConstKind::Error(_) => "Error".to_string(),
                     // These variants shouldn't exist in the MIR.
                     ty::ConstKind::Placeholder(_)
@@ -476,6 +481,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                 ConstantKind::Val(val, _) => format!("Value({})", fmt_val(&val)),
             };
 
+            // This reflects what `Const` looked liked before `val` was renamed
+            // as `kind`. We print it like this to avoid having to update
+            // expected output in a lot of tests.
             self.push(&format!("+ literal: Const {{ ty: {}, val: {} }}", literal.ty(), val));
         }
     }
@@ -662,7 +670,8 @@ pub fn write_allocations<'tcx>(
     ) -> impl DoubleEndedIterator<Item = AllocId> + '_ {
         alloc.inner().relocations().values().map(|id| *id)
     }
-    fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
+
+    fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
         match val {
             ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
                 Either::Left(Either::Left(std::iter::once(ptr.provenance)))
@@ -678,17 +687,11 @@ pub fn write_allocations<'tcx>(
     struct CollectAllocIds(BTreeSet<AllocId>);
 
     impl<'tcx> Visitor<'tcx> for CollectAllocIds {
-        fn visit_const(&mut self, c: ty::Const<'tcx>, _loc: Location) {
-            if let ty::ConstKind::Value(val) = c.val() {
-                self.0.extend(alloc_ids_from_const(val));
-            }
-        }
-
         fn visit_constant(&mut self, c: &Constant<'tcx>, loc: Location) {
             match c.literal {
                 ConstantKind::Ty(c) => self.visit_const(c, loc),
                 ConstantKind::Val(val, _) => {
-                    self.0.extend(alloc_ids_from_const(val));
+                    self.0.extend(alloc_ids_from_const_val(val));
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 01945b543b1..da4793fa039 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -1,6 +1,6 @@
 //! Values computed by queries that use MIR.
 
-use crate::mir::{self, Body, Promoted};
+use crate::mir::{Body, ConstantKind, Promoted};
 use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
 use rustc_data_structures::stable_map::FxHashMap;
 use rustc_data_structures::vec_map::VecMap;
@@ -427,7 +427,7 @@ pub struct DestructuredConst<'tcx> {
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct DestructuredMirConstant<'tcx> {
     pub variant: Option<VariantIdx>,
-    pub fields: &'tcx [mir::ConstantKind<'tcx>],
+    pub fields: &'tcx [ConstantKind<'tcx>],
 }
 
 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs
index 4872a7835e3..99d13fcfef4 100644
--- a/compiler/rustc_middle/src/mir/switch_sources.rs
+++ b/compiler/rustc_middle/src/mir/switch_sources.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::stable_map::FxHashMap;
 use rustc_data_structures::sync::OnceCell;
 use rustc_index::vec::IndexVec;
-use rustc_serialize as serialize;
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use smallvec::SmallVec;
 
 use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
@@ -54,12 +54,12 @@ impl SwitchSourceCache {
     }
 }
 
-impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache {
+impl<S: Encoder> Encodable<S> for SwitchSourceCache {
     #[inline]
     fn encode(&self, _s: &mut S) {}
 }
 
-impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache {
+impl<D: Decoder> Decodable<D> for SwitchSourceCache {
     #[inline]
     fn decode(_: &mut D) -> Self {
         Self::new()
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index c859d93043e..c65e79a80fb 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -1,3 +1,4 @@
+use crate::mir;
 use crate::mir::interpret::Scalar;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
@@ -676,7 +677,7 @@ impl<'tcx> TerminatorKind<'tcx> {
                     .values
                     .iter()
                     .map(|&u| {
-                        ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
+                        mir::ConstantKind::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
                             .to_string()
                             .into()
                     })
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index f745e55307a..7228e3f33b1 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -1,7 +1,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::OnceCell;
 use rustc_index::bit_set::BitSet;
-use rustc_serialize as serialize;
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
 use super::*;
 
@@ -365,12 +365,12 @@ impl PostorderCache {
     }
 }
 
-impl<S: serialize::Encoder> serialize::Encodable<S> for PostorderCache {
+impl<S: Encoder> Encodable<S> for PostorderCache {
     #[inline]
     fn encode(&self, _s: &mut S) {}
 }
 
-impl<D: serialize::Decoder> serialize::Decodable<D> for PostorderCache {
+impl<D: Decoder> Decodable<D> for PostorderCache {
     #[inline]
     fn decode(_: &mut D) -> Self {
         Self::new()
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 5b48f164016..caa1d4cd34e 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -967,36 +967,26 @@ rustc_queries! {
     query eval_to_valtree(
         key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>
     ) -> EvalToValTreeResult<'tcx> {
-        desc { "evaluate type-level constant" }
-        remap_env_constness
+        desc { "evaluating type-level constant" }
     }
 
     /// Converts a type level constant value into `ConstValue`
     query valtree_to_const_val(key: (Ty<'tcx>, ty::ValTree<'tcx>)) -> ConstValue<'tcx> {
-        desc { "convert type-level constant value to mir constant value"}
+        desc { "converting type-level constant value to mir constant value"}
     }
 
     /// Destructure a constant ADT or array into its variant index and its
     /// field values or return `None` if constant is invalid.
     ///
     /// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
-    query try_destructure_const(key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>) -> Option<mir::DestructuredConst<'tcx>> {
-        desc { "destructure type level constant"}
+    query try_destructure_const(key: ty::Const<'tcx>) -> Option<ty::DestructuredConst<'tcx>> {
+        desc { "destructuring type level constant"}
     }
 
     /// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index
     /// and its field values.
     query try_destructure_mir_constant(key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>) -> Option<mir::DestructuredMirConstant<'tcx>> {
-        desc { "destructure mir constant"}
-        remap_env_constness
-    }
-
-    /// Dereference a constant reference or raw pointer and turn the result into a constant
-    /// again.
-    query deref_const(
-        key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>
-    ) -> ty::Const<'tcx> {
-        desc { "deref constant" }
+        desc { "destructuring mir constant"}
         remap_env_constness
     }
 
@@ -1005,7 +995,7 @@ rustc_queries! {
     query deref_mir_constant(
         key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
     ) -> mir::ConstantKind<'tcx> {
-        desc { "deref constant" }
+        desc { "dereferencing mir constant" }
         remap_env_constness
     }
 
diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs
index 015bdb5783f..70abdb9ab4c 100644
--- a/compiler/rustc_middle/src/traits/chalk.rs
+++ b/compiler/rustc_middle/src/traits/chalk.rs
@@ -5,7 +5,6 @@
 //! its name suggest, is to provide an abstraction boundary for creating
 //! interned Chalk types.
 
-use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::{self, AdtDef, TyCtxt};
 
 use rustc_hir::def_id::DefId;
@@ -62,7 +61,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
     type InternedType = Box<chalk_ir::TyData<Self>>;
     type InternedLifetime = Box<chalk_ir::LifetimeData<Self>>;
     type InternedConst = Box<chalk_ir::ConstData<Self>>;
-    type InternedConcreteConst = ConstValue<'tcx>;
+    type InternedConcreteConst = ty::ValTree<'tcx>;
     type InternedGenericArg = Box<chalk_ir::GenericArgData<Self>>;
     type InternedGoal = Box<chalk_ir::GoalData<Self>>;
     type InternedGoals = Vec<chalk_ir::Goal<Self>>;
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 4006b2fcf17..912b09eeca8 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -933,7 +933,7 @@ impl ObjectSafetyViolation {
                                  trait objects",
                                 name
                             ),
-                            sugg.to_string(),
+                            sugg,
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -957,7 +957,7 @@ impl ObjectSafetyViolation {
                         "consider changing method `{}`'s `self` parameter to be `&self`",
                         name
                     ),
-                    "&Self".to_string(),
+                    "&Self",
                     Applicability::MachineApplicable,
                 );
             }
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index 3243ef28ff0..e6aab30a150 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -96,7 +96,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
             return Ok(a);
         }
 
-        match (a.val(), b.val()) {
+        match (a.kind(), b.kind()) {
             (_, ty::ConstKind::Infer(InferConst::Fresh(_))) => {
                 return Ok(a);
             }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 7af7eb4f5ec..bc52259b151 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,5 +1,5 @@
-use crate::mir::interpret::ConstValue;
-use crate::mir::interpret::{LitToConstInput, Scalar};
+use crate::mir::interpret::LitToConstInput;
+use crate::mir::ConstantKind;
 use crate::ty::{
     self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty,
     TyCtxt, TypeFoldable,
@@ -29,7 +29,7 @@ impl<'tcx> fmt::Debug for Const<'tcx> {
         // This reflects what `Const` looked liked before `Interned` was
         // introduced. We print it like this to avoid having to update expected
         // output in a lot of tests.
-        write!(f, "Const {{ ty: {:?}, val: {:?} }}", self.ty(), self.val())
+        write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind())
     }
 }
 
@@ -37,7 +37,7 @@ impl<'tcx> fmt::Debug for Const<'tcx> {
 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
 pub struct ConstS<'tcx> {
     pub ty: Ty<'tcx>,
-    pub val: ConstKind<'tcx>,
+    pub kind: ConstKind<'tcx>,
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@@ -50,8 +50,8 @@ impl<'tcx> Const<'tcx> {
     }
 
     #[inline]
-    pub fn val(self) -> ConstKind<'tcx> {
-        self.0.val
+    pub fn kind(self) -> ConstKind<'tcx> {
+        self.0.kind
     }
 
     /// Literals and const generic parameters are eagerly converted to a constant, everything else
@@ -83,7 +83,7 @@ impl<'tcx> Const<'tcx> {
         match Self::try_eval_lit_or_param(tcx, ty, expr) {
             Some(v) => v,
             None => tcx.mk_const(ty::ConstS {
-                val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                     def: def.to_global(),
                     substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
                     promoted: None,
@@ -145,7 +145,7 @@ impl<'tcx> Const<'tcx> {
                 let index = generics.param_def_id_to_index[&def_id];
                 let name = tcx.hir().name(hir_id);
                 Some(tcx.mk_const(ty::ConstS {
-                    val: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
+                    kind: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
                     ty,
                 }))
             }
@@ -180,7 +180,7 @@ impl<'tcx> Const<'tcx> {
                     InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty })
                         .substs;
                 tcx.mk_const(ty::ConstS {
-                    val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                         def: ty::WithOptConstParam::unknown(def_id).to_global(),
                         substs,
                         promoted: None,
@@ -195,14 +195,21 @@ impl<'tcx> Const<'tcx> {
 
     /// Interns the given value as a constant.
     #[inline]
-    pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self {
-        tcx.mk_const(ConstS { val: ConstKind::Value(val), ty })
+    pub fn from_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Self {
+        tcx.mk_const(ConstS { kind: ConstKind::Value(val), ty })
     }
 
-    #[inline]
-    /// Interns the given scalar as a constant.
-    pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> Self {
-        Self::from_value(tcx, ConstValue::Scalar(val), ty)
+    /// Panics if self.kind != ty::ConstKind::Value
+    pub fn to_valtree(self) -> ty::ValTree<'tcx> {
+        match self.kind() {
+            ty::ConstKind::Value(valtree) => valtree,
+            _ => bug!("expected ConstKind::Value"),
+        }
+    }
+
+    pub fn from_scalar_int(tcx: TyCtxt<'tcx>, i: ScalarInt, ty: Ty<'tcx>) -> Self {
+        let valtree = ty::ValTree::from_scalar_int(i);
+        Self::from_value(tcx, valtree, ty)
     }
 
     #[inline]
@@ -212,13 +219,14 @@ impl<'tcx> Const<'tcx> {
             .layout_of(ty)
             .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
             .size;
-        Self::from_scalar(tcx, Scalar::from_uint(bits, size), ty.value)
+        Self::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap(), ty.value)
     }
 
     #[inline]
     /// Creates an interned zst constant.
     pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
-        Self::from_scalar(tcx, Scalar::ZST, ty)
+        let valtree = ty::ValTree::zst();
+        Self::from_value(tcx, valtree, ty)
     }
 
     #[inline]
@@ -246,34 +254,49 @@ impl<'tcx> Const<'tcx> {
         assert_eq!(self.ty(), ty);
         let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
         // if `ty` does not depend on generic parameters, use an empty param_env
-        self.val().eval(tcx, param_env).try_to_bits(size)
+        self.kind().eval(tcx, param_env).try_to_bits(size)
     }
 
     #[inline]
     pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
-        self.val().eval(tcx, param_env).try_to_bool()
+        self.kind().eval(tcx, param_env).try_to_bool()
     }
 
     #[inline]
     pub fn try_eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u64> {
-        self.val().eval(tcx, param_env).try_to_machine_usize(tcx)
+        self.kind().eval(tcx, param_env).try_to_machine_usize(tcx)
     }
 
     #[inline]
     /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
     /// unevaluated constant.
     pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
-        if let Some(val) = self.val().try_eval(tcx, param_env) {
+        if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
             match val {
                 Ok(val) => Const::from_value(tcx, val, self.ty()),
                 Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()),
             }
         } else {
+            // Either the constant isn't evaluatable or ValTree creation failed.
             self
         }
     }
 
     #[inline]
+    /// Tries to evaluate the constant if it is `Unevaluated` and creates a ConstValue if the
+    /// evaluation succeeds. If it doesn't succeed, returns the unevaluated constant.
+    pub fn eval_for_mir(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> ConstantKind<'tcx> {
+        if let Some(val) = self.kind().try_eval_for_mir(tcx, param_env) {
+            match val {
+                Ok(const_val) => ConstantKind::from_value(const_val, self.ty()),
+                Err(ErrorGuaranteed { .. }) => ConstantKind::Ty(tcx.const_error(self.ty())),
+            }
+        } else {
+            ConstantKind::Ty(self)
+        }
+    }
+
+    #[inline]
     /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
     pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
         self.try_eval_bits(tcx, param_env, ty)
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 35d286d2c57..10d03065c79 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -63,7 +63,7 @@ pub enum ConstKind<'tcx> {
     Unevaluated(Unevaluated<'tcx>),
 
     /// Used to hold computed value.
-    Value(ConstValue<'tcx>),
+    Value(ty::ValTree<'tcx>),
 
     /// A placeholder for a const which could not be computed; this is
     /// propagated to avoid useless error messages.
@@ -75,7 +75,7 @@ static_assert_size!(ConstKind<'_>, 40);
 
 impl<'tcx> ConstKind<'tcx> {
     #[inline]
-    pub fn try_to_value(self) -> Option<ConstValue<'tcx>> {
+    pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
         if let ConstKind::Value(val) = self { Some(val) } else { None }
     }
 
@@ -86,7 +86,7 @@ impl<'tcx> ConstKind<'tcx> {
 
     #[inline]
     pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
-        Some(self.try_to_value()?.try_to_scalar()?.assert_int())
+        self.try_to_value()?.try_to_scalar_int()
     }
 
     #[inline]
@@ -115,23 +115,65 @@ pub enum InferConst<'tcx> {
     Fresh(u32),
 }
 
+enum EvalMode {
+    Typeck,
+    Mir,
+}
+
+enum EvalResult<'tcx> {
+    ValTree(ty::ValTree<'tcx>),
+    ConstVal(ConstValue<'tcx>),
+}
+
 impl<'tcx> ConstKind<'tcx> {
     #[inline]
     /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
     /// unevaluated constant.
     pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
-        self.try_eval(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
+        self.try_eval_for_typeck(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
     }
 
     #[inline]
     /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
     /// return `None`.
     // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
-    pub fn try_eval(
+    pub fn try_eval_for_mir(
         self,
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
     ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
+        match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
+            Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
+            Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
+            Some(Err(e)) => Some(Err(e)),
+            None => None,
+        }
+    }
+
+    #[inline]
+    /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
+    /// return `None`.
+    // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
+    pub fn try_eval_for_typeck(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+    ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
+        match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
+            Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
+            Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
+            Some(Err(e)) => Some(Err(e)),
+            None => None,
+        }
+    }
+
+    #[inline]
+    fn try_eval_inner(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+        eval_mode: EvalMode,
+    ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
         if let ConstKind::Unevaluated(unevaluated) = self {
             use crate::mir::interpret::ErrorHandled;
 
@@ -166,14 +208,29 @@ impl<'tcx> ConstKind<'tcx> {
             let (param_env, unevaluated) = param_env_and.into_parts();
             // try to resolve e.g. associated constants to their definition on an impl, and then
             // evaluate the const.
-            match tcx.const_eval_resolve(param_env, unevaluated, None) {
-                // NOTE(eddyb) `val` contains no lifetimes/types/consts,
-                // and we use the original type, so nothing from `substs`
-                // (which may be identity substs, see above),
-                // can leak through `val` into the const we return.
-                Ok(val) => Some(Ok(val)),
-                Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
-                Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+            match eval_mode {
+                EvalMode::Typeck => {
+                    match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
+                        // NOTE(eddyb) `val` contains no lifetimes/types/consts,
+                        // and we use the original type, so nothing from `substs`
+                        // (which may be identity substs, see above),
+                        // can leak through `val` into the const we return.
+                        Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
+                        Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
+                        Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+                    }
+                }
+                EvalMode::Mir => {
+                    match tcx.const_eval_resolve(param_env, unevaluated, None) {
+                        // NOTE(eddyb) `val` contains no lifetimes/types/consts,
+                        // and we use the original type, so nothing from `substs`
+                        // (which may be identity substs, see above),
+                        // can leak through `val` into the const we return.
+                        Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
+                        Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
+                        Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+                    }
+                }
             }
         } else {
             None
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 418848f69d7..973dc3dd4a1 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -1,4 +1,6 @@
 use super::ScalarInt;
+use crate::mir::interpret::{AllocId, Scalar};
+use crate::ty::{self, Ty, TyCtxt};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 
 #[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
@@ -50,4 +52,61 @@ impl<'tcx> ValTree<'tcx> {
             _ => bug!("expected branch, got {:?}", self),
         }
     }
+
+    pub fn from_raw_bytes<'a>(tcx: TyCtxt<'tcx>, bytes: &'a [u8]) -> Self {
+        let branches = bytes.iter().map(|b| Self::Leaf(ScalarInt::from(*b)));
+        let interned = tcx.arena.alloc_from_iter(branches);
+
+        Self::Branch(interned)
+    }
+
+    pub fn from_scalar_int(i: ScalarInt) -> Self {
+        Self::Leaf(i)
+    }
+
+    pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
+        self.try_to_scalar_int().map(Scalar::Int)
+    }
+
+    pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
+        match self {
+            Self::Leaf(s) => Some(s),
+            Self::Branch(_) => None,
+        }
+    }
+
+    pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+        self.try_to_scalar_int().map(|s| s.try_to_machine_usize(tcx).ok()).flatten()
+    }
+
+    /// Get the values inside the ValTree as a slice of bytes. This only works for
+    /// constants with types &str and &[u8].
+    pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> {
+        match ty.kind() {
+            ty::Ref(_, inner_ty, _) => match inner_ty.kind() {
+                ty::Str => {
+                    let leafs = self
+                        .unwrap_branch()
+                        .into_iter()
+                        .map(|v| v.unwrap_leaf().try_to_u8().unwrap())
+                        .collect::<Vec<_>>();
+
+                    return Some(tcx.arena.alloc_from_iter(leafs.into_iter()));
+                }
+                ty::Slice(slice_ty) if *slice_ty == tcx.types.u8 => {
+                    let leafs = self
+                        .unwrap_branch()
+                        .into_iter()
+                        .map(|v| v.unwrap_leaf().try_to_u8().unwrap())
+                        .collect::<Vec<_>>();
+
+                    return Some(tcx.arena.alloc_from_iter(leafs.into_iter()));
+                }
+                _ => {}
+            },
+            _ => {}
+        }
+
+        None
+    }
 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 610234d45ce..85d9b6c17d2 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -8,7 +8,7 @@ use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
 use crate::middle::resolve_lifetime;
 use crate::middle::stability;
-use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
+use crate::mir::interpret::{self, Allocation, ConstAllocation};
 use crate::mir::{
     Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
 };
@@ -902,7 +902,7 @@ impl<'tcx> CanonicalUserType<'tcx> {
                             _ => false,
                         },
 
-                        GenericArgKind::Const(ct) => match ct.val() {
+                        GenericArgKind::Const(ct) => match ct.kind() {
                             ty::ConstKind::Bound(debruijn, b) => {
                                 // We only allow a `ty::INNERMOST` index in substitutions.
                                 assert_eq!(debruijn, ty::INNERMOST);
@@ -991,7 +991,7 @@ impl<'tcx> CommonConsts<'tcx> {
 
         CommonConsts {
             unit: mk_const(ty::ConstS {
-                val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::ZST)),
+                kind: ty::ConstKind::Value(ty::ValTree::zst()),
                 ty: types.unit,
             }),
         }
@@ -1300,7 +1300,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ) -> Const<'tcx> {
         let reported = self.sess.delay_span_bug(span, msg);
         self.mk_const(ty::ConstS {
-            val: ty::ConstKind::Error(DelaySpanBugEmitted { reported, _priv: () }),
+            kind: ty::ConstKind::Error(DelaySpanBugEmitted { reported, _priv: () }),
             ty,
         })
     }
@@ -1550,7 +1550,7 @@ impl<'tcx> TyCtxt<'tcx> {
             Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {}
             Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {}
             Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {}
-            Node::Expr(&hir::Expr { kind: ExprKind::Closure(..), .. }) => {}
+            Node::Expr(&hir::Expr { kind: ExprKind::Closure { .. }, .. }) => {}
             _ => return None,
         }
 
@@ -2467,7 +2467,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline]
     pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
-        self.mk_const(ty::ConstS { val: ty::ConstKind::Infer(InferConst::Var(v)), ty })
+        self.mk_const(ty::ConstS { kind: ty::ConstKind::Infer(InferConst::Var(v)), ty })
     }
 
     #[inline]
@@ -2487,7 +2487,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline]
     pub fn mk_const_infer(self, ic: InferConst<'tcx>, ty: Ty<'tcx>) -> ty::Const<'tcx> {
-        self.mk_const(ty::ConstS { val: ty::ConstKind::Infer(ic), ty })
+        self.mk_const(ty::ConstS { kind: ty::ConstKind::Infer(ic), ty })
     }
 
     #[inline]
@@ -2497,7 +2497,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline]
     pub fn mk_const_param(self, index: u32, name: Symbol, ty: Ty<'tcx>) -> Const<'tcx> {
-        self.mk_const(ty::ConstS { val: ty::ConstKind::Param(ParamConst { index, name }), ty })
+        self.mk_const(ty::ConstS { kind: ty::ConstKind::Param(ParamConst { index, name }), ty })
     }
 
     pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 1acded8c6e4..a84b3c9373b 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -478,7 +478,7 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
     }
 
     fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match c.val() {
+        match c.kind() {
             ConstKind::Infer(..)
             | ConstKind::Bound(..)
             | ConstKind::Placeholder(..)
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index a6c14ea0de3..812dd2adc2e 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -254,7 +254,7 @@ impl<'tcx> Ty<'tcx> {
                 }
 
                 let n = tcx.lift(n).unwrap();
-                if let ty::ConstKind::Value(v) = n.val() {
+                if let ty::ConstKind::Value(v) = n.kind() {
                     if let Some(n) = v.try_to_machine_usize(tcx) {
                         return format!("array of {} element{}", n, pluralize!(n)).into();
                     }
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 208cd9ba16a..a8145e6820c 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -363,7 +363,7 @@ impl DeepRejectCtxt {
     }
 
     pub fn consts_may_unify(self, obligation_ct: ty::Const<'_>, impl_ct: ty::Const<'_>) -> bool {
-        match impl_ct.val() {
+        match impl_ct.kind() {
             ty::ConstKind::Param(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
                 return true;
             }
@@ -373,8 +373,8 @@ impl DeepRejectCtxt {
             }
         }
 
-        let k = impl_ct.val();
-        match obligation_ct.val() {
+        let k = impl_ct.kind();
+        match obligation_ct.kind() {
             ty::ConstKind::Param(_) => match self.treat_obligation_params {
                 TreatParams::AsPlaceholder => false,
                 TreatParams::AsInfer => true,
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 7a3d615862c..ea6bb8a7abd 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -288,7 +288,7 @@ impl FlagComputation {
 
     fn add_const(&mut self, c: ty::Const<'_>) {
         self.add_ty(c.ty());
-        match c.val() {
+        match c.kind() {
             ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated),
             ty::ConstKind::Infer(infer) => {
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 5ccf735f1d2..99aa182f3a6 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -718,7 +718,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => {
                 let ct = (self.fld_c)(bound_const, ct.ty());
                 ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32())
@@ -865,7 +865,7 @@ impl<'tcx> TyCtxt<'tcx> {
             },
             |c, ty| {
                 self.mk_const(ty::ConstS {
-                    val: ty::ConstKind::Bound(
+                    kind: ty::ConstKind::Bound(
                         ty::INNERMOST,
                         ty::BoundVar::from_usize(c.as_usize() + bound_vars),
                     ),
@@ -1118,13 +1118,13 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.val() {
+        if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind() {
             if self.amount == 0 || debruijn < self.current_index {
                 ct
             } else {
                 let debruijn = debruijn.shifted_in(self.amount);
                 self.tcx.mk_const(ty::ConstS {
-                    val: ty::ConstKind::Bound(debruijn, bound_ct),
+                    kind: ty::ConstKind::Bound(debruijn, bound_ct),
                     ty: ct.ty(),
                 })
             }
@@ -1234,7 +1234,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
         // otherwise we do want to remember to visit the rest of the
         // const, as it has types/regions embedded in a lot of other
         // places.
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
                 ControlFlow::Break(FoundEscapingVars)
             }
@@ -1389,7 +1389,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
         // ignore the inputs of an unevaluated const, as they may not appear
         // in the normalized form
         if self.just_constrained {
-            if let ty::ConstKind::Unevaluated(..) = c.val() {
+            if let ty::ConstKind::Unevaluated(..) = c.kind() {
                 return ControlFlow::CONTINUE;
             }
         }
@@ -1434,7 +1434,7 @@ impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
     }
 
     fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if let ty::ConstKind::Placeholder(placeholder) = c.val() {
+        if let ty::ConstKind::Placeholder(placeholder) = c.kind() {
             self.max_universe = ty::UniverseIndex::from_u32(
                 self.max_universe.as_u32().max(placeholder.universe.as_u32()),
             );
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index b7130e69f35..e8dd179eac1 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -369,7 +369,6 @@ impl<'tcx> Instance<'tcx> {
     }
 
     // This should be kept up to date with `resolve`.
-    #[instrument(level = "debug", skip(tcx))]
     pub fn resolve_opt_const_arg(
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7f0f3755c4b..b386ed68dd2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -42,7 +42,7 @@ use rustc_query_system::ich::StableHashingContext;
 use rustc_session::cstore::CrateStoreDyn;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
-use rustc_target::abi::Align;
+use rustc_target::abi::{Align, VariantIdx};
 pub use subst::*;
 pub use vtable::*;
 
@@ -2161,22 +2161,28 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
+    #[instrument(skip(self), level = "debug")]
     pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
         match instance {
-            ty::InstanceDef::Item(def) => match self.def_kind(def.did) {
-                DefKind::Const
-                | DefKind::Static(..)
-                | DefKind::AssocConst
-                | DefKind::Ctor(..)
-                | DefKind::AnonConst
-                | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
-                // If the caller wants `mir_for_ctfe` of a function they should not be using
-                // `instance_mir`, so we'll assume const fn also wants the optimized version.
-                _ => {
-                    assert_eq!(def.const_param_did, None);
-                    self.optimized_mir(def.did)
+            ty::InstanceDef::Item(def) => {
+                debug!("calling def_kind on def: {:?}", def);
+                let def_kind = self.def_kind(def.did);
+                debug!("returned from def_kind: {:?}", def_kind);
+                match def_kind {
+                    DefKind::Const
+                    | DefKind::Static(..)
+                    | DefKind::AssocConst
+                    | DefKind::Ctor(..)
+                    | DefKind::AnonConst
+                    | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
+                    // If the caller wants `mir_for_ctfe` of a function they should not be using
+                    // `instance_mir`, so we'll assume const fn also wants the optimized version.
+                    _ => {
+                        assert_eq!(def.const_param_did, None);
+                        self.optimized_mir(def.did)
+                    }
                 }
-            },
+            }
             ty::InstanceDef::VtableShim(..)
             | ty::InstanceDef::ReifyShim(..)
             | ty::InstanceDef::Intrinsic(..)
@@ -2447,3 +2453,10 @@ pub struct FoundRelationships {
     /// _>::AssocType = ?T`
     pub output: bool,
 }
+
+/// The constituent parts of a type level constant of kind ADT or array.
+#[derive(Copy, Clone, Debug, HashStable)]
+pub struct DestructuredConst<'tcx> {
+    pub variant: Option<VariantIdx>,
+    pub fields: &'tcx [ty::Const<'tcx>],
+}
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 5ad93d77820..7ae23d371e5 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -302,6 +302,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'_> {
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
     type Output = P::Type;
     type Error = P::Error;
+
     fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
         cx.print_type(*self)
     }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 53a97a46b2d..58dab0f96ab 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,4 +1,4 @@
-use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar};
+use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
 use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
 use crate::ty::{
     self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable,
@@ -748,14 +748,14 @@ pub trait PrettyPrinter<'tcx>:
                 p!("[", print(ty), "; ");
                 if self.tcx().sess.verbose() {
                     p!(write("{:?}", sz));
-                } else if let ty::ConstKind::Unevaluated(..) = sz.val() {
+                } else if let ty::ConstKind::Unevaluated(..) = sz.kind() {
                     // Do not try to evaluate unevaluated constants. If we are const evaluating an
                     // array length anon const, rustc will (with debug assertions) print the
                     // constant's path. Which will end up here again.
                     p!("_");
-                } else if let Some(n) = sz.val().try_to_bits(self.tcx().data_layout.pointer_size) {
+                } else if let Some(n) = sz.kind().try_to_bits(self.tcx().data_layout.pointer_size) {
                     p!(write("{}", n));
-                } else if let ty::ConstKind::Param(param) = sz.val() {
+                } else if let ty::ConstKind::Param(param) = sz.kind() {
                     p!(print(param));
                 } else {
                     p!("_");
@@ -1165,7 +1165,7 @@ pub trait PrettyPrinter<'tcx>:
         define_scoped_cx!(self);
 
         if self.tcx().sess.verbose() {
-            p!(write("Const({:?}: {:?})", ct.val(), ct.ty()));
+            p!(write("Const({:?}: {:?})", ct.kind(), ct.ty()));
             return Ok(self);
         }
 
@@ -1186,7 +1186,7 @@ pub trait PrettyPrinter<'tcx>:
             }};
         }
 
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Unevaluated(ty::Unevaluated {
                 def,
                 substs,
@@ -1224,7 +1224,7 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
             ty::ConstKind::Value(value) => {
-                return self.pretty_print_const_value(value, ct.ty(), print_ty);
+                return self.pretty_print_const_valtree(value, ct.ty(), print_ty);
             }
 
             ty::ConstKind::Bound(debruijn, bound_var) => {
@@ -1262,7 +1262,7 @@ pub trait PrettyPrinter<'tcx>:
             ty::Ref(_, inner, _) => {
                 if let ty::Array(elem, len) = inner.kind() {
                     if let ty::Uint(ty::UintTy::U8) = elem.kind() {
-                        if let ty::ConstKind::Value(ConstValue::Scalar(int)) = len.val() {
+                        if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() {
                             match self.tcx().get_global_alloc(alloc_id) {
                                 Some(GlobalAlloc::Memory(alloc)) => {
                                     let len = int.assert_bits(self.tcx().data_layout.pointer_size);
@@ -1408,85 +1408,62 @@ pub trait PrettyPrinter<'tcx>:
         Ok(self)
     }
 
-    fn pretty_print_const_value(
+    fn pretty_print_const_valtree(
         mut self,
-        ct: ConstValue<'tcx>,
+        valtree: ty::ValTree<'tcx>,
         ty: Ty<'tcx>,
         print_ty: bool,
     ) -> Result<Self::Const, Self::Error> {
         define_scoped_cx!(self);
 
         if self.tcx().sess.verbose() {
-            p!(write("ConstValue({:?}: ", ct), print(ty), ")");
+            p!(write("ValTree({:?}: ", valtree), print(ty), ")");
             return Ok(self);
         }
 
         let u8_type = self.tcx().types.u8;
-
-        match (ct, ty.kind()) {
-            // Byte/string slices, printed as (byte) string literals.
-            (ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => {
-                match inner.kind() {
-                    ty::Slice(t) => {
-                        if *t == u8_type {
-                            // The `inspect` here is okay since we checked the bounds, and there are
-                            // no relocations (we have an active slice reference here). We don't use
-                            // this result to affect interpreter execution.
-                            let byte_str = data
-                                .inner()
-                                .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
-                            return self.pretty_print_byte_str(byte_str);
-                        }
-                    }
-                    ty::Str => {
-                        // The `inspect` here is okay since we checked the bounds, and there are no
-                        // relocations (we have an active `str` reference here). We don't use this
-                        // result to affect interpreter execution.
-                        let slice = data
-                            .inner()
-                            .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
-                        p!(write("{:?}", String::from_utf8_lossy(slice)));
-                        return Ok(self);
-                    }
-                    _ => {}
+        match (valtree, ty.kind()) {
+            (ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
+                ty::Slice(t) if *t == u8_type => {
+                    let bytes = valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
+                        bug!(
+                            "expected to convert valtree {:?} to raw bytes for type {:?}",
+                            valtree,
+                            t
+                        )
+                    });
+                    return self.pretty_print_byte_str(bytes);
                 }
-            }
-            (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
-                let n = n.val().try_to_bits(self.tcx().data_layout.pointer_size).unwrap();
-                // cast is ok because we already checked for pointer size (32 or 64 bit) above
-                let range = AllocRange { start: offset, size: Size::from_bytes(n) };
-
-                let byte_str = alloc.inner().get_bytes(&self.tcx(), range).unwrap();
+                ty::Str => {
+                    let bytes = valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
+                        bug!("expected to convert valtree to raw bytes for type {:?}", ty)
+                    });
+                    p!(write("{:?}", String::from_utf8_lossy(bytes)));
+                    return Ok(self);
+                }
+                _ => {}
+            },
+            (ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => {
+                let bytes = valtree.try_to_raw_bytes(self.tcx(), *t).unwrap_or_else(|| {
+                    bug!("expected to convert valtree to raw bytes for type {:?}", t)
+                });
                 p!("*");
-                p!(pretty_print_byte_str(byte_str));
+                p!(pretty_print_byte_str(bytes));
                 return Ok(self);
             }
-
             // Aggregates, printed as array/tuple/struct/variant construction syntax.
-            //
-            // NB: the `has_param_types_or_consts` check ensures that we can use
-            // 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)
-            //
-            // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
-            // correct `ty::ParamEnv` to allow printing *all* constant values.
-            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
+            (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
                 let Some(contents) = self.tcx().try_destructure_const(
-                    ty::ParamEnv::reveal_all()
-                        .and(self.tcx().mk_const(ty::ConstS { val: ty::ConstKind::Value(ct), ty })),
+                    ty::Const::from_value(self.tcx(), valtree, ty)
                 ) else {
                     // Fall back to debug pretty printing for invalid constants.
-                    p!(write("{:?}", ct));
+                    p!(write("{:?}", valtree));
                     if print_ty {
                         p!(": ", print(ty));
                     }
                     return Ok(self);
                 };
-
                 let fields = contents.fields.iter().copied();
-
                 match *ty.kind() {
                     ty::Array(..) => {
                         p!("[", comma_sep(fields), "]");
@@ -1513,7 +1490,6 @@ pub trait PrettyPrinter<'tcx>:
                             contents.variant.expect("destructed const of adt without variant idx");
                         let variant_def = &def.variant(variant_idx);
                         p!(print_value_path(variant_def.def_id, substs));
-
                         match variant_def.ctor_kind {
                             CtorKind::Const => {}
                             CtorKind::Fn => {
@@ -1535,21 +1511,22 @@ pub trait PrettyPrinter<'tcx>:
                     }
                     _ => unreachable!(),
                 }
-
                 return Ok(self);
             }
-
-            (ConstValue::Scalar(scalar), _) => {
-                return self.pretty_print_const_scalar(scalar, ty, print_ty);
+            (ty::ValTree::Leaf(leaf), _) => {
+                return self.pretty_print_const_scalar_int(leaf, ty, print_ty);
             }
-
             // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
             // their fields instead of just dumping the memory.
             _ => {}
         }
 
         // fallback
-        p!(write("{:?}", ct));
+        if valtree == ty::ValTree::zst() {
+            p!(write("<ZST>"));
+        } else {
+            p!(write("{:?}", valtree));
+        }
         if print_ty {
             p!(": ", print(ty));
         }
@@ -2296,7 +2273,6 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         Ok(inner)
     }
 
-    #[instrument(skip(self), level = "debug")]
     fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
     where
         T: TypeFoldable<'tcx>,
@@ -2309,7 +2285,6 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
             type BreakTy = ();
 
-            #[instrument(skip(self), level = "trace")]
             fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
                 trace!("address: {:p}", r.0.0);
                 if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
@@ -2326,7 +2301,6 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
 
             // We collect types in order to prevent really large types from compiling for
             // a really long time. See issue #83150 for why this is necessary.
-            #[instrument(skip(self), level = "trace")]
             fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 let not_previously_inserted = self.type_collector.insert(ty);
                 if not_previously_inserted {
@@ -2353,6 +2327,7 @@ where
 {
     type Output = P;
     type Error = P::Error;
+
     fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
         cx.in_binder(self)
     }
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 8677405eebe..51980acd38f 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -4,7 +4,6 @@
 //! types or regions but can be other things. Examples of type relations are
 //! subtyping, type equality, etc.
 
-use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar};
 use crate::ty::error::{ExpectedFound, TypeError};
 use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
 use crate::ty::{self, ImplSubject, Term, Ty, TyCtxt, TypeFoldable};
@@ -579,10 +578,15 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
     debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
     let tcx = relation.tcx();
 
-    // FIXME(oli-obk): once const generics can have generic types, this assertion
-    // will likely get triggered. Move to `normalize_erasing_regions` at that point.
-    let a_ty = tcx.erase_regions(a.ty());
-    let b_ty = tcx.erase_regions(b.ty());
+    let a_ty;
+    let b_ty;
+    if relation.tcx().features().adt_const_params {
+        a_ty = tcx.normalize_erasing_regions(relation.param_env(), a.ty());
+        b_ty = tcx.normalize_erasing_regions(relation.param_env(), b.ty());
+    } else {
+        a_ty = tcx.erase_regions(a.ty());
+        b_ty = tcx.erase_regions(b.ty());
+    }
     if a_ty != b_ty {
         relation.tcx().sess.delay_span_bug(
             DUMMY_SP,
@@ -597,7 +601,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
     // Currently, the values that can be unified are primitive types,
     // and those that derive both `PartialEq` and `Eq`, corresponding
     // to structural-match types.
-    let is_match = match (a.val(), b.val()) {
+    let is_match = match (a.kind(), b.kind()) {
         (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
             // The caller should handle these cases!
             bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
@@ -608,9 +612,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
 
         (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index,
         (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
-        (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
-            check_const_value_eq(relation, a_val, b_val, a, b)?
-        }
+        (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val,
 
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
             if tcx.features().generic_const_exprs =>
@@ -631,7 +633,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
                 bu.substs,
             )?;
             return Ok(tcx.mk_const(ty::ConstS {
-                val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                     def: au.def,
                     substs,
                     promoted: au.promoted,
@@ -644,66 +646,6 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
     if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) }
 }
 
-fn check_const_value_eq<'tcx, R: TypeRelation<'tcx>>(
-    relation: &mut R,
-    a_val: ConstValue<'tcx>,
-    b_val: ConstValue<'tcx>,
-    // FIXME(oli-obk): these arguments should go away with valtrees
-    a: ty::Const<'tcx>,
-    b: ty::Const<'tcx>,
-    // FIXME(oli-obk): this should just be `bool` with valtrees
-) -> RelateResult<'tcx, bool> {
-    let tcx = relation.tcx();
-    Ok(match (a_val, b_val) {
-        (ConstValue::Scalar(Scalar::Int(a_val)), ConstValue::Scalar(Scalar::Int(b_val))) => {
-            a_val == b_val
-        }
-        (
-            ConstValue::Scalar(Scalar::Ptr(a_val, _a_size)),
-            ConstValue::Scalar(Scalar::Ptr(b_val, _b_size)),
-        ) => {
-            a_val == b_val
-                || match (tcx.global_alloc(a_val.provenance), tcx.global_alloc(b_val.provenance)) {
-                    (GlobalAlloc::Function(a_instance), GlobalAlloc::Function(b_instance)) => {
-                        a_instance == b_instance
-                    }
-                    _ => false,
-                }
-        }
-
-        (ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
-            get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val)
-        }
-
-        (ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. })
-            if a.ty().is_ref() || b.ty().is_ref() =>
-        {
-            if a.ty().is_ref() && b.ty().is_ref() {
-                alloc_a == alloc_b
-            } else {
-                false
-            }
-        }
-        (ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
-            let a_destructured = tcx.destructure_const(relation.param_env().and(a));
-            let b_destructured = tcx.destructure_const(relation.param_env().and(b));
-
-            // Both the variant and each field have to be equal.
-            if a_destructured.variant == b_destructured.variant {
-                for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) {
-                    relation.consts(*a_field, *b_field)?;
-                }
-
-                true
-            } else {
-                false
-            }
-        }
-
-        _ => false,
-    })
-}
-
 impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 9759bec996e..961792260e4 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -1148,9 +1148,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Const<'tcx> {
         folder: &mut F,
     ) -> Result<Self, F::Error> {
         let ty = self.ty().try_fold_with(folder)?;
-        let val = self.val().try_fold_with(folder)?;
-        if ty != self.ty() || val != self.val() {
-            Ok(folder.tcx().mk_const(ty::ConstS { ty, val }))
+        let kind = self.kind().try_fold_with(folder)?;
+        if ty != self.ty() || kind != self.kind() {
+            Ok(folder.tcx().mk_const(ty::ConstS { ty, kind }))
         } else {
             Ok(self)
         }
@@ -1158,7 +1158,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Const<'tcx> {
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
         self.ty().visit_with(visitor)?;
-        self.val().visit_with(visitor)
+        self.kind().visit_with(visitor)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 1ae16a9015a..ca29dd7c08f 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -571,7 +571,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
     }
 
     fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if let ty::ConstKind::Param(p) = c.val() {
+        if let ty::ConstKind::Param(p) = c.kind() {
             self.const_for_param(p, c)
         } else {
             c.super_fold_with(self)
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 22cb46a4cbc..33ef0283745 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -450,7 +450,7 @@ impl<'tcx> TyCtxt<'tcx> {
                         // Error: not a type param
                         _ => false,
                     },
-                    GenericArgKind::Const(ct) => match ct.val() {
+                    GenericArgKind::Const(ct) => match ct.kind() {
                         ty::ConstKind::Param(ref pc) => {
                             !impl_generics.const_param(pc, self).pure_wrt_drop
                         }
@@ -492,7 +492,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     }
                     _ => return Err(NotUniqueParam::NotParam(t.into())),
                 },
-                GenericArgKind::Const(c) => match c.val() {
+                GenericArgKind::Const(c) => match c.kind() {
                     ty::ConstKind::Param(p) => {
                         if !seen.insert(p.index) {
                             return Err(NotUniqueParam::DuplicateParam(c.into()));
@@ -1127,7 +1127,7 @@ pub fn needs_drop_components<'tcx>(
         ty::Array(elem_ty, size) => {
             match needs_drop_components(*elem_ty, target_layout) {
                 Ok(v) if v.is_empty() => Ok(v),
-                res => match size.val().try_to_bits(target_layout.pointer_size) {
+                res => match size.kind().try_to_bits(target_layout.pointer_size) {
                     // Arrays of size zero don't need drop, even if their element
                     // type does.
                     Some(0) => Ok(SmallVec::new()),
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 09946f02448..02fe1f3a7bd 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -190,7 +190,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
         GenericArgKind::Lifetime(_) => {}
         GenericArgKind::Const(parent_ct) => {
             stack.push(parent_ct.ty().into());
-            match parent_ct.val() {
+            match parent_ct.kind() {
                 ty::ConstKind::Infer(_)
                 | ty::ConstKind::Param(_)
                 | ty::ConstKind::Placeholder(_)
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 035e94eecee..3d6e50f0c06 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -1,12 +1,16 @@
 //! See docs in build/expr/mod.rs
 
-use crate::build::{lit_to_mir_constant, Builder};
+use crate::build::{parse_float_into_constval, Builder};
+use rustc_ast as ast;
 use rustc_hir::def_id::DefId;
-use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar};
+use rustc_middle::mir::interpret::{
+    Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
+};
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
+use rustc_target::abi::Size;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, yielding a compile-time constant. Assumes that
@@ -15,7 +19,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let create_uneval_from_def_id =
             |tcx: TyCtxt<'tcx>, def_id: DefId, ty: Ty<'tcx>, substs: SubstsRef<'tcx>| {
                 let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
-                tcx.mk_const(ty::ConstS { val: ty::ConstKind::Unevaluated(uneval), ty })
+                tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Unevaluated(uneval), ty })
             };
 
         let this = self;
@@ -64,7 +68,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
             ExprKind::ConstParam { param, def_id: _ } => {
                 let const_param =
-                    tcx.mk_const(ty::ConstS { val: ty::ConstKind::Param(param), ty: expr.ty });
+                    tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Param(param), ty: expr.ty });
                 let literal = ConstantKind::Ty(const_param);
 
                 Constant { user_ty: None, span, literal }
@@ -84,3 +88,54 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 }
+
+#[instrument(skip(tcx, lit_input))]
+pub(crate) fn lit_to_mir_constant<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    lit_input: LitToConstInput<'tcx>,
+) -> Result<ConstantKind<'tcx>, LitToConstError> {
+    let LitToConstInput { lit, ty, neg } = lit_input;
+    let trunc = |n| {
+        let param_ty = ty::ParamEnv::reveal_all().and(ty);
+        let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
+        trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
+        let result = width.truncate(n);
+        trace!("trunc result: {}", result);
+        Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
+    };
+
+    let value = match (lit, &ty.kind()) {
+        (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
+            let s = s.as_str();
+            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
+            let allocation = tcx.intern_const_alloc(allocation);
+            ConstValue::Slice { data: allocation, start: 0, end: s.len() }
+        }
+        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+            if matches!(inner_ty.kind(), ty::Slice(_)) =>
+        {
+            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
+            let allocation = tcx.intern_const_alloc(allocation);
+            ConstValue::Slice { data: allocation, start: 0, end: data.len() }
+        }
+        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+            let id = tcx.allocate_bytes(data);
+            ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
+        }
+        (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
+            ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
+        }
+        (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
+            trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
+        }
+        (ast::LitKind::Float(n, _), ty::Float(fty)) => {
+            parse_float_into_constval(*n, *fty, neg).ok_or(LitToConstError::Reported)?
+        }
+        (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
+        (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
+        (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
+        _ => return Err(LitToConstError::TypeError),
+    };
+
+    Ok(ConstantKind::Val(value, ty))
+}
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 793066e43c3..e2399818929 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -1,9 +1,10 @@
 use crate::build;
+pub(crate) use crate::build::expr::as_constant::lit_to_mir_constant;
 use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::scope::DropKind;
-use crate::thir::constant::parse_float;
 use crate::thir::pattern::pat_from_hir;
-use rustc_ast as ast;
+use rustc_apfloat::ieee::{Double, Single};
+use rustc_apfloat::Float;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
@@ -14,15 +15,15 @@ use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
 use rustc_middle::middle::region;
-use rustc_middle::mir::interpret::Allocation;
-use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar};
+use rustc_middle::mir::interpret::ConstValue;
+use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeckResults};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use rustc_target::abi::Size;
+use rustc_span::Symbol;
 use rustc_target::spec::abi::Abi;
 
 use super::lints;
@@ -67,8 +68,8 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
 
     // Figure out what primary body this item has.
     let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) {
-        Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, decl, body_id, _, _), .. }) => {
-            (*body_id, decl.output.span(), None)
+        Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { fn_decl, body, .. }, .. }) => {
+            (*body, fn_decl.output.span(), None)
         }
         Node::Item(hir::Item {
             kind: hir::ItemKind::Fn(hir::FnSig { decl, .. }, _, body_id),
@@ -266,57 +267,6 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
     })
 }
 
-#[instrument(skip(tcx, lit_input))]
-pub(crate) fn lit_to_mir_constant<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    lit_input: LitToConstInput<'tcx>,
-) -> Result<ConstantKind<'tcx>, LitToConstError> {
-    let LitToConstInput { lit, ty, neg } = lit_input;
-    let trunc = |n| {
-        let param_ty = ty::ParamEnv::reveal_all().and(ty);
-        let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
-        trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
-        let result = width.truncate(n);
-        trace!("trunc result: {}", result);
-        Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
-    };
-
-    let value = match (lit, &ty.kind()) {
-        (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
-            let s = s.as_str();
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
-            let allocation = tcx.intern_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, start: 0, end: s.len() }
-        }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
-            if matches!(inner_ty.kind(), ty::Slice(_)) =>
-        {
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
-            let allocation = tcx.intern_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, start: 0, end: data.len() }
-        }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
-            let id = tcx.allocate_bytes(data);
-            ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
-        }
-        (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
-            ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
-        }
-        (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
-            trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
-        }
-        (ast::LitKind::Float(n, _), ty::Float(fty)) => {
-            parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)?
-        }
-        (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
-        (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
-        (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
-        _ => return Err(LitToConstError::TypeError),
-    };
-
-    Ok(ConstantKind::Val(value, ty))
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
 
@@ -1137,6 +1087,70 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 }
 
+fn parse_float_into_constval<'tcx>(
+    num: Symbol,
+    float_ty: ty::FloatTy,
+    neg: bool,
+) -> Option<ConstValue<'tcx>> {
+    parse_float_into_scalar(num, float_ty, neg).map(ConstValue::Scalar)
+}
+
+pub(crate) fn parse_float_into_scalar(
+    num: Symbol,
+    float_ty: ty::FloatTy,
+    neg: bool,
+) -> Option<Scalar> {
+    let num = num.as_str();
+    match float_ty {
+        ty::FloatTy::F32 => {
+            let Ok(rust_f) = num.parse::<f32>() else { return None };
+            let mut f = num.parse::<Single>().unwrap_or_else(|e| {
+                panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
+            });
+
+            assert!(
+                u128::from(rust_f.to_bits()) == f.to_bits(),
+                "apfloat::ieee::Single gave different result for `{}`: \
+                 {}({:#x}) vs Rust's {}({:#x})",
+                rust_f,
+                f,
+                f.to_bits(),
+                Single::from_bits(rust_f.to_bits().into()),
+                rust_f.to_bits()
+            );
+
+            if neg {
+                f = -f;
+            }
+
+            Some(Scalar::from_f32(f))
+        }
+        ty::FloatTy::F64 => {
+            let Ok(rust_f) = num.parse::<f64>() else { return None };
+            let mut f = num.parse::<Double>().unwrap_or_else(|e| {
+                panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
+            });
+
+            assert!(
+                u128::from(rust_f.to_bits()) == f.to_bits(),
+                "apfloat::ieee::Double gave different result for `{}`: \
+                 {}({:#x}) vs Rust's {}({:#x})",
+                rust_f,
+                f,
+                f.to_bits(),
+                Double::from_bits(rust_f.to_bits().into()),
+                rust_f.to_bits()
+            );
+
+            if neg {
+                f = -f;
+            }
+
+            Some(Scalar::from_f64(f))
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Builder methods are broken up into modules, depending on what kind
 // of thing is being lowered. Note that they use the `unpack` macro
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index d82e6688633..a7e4403a242 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -1,13 +1,7 @@
-use rustc_apfloat::Float;
 use rustc_ast as ast;
-use rustc_middle::mir::interpret::{
-    Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
-};
-use rustc_middle::ty::{self, ParamEnv, TyCtxt};
-use rustc_span::symbol::Symbol;
-use rustc_target::abi::Size;
+use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
+use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
 
-// FIXME Once valtrees are available, get rid of this function and the query
 pub(crate) fn lit_to_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     lit_input: LitToConstInput<'tcx>,
@@ -20,94 +14,39 @@ pub(crate) fn lit_to_const<'tcx>(
         trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
         let result = width.truncate(n);
         trace!("trunc result: {}", result);
-        Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
+
+        Ok(ScalarInt::try_from_uint(result, width)
+            .unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result)))
     };
 
-    let lit = match (lit, &ty.kind()) {
+    let valtree = match (lit, &ty.kind()) {
         (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
-            let s = s.as_str();
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
-            let allocation = tcx.intern_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, start: 0, end: s.len() }
+            let str_bytes = s.as_str().as_bytes();
+            ty::ValTree::from_raw_bytes(tcx, str_bytes)
         }
         (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
             if matches!(inner_ty.kind(), ty::Slice(_)) =>
         {
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
-            let allocation = tcx.intern_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, start: 0, end: data.len() }
+            let bytes = data as &[u8];
+            ty::ValTree::from_raw_bytes(tcx, bytes)
         }
         (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
-            let id = tcx.allocate_bytes(data);
-            ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
+            let bytes = data as &[u8];
+            ty::ValTree::from_raw_bytes(tcx, bytes)
         }
         (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
-            ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
+            ty::ValTree::from_scalar_int((*n).into())
         }
         (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
-            trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
-        }
-        (ast::LitKind::Float(n, _), ty::Float(fty)) => {
-            parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)?
+            let scalar_int =
+                trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?;
+            ty::ValTree::from_scalar_int(scalar_int)
         }
-        (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
-        (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
+        (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),
+        (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()),
         (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
         _ => return Err(LitToConstError::TypeError),
     };
-    Ok(ty::Const::from_value(tcx, lit, ty))
-}
-
-// FIXME move this to rustc_mir_build::build
-pub(crate) fn parse_float<'tcx>(
-    num: Symbol,
-    fty: ty::FloatTy,
-    neg: bool,
-) -> Option<ConstValue<'tcx>> {
-    let num = num.as_str();
-    use rustc_apfloat::ieee::{Double, Single};
-    let scalar = match fty {
-        ty::FloatTy::F32 => {
-            let Ok(rust_f) = num.parse::<f32>() else { return None };
-            let mut f = num.parse::<Single>().unwrap_or_else(|e| {
-                panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
-            });
-            assert!(
-                u128::from(rust_f.to_bits()) == f.to_bits(),
-                "apfloat::ieee::Single gave different result for `{}`: \
-                 {}({:#x}) vs Rust's {}({:#x})",
-                rust_f,
-                f,
-                f.to_bits(),
-                Single::from_bits(rust_f.to_bits().into()),
-                rust_f.to_bits()
-            );
-            if neg {
-                f = -f;
-            }
-            Scalar::from_f32(f)
-        }
-        ty::FloatTy::F64 => {
-            let Ok(rust_f) = num.parse::<f64>() else { return None };
-            let mut f = num.parse::<Double>().unwrap_or_else(|e| {
-                panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
-            });
-            assert!(
-                u128::from(rust_f.to_bits()) == f.to_bits(),
-                "apfloat::ieee::Double gave different result for `{}`: \
-                 {}({:#x}) vs Rust's {}({:#x})",
-                rust_f,
-                f,
-                f.to_bits(),
-                Double::from_bits(rust_f.to_bits().into()),
-                rust_f.to_bits()
-            );
-            if neg {
-                f = -f;
-            }
-            Scalar::from_f64(f)
-        }
-    };
 
-    Some(ConstValue::Scalar(scalar))
+    Ok(ty::Const::from_value(tcx, valtree, ty))
 }
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index fb2f5861c6f..b5f3cd828a0 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -418,7 +418,7 @@ impl<'tcx> Cx<'tcx> {
                 }
             },
 
-            hir::ExprKind::Closure(..) => {
+            hir::ExprKind::Closure { .. } => {
                 let closure_ty = self.typeck_results().expr_ty(expr);
                 let (def_id, substs, movability) = match *closure_ty.kind() {
                     ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index f694e009ab9..845be2ab264 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -371,6 +371,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
             }
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
                 let destructured = tcx.destructure_mir_constant(param_env, cv);
+
                 PatKind::Variant {
                     adt_def: *adt_def,
                     substs,
@@ -502,7 +503,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
                 // deref pattern.
                 _ => {
                     if !pointee_ty.is_sized(tcx.at(span), param_env) {
-                        // `tcx.deref_const()` below will ICE with an unsized type
+                        // `tcx.deref_mir_constant()` below will ICE with an unsized type
                         // (except slices, which are handled in a separate arm above).
                         let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
                         if self.include_lint_checks {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index b7de3f28872..26532ae33d0 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -153,7 +153,7 @@ impl IntRange {
                             return None;
                         }
                     }
-                    mir::ConstantKind::Ty(c) => match c.val() {
+                    mir::ConstantKind::Ty(c) => match c.kind() {
                         ty::ConstKind::Value(_) => bug!(
                             "encountered ConstValue in mir::ConstantKind::Ty, whereas this is expected to be in ConstantKind::Val"
                         ),
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 417cf0f89c4..f5d957e30ff 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -185,11 +185,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             }
             (Some(PatKind::Constant { value: lo }), None) => {
                 let hi = ty.numeric_max_val(self.tcx)?;
-                Some((*lo, hi.into()))
+                Some((*lo, mir::ConstantKind::from_const(hi, self.tcx)))
             }
             (None, Some(PatKind::Constant { value: hi })) => {
                 let lo = ty.numeric_min_val(self.tcx)?;
-                Some((lo.into(), *hi))
+                Some((mir::ConstantKind::from_const(lo, self.tcx), *hi))
             }
             _ => None,
         }
@@ -553,7 +553,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
         match value {
             mir::ConstantKind::Ty(c) => {
-                match c.val() {
+                match c.kind() {
                     ConstKind::Param(_) => {
                         self.errors.push(PatternError::ConstParamInPattern(span));
                         return PatKind::Wild;
@@ -798,11 +798,12 @@ pub(crate) fn compare_const_vals<'tcx>(
     if let ty::Str = ty.kind() && let (
         Some(a_val @ ConstValue::Slice { .. }),
         Some(b_val @ ConstValue::Slice { .. }),
-    ) = (a.try_val(), b.try_val())
+    ) = (a.try_to_value(tcx), b.try_to_value(tcx))
     {
         let a_bytes = get_slice_bytes(&tcx, a_val);
         let b_bytes = get_slice_bytes(&tcx, b_val);
         return from_bool(a_bytes == b_bytes);
     }
+
     fallback()
 }
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index ffd7e3cd06b..a0c70a3fd81 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -18,6 +18,5 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_serialize = { path = "../rustc_serialize" }
-rustc_session = { path = "../rustc_session" }
 rustc_target = { path = "../rustc_target" }
 rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 027af5b9c1f..8d16c5f22c3 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -1032,7 +1032,7 @@ where
         Operand::Constant(Box::new(Constant {
             span: self.source_info.span,
             user_ty: None,
-            literal: ty::Const::from_usize(self.tcx(), val.into()).into(),
+            literal: ConstantKind::from_usize(self.tcx(), val.into()),
         }))
     }
 
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index 4c1a7eaf6f0..8a8098e9ab9 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -19,7 +19,6 @@ rustc_index = { path = "../rustc_index" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_const_eval = { path = "../rustc_const_eval" }
 rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
-rustc_query_system = { path = "../rustc_query_system" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs
index 3577b3d2d80..8944ebed9a7 100644
--- a/compiler/rustc_mir_transform/src/const_debuginfo.rs
+++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs
@@ -19,7 +19,7 @@ impl<'tcx> MirPass<'tcx> for ConstDebugInfo {
         sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() > 0
     }
 
-    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("running ConstDebugInfo on {:?}", body.source);
 
         for (local, constant) in find_optimization_oportunities(body) {
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index b17485fd542..412a5b4fc91 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -67,6 +67,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
         true
     }
 
+    #[instrument(skip(self, tcx), level = "debug")]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // will be evaluated by miri and produce its errors there
         if body.source.promoted.is_some() {
@@ -687,7 +688,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         Operand::Constant(Box::new(Constant {
             span,
             user_ty: None,
-            literal: ty::Const::from_scalar(self.tcx, scalar, ty).into(),
+            literal: ConstantKind::from_scalar(self.tcx, scalar, ty),
         }))
     }
 
@@ -699,7 +700,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     ) {
         if let Rvalue::Use(Operand::Constant(c)) = rval {
             match c.literal {
-                ConstantKind::Ty(c) if matches!(c.val(), ConstKind::Unevaluated(..)) => {}
+                ConstantKind::Ty(c) if matches!(c.kind(), ConstKind::Unevaluated(..)) => {}
                 _ => {
                     trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
                     return;
@@ -765,20 +766,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                             if let Some(Some(alloc)) = alloc {
                                 // Assign entire constant in a single statement.
                                 // We can't use aggregates, as we run after the aggregate-lowering `MirPhase`.
+                                let const_val = ConstValue::ByRef { alloc, offset: Size::ZERO };
+                                let literal = ConstantKind::Val(const_val, ty);
                                 *rval = Rvalue::Use(Operand::Constant(Box::new(Constant {
                                     span: source_info.span,
                                     user_ty: None,
-                                    literal: self
-                                        .ecx
-                                        .tcx
-                                        .mk_const(ty::ConstS {
-                                            ty,
-                                            val: ty::ConstKind::Value(ConstValue::ByRef {
-                                                alloc,
-                                                offset: Size::ZERO,
-                                            }),
-                                        })
-                                        .into(),
+                                    literal,
                                 })));
                             }
                         }
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 84fdb136bd4..15ad13009e5 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -474,7 +474,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 let err = ConstEvalErr::new(&self.ecx, error, Some(c.span));
                 if let Some(lint_root) = self.lint_root(source_info) {
                     let lint_only = match c.literal {
-                        ConstantKind::Ty(ct) => match ct.val() {
+                        ConstantKind::Ty(ct) => match ct.kind() {
                             // Promoteds must lint and not error as the user didn't ask for them
                             ConstKind::Unevaluated(ty::Unevaluated {
                                 def: _,
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 8a9f2107316..e0e27c53f18 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -470,7 +470,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         Rvalue::Use(Operand::Constant(Box::new(Constant {
             span,
             user_ty: None,
-            literal: ty::Const::from_bool(self.tcx, val).into(),
+            literal: ConstantKind::from_bool(self.tcx, val),
         })))
     }
 
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 89895fddd0c..f3c67319596 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -991,7 +991,7 @@ fn insert_panic_block<'tcx>(
         cond: Operand::Constant(Box::new(Constant {
             span: body.span,
             user_ty: None,
-            literal: ty::Const::from_bool(tcx, false).into(),
+            literal: ConstantKind::from_bool(tcx, false),
         })),
         expected: true,
         msg: message,
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index a1490d77ccb..49403ba03a4 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -614,7 +614,7 @@ impl<'tcx> Inliner<'tcx> {
                 caller_body.required_consts.extend(
                     callee_body.required_consts.iter().copied().filter(|&ct| {
                         match ct.literal.const_for_ty() {
-                            Some(ct) => matches!(ct.val(), ConstKind::Unevaluated(_)),
+                            Some(ct) => matches!(ct.kind(), ConstKind::Unevaluated(_)),
                             None => true,
                         }
                     }),
diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 4fbb7643378..ea10ec5f25c 100644
--- a/compiler/rustc_mir_transform/src/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -3,8 +3,8 @@
 use crate::MirPass;
 use rustc_hir::Mutability;
 use rustc_middle::mir::{
-    BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
-    Statement, StatementKind, Terminator, TerminatorKind, UnOp,
+    BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
+    SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
 };
 use rustc_middle::ty::{self, TyCtxt};
 
@@ -129,8 +129,8 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
                     return;
                 }
 
-                let constant =
-                    Constant { span: source_info.span, literal: len.into(), user_ty: None };
+                let literal = ConstantKind::from_const(len, self.tcx);
+                let constant = Constant { span: source_info.span, literal, user_ty: None };
                 *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
             }
         }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 0e52da57e60..b8932251465 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -531,8 +531,10 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
         None => {}
         Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
     }
+    debug!("about to call mir_drops_elaborated...");
     let mut body =
         tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
+    debug!("body: {:#?}", body);
     run_optimization_passes(tcx, &mut body);
 
     debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 65801069560..989b94b68c1 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -34,7 +34,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                                     Rvalue::Use(Operand::Constant(Box::new(Constant {
                                         span: terminator.source_info.span,
                                         user_ty: None,
-                                        literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(),
+                                        literal: ConstantKind::zero_sized(tcx.types.unit),
                                     }))),
                                 ))),
                             });
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index f925d13b2fb..89808d3d4cd 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -15,7 +15,7 @@ impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
         sess.panic_strategy() != PanicStrategy::Abort
     }
 
-    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!("remove_noop_landing_pads({:?})", body);
         self.remove_nop_landing_pads(body)
     }
@@ -81,6 +81,8 @@ impl RemoveNoopLandingPads {
     }
 
     fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
+        debug!("body: {:#?}", body);
+
         // make sure there's a single resume block
         let resume_block = {
             let patch = MirPatch::new(body);
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index b87220a3aa4..827ce0c02ac 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -15,7 +15,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
 impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
     fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
         let literal = constant.literal;
-        if let Some(ct) = literal.const_for_ty() && let ConstKind::Unevaluated(_) = ct.val() {
+        if let Some(ct) = literal.const_for_ty() && let ConstKind::Unevaluated(_) = ct.kind() {
             self.required_consts.push(*constant);
         }
     }
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 78a4ece2ecb..3be1783ae33 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -430,7 +430,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         let func = Operand::Constant(Box::new(Constant {
             span: self.span,
             user_ty: None,
-            literal: ty::Const::zero_sized(tcx, func_ty).into(),
+            literal: ConstantKind::zero_sized(func_ty),
         }));
 
         let ref_loc = self.make_place(
@@ -630,7 +630,7 @@ fn build_call_shim<'tcx>(
                 Operand::Constant(Box::new(Constant {
                     span,
                     user_ty: None,
-                    literal: ty::Const::zero_sized(tcx, ty).into(),
+                    literal: ConstantKind::zero_sized(ty),
                 })),
                 rcvr.into_iter().collect::<Vec<_>>(),
             )
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index f812afe6b62..e4ac47f4982 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -10,7 +10,6 @@ doctest = false
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
 tracing = "0.1"
 rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index a9ca8921797..2af22e129a5 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -323,6 +323,7 @@ impl<'tcx> InliningMap<'tcx> {
     }
 }
 
+#[instrument(skip(tcx, mode), level = "debug")]
 pub fn collect_crate_mono_items(
     tcx: TyCtxt<'_>,
     mode: MonoItemCollectionMode,
@@ -362,6 +363,7 @@ pub fn collect_crate_mono_items(
 
 // Find all non-generic items by walking the HIR. These items serve as roots to
 // start monomorphizing from.
+#[instrument(skip(tcx, mode), level = "debug")]
 fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
     debug!("collecting roots");
     let mut roots = MonoItems { compute_inlining: false, tcx, items: Vec::new() };
@@ -400,6 +402,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
 
 /// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
 /// post-monorphization error is encountered during a collection step.
+#[instrument(skip(tcx, visited, recursion_depths, recursion_limit, inlining_map), level = "debug")]
 fn collect_items_rec<'tcx>(
     tcx: TyCtxt<'tcx>,
     starting_point: Spanned<MonoItem<'tcx>>,
@@ -752,13 +755,15 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
     /// This does not walk the constant, as it has been handled entirely here and trying
     /// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily
     /// work, as some constants cannot be represented in the type system.
+    #[instrument(skip(self), level = "debug")]
     fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) {
         let literal = self.monomorphize(constant.literal);
         let val = match literal {
             mir::ConstantKind::Val(val, _) => val,
-            mir::ConstantKind::Ty(ct) => match ct.val() {
-                ty::ConstKind::Value(val) => val,
+            mir::ConstantKind::Ty(ct) => match ct.kind() {
+                ty::ConstKind::Value(val) => self.tcx.valtree_to_const_val((ct.ty(), val)),
                 ty::ConstKind::Unevaluated(ct) => {
+                    debug!(?ct);
                     let param_env = ty::ParamEnv::reveal_all();
                     match self.tcx.const_eval_resolve(param_env, ct, None) {
                         // The `monomorphize` call should have evaluated that constant already.
@@ -778,14 +783,18 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
         self.visit_ty(literal.ty(), TyContext::Location(location));
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn visit_const(&mut self, constant: ty::Const<'tcx>, location: Location) {
         debug!("visiting const {:?} @ {:?}", constant, location);
 
         let substituted_constant = self.monomorphize(constant);
         let param_env = ty::ParamEnv::reveal_all();
 
-        match substituted_constant.val() {
-            ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
+        match substituted_constant.kind() {
+            ty::ConstKind::Value(val) => {
+                let const_val = self.tcx.valtree_to_const_val((constant.ty(), val));
+                collect_const_value(self.tcx, const_val, self.output)
+            }
             ty::ConstKind::Unevaluated(unevaluated) => {
                 match self.tcx.const_eval_resolve(param_env, unevaluated, None) {
                     // The `monomorphize` call should have evaluated that constant already.
@@ -1120,6 +1129,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
     }
 }
 
+#[instrument(skip(tcx), level = "debug")]
 fn create_fn_mono_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: Instance<'tcx>,
@@ -1133,7 +1143,10 @@ fn create_fn_mono_item<'tcx>(
         crate::util::dump_closure_profile(tcx, instance);
     }
 
-    respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
+    let respanned = respan(source, MonoItem::Fn(instance.polymorphize(tcx)));
+    debug!(?respanned);
+
+    respanned
 }
 
 /// Creates a `MonoItem` for each method that is referenced by the vtable for
@@ -1275,6 +1288,7 @@ impl<'v> RootCollector<'_, 'v> {
 
     /// If `def_id` represents a root, pushes it onto the list of
     /// outputs. (Note that all roots must be monomorphic.)
+    #[instrument(skip(self), level = "debug")]
     fn push_if_root(&mut self, def_id: LocalDefId) {
         if self.is_root(def_id) {
             debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
@@ -1415,17 +1429,17 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIte
 }
 
 /// Scans the MIR in order to find function calls, closures, and drop-glue.
+#[instrument(skip(tcx, output), level = "debug")]
 fn collect_neighbours<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: Instance<'tcx>,
     output: &mut MonoItems<'tcx>,
 ) {
-    debug!("collect_neighbours: {:?}", instance.def_id());
     let body = tcx.instance_mir(instance.def);
-
     MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(&body);
 }
 
+#[instrument(skip(tcx, output), level = "debug")]
 fn collect_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     value: ConstValue<'tcx>,
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index dc1f1c9927d..f29143b4480 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -283,7 +283,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
             return ControlFlow::CONTINUE;
         }
 
-        match c.val() {
+        match c.kind() {
             ty::ConstKind::Param(param) => {
                 debug!(?param);
                 self.unused_parameters.clear(param.index);
@@ -353,7 +353,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
             return ControlFlow::CONTINUE;
         }
 
-        match c.val() {
+        match c.kind() {
             ty::ConstKind::Param(param) => {
                 if self.unused_parameters.contains(param.index).unwrap_or(false) {
                     ControlFlow::CONTINUE
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index bec4561928c..273827864f1 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -105,7 +105,7 @@ pub(crate) fn emit_unescape_error(
                     handler.span_suggestion(
                         span,
                         "consider removing the non-printing characters",
-                        ch.to_string(),
+                        ch,
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -141,7 +141,7 @@ pub(crate) fn emit_unescape_error(
                 .span_suggestion(
                     char_span,
                     "escape the character",
-                    c.escape_default().to_string(),
+                    c.escape_default(),
                     Applicability::MachineApplicable,
                 )
                 .emit();
@@ -157,7 +157,7 @@ pub(crate) fn emit_unescape_error(
                 .span_suggestion(
                     span,
                     "escape the character",
-                    "\\r".to_string(),
+                    "\\r",
                     Applicability::MachineApplicable,
                 )
                 .emit();
@@ -299,7 +299,7 @@ pub(crate) fn emit_unescape_error(
                 .span_suggestion_verbose(
                     span.shrink_to_hi(),
                     "terminate the unicode escape",
-                    "}".to_string(),
+                    "}",
                     Applicability::MaybeIncorrect,
                 )
                 .emit();
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index faa686c3e57..2c68cc5895c 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -369,7 +369,7 @@ pub(super) fn check_for_substitution<'a>(
             "Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
             ch, u_name, ascii_char, ascii_name
         );
-        err.span_suggestion(span, &msg, ascii_char.to_string(), Applicability::MaybeIncorrect);
+        err.span_suggestion(span, &msg, ascii_char, Applicability::MaybeIncorrect);
     }
     token.clone()
 }
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index df1765952ce..f3bdd63ee6d 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -282,7 +282,7 @@ fn error_malformed_cfg_attr_missing(span: Span, parse_sess: &ParseSess) {
         .span_suggestion(
             span,
             "missing condition and attribute",
-            CFG_ATTR_GRAMMAR_HELP.to_string(),
+            CFG_ATTR_GRAMMAR_HELP,
             Applicability::HasPlaceholders,
         )
         .note(CFG_ATTR_NOTE_REF)
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 3ae8bb07cd0..acdbddf4099 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -78,7 +78,7 @@ impl<'a> Parser<'a> {
                         err.span_suggestion_verbose(
                             replacement_span,
                             "you might have meant to write a regular comment",
-                            String::new(),
+                            "",
                             rustc_errors::Applicability::MachineApplicable,
                         );
                     }
@@ -200,12 +200,11 @@ impl<'a> Parser<'a> {
                         item.kind.descr(),
                         attr_name
                     ),
-                    (match attr_type {
+                    match attr_type {
                         OuterAttributeType::Attribute => "",
                         OuterAttributeType::DocBlockComment => "*",
                         OuterAttributeType::DocComment => "/",
-                    })
-                    .to_string(),
+                    },
                     rustc_errors::Applicability::MachineApplicable,
                 );
                 return None;
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 6a44f5d6653..c56f70e853d 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -28,6 +28,7 @@ use std::ops::{Deref, DerefMut};
 
 use std::mem::take;
 
+use crate::parser;
 use tracing::{debug, trace};
 
 const TURBOFISH_SUGGESTION_STR: &str =
@@ -431,7 +432,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion_verbose(
                     ident.span.shrink_to_lo(),
                     &format!("escape `{}` to use it as an identifier", ident.name),
-                    "r#".to_owned(),
+                    "r#",
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -445,7 +446,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion(
                     self.token.span,
                     "remove this comma",
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 );
             }
@@ -481,6 +482,35 @@ impl<'a> Parser<'a> {
             .map(|x| TokenType::Token(x.clone()))
             .chain(inedible.iter().map(|x| TokenType::Token(x.clone())))
             .chain(self.expected_tokens.iter().cloned())
+            .filter_map(|token| {
+                // filter out suggestions which suggest the same token which was found and deemed incorrect
+                fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
+                    if let TokenKind::Ident(current_sym, _) = found {
+                        if let TokenType::Keyword(suggested_sym) = expected {
+                            return current_sym == suggested_sym;
+                        }
+                    }
+                    false
+                }
+                if token != parser::TokenType::Token(self.token.kind.clone()) {
+                    let eq = is_ident_eq_keyword(&self.token.kind, &token);
+                    // if the suggestion is a keyword and the found token is an ident,
+                    // the content of which are equal to the suggestion's content,
+                    // we can remove that suggestion (see the return None statement below)
+
+                    // if this isn't the case however, and the suggestion is a token the
+                    // content of which is the same as the found token's, we remove it as well
+                    if !eq {
+                        if let TokenType::Token(kind) = &token {
+                            if kind == &self.token.kind {
+                                return None;
+                            }
+                        }
+                        return Some(token);
+                    }
+                }
+                return None;
+            })
             .collect::<Vec<_>>();
         expected.sort_by_cached_key(|x| x.to_string());
         expected.dedup();
@@ -518,7 +548,7 @@ impl<'a> Parser<'a> {
                 self.bump();
                 let sp = self.prev_token.span;
                 self.struct_span_err(sp, &msg)
-                    .span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl)
+                    .span_suggestion_short(sp, "change this to `;`", ";", appl)
                     .emit();
                 return Ok(true);
             } else if self.look_ahead(0, |t| {
@@ -537,7 +567,7 @@ impl<'a> Parser<'a> {
                 let sp = self.prev_token.span.shrink_to_hi();
                 self.struct_span_err(sp, &msg)
                     .span_label(self.token.span, "unexpected token")
-                    .span_suggestion_short(sp, "add `;` here", ";".to_string(), appl)
+                    .span_suggestion_short(sp, "add `;` here", ";", appl)
                     .emit();
                 return Ok(true);
             }
@@ -664,7 +694,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion(
                     span,
                     &format!("remove the extra `#`{}", pluralize!(count)),
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 );
                 err.span_label(
@@ -761,7 +791,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion(
                     sp,
                     "maybe write a path separator here",
-                    "::".to_string(),
+                    "::",
                     if allow_unstable {
                         Applicability::MaybeIncorrect
                     } else {
@@ -773,7 +803,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion(
                     sp,
                     "try using a semicolon",
-                    ";".to_string(),
+                    ";",
                     Applicability::MaybeIncorrect,
                 );
             } else if allow_unstable {
@@ -917,7 +947,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 span,
                 &format!("remove extra angle bracket{}", pluralize!(total_num_of_gt)),
-                String::new(),
+                "",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -999,7 +1029,7 @@ impl<'a> Parser<'a> {
                         e.span_suggestion_verbose(
                             binop.span.shrink_to_lo(),
                             TURBOFISH_SUGGESTION_STR,
-                            "::".to_string(),
+                            "::",
                             Applicability::MaybeIncorrect,
                         )
                         .emit();
@@ -1158,7 +1188,7 @@ impl<'a> Parser<'a> {
                     err.span_suggestion_verbose(
                         op.span.shrink_to_lo(),
                         TURBOFISH_SUGGESTION_STR,
-                        "::".to_string(),
+                        "::",
                         Applicability::MaybeIncorrect,
                     );
                 };
@@ -1701,7 +1731,7 @@ impl<'a> Parser<'a> {
                     Applicability::MachineApplicable,
                 );
             }
-            err.span_suggestion(lo.shrink_to_lo(), &format!("{prefix}you can still access the deprecated `try!()` macro using the \"raw identifier\" syntax"), "r#".to_string(), Applicability::MachineApplicable);
+            err.span_suggestion(lo.shrink_to_lo(), &format!("{prefix}you can still access the deprecated `try!()` macro using the \"raw identifier\" syntax"), "r#", Applicability::MachineApplicable);
             err.emit();
             Ok(self.mk_expr_err(lo.to(hi)))
         } else {
@@ -1997,7 +2027,7 @@ impl<'a> Parser<'a> {
             err.span_suggestion(
                 span,
                 "declare the type after the parameter binding",
-                String::from("<identifier>: <type>"),
+                "<identifier>: <type>",
                 Applicability::HasPlaceholders,
             );
             return Some(ident);
@@ -2102,7 +2132,7 @@ impl<'a> Parser<'a> {
         .span_suggestion_short(
             pat.span,
             "give this argument a name or use an underscore to ignore it",
-            "_".to_owned(),
+            "_",
             Applicability::MachineApplicable,
         )
         .emit();
@@ -2336,7 +2366,7 @@ impl<'a> Parser<'a> {
             err.span_suggestion_verbose(
                 start.until(self.token.span),
                 "the `const` keyword is only needed in the definition of the type",
-                String::new(),
+                "",
                 Applicability::MaybeIncorrect,
             );
             err.emit();
@@ -2394,7 +2424,7 @@ impl<'a> Parser<'a> {
                     err.span_suggestion(
                         snapshot.token.span,
                         "if you meant to use an associated type binding, replace `==` with `=`",
-                        "=".to_string(),
+                        "=",
                         Applicability::MaybeIncorrect,
                     );
                     let value = self.mk_expr_err(start.to(expr.span));
@@ -2408,7 +2438,7 @@ impl<'a> Parser<'a> {
                     err.span_suggestion(
                         snapshot.token.span,
                         "write a path separator here",
-                        "::".to_string(),
+                        "::",
                         Applicability::MaybeIncorrect,
                     );
                     err.emit();
@@ -2461,7 +2491,7 @@ impl<'a> Parser<'a> {
         err.span_suggestion_verbose(
             move_async_span,
             "try switching the order",
-            "async move".to_owned(),
+            "async move",
             Applicability::MaybeIncorrect,
         );
         err
@@ -2566,7 +2596,7 @@ impl<'a> Parser<'a> {
                             err.span_suggestion(
                                 span,
                                 "maybe write a path separator here",
-                                "::".to_string(),
+                                "::",
                                 Applicability::MaybeIncorrect,
                             );
                         } else {
@@ -2596,7 +2626,7 @@ impl<'a> Parser<'a> {
         err.tool_only_span_suggestion(
             label.ident.span.until(self.token.span),
             "remove this block label",
-            String::new(),
+            "",
             Applicability::MachineApplicable,
         );
         err.emit();
@@ -2669,7 +2699,7 @@ impl<'a> Parser<'a> {
                     err.span_suggestion(
                         between_span,
                         "use single colon",
-                        ": ".to_owned(),
+                        ": ",
                         Applicability::MachineApplicable,
                     );
                     return Err(err);
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 324e04b1981..81bab0e3513 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -230,7 +230,7 @@ impl<'a> Parser<'a> {
                     .span_suggestion_short(
                         sp,
                         &format!("`{s}=` is not a valid comparison operator, use `{s}`", s = sugg),
-                        sugg.to_string(),
+                        sugg,
                         Applicability::MachineApplicable,
                     )
                     .emit();
@@ -247,7 +247,7 @@ impl<'a> Parser<'a> {
                     .span_suggestion_short(
                         sp,
                         "`<>` is not a valid comparison operator, use `!=`",
-                        "!=".to_string(),
+                        "!=",
                         Applicability::MachineApplicable,
                     )
                     .emit();
@@ -459,7 +459,7 @@ impl<'a> Parser<'a> {
             .span_suggestion_short(
                 self.token.span,
                 &format!("use `{good}` to perform logical {english}"),
-                good.to_string(),
+                good,
                 Applicability::MachineApplicable,
             )
             .note("unlike in e.g., python and PHP, `&&` and `||` are used for logical operators")
@@ -584,7 +584,7 @@ impl<'a> Parser<'a> {
                     err.span_suggestion_verbose(
                         lo,
                         "try removing the `+`",
-                        "".to_string(),
+                        "",
                         Applicability::MachineApplicable,
                     );
                 }
@@ -634,7 +634,7 @@ impl<'a> Parser<'a> {
             .span_suggestion_short(
                 lo,
                 "use `!` to perform bitwise not",
-                "!".to_owned(),
+                "!",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -673,7 +673,7 @@ impl<'a> Parser<'a> {
             // trailing whitespace after the `!` in our suggestion
             self.sess.source_map().span_until_non_whitespace(lo.to(not_token.span)),
             "use `!` to perform logical negation",
-            "!".to_owned(),
+            "!",
             Applicability::MachineApplicable,
         )
         .emit();
@@ -744,7 +744,7 @@ impl<'a> Parser<'a> {
                                     .span_suggestion(
                                         label.ident.span,
                                         "use the correct loop label format",
-                                        label.ident.to_string(),
+                                        label.ident,
                                         Applicability::MachineApplicable,
                                     )
                                     .emit();
@@ -885,7 +885,7 @@ impl<'a> Parser<'a> {
                         "{}remove the type ascription",
                         if is_nightly { "alternatively, " } else { "" }
                     ),
-                    String::new(),
+                    "",
                     if is_nightly {
                         Applicability::MaybeIncorrect
                     } else {
@@ -929,7 +929,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 lt_span,
                 "remove the lifetime annotation",
-                String::new(),
+                "",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -980,12 +980,26 @@ impl<'a> Parser<'a> {
 
     fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
         loop {
-            if self.eat(&token::Question) {
+            let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
+                // we are using noexpect here because we don't expect a `?` directly after a `return`
+                // which could be suggested otherwise
+                self.eat_noexpect(&token::Question)
+            } else {
+                self.eat(&token::Question)
+            };
+            if has_question {
                 // `expr?`
                 e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e), AttrVec::new());
                 continue;
             }
-            if self.eat(&token::Dot) {
+            let has_dot = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
+                // we are using noexpect here because we don't expect a `.` directly after a `return`
+                // which could be suggested otherwise
+                self.eat_noexpect(&token::Dot)
+            } else {
+                self.eat(&token::Dot)
+            };
+            if has_dot {
                 // expr.f
                 e = self.parse_dot_suffix_expr(lo, e)?;
                 continue;
@@ -1541,9 +1555,13 @@ impl<'a> Parser<'a> {
             self.parse_for_expr(label, lo, attrs)
         } else if self.eat_keyword(kw::Loop) {
             self.parse_loop_expr(label, lo, attrs)
-        } else if self.check(&token::OpenDelim(Delimiter::Brace)) || self.token.is_whole_block() {
+        } else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace))
+            || self.token.is_whole_block()
+        {
             self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs)
-        } else if !ate_colon && (self.check(&TokenKind::Comma) || self.check(&TokenKind::Gt)) {
+        } else if !ate_colon
+            && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
+        {
             // We're probably inside of a `Path<'a>` that needs a turbofish
             let msg = "expected `while`, `for`, `loop` or `{` after a label";
             self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
@@ -1626,7 +1644,7 @@ impl<'a> Parser<'a> {
             .span_suggestion_short(
                 lo.shrink_to_hi(),
                 "add `:` after the label",
-                ": ".to_string(),
+                ": ",
                 Applicability::MachineApplicable,
             )
             .note("labels are used before loops and blocks, allowing e.g., `break 'label` to them")
@@ -1645,7 +1663,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 span_dc,
                 "replace with the new syntax",
-                "try".to_string(),
+                "try",
                 Applicability::MachineApplicable,
             )
             .note("following RFC #2388, the new non-placeholder syntax is `try`")
@@ -2088,7 +2106,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 span_for,
                 "remove the parameters",
-                String::new(),
+                "",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -2230,36 +2248,59 @@ impl<'a> Parser<'a> {
         &mut self,
         attrs: AttrVec,
         lo: Span,
-        cond: P<Expr>,
+        mut cond: P<Expr>,
     ) -> PResult<'a, P<Expr>> {
-        let missing_then_block_binop_span = || {
-            match cond.kind {
-                ExprKind::Binary(Spanned { span: binop_span, .. }, _, ref right)
-                    if let ExprKind::Block(..) = right.kind => Some(binop_span),
-                _ => None
+        let cond_span = cond.span;
+        // Tries to interpret `cond` as either a missing expression if it's a block,
+        // or as an unfinished expression if it's a binop and the RHS is a block.
+        // We could probably add more recoveries here too...
+        let mut recover_block_from_condition = |this: &mut Self| {
+            let block = match &mut cond.kind {
+                ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
+                    if let ExprKind::Block(_, None) = right.kind => {
+                        this.error_missing_if_then_block(lo, cond_span.shrink_to_lo().to(*binop_span), true).emit();
+                        std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi()))
+                    },
+                ExprKind::Block(_, None) => {
+                    this.error_missing_if_cond(lo, cond_span).emit();
+                    std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi()))
+                }
+                _ => {
+                    return None;
+                }
+            };
+            if let ExprKind::Block(block, _) = &block.kind {
+                Some(block.clone())
+            } else {
+                unreachable!()
             }
         };
-        // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then
-        // verify that the last statement is either an implicit return (no `;`) or an explicit
-        // return. This won't catch blocks with an explicit `return`, but that would be caught by
-        // the dead code lint.
-        let thn = if self.token.is_keyword(kw::Else) || !cond.returns() {
-            if let Some(binop_span) = missing_then_block_binop_span() {
-                self.error_missing_if_then_block(lo, None, Some(binop_span)).emit();
-                self.mk_block_err(cond.span)
+        // Parse then block
+        let thn = if self.token.is_keyword(kw::Else) {
+            if let Some(block) = recover_block_from_condition(self) {
+                block
             } else {
-                self.error_missing_if_cond(lo, cond.span)
+                self.error_missing_if_then_block(lo, cond_span, false).emit();
+                self.mk_block_err(cond_span.shrink_to_hi())
             }
         } else {
             let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery.
-            let not_block = self.token != token::OpenDelim(Delimiter::Brace);
-            let block = self.parse_block().map_err(|err| {
-                if not_block {
-                    self.error_missing_if_then_block(lo, Some(err), missing_then_block_binop_span())
+            let block = if self.check(&token::OpenDelim(Delimiter::Brace)) {
+                self.parse_block()?
+            } else {
+                if let Some(block) = recover_block_from_condition(self) {
+                    block
                 } else {
-                    err
+                    // Parse block, which will always fail, but we can add a nice note to the error
+                    self.parse_block().map_err(|mut err| {
+                        err.span_note(
+                            cond_span,
+                            "the `if` expression is missing a block after this condition",
+                        );
+                        err
+                    })?
                 }
-            })?;
+            };
             self.error_on_if_block_attrs(lo, false, block.span, &attrs);
             block
         };
@@ -2270,31 +2311,34 @@ impl<'a> Parser<'a> {
     fn error_missing_if_then_block(
         &self,
         if_span: Span,
-        err: Option<DiagnosticBuilder<'a, ErrorGuaranteed>>,
-        binop_span: Option<Span>,
+        cond_span: Span,
+        is_unfinished: bool,
     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
-        let msg = "this `if` expression has a condition, but no block";
-
-        let mut err = if let Some(mut err) = err {
-            err.span_label(if_span, msg);
-            err
+        let mut err = self.struct_span_err(
+            if_span,
+            "this `if` expression is missing a block after the condition",
+        );
+        if is_unfinished {
+            err.span_help(cond_span, "this binary operation is possibly unfinished");
         } else {
-            self.struct_span_err(if_span, msg)
-        };
-
-        if let Some(binop_span) = binop_span {
-            err.span_help(binop_span, "maybe you forgot the right operand of the condition?");
+            err.span_help(cond_span.shrink_to_hi(), "add a block here");
         }
-
         err
     }
 
-    fn error_missing_if_cond(&self, lo: Span, span: Span) -> P<ast::Block> {
-        let sp = self.sess.source_map().next_point(lo);
-        self.struct_span_err(sp, "missing condition for `if` expression")
-            .span_label(sp, "expected if condition here")
-            .emit();
-        self.mk_block_err(span)
+    fn error_missing_if_cond(
+        &self,
+        lo: Span,
+        span: Span,
+    ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+        let next_span = self.sess.source_map().next_point(lo);
+        let mut err = self.struct_span_err(next_span, "missing condition for `if` expression");
+        err.span_label(next_span, "expected condition here");
+        err.span_label(
+            self.sess.source_map().start_point(span),
+            "if this block is the condition of the `if` expression, then it must be followed by another block"
+        );
+        err
     }
 
     /// Parses the condition of a `if` or `while` expression.
@@ -2352,7 +2396,7 @@ impl<'a> Parser<'a> {
                         .span_suggestion(
                             cond.span.shrink_to_lo(),
                             "add an `if` if this is the condition of a chained `else if` statement",
-                            "if ".to_string(),
+                            "if ",
                             Applicability::MaybeIncorrect,
                         )
                         .emit();
@@ -2388,12 +2432,7 @@ impl<'a> Parser<'a> {
         self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches")
             .span_label(branch_span, "the attributes are attached to this branch")
             .span_label(ctx_span, format!("the branch belongs to this `{ctx}`"))
-            .span_suggestion(
-                span,
-                "remove the attributes",
-                String::new(),
-                Applicability::MachineApplicable,
-            )
+            .span_suggestion(span, "remove the attributes", "", Applicability::MachineApplicable)
             .emit();
     }
 
@@ -2502,7 +2541,7 @@ impl<'a> Parser<'a> {
                 e.span_suggestion_short(
                     match_span,
                     "try removing this `match`",
-                    String::new(),
+                    "",
                     Applicability::MaybeIncorrect, // speculative
                 );
             }
@@ -2578,7 +2617,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion(
                     semi_sp,
                     "use a comma to end a `match` arm expression",
-                    ",".to_string(),
+                    ",",
                     Applicability::MachineApplicable,
                 );
             }
@@ -2679,7 +2718,7 @@ impl<'a> Parser<'a> {
                     err.span_suggestion(
                         this.token.span,
                         "try using a fat arrow here",
-                        "=>".to_string(),
+                        "=>",
                         Applicability::MaybeIncorrect,
                     );
                     err.emit();
@@ -2739,7 +2778,7 @@ impl<'a> Parser<'a> {
                                 err.span_suggestion_short(
                                     arm_start_span.shrink_to_hi(),
                                     "missing a comma here to end this `match` arm",
-                                    ",".to_owned(),
+                                    ",",
                                     Applicability::MachineApplicable,
                                 );
                                 return Err(err);
@@ -2768,7 +2807,7 @@ impl<'a> Parser<'a> {
                                 .span_suggestion(
                                     hi.shrink_to_hi(),
                                     "missing a comma here to end this `match` arm",
-                                    ",".to_owned(),
+                                    ",",
                                     Applicability::MachineApplicable,
                                 )
                                 .emit();
@@ -3049,7 +3088,7 @@ impl<'a> Parser<'a> {
         .span_suggestion_short(
             self.token.span,
             "remove this comma",
-            String::new(),
+            "",
             Applicability::MachineApplicable,
         )
         .note("the base struct must always be the last field")
@@ -3103,7 +3142,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 field_name.span.shrink_to_hi().to(self.token.span),
                 "replace equals symbol with a colon",
-                ":".to_string(),
+                ":",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -3114,13 +3153,13 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 span,
                 "use `..` for an exclusive range",
-                "..".to_owned(),
+                "..",
                 Applicability::MaybeIncorrect,
             )
             .span_suggestion(
                 span,
                 "or `..=` for an inclusive range",
-                "..=".to_owned(),
+                "..=",
                 Applicability::MaybeIncorrect,
             )
             .emit();
@@ -3132,7 +3171,7 @@ impl<'a> Parser<'a> {
                 span,
                 "if you meant to write a comparison against a negative value, add a \
              space in between `<` and `-`",
-                "< -".to_string(),
+                "< -",
                 Applicability::MaybeIncorrect,
             )
             .emit();
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 1930dec8c3b..1acfd93d86f 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -271,7 +271,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion_verbose(
                     prev_token.shrink_to_hi().to(self.prev_token.span),
                     "consider joining the two `where` clauses into one",
-                    ",".to_owned(),
+                    ",",
                     Applicability::MaybeIncorrect,
                 );
                 err.emit();
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 48c3c467bec..1d50ce767af 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -298,7 +298,7 @@ impl<'a> Parser<'a> {
                     .span_suggestion_short(
                         span,
                         "items are imported using the `use` keyword",
-                        "use".to_owned(),
+                        "use",
                         Applicability::MachineApplicable,
                     )
                     .emit();
@@ -458,7 +458,7 @@ impl<'a> Parser<'a> {
                     err.span_suggestion(
                         path.span,
                         "perhaps you meant to define a macro",
-                        "macro_rules".to_string(),
+                        "macro_rules",
                         Applicability::MachineApplicable,
                     );
                 }
@@ -486,7 +486,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion_verbose(
                     self.token.span,
                     "consider removing this semicolon",
-                    String::new(),
+                    "",
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -606,7 +606,7 @@ impl<'a> Parser<'a> {
                         .span_suggestion_short(
                             missing_for_span,
                             "add `for` here",
-                            " for ".to_string(),
+                            " for ",
                             Applicability::MachineApplicable,
                         )
                         .emit();
@@ -1082,7 +1082,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 span.with_hi(ident.span.lo()),
                 "try using a static value",
-                "static ".to_string(),
+                "static ",
                 Applicability::MachineApplicable,
             )
             .note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")
@@ -1121,7 +1121,7 @@ impl<'a> Parser<'a> {
                 .span_suggestion(
                     const_span,
                     "you might want to declare a static instead",
-                    "static".to_owned(),
+                    "static",
                     Applicability::MaybeIncorrect,
                 )
                 .emit();
@@ -1555,7 +1555,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion_short(
                     self.prev_token.span,
                     "field names and their types are separated with `:`",
-                    ":".to_string(),
+                    ":",
                     Applicability::MachineApplicable,
                 );
                 err.emit();
@@ -1582,7 +1582,7 @@ impl<'a> Parser<'a> {
                 .span_suggestion_verbose(
                     self.token.span,
                     "write a path separator here",
-                    "::".to_string(),
+                    "::",
                     Applicability::MaybeIncorrect,
                 )
                 .emit();
@@ -1595,7 +1595,7 @@ impl<'a> Parser<'a> {
                 .span_suggestion(
                     sp,
                     "remove this unsupported default value",
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 )
                 .emit();
@@ -1691,7 +1691,7 @@ impl<'a> Parser<'a> {
                     .span_suggestion(
                         macro_rules_span,
                         "add a `!`",
-                        "macro_rules!".to_owned(),
+                        "macro_rules!",
                         Applicability::MachineApplicable,
                     )
                     .emit();
@@ -1720,12 +1720,7 @@ impl<'a> Parser<'a> {
             // Handle macro_rules! foo!
             let span = self.prev_token.span;
             self.struct_span_err(span, "macro names aren't followed by a `!`")
-                .span_suggestion(
-                    span,
-                    "remove the `!`",
-                    "".to_owned(),
-                    Applicability::MachineApplicable,
-                )
+                .span_suggestion(span, "remove the `!`", "", Applicability::MachineApplicable)
                 .emit();
         }
 
@@ -1751,7 +1746,7 @@ impl<'a> Parser<'a> {
                 .span_suggestion(
                     vis.span,
                     "try exporting the macro",
-                    "#[macro_export]".to_owned(),
+                    "#[macro_export]",
                     Applicability::MaybeIncorrect, // speculative
                 )
                 .emit();
@@ -1760,7 +1755,7 @@ impl<'a> Parser<'a> {
                 .span_suggestion(
                     vis.span,
                     "remove the visibility",
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 )
                 .help(&format!("try adjusting the macro to put `{vstr}` inside the invocation"))
@@ -1794,14 +1789,14 @@ impl<'a> Parser<'a> {
             err.span_suggestion(
                 span,
                 "change the delimiters to curly braces",
-                " { /* items */ }".to_string(),
+                " { /* items */ }",
                 Applicability::HasPlaceholders,
             );
         }
         err.span_suggestion(
             span.shrink_to_hi(),
             "add a semicolon",
-            ';'.to_string(),
+            ';',
             Applicability::MaybeIncorrect,
         );
         err.emit();
@@ -1826,7 +1821,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 item.unwrap().span,
                 &format!("consider creating a new `{kw_str}` definition instead of nesting"),
-                String::new(),
+                "",
                 Applicability::MaybeIncorrect,
             )
             .emit();
@@ -2086,7 +2081,7 @@ impl<'a> Parser<'a> {
                         err.span_suggestion(
                             self.token.uninterpolated_span(),
                             &format!("`{original_kw}` already used earlier, remove this one"),
-                            "".to_string(),
+                            "",
                             Applicability::MachineApplicable,
                         )
                         .span_note(original_sp, &format!("`{original_kw}` first seen here"));
@@ -2134,7 +2129,7 @@ impl<'a> Parser<'a> {
                                 err.span_suggestion(
                                     current_vis.span,
                                     "there is already a visibility modifier, remove one",
-                                    "".to_string(),
+                                    "",
                                     Applicability::MachineApplicable,
                                 )
                                 .span_note(orig_vis.span, "explicit visibility first seen here");
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 6e6c1ffe747..6d6667717f0 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -547,6 +547,22 @@ impl<'a> Parser<'a> {
         is_present
     }
 
+    fn check_noexpect(&self, tok: &TokenKind) -> bool {
+        self.token == *tok
+    }
+
+    /// Consumes a token 'tok' if it exists. Returns whether the given token was present.
+    ///
+    /// the main purpose of this function is to reduce the cluttering of the suggestions list
+    /// which using the normal eat method could introduce in some cases.
+    pub fn eat_noexpect(&mut self, tok: &TokenKind) -> bool {
+        let is_present = self.check_noexpect(tok);
+        if is_present {
+            self.bump()
+        }
+        is_present
+    }
+
     /// Consumes a token 'tok' if it exists. Returns whether the given token was present.
     pub fn eat(&mut self, tok: &TokenKind) -> bool {
         let is_present = self.check(tok);
@@ -1350,7 +1366,7 @@ impl<'a> Parser<'a> {
                         .span_suggestion(
                             lit.span,
                             "specify the ABI with a string literal",
-                            "\"C\"".to_string(),
+                            "\"C\"",
                             Applicability::MaybeIncorrect,
                         )
                         .emit();
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index ca7915ed17a..ba77a395840 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -218,12 +218,7 @@ impl<'a> Parser<'a> {
         if let token::OrOr = self.token.kind {
             let span = self.token.span;
             let mut err = self.struct_span_err(span, "unexpected `||` before function parameter");
-            err.span_suggestion(
-                span,
-                "remove the `||`",
-                String::new(),
-                Applicability::MachineApplicable,
-            );
+            err.span_suggestion(span, "remove the `||`", "", Applicability::MachineApplicable);
             err.note("alternatives in or-patterns are separated with `|`, not `||`");
             err.emit();
             self.bump();
@@ -287,7 +282,7 @@ impl<'a> Parser<'a> {
         err.span_suggestion(
             self.token.span,
             "use a single `|` to separate multiple alternative patterns",
-            "|".to_owned(),
+            "|",
             Applicability::MachineApplicable,
         );
         if let Some(lo) = lo {
@@ -303,7 +298,7 @@ impl<'a> Parser<'a> {
         err.span_suggestion(
             span,
             &format!("remove the `{}`", pprust::token_to_string(&self.token)),
-            String::new(),
+            "",
             Applicability::MachineApplicable,
         );
         if let Some(lo) = lo {
@@ -433,7 +428,7 @@ impl<'a> Parser<'a> {
             .span_suggestion_short(
                 lo,
                 "for a rest pattern, use `..` instead of `...`",
-                "..".to_owned(),
+                "..",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -537,12 +532,7 @@ impl<'a> Parser<'a> {
 
             let span = self.prev_token.span;
             self.struct_span_err(span, &format!("unexpected lifetime `{}` in pattern", name))
-                .span_suggestion(
-                    span,
-                    "remove the lifetime",
-                    String::new(),
-                    Applicability::MachineApplicable,
-                )
+                .span_suggestion(span, "remove the lifetime", "", Applicability::MachineApplicable)
                 .emit();
         }
     }
@@ -665,7 +655,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 span,
                 "remove the additional `mut`s",
-                String::new(),
+                "",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -759,24 +749,14 @@ impl<'a> Parser<'a> {
 
     fn error_inclusive_range_with_extra_equals(&self, span: Span) {
         self.struct_span_err(span, "unexpected `=` after inclusive range")
-            .span_suggestion_short(
-                span,
-                "use `..=` instead",
-                "..=".to_string(),
-                Applicability::MaybeIncorrect,
-            )
+            .span_suggestion_short(span, "use `..=` instead", "..=", Applicability::MaybeIncorrect)
             .note("inclusive ranges end with a single equals sign (`..=`)")
             .emit();
     }
 
     fn error_inclusive_range_with_no_end(&self, span: Span) {
         struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end")
-            .span_suggestion_short(
-                span,
-                "use `..` instead",
-                "..".to_string(),
-                Applicability::MachineApplicable,
-            )
+            .span_suggestion_short(span, "use `..` instead", "..", Applicability::MachineApplicable)
             .note("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)")
             .emit();
     }
@@ -794,7 +774,7 @@ impl<'a> Parser<'a> {
                 .span_suggestion_short(
                     re.span,
                     "use `..=` instead",
-                    "..=".to_string(),
+                    "..=",
                     Applicability::MachineApplicable,
                 )
                 .emit();
@@ -1035,7 +1015,7 @@ impl<'a> Parser<'a> {
                         err.span_suggestion_short(
                             sp,
                             "remove this comma",
-                            String::new(),
+                            "",
                             Applicability::MachineApplicable,
                         );
                     }
@@ -1107,7 +1087,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 self.token.span,
                 "to omit remaining fields, use one fewer `.`",
-                "..".to_owned(),
+                "..",
                 Applicability::MachineApplicable,
             )
             .emit();
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 5c6fb376cd4..5cf1758c31f 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -2,7 +2,7 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{Parser, Restrictions, TokenType};
 use crate::maybe_whole;
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Token};
+use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::{
     self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocConstraint,
     AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
@@ -96,7 +96,7 @@ impl<'a> Parser<'a> {
     ///                ^ help: use double colon
     /// ```
     fn recover_colon_before_qpath_proj(&mut self) -> bool {
-        if self.token.kind != token::Colon
+        if !self.check_noexpect(&TokenKind::Colon)
             || self.look_ahead(1, |t| !t.is_ident() || t.is_reserved_ident())
         {
             return false;
@@ -112,7 +112,7 @@ impl<'a> Parser<'a> {
             .span_suggestion(
                 self.prev_token.span,
                 "use double colon",
-                "::".to_string(),
+                "::",
                 Applicability::MachineApplicable,
             )
             .emit();
@@ -283,7 +283,7 @@ impl<'a> Parser<'a> {
                             err.span_suggestion_verbose(
                                 arg.span().shrink_to_hi(),
                                 "you might have meant to end the type parameters here",
-                                ">".to_string(),
+                                ">",
                                 Applicability::MaybeIncorrect,
                             );
                         }
@@ -455,7 +455,7 @@ impl<'a> Parser<'a> {
                             "remove extra angle bracket{}",
                             pluralize!(snapshot.unmatched_angle_bracket_count)
                         ),
-                        String::new(),
+                        "",
                         Applicability::MachineApplicable,
                     )
                     .emit();
@@ -478,7 +478,7 @@ impl<'a> Parser<'a> {
         while let Some(arg) = self.parse_angle_arg(ty_generics)? {
             args.push(arg);
             if !self.eat(&token::Comma) {
-                if self.token.kind == token::Semi
+                if self.check_noexpect(&TokenKind::Semi)
                     && self.look_ahead(1, |t| t.is_ident() || t.is_lifetime())
                 {
                     // Add `>` to the list of expected tokens.
@@ -489,7 +489,7 @@ impl<'a> Parser<'a> {
                     err.span_suggestion_verbose(
                         self.prev_token.span.until(self.token.span),
                         "use a comma to separate type parameters",
-                        ", ".to_string(),
+                        ", ",
                         Applicability::MachineApplicable,
                     );
                     err.emit();
@@ -517,7 +517,11 @@ impl<'a> Parser<'a> {
         let arg = self.parse_generic_arg(ty_generics)?;
         match arg {
             Some(arg) => {
-                if self.check(&token::Colon) | self.check(&token::Eq) {
+                // we are using noexpect here because we first want to find out if either `=` or `:`
+                // is present and then use that info to push the other token onto the tokens list
+                let separated =
+                    self.check_noexpect(&token::Colon) || self.check_noexpect(&token::Eq);
+                if separated && (self.check(&token::Colon) | self.check(&token::Eq)) {
                     let arg_span = arg.span();
                     let (binder, ident, gen_args) = match self.get_ident_from_generic_arg(&arg) {
                         Ok(ident_gen_args) => ident_gen_args,
@@ -553,6 +557,14 @@ impl<'a> Parser<'a> {
                         AssocConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
                     Ok(Some(AngleBracketedArg::Constraint(constraint)))
                 } else {
+                    // we only want to suggest `:` and `=` in contexts where the previous token
+                    // is an ident and the current token or the next token is an ident
+                    if self.prev_token.is_ident()
+                        && (self.token.is_ident() || self.look_ahead(1, |token| token.is_ident()))
+                    {
+                        self.check(&token::Colon);
+                        self.check(&token::Eq);
+                    }
                     Ok(Some(AngleBracketedArg::Arg(arg)))
                 }
             }
@@ -592,13 +604,13 @@ impl<'a> Parser<'a> {
                     err.span_suggestion(
                         self.sess.source_map().next_point(eq).to(before_next),
                         "to constrain the associated type, add a type after `=`",
-                        " TheType".to_string(),
+                        " TheType",
                         Applicability::HasPlaceholders,
                     );
                     err.span_suggestion(
                         eq.to(before_next),
                         &format!("remove the `=` if `{}` is a type", ident),
-                        String::new(),
+                        "",
                         Applicability::MaybeIncorrect,
                     )
                 } else {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 7907ec44e98..51bd9d2d386 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -209,7 +209,7 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, Stmt> {
         let stmt = self.recover_local_after_let(lo, attrs)?;
         self.struct_span_err(lo, "invalid variable declaration")
-            .span_suggestion(lo, msg, sugg.to_string(), Applicability::MachineApplicable)
+            .span_suggestion(lo, msg, sugg, Applicability::MachineApplicable)
             .emit();
         Ok(stmt)
     }
@@ -260,7 +260,10 @@ impl<'a> Parser<'a> {
                     if let Ok(snip) = self.span_to_snippet(pat.span) {
                         err.span_label(pat.span, format!("while parsing the type for `{}`", snip));
                     }
-                    let err = if self.check(&token::Eq) {
+                    // we use noexpect here because we don't actually expect Eq to be here
+                    // but we are still checking for it in order to be able to handle it if
+                    // it is there
+                    let err = if self.check_noexpect(&token::Eq) {
                         err.emit();
                         None
                     } else {
@@ -287,7 +290,7 @@ impl<'a> Parser<'a> {
                 err.span_suggestion_short(
                     colon_sp,
                     "use `=` if you meant to assign",
-                    " =".to_string(),
+                    " =",
                     Applicability::MachineApplicable,
                 );
                 err.emit();
@@ -391,7 +394,7 @@ impl<'a> Parser<'a> {
                 .span_suggestion_short(
                     self.token.span,
                     "initialize the variable",
-                    "=".to_string(),
+                    "=",
                     Applicability::MaybeIncorrect,
                 )
                 .help("if you meant to overwrite, remove the `let` binding")
@@ -429,10 +432,23 @@ impl<'a> Parser<'a> {
         //
         // which is valid in other languages, but not Rust.
         match self.parse_stmt_without_recovery(false, ForceCollect::No) {
-            // If the next token is an open brace (e.g., `if a b {`), the place-
-            // inside-a-block suggestion would be more likely wrong than right.
+            // If the next token is an open brace, e.g., we have:
+            //
+            //     if expr other_expr {
+            //        ^    ^          ^- lookahead(1) is a brace
+            //        |    |- current token is not "else"
+            //        |- (statement we just parsed)
+            //
+            // the place-inside-a-block suggestion would be more likely wrong than right.
+            //
+            // FIXME(compiler-errors): this should probably parse an arbitrary expr and not
+            // just lookahead one token, so we can see if there's a brace after _that_,
+            // since we want to protect against:
+            //     `if 1 1 + 1 {` being suggested as  `if { 1 } 1 + 1 {`
+            //                                            +   +
             Ok(Some(_))
-                if self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace))
+                if (!self.token.is_keyword(kw::Else)
+                    && self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace)))
                     || do_not_suggest_help => {}
             // Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836).
             Ok(Some(Stmt { kind: StmtKind::Empty, .. })) => {}
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index dee025cfd3c..31b40a83e60 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -216,7 +216,7 @@ impl<'a> Parser<'a> {
                 .span_suggestion_short(
                     self.prev_token.span,
                     "use `->` instead",
-                    "->".to_string(),
+                    "->",
                     Applicability::MachineApplicable,
                 )
                 .emit();
@@ -479,7 +479,7 @@ impl<'a> Parser<'a> {
             err.span_suggestion(
                 span,
                 "place `mut` before `dyn`",
-                "&mut dyn".to_string(),
+                "&mut dyn",
                 Applicability::MachineApplicable,
             );
             err.emit();
@@ -548,7 +548,7 @@ impl<'a> Parser<'a> {
             .span_suggestion_short(
                 qual_span,
                 &format!("remove the `{}` qualifier", qual),
-                String::new(),
+                "",
                 Applicability::MaybeIncorrect,
             )
             .emit();
@@ -648,7 +648,7 @@ impl<'a> Parser<'a> {
                     .span_suggestion(
                         self.token.span,
                         "remove this keyword",
-                        String::new(),
+                        "",
                         Applicability::MachineApplicable,
                     )
                     .emit();
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index a3ef1981e84..787d37277c6 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -12,7 +12,6 @@ rustc_errors = { path = "../rustc_errors" }
 rustc_expand = { path = "../rustc_expand" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
-rustc_parse = { path = "../rustc_parse" }
 rustc_session = { path = "../rustc_session" }
 rustc_target = { path = "../rustc_target" }
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 5cc97d326d3..6c19ec915b1 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -118,6 +118,9 @@ impl CheckAttrVisitor<'_> {
                 sym::rustc_lint_query_instability => {
                     self.check_rustc_lint_query_instability(&attr, span, target)
                 }
+                sym::rustc_lint_diagnostics => {
+                    self.check_rustc_lint_diagnostics(&attr, span, target)
+                }
                 sym::rustc_clean
                 | sym::rustc_dirty
                 | sym::rustc_if_this_changed
@@ -149,9 +152,7 @@ impl CheckAttrVisitor<'_> {
                 sym::link_name => self.check_link_name(hir_id, attr, span, target),
                 sym::link_section => self.check_link_section(hir_id, attr, span, target),
                 sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
-                sym::deprecated | sym::rustc_deprecated => {
-                    self.check_deprecated(hir_id, attr, span, target)
-                }
+                sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
                 sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
                 sym::path => self.check_generic_attr(hir_id, attr, target, &[Target::Mod]),
                 sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
@@ -918,7 +919,7 @@ impl CheckAttrVisitor<'_> {
                         .span_suggestion(
                             replacement_span,
                             "remove this attribute",
-                            String::new(),
+                            "",
                             Applicability::MachineApplicable,
                         )
                         .emit();
@@ -1158,7 +1159,7 @@ impl CheckAttrVisitor<'_> {
                                         diag.span_suggestion_short(
                                             i_meta.span,
                                             "use `notable_trait` instead",
-                                            String::from("notable_trait"),
+                                            "notable_trait",
                                             Applicability::MachineApplicable,
                                         );
                                         diag.note("`doc(spotlight)` is now a no-op");
@@ -1624,12 +1625,9 @@ impl CheckAttrVisitor<'_> {
         }
     }
 
-    fn check_rustc_lint_query_instability(
-        &self,
-        attr: &Attribute,
-        span: Span,
-        target: Target,
-    ) -> bool {
+    /// Helper function for checking that the provided attribute is only applied to a function or
+    /// method.
+    fn check_applied_to_fn_or_method(&self, attr: &Attribute, span: Span, target: Target) -> bool {
         let is_function = matches!(target, Target::Fn | Target::Method(..));
         if !is_function {
             self.tcx
@@ -1643,6 +1641,23 @@ impl CheckAttrVisitor<'_> {
         }
     }
 
+    /// Checks that the `#[rustc_lint_query_instability]` attribute is only applied to a function
+    /// or method.
+    fn check_rustc_lint_query_instability(
+        &self,
+        attr: &Attribute,
+        span: Span,
+        target: Target,
+    ) -> bool {
+        self.check_applied_to_fn_or_method(attr, span, target)
+    }
+
+    /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or
+    /// method.
+    fn check_rustc_lint_diagnostics(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+        self.check_applied_to_fn_or_method(attr, span, target)
+    }
+
     /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph
     /// option is passed to the compiler.
     fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool {
@@ -1720,7 +1735,7 @@ impl CheckAttrVisitor<'_> {
                     .span_suggestion(
                         attr.span,
                         "remove this attribute",
-                        String::new(),
+                        "",
                         Applicability::MachineApplicable,
                     )
                     .emit();
@@ -2259,7 +2274,7 @@ impl CheckAttrVisitor<'_> {
                 .span_suggestion(
                     attr.span,
                     "remove this attribute",
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 )
                 .note(&note)
@@ -2340,7 +2355,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         let target = match expr.kind {
-            hir::ExprKind::Closure(..) => Target::Closure,
+            hir::ExprKind::Closure { .. } => Target::Closure,
             _ => Target::Expression,
         };
 
@@ -2487,7 +2502,7 @@ fn check_duplicates(
                         db.span_note(other, "attribute also specified here").span_suggestion(
                             this,
                             "remove this attribute",
-                            String::new(),
+                            "",
                             Applicability::MachineApplicable,
                         );
                         if matches!(duplicates, FutureWarnFollowing | FutureWarnPreceding) {
@@ -2522,7 +2537,7 @@ fn check_duplicates(
                     .span_suggestion(
                         this,
                         "remove this attribute",
-                        String::new(),
+                        "",
                         Applicability::MachineApplicable,
                     )
                     .emit();
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index b09d9831d43..80a263f4cb2 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -405,7 +405,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
                 }
                 intravisit::walk_expr(self, expr);
             }
-            hir::ExprKind::Closure(..) => {
+            hir::ExprKind::Closure { .. } => {
                 // Interesting control flow (for loops can contain labeled
                 // breaks or continues)
                 self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
@@ -833,7 +833,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
             hir::ExprKind::Field(ref e, _) => self.propagate_through_expr(&e, succ),
 
-            hir::ExprKind::Closure(..) => {
+            hir::ExprKind::Closure { .. } => {
                 debug!("{:?} is an ExprKind::Closure", expr);
 
                 // the construction of a closure itself is not important,
@@ -1387,7 +1387,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
         | hir::ExprKind::AddrOf(..)
         | hir::ExprKind::Struct(..)
         | hir::ExprKind::Repeat(..)
-        | hir::ExprKind::Closure(..)
+        | hir::ExprKind::Closure { .. }
         | hir::ExprKind::Path(_)
         | hir::ExprKind::Yield(..)
         | hir::ExprKind::Box(..)
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index e0dac09870d..9cfef26fd03 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -57,14 +57,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
             hir::ExprKind::Loop(ref b, _, source, _) => {
                 self.with_context(Loop(source), |v| v.visit_block(&b));
             }
-            hir::ExprKind::Closure(_, ref function_decl, b, span, movability) => {
+            hir::ExprKind::Closure { ref fn_decl, body, fn_decl_span, movability, .. } => {
                 let cx = if let Some(Movability::Static) = movability {
-                    AsyncClosure(span)
+                    AsyncClosure(fn_decl_span)
                 } else {
-                    Closure(span)
+                    Closure(fn_decl_span)
                 };
-                self.visit_fn_decl(&function_decl);
-                self.with_context(cx, |v| v.visit_nested_body(b));
+                self.visit_fn_decl(&fn_decl);
+                self.with_context(cx, |v| v.visit_nested_body(body));
             }
             hir::ExprKind::Block(ref b, Some(_label)) => {
                 self.with_context(LabeledBlock, |v| v.visit_block(&b));
@@ -166,7 +166,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
                                             break_expr.span,
                                             "alternatively, you might have meant to use the \
                                              available loop label",
-                                            label.ident.to_string(),
+                                            label.ident,
                                             Applicability::MaybeIncorrect,
                                         );
                                     }
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 83f728d4076..40844b84af0 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -212,7 +212,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
             | ExprKind::Loop(..)
             | ExprKind::Match(..)
             | ExprKind::If(..)
-            | ExprKind::Closure(..)
+            | ExprKind::Closure { .. }
             | ExprKind::Assign(..)
             | ExprKind::AssignOp(..)
             | ExprKind::Field(..)
@@ -308,7 +308,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
                 last_span,
                 "consider specifying that the asm block is responsible \
                 for returning from the function",
-                String::from(", options(noreturn)"),
+                ", options(noreturn)",
                 Applicability::MachineApplicable,
             )
             .emit();
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 75376cdc592..6e622ff031e 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -273,7 +273,7 @@ impl<'tcx> ReachableContext<'tcx> {
                 }
                 hir::ImplItemKind::TyAlias(_) => {}
             },
-            Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., body, _, _), .. }) => {
+            Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { body, .. }, .. }) => {
                 self.visit_nested_body(body);
             }
             // Nothing to recurse on for these
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 144a60faad2..9eaefc8b8aa 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -125,7 +125,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
                         .span_suggestion_short(
                             *span,
                             "remove the unnecessary deprecation attribute",
-                            String::new(),
+                            "",
                             rustc_errors::Applicability::MachineApplicable,
                         )
                         .emit();
diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs
index 25fe8e45825..97a461272b4 100644
--- a/compiler/rustc_passes/src/upvars.rs
+++ b/compiler/rustc_passes/src/upvars.rs
@@ -75,7 +75,7 @@ impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> {
     }
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-        if let hir::ExprKind::Closure(..) = expr.kind {
+        if let hir::ExprKind::Closure { .. } = expr.kind {
             let closure_def_id = self.tcx.hir().local_def_id(expr.hir_id);
             if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
                 // Every capture of a closure expression is a local in scope,
diff --git a/compiler/rustc_plugin_impl/Cargo.toml b/compiler/rustc_plugin_impl/Cargo.toml
index f5071eb6e8f..b6ea533c80b 100644
--- a/compiler/rustc_plugin_impl/Cargo.toml
+++ b/compiler/rustc_plugin_impl/Cargo.toml
@@ -9,9 +9,7 @@ doctest = false
 
 [dependencies]
 libloading = "0.7.1"
-rustc_middle = { path = "../rustc_middle" }
 rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_lint = { path = "../rustc_lint" }
 rustc_metadata = { path = "../rustc_metadata" }
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index e77e5a3ca02..b27c986d0f9 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1981,7 +1981,7 @@ fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility {
             match tcx.hir().get(hir_id) {
                 // Unique types created for closures participate in type privacy checking.
                 // They have visibilities inherited from the module they are defined in.
-                Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. })
+                Node::Expr(hir::Expr { kind: hir::ExprKind::Closure{..}, .. })
                 // - AST lowering creates dummy `use` items which don't
                 //   get their entries in the resolver's visibility table.
                 // - AST lowering also creates opaque type items with inherited visibilities.
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index 856f09b6fcc..5673bb83b15 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -20,7 +20,6 @@ rustc_query_system = { path = "../rustc_query_system" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-rustc_type_ir = { path = "../rustc_type_ir" }
 tracing = "0.1"
 
 [features]
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index c2c876f7f1a..d7327ca4bc6 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_query_system::dep_graph::DepContext;
 use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffects};
 use rustc_serialize::{
-    opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
+    opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder},
     Decodable, Decoder, Encodable, Encoder,
 };
 use rustc_session::Session;
@@ -158,7 +158,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
 
         // Wrap in a scope so we can borrow `data`.
         let footer: Footer = {
-            let mut decoder = opaque::Decoder::new(&data, start_pos);
+            let mut decoder = MemDecoder::new(&data, start_pos);
 
             // Decode the *position* of the footer, which can be found in the
             // last 8 bytes of the file.
@@ -437,7 +437,7 @@ impl<'sess> OnDiskCache<'sess> {
         let serialized_data = self.serialized_data.read();
         let mut decoder = CacheDecoder {
             tcx,
-            opaque: opaque::Decoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()),
+            opaque: MemDecoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()),
             source_map: self.source_map,
             file_index_to_file: &self.file_index_to_file,
             file_index_to_stable_id: &self.file_index_to_stable_id,
@@ -458,7 +458,7 @@ impl<'sess> OnDiskCache<'sess> {
 /// will also handle things that contain `Ty` instances.
 pub struct CacheDecoder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    opaque: opaque::Decoder<'a>,
+    opaque: MemDecoder<'a>,
     source_map: &'a SourceMap,
     file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
     file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
@@ -510,7 +510,7 @@ trait DecoderWithPosition: Decoder {
     fn position(&self) -> usize;
 }
 
-impl<'a> DecoderWithPosition for opaque::Decoder<'a> {
+impl<'a> DecoderWithPosition for MemDecoder<'a> {
     fn position(&self) -> usize {
         self.position()
     }
@@ -586,7 +586,7 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> {
     {
         debug_assert!(pos < self.opaque.data.len());
 
-        let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
+        let new_opaque = MemDecoder::new(self.opaque.data, pos);
         let old_opaque = mem::replace(&mut self.opaque, new_opaque);
         let r = f(self);
         self.opaque = old_opaque;
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index b20aa7b5346..551f094209e 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -275,6 +275,9 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
             let query_name = profiler.get_or_alloc_cached_string(query_name);
             let event_id = event_id_builder.from_label(query_name).to_string_id();
 
+            // FIXME(eddyb) make this O(1) by using a pre-cached query name `EventId`,
+            // instead of passing the `DepNodeIndex` to `finish_with_query_invocation_id`,
+            // when recording the event in the first place.
             let mut query_invocation_ids = Vec::new();
             query_cache.iter(&mut |_, _, i| {
                 query_invocation_ids.push(i.into());
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 85fbb08eeeb..b5a37cf324b 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -21,7 +21,6 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
-rustc_type_ir = { path = "../rustc_type_ir" }
 parking_lot = "0.11"
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
 
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index 7fde9c0119b..d583b45698a 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -19,7 +19,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sync::Lock;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_serialize::opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize};
+use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use smallvec::SmallVec;
 use std::convert::TryInto;
@@ -96,11 +96,11 @@ impl<K: DepKind> SerializedDepGraph<K> {
     }
 }
 
-impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>>
+impl<'a, K: DepKind + Decodable<MemDecoder<'a>>> Decodable<MemDecoder<'a>>
     for SerializedDepGraph<K>
 {
     #[instrument(level = "debug", skip(d))]
-    fn decode(d: &mut opaque::Decoder<'a>) -> SerializedDepGraph<K> {
+    fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph<K> {
         let start_position = d.position();
 
         // The last 16 bytes are the node count and edge count.
diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs
index 03ef8578eb7..7e36eadd62c 100644
--- a/compiler/rustc_query_system/src/ich/hcx.rs
+++ b/compiler/rustc_query_system/src/ich/hcx.rs
@@ -1,6 +1,5 @@
 use crate::ich;
 use rustc_ast as ast;
-use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
 use rustc_data_structures::sync::Lrc;
@@ -13,11 +12,6 @@ use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
 
-fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
-    debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty());
-    ich::IGNORED_ATTRIBUTES.iter().copied().collect()
-}
-
 /// This is the context state available during incr. comp. hashing. It contains
 /// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e.,
 /// a reference to the `TyCtxt`) and it holds a few caches for speeding up various
@@ -161,10 +155,7 @@ impl<'a> StableHashingContext<'a> {
 
     #[inline]
     pub fn is_ignored_attr(&self, name: Symbol) -> bool {
-        thread_local! {
-            static IGNORED_ATTRIBUTES: FxHashSet<Symbol> = compute_ignored_attr_names();
-        }
-        IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name))
+        ich::IGNORED_ATTRIBUTES.contains(&name)
     }
 
     #[inline]
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index f8fa7a0941d..b0e7679af97 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -10,7 +10,9 @@ use crate::imports::{Import, ImportKind};
 use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
 use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
-use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError};
+use crate::{
+    MacroData, NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError,
+};
 use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError};
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
@@ -20,7 +22,6 @@ use rustc_ast_lowering::ResolverAstLowering;
 use rustc_attr as attr;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{struct_span_err, Applicability};
-use rustc_expand::base::SyntaxExtension;
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def::{self, *};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
@@ -180,26 +181,32 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    pub(crate) fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
+    pub(crate) fn get_macro(&mut self, res: Res) -> Option<MacroData> {
         match res {
             Res::Def(DefKind::Macro(..), def_id) => Some(self.get_macro_by_def_id(def_id)),
-            Res::NonMacroAttr(_) => Some(self.non_macro_attr.clone()),
+            Res::NonMacroAttr(_) => {
+                Some(MacroData { ext: self.non_macro_attr.clone(), macro_rules: false })
+            }
             _ => None,
         }
     }
 
-    pub(crate) fn get_macro_by_def_id(&mut self, def_id: DefId) -> Lrc<SyntaxExtension> {
-        if let Some(ext) = self.macro_map.get(&def_id) {
-            return ext.clone();
+    pub(crate) fn get_macro_by_def_id(&mut self, def_id: DefId) -> MacroData {
+        if let Some(macro_data) = self.macro_map.get(&def_id) {
+            return macro_data.clone();
         }
 
-        let ext = Lrc::new(match self.cstore().load_macro_untracked(def_id, &self.session) {
-            LoadedMacro::MacroDef(item, edition) => self.compile_macro(&item, edition).0,
-            LoadedMacro::ProcMacro(ext) => ext,
-        });
+        let (ext, macro_rules) = match self.cstore().load_macro_untracked(def_id, &self.session) {
+            LoadedMacro::MacroDef(item, edition) => (
+                Lrc::new(self.compile_macro(&item, edition).0),
+                matches!(item.kind, ItemKind::MacroDef(def) if def.macro_rules),
+            ),
+            LoadedMacro::ProcMacro(extz) => (Lrc::new(extz), false),
+        };
 
-        self.macro_map.insert(def_id, ext.clone());
-        ext
+        let macro_data = MacroData { ext, macro_rules };
+        self.macro_map.insert(def_id, macro_data.clone());
+        macro_data
     }
 
     pub(crate) fn build_reduced_graph(
@@ -1251,7 +1258,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         };
 
         let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id.to_def_id());
-        self.r.macro_map.insert(def_id.to_def_id(), ext);
+        self.r.macro_map.insert(def_id.to_def_id(), MacroData { ext, macro_rules });
         self.r.local_macro_def_scopes.insert(def_id, parent_scope.module);
 
         if macro_rules {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index b1fe418f687..3b70b90c871 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -271,7 +271,7 @@ impl<'a> Resolver<'a> {
                 err.tool_only_span_suggestion(
                     import.use_span_with_attributes,
                     "remove unnecessary import",
-                    String::new(),
+                    "",
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -396,19 +396,14 @@ impl<'a> Resolver<'a> {
         // previous imports.
         if found_closing_brace {
             if let Some(span) = extend_span_to_previous_binding(self.session, span) {
-                err.tool_only_span_suggestion(
-                    span,
-                    message,
-                    String::new(),
-                    Applicability::MaybeIncorrect,
-                );
+                err.tool_only_span_suggestion(span, message, "", Applicability::MaybeIncorrect);
             } else {
                 // Remove the entire line if we cannot extend the span back, this indicates an
                 // `issue_52891::{self}` case.
                 err.span_suggestion(
                     import.use_span_with_attributes,
                     message,
-                    String::new(),
+                    "",
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -416,7 +411,7 @@ impl<'a> Resolver<'a> {
             return;
         }
 
-        err.span_suggestion(span, message, String::new(), Applicability::MachineApplicable);
+        err.span_suggestion(span, message, "", Applicability::MachineApplicable);
     }
 
     pub(crate) fn lint_if_path_starts_with_module(
@@ -763,7 +758,7 @@ impl<'a> Resolver<'a> {
                         err.span_suggestion(
                             span,
                             "try using similarly named label",
-                            ident.name.to_string(),
+                            ident.name,
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -796,7 +791,7 @@ impl<'a> Resolver<'a> {
                     err.span_suggestion(
                         span,
                         "consider importing the module directly",
-                        "".to_string(),
+                        "",
                         Applicability::MachineApplicable,
                     );
 
@@ -1007,7 +1002,7 @@ impl<'a> Resolver<'a> {
                         err.span_suggestion(
                             span,
                             "try using similarly named label",
-                            ident.name.to_string(),
+                            ident.name,
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -1618,12 +1613,7 @@ impl<'a> Resolver<'a> {
                 format!("maybe you meant this {}", suggestion.res.descr())
             }
         };
-        err.span_suggestion(
-            span,
-            &msg,
-            suggestion.candidate.to_string(),
-            Applicability::MaybeIncorrect,
-        );
+        err.span_suggestion(span, &msg, suggestion.candidate, Applicability::MaybeIncorrect);
         true
     }
 
@@ -2535,7 +2525,7 @@ fn show_candidates(
                 err.span_suggestion_verbose(
                     first.ident.span.until(last.ident.span),
                     &format!("if you import `{}`, refer to it directly", last.ident),
-                    String::new(),
+                    "",
                     Applicability::Unspecified,
                 );
             }
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index b25393c3ed8..e934e189f05 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -241,7 +241,7 @@ impl<'a> Resolver<'a> {
                 {
                     // The macro is a proc macro derive
                     if let Some(def_id) = module.expansion.expn_data().macro_def_id {
-                        let ext = self.get_macro_by_def_id(def_id);
+                        let ext = self.get_macro_by_def_id(def_id).ext;
                         if ext.builtin_name.is_none()
                             && ext.macro_kind() == MacroKind::Derive
                             && parent.expansion.outer_expn_is_descendant_of(*ctxt)
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index de83a3a5932..c6aa57f039d 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -12,7 +12,7 @@ use rustc_ast::NodeId;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
-use rustc_hir::def::{self, PartialRes};
+use rustc_hir::def::{self, DefKind, PartialRes};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::span_bug;
 use rustc_middle::ty;
@@ -922,11 +922,28 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                         .note(&format!("consider declaring type or module `{}` with `pub`", ident))
                         .emit();
                 } else {
-                    let note_msg =
-                        format!("consider marking `{}` as `pub` in the imported module", ident);
-                    struct_span_err!(self.r.session, import.span, E0364, "{}", error_msg)
-                        .span_note(import.span, &note_msg)
-                        .emit();
+                    let mut err =
+                        struct_span_err!(self.r.session, import.span, E0364, "{error_msg}");
+                    match binding.kind {
+                        NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id), _)
+                            // exclude decl_macro
+                            if self.r.get_macro_by_def_id(def_id).macro_rules =>
+                        {
+                            err.span_help(
+                                binding.span,
+                                "consider adding a `#[macro_export]` to the macro in the imported module",
+                            );
+                        }
+                        _ => {
+                            err.span_note(
+                                import.span,
+                                &format!(
+                                    "consider marking `{ident}` as `pub` in the imported module"
+                                ),
+                            );
+                        }
+                    }
+                    err.emit();
                 }
             }
         }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 68ddc37c3a8..460d505ba98 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -280,7 +280,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     err.span_suggestion_verbose(
                         expr_span.shrink_to_lo(),
                         "you might have meant to use pattern matching",
-                        "let ".to_string(),
+                        "let ",
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -294,7 +294,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             err.span_suggestion_short(
                 span,
                 "you might have meant to use `self` here instead",
-                "self".to_string(),
+                "self",
                 Applicability::MaybeIncorrect,
             );
             if !self.self_value_is_available(path[0].ident.span) {
@@ -317,7 +317,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         span,
                         "if you meant to use `self`, you are also missing a `self` receiver \
                          argument",
-                        sugg.to_string(),
+                        sugg,
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -376,7 +376,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         err.span_suggestion_verbose(
                             span,
                             "add a `self` receiver parameter to make the associated `fn` a method",
-                            sugg.to_string(),
+                            sugg,
                             Applicability::MaybeIncorrect,
                         );
                         "doesn't"
@@ -396,7 +396,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
 
         // Try to lookup name in more relaxed fashion for better error reporting.
         let ident = path.last().unwrap().ident;
-        let candidates = self
+        let mut candidates = self
             .r
             .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
             .into_iter()
@@ -408,6 +408,18 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             })
             .collect::<Vec<_>>();
         let crate_def_id = CRATE_DEF_ID.to_def_id();
+        // Try to filter out intrinsics candidates, as long as we have
+        // some other candidates to suggest.
+        let intrinsic_candidates: Vec<_> = candidates
+            .drain_filter(|sugg| {
+                let path = path_names_to_string(&sugg.path);
+                path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::")
+            })
+            .collect();
+        if candidates.is_empty() {
+            // Put them back if we have no more candidates to suggest...
+            candidates.extend(intrinsic_candidates);
+        }
         if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) {
             let mut enum_candidates: Vec<_> = self
                 .r
@@ -612,7 +624,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         err.span_suggestion_short(
                             pat_sp.between(ty_sp),
                             "use `=` if you meant to assign",
-                            " = ".to_string(),
+                            " = ",
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -642,7 +654,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                                 err.span_suggestion(
                                     span,
                                     "use the similarly named label",
-                                    label_ident.name.to_string(),
+                                    label_ident.name,
                                     Applicability::MaybeIncorrect,
                                 );
                                 // Do not lint against unused label when we suggest them.
@@ -656,7 +668,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     err.span_suggestion(
                         span,
                         "perhaps you intended to use this type",
-                        correct.to_string(),
+                        correct,
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -687,7 +699,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         err.span_suggestion_verbose(
                             constraint.ident.span.between(trait_ref.span),
                             "you might have meant to write a path instead of an associated type bound",
-                            "::".to_string(),
+                            "::",
                             Applicability::MachineApplicable,
                         );
                     }
@@ -1079,7 +1091,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 err.span_suggestion_verbose(
                     span.shrink_to_hi(),
                     "use `!` to invoke the macro",
-                    "!".to_string(),
+                    "!",
                     Applicability::MaybeIncorrect,
                 );
                 if path_str == "try" && span.rust_2015() {
@@ -1228,7 +1240,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         err.span_suggestion(
                             span,
                             "use this syntax instead",
-                            path_str.to_string(),
+                            path_str,
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -1507,7 +1519,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         err.span_suggestion_short(
                             colon_sp,
                             "maybe you meant to write `;` here",
-                            ";".to_string(),
+                            ";",
                             Applicability::MaybeIncorrect,
                         );
                     } else {
@@ -1518,7 +1530,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                             err.span_suggestion(
                                 colon_sp,
                                 "maybe you meant to write a path separator here",
-                                "::".to_string(),
+                                "::",
                                 Applicability::MaybeIncorrect,
                             );
                             show_label = false;
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 92a65fe249f..ac4e23cc04d 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -866,6 +866,12 @@ struct DeriveData {
     has_derive_copy: bool,
 }
 
+#[derive(Clone)]
+struct MacroData {
+    ext: Lrc<SyntaxExtension>,
+    macro_rules: bool,
+}
+
 /// The main resolver class.
 ///
 /// This is the visitor that walks the whole crate.
@@ -965,7 +971,7 @@ pub struct Resolver<'a> {
     registered_attrs: FxHashSet<Ident>,
     registered_tools: RegisteredTools,
     macro_use_prelude: FxHashMap<Symbol, &'a NameBinding<'a>>,
-    macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
+    macro_map: FxHashMap<DefId, MacroData>,
     dummy_ext_bang: Lrc<SyntaxExtension>,
     dummy_ext_derive: Lrc<SyntaxExtension>,
     non_macro_attr: Lrc<SyntaxExtension>,
@@ -1522,7 +1528,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn is_builtin_macro(&mut self, res: Res) -> bool {
-        self.get_macro(res).map_or(false, |ext| ext.builtin_name.is_some())
+        self.get_macro(res).map_or(false, |macro_data| macro_data.ext.builtin_name.is_some())
     }
 
     fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 3fb34cdcd9b..c86c2280d19 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -658,7 +658,7 @@ impl<'a> Resolver<'a> {
             res
         };
 
-        res.map(|res| (self.get_macro(res), res))
+        res.map(|res| (self.get_macro(res).map(|macro_data| macro_data.ext), res))
     }
 
     pub(crate) fn finalize_macro_resolutions(&mut self) {
@@ -853,7 +853,7 @@ impl<'a> Resolver<'a> {
         // Reserve some names that are not quite covered by the general check
         // performed on `Resolver::builtin_attrs`.
         if ident.name == sym::cfg || ident.name == sym::cfg_attr {
-            let macro_kind = self.get_macro(res).map(|ext| ext.macro_kind());
+            let macro_kind = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kind());
             if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
                 self.session.span_err(
                     ident.span,
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index fe417f45e88..6eb2f2d929d 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -1360,15 +1360,15 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
                     }
                 }
             }
-            hir::ExprKind::Closure(_, ref decl, body, _fn_decl_span, _) => {
+            hir::ExprKind::Closure { ref fn_decl, body, .. } => {
                 let id = format!("${}", ex.hir_id);
 
                 // walk arg and return types
-                for ty in decl.inputs {
+                for ty in fn_decl.inputs {
                     self.visit_ty(ty);
                 }
 
-                if let hir::FnRetTy::Return(ref ret_ty) = decl.output {
+                if let hir::FnRetTy::Return(ref ret_ty) = fn_decl.output {
                     self.visit_ty(ret_ty);
                 }
 
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index b2dbf937eb7..f828c0b7106 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -1,5 +1,5 @@
 use crate::leb128::{self, max_leb128_len};
-use crate::serialize::{self, Decoder as _, Encoder as _};
+use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::convert::TryInto;
 use std::fs::File;
 use std::io::{self, Write};
@@ -11,13 +11,13 @@ use std::ptr;
 // Encoder
 // -----------------------------------------------------------------------------
 
-pub struct Encoder {
+pub struct MemEncoder {
     pub data: Vec<u8>,
 }
 
-impl Encoder {
-    pub fn new() -> Encoder {
-        Encoder { data: vec![] }
+impl MemEncoder {
+    pub fn new() -> MemEncoder {
+        MemEncoder { data: vec![] }
     }
 
     #[inline]
@@ -53,7 +53,7 @@ macro_rules! write_leb128 {
 /// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout
 const STR_SENTINEL: u8 = 0xC1;
 
-impl serialize::Encoder for Encoder {
+impl Encoder for MemEncoder {
     type Ok = Vec<u8>;
     type Err = !;
 
@@ -161,7 +161,7 @@ pub type FileEncodeResult = Result<usize, io::Error>;
 // `FileEncoder` encodes data to file via fixed-size buffer.
 //
 // When encoding large amounts of data to a file, using `FileEncoder` may be
-// preferred over using `Encoder` to encode to a `Vec`, and then writing the
+// preferred over using `MemEncoder` to encode to a `Vec`, and then writing the
 // `Vec` to file, as the latter uses as much memory as there is encoded data,
 // while the former uses the fixed amount of memory allocated to the buffer.
 // `FileEncoder` also has the advantage of not needing to reallocate as data
@@ -425,7 +425,7 @@ macro_rules! file_encoder_write_leb128 {
     }};
 }
 
-impl serialize::Encoder for FileEncoder {
+impl Encoder for FileEncoder {
     type Ok = usize;
     type Err = io::Error;
 
@@ -535,15 +535,15 @@ impl serialize::Encoder for FileEncoder {
 // Decoder
 // -----------------------------------------------------------------------------
 
-pub struct Decoder<'a> {
+pub struct MemDecoder<'a> {
     pub data: &'a [u8],
     position: usize,
 }
 
-impl<'a> Decoder<'a> {
+impl<'a> MemDecoder<'a> {
     #[inline]
-    pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> {
-        Decoder { data, position }
+    pub fn new(data: &'a [u8], position: usize) -> MemDecoder<'a> {
+        MemDecoder { data, position }
     }
 
     #[inline]
@@ -566,7 +566,7 @@ macro_rules! read_leb128 {
     ($dec:expr, $fun:ident) => {{ leb128::$fun($dec.data, &mut $dec.position) }};
 }
 
-impl<'a> serialize::Decoder for Decoder<'a> {
+impl<'a> Decoder for MemDecoder<'a> {
     #[inline]
     fn read_u128(&mut self) -> u128 {
         read_leb128!(self, read_u128_leb128)
@@ -688,25 +688,25 @@ impl<'a> serialize::Decoder for Decoder<'a> {
 
 // Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
 // since the default implementations call `encode` on their slices internally.
-impl serialize::Encodable<Encoder> for [u8] {
-    fn encode(&self, e: &mut Encoder) {
-        serialize::Encoder::emit_usize(e, self.len());
+impl Encodable<MemEncoder> for [u8] {
+    fn encode(&self, e: &mut MemEncoder) {
+        Encoder::emit_usize(e, self.len());
         e.emit_raw_bytes(self);
     }
 }
 
-impl serialize::Encodable<FileEncoder> for [u8] {
+impl Encodable<FileEncoder> for [u8] {
     fn encode(&self, e: &mut FileEncoder) {
-        serialize::Encoder::emit_usize(e, self.len());
+        Encoder::emit_usize(e, self.len());
         e.emit_raw_bytes(self);
     }
 }
 
 // Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc.,
 // since the default implementations call `decode` to produce a `Vec<u8>` internally.
-impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> {
-    fn decode(d: &mut Decoder<'a>) -> Self {
-        let len = serialize::Decoder::read_usize(d);
+impl<'a> Decodable<MemDecoder<'a>> for Vec<u8> {
+    fn decode(d: &mut MemDecoder<'a>) -> Self {
+        let len = Decoder::read_usize(d);
         d.read_raw_bytes(len).to_owned()
     }
 }
@@ -718,9 +718,9 @@ impl IntEncodedWithFixedSize {
     pub const ENCODED_SIZE: usize = 8;
 }
 
-impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize {
+impl Encodable<MemEncoder> for IntEncodedWithFixedSize {
     #[inline]
-    fn encode(&self, e: &mut Encoder) {
+    fn encode(&self, e: &mut MemEncoder) {
         let _start_pos = e.position();
         e.emit_raw_bytes(&self.0.to_le_bytes());
         let _end_pos = e.position();
@@ -728,7 +728,7 @@ impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize {
     }
 }
 
-impl serialize::Encodable<FileEncoder> for IntEncodedWithFixedSize {
+impl Encodable<FileEncoder> for IntEncodedWithFixedSize {
     #[inline]
     fn encode(&self, e: &mut FileEncoder) {
         let _start_pos = e.position();
@@ -738,9 +738,9 @@ impl serialize::Encodable<FileEncoder> for IntEncodedWithFixedSize {
     }
 }
 
-impl<'a> serialize::Decodable<Decoder<'a>> for IntEncodedWithFixedSize {
+impl<'a> Decodable<MemDecoder<'a>> for IntEncodedWithFixedSize {
     #[inline]
-    fn decode(decoder: &mut Decoder<'a>) -> IntEncodedWithFixedSize {
+    fn decode(decoder: &mut MemDecoder<'a>) -> IntEncodedWithFixedSize {
         let _start_pos = decoder.position();
         let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE);
         let value = u64::from_le_bytes(bytes.try_into().unwrap());
diff --git a/compiler/rustc_serialize/tests/opaque.rs b/compiler/rustc_serialize/tests/opaque.rs
index 703b7f5e7a5..4eafb6fabde 100644
--- a/compiler/rustc_serialize/tests/opaque.rs
+++ b/compiler/rustc_serialize/tests/opaque.rs
@@ -1,7 +1,7 @@
 #![allow(rustc::internal)]
 
 use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque::{Decoder, Encoder};
+use rustc_serialize::opaque::{MemDecoder, MemEncoder};
 use rustc_serialize::{Decodable, Encodable, Encoder as EncoderTrait};
 use std::fmt::Debug;
 
@@ -28,16 +28,18 @@ struct Struct {
     q: Option<u32>,
 }
 
-fn check_round_trip<T: Encodable<Encoder> + for<'a> Decodable<Decoder<'a>> + PartialEq + Debug>(
+fn check_round_trip<
+    T: Encodable<MemEncoder> + for<'a> Decodable<MemDecoder<'a>> + PartialEq + Debug,
+>(
     values: Vec<T>,
 ) {
-    let mut encoder = Encoder::new();
+    let mut encoder = MemEncoder::new();
     for value in &values {
         Encodable::encode(value, &mut encoder);
     }
 
     let data = encoder.finish().unwrap();
-    let mut decoder = Decoder::new(&data[..], 0);
+    let mut decoder = MemDecoder::new(&data[..], 0);
 
     for value in values {
         let decoded = Decodable::decode(&mut decoder);
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 59b4981dd01..044be906b55 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -5,6 +5,7 @@
 #![feature(never_type)]
 #![feature(once_cell)]
 #![feature(option_get_or_insert_default)]
+#![feature(rustc_attrs)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 007fa87189f..441e1f9f6a2 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1473,6 +1473,12 @@ options! {
         for example: `-Z self-profile-events=default,query-keys`
         all options: none, all, default, generic-activity, query-provider, query-cache-hit
                      query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes"),
+    self_profile_counter: String = ("wall-time".to_string(), parse_string, [UNTRACKED],
+        "counter used by the self profiler (default: `wall-time`), one of:
+        `wall-time` (monotonic clock, i.e. `std::time::Instant`)
+        `instructions:u` (retired instructions, userspace-only)
+        `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy)"
+    ),
     share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "make the current crate share its generic instantiations"),
     show_span: Option<String> = (None, parse_opt_string, [TRACKED],
@@ -1579,6 +1585,9 @@ options! {
         "in general, enable more debug printouts (default: no)"),
     verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
         "verify LLVM IR (default: no)"),
+    virtual_function_elimination: bool = (false, parse_bool, [TRACKED],
+        "enables dead virtual function elimination optimization. \
+        Requires `-Clto[=[fat,yes]]`"),
     wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
         "whether to build a wasi command or reactor"),
 
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 6fb87e15a33..a5ccae047fc 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -311,6 +311,7 @@ impl ParseSess {
         self.create_warning(warning).emit()
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_err(
         &self,
         msg: impl Into<DiagnosticMessage>,
@@ -318,6 +319,7 @@ impl ParseSess {
         self.span_diagnostic.struct_err(msg)
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         self.span_diagnostic.struct_warn(msg)
     }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index b2c23cda6aa..2186456576a 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -209,6 +209,7 @@ pub struct PerfStats {
 
 /// Trait implemented by error types. This should not be implemented manually. Instead, use
 /// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic].
+#[rustc_diagnostic_item = "SessionDiagnostic"]
 pub trait SessionDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> {
     /// Write out as a diagnostic out of `sess`.
     #[must_use]
@@ -1252,7 +1253,8 @@ pub fn build_session(
         let profiler = SelfProfiler::new(
             directory,
             sopts.crate_name.as_deref(),
-            &sopts.debugging_opts.self_profile_events,
+            sopts.debugging_opts.self_profile_events.as_ref().map(|xs| &xs[..]),
+            &sopts.debugging_opts.self_profile_counter,
         );
         match profiler {
             Ok(profiler) => Some(Arc::new(profiler)),
@@ -1431,14 +1433,14 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         );
     }
 
-    // LLVM CFI requires LTO.
-    if sess.is_sanitizer_cfi_enabled() {
-        if sess.opts.cg.lto == config::LtoCli::Unspecified
-            || sess.opts.cg.lto == config::LtoCli::No
-            || sess.opts.cg.lto == config::LtoCli::Thin
-        {
+    // LLVM CFI and VFE both require LTO.
+    if sess.lto() != config::Lto::Fat {
+        if sess.is_sanitizer_cfi_enabled() {
             sess.err("`-Zsanitizer=cfi` requires `-Clto`");
         }
+        if sess.opts.debugging_opts.virtual_function_elimination {
+            sess.err("`-Zvirtual-function-elimination` requires `-Clto`");
+        }
     }
 
     if sess.opts.debugging_opts.stack_protector != StackProtector::None {
diff --git a/compiler/rustc_smir/.gitignore b/compiler/rustc_smir/.gitignore
new file mode 100644
index 00000000000..eb5a316cbd1
--- /dev/null
+++ b/compiler/rustc_smir/.gitignore
@@ -0,0 +1 @@
+target
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
new file mode 100644
index 00000000000..5e0d1f369a6
--- /dev/null
+++ b/compiler/rustc_smir/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+name = "rustc_smir"
+version = "0.0.0"
+edition = "2021"
+
+[dependencies]
+rustc_borrowck = { path = "../rustc_borrowck", optional = true }
+rustc_driver = { path = "../rustc_driver", optional = true }
+rustc_hir = { path = "../rustc_hir", optional = true }
+rustc_interface = { path = "../rustc_interface", optional = true }
+rustc_middle = { path = "../rustc_middle", optional = true }
+rustc_mir_dataflow = { path = "../rustc_mir_dataflow", optional = true }
+rustc_mir_transform = { path = "../rustc_mir_transform", optional = true }
+rustc_serialize = { path = "../rustc_serialize", optional = true }
+rustc_trait_selection = { path = "../rustc_trait_selection", optional = true }
+
+[features]
+default = [
+    "rustc_borrowck",
+    "rustc_driver",
+    "rustc_hir",
+    "rustc_interface",
+    "rustc_middle",
+    "rustc_mir_dataflow",
+    "rustc_mir_transform",
+    "rustc_serialize",
+    "rustc_trait_selection",
+]
diff --git a/compiler/rustc_smir/README.md b/compiler/rustc_smir/README.md
new file mode 100644
index 00000000000..ae49098dd0c
--- /dev/null
+++ b/compiler/rustc_smir/README.md
@@ -0,0 +1,75 @@
+This crate is regularly synced with its mirror in the rustc repo at `compiler/rustc_smir`.
+
+We use `git subtree` for this to preserve commits and allow the rustc repo to
+edit these crates without having to touch this repo. This keeps the crates compiling
+while allowing us to independently work on them here. The effort of keeping them in
+sync is pushed entirely onto us, without affecting rustc workflows negatively.
+This may change in the future, but changes to policy should only be done via a
+compiler team MCP.
+
+## Instructions for working on this crate locally
+
+Since the crate is the same in the rustc repo and here, the dependencies on rustc_* crates
+will only either work here or there, but never in both places at the same time. Thus we use
+optional dependencies on the rustc_* crates, requiring local development to use
+
+```
+cargo build --no-default-features -Zavoid-dev-deps
+```
+
+in order to compile successfully.
+
+## Instructions for syncing
+
+### Updating this repository
+
+In the rustc repo, execute
+
+```
+git subtree push --prefix=compiler/rustc_smir url_to_your_fork_of_project_stable_mir some_feature_branch
+```
+
+and then open a PR of your `some_feature_branch` against https://github.com/rust-lang/project-stable-mir
+
+### Updating the rustc library
+
+First we need to bump our stack limit, as the rustc repo otherwise quickly hits that:
+
+```
+ulimit -s 60000
+```
+
+#### Maximum function recursion depth (1000) reached
+
+Then we need to disable `dash` as the default shell for sh scripts, as otherwise we run into a
+hard limit of a recursion depth of 1000:
+
+```
+sudo dpkg-reconfigure dash
+```
+
+and then select `No` to disable dash.
+
+
+#### Patching your `git worktree`
+
+The regular git worktree does not scale to repos of the size of the rustc repo.
+So download the `git-subtree.sh` from https://github.com/gitgitgadget/git/pull/493/files and run
+
+```
+sudo cp --backup /path/to/patched/git-subtree.sh /usr/lib/git-core/git-subtree
+sudo chmod --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subtree
+sudo chown --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subtree
+```
+
+#### Actually doing a sync
+
+In the rustc repo, execute
+
+```
+git subtree pull --prefix=compiler/rustc_smir https://github.com/rust-lang/project-stable-mir smir
+```
+
+Note: only ever sync to rustc from the project-stable-mir's `smir` branch. Do not sync with your own forks.
+
+Then open a PR against rustc just like a regular PR.
diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/rustc_smir/rust-toolchain.toml
new file mode 100644
index 00000000000..7b696fc1f5c
--- /dev/null
+++ b/compiler/rustc_smir/rust-toolchain.toml
@@ -0,0 +1,3 @@
+[toolchain]
+channel = "nightly-2022-06-01"
+components = [ "rustfmt", "rustc-dev" ]
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
new file mode 100644
index 00000000000..5c7aaf35b90
--- /dev/null
+++ b/compiler/rustc_smir/src/lib.rs
@@ -0,0 +1,17 @@
+//! The WIP stable interface to rustc internals.
+//!
+//! For more information see https://github.com/rust-lang/project-stable-mir
+//!
+//! # Note
+//!
+//! This API is still completely unstable and subject to change.
+
+#![doc(
+    html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
+    test(attr(allow(unused_variables), deny(warnings)))
+)]
+#![cfg_attr(not(feature = "default"), feature(rustc_private))]
+
+pub mod mir;
+
+pub mod very_unstable;
diff --git a/compiler/rustc_smir/src/mir.rs b/compiler/rustc_smir/src/mir.rs
new file mode 100644
index 00000000000..855605b1a4f
--- /dev/null
+++ b/compiler/rustc_smir/src/mir.rs
@@ -0,0 +1,10 @@
+pub use crate::very_unstable::middle::mir::{
+    visit::MutVisitor, AggregateKind, AssertKind, BasicBlock, BasicBlockData, BinOp, BindingForm,
+    BlockTailInfo, Body, BorrowKind, CastKind, ClearCrossCrate, Constant, ConstantKind,
+    CopyNonOverlapping, Coverage, FakeReadCause, Field, GeneratorInfo, ImplicitSelfKind,
+    InlineAsmOperand, Local, LocalDecl, LocalInfo, LocalKind, Location, MirPhase, MirSource,
+    NullOp, Operand, Place, PlaceRef, ProjectionElem, ProjectionKind, Promoted, RetagKind, Rvalue,
+    Safety, SourceInfo, SourceScope, SourceScopeData, SourceScopeLocalData, Statement,
+    StatementKind, UnOp, UserTypeProjection, UserTypeProjections, VarBindingForm, VarDebugInfo,
+    VarDebugInfoContents,
+};
diff --git a/compiler/rustc_smir/src/very_unstable.rs b/compiler/rustc_smir/src/very_unstable.rs
new file mode 100644
index 00000000000..12ba133dbb1
--- /dev/null
+++ b/compiler/rustc_smir/src/very_unstable.rs
@@ -0,0 +1,27 @@
+//! This module reexports various crates and modules from unstable rustc APIs.
+//! Add anything you need here and it will get slowly transferred to a stable API.
+//! Only use rustc_smir in your dependencies and use the reexports here instead of
+//! directly referring to the unstable crates.
+
+macro_rules! crates {
+    ($($rustc_name:ident -> $name:ident,)*) => {
+        $(
+            #[cfg(not(feature = "default"))]
+            pub extern crate $rustc_name as $name;
+            #[cfg(feature = "default")]
+            pub use $rustc_name as $name;
+        )*
+    }
+}
+
+crates! {
+    rustc_borrowck -> borrowck,
+    rustc_driver -> driver,
+    rustc_hir -> hir,
+    rustc_interface -> interface,
+    rustc_middle -> middle,
+    rustc_mir_dataflow -> dataflow,
+    rustc_mir_transform -> transform,
+    rustc_serialize -> serialize,
+    rustc_trait_selection -> trait_selection,
+}
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index d7e2f621065..5d3d56b1e66 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1911,13 +1911,13 @@ impl_pos! {
     pub struct CharPos(pub usize);
 }
 
-impl<S: rustc_serialize::Encoder> Encodable<S> for BytePos {
+impl<S: Encoder> Encodable<S> for BytePos {
     fn encode(&self, s: &mut S) {
         s.emit_u32(self.0);
     }
 }
 
-impl<D: rustc_serialize::Decoder> Decodable<D> for BytePos {
+impl<D: Decoder> Decodable<D> for BytePos {
     fn decode(d: &mut D) -> BytePos {
         BytePos(d.read_u32())
     }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7b0fa65e808..11ca017ed95 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -125,6 +125,7 @@ symbols! {
     Symbols {
         AcqRel,
         Acquire,
+        AddSubdiagnostic,
         Alignment,
         Any,
         Arc,
@@ -156,6 +157,7 @@ symbols! {
         C,
         CStr,
         CString,
+        Capture,
         Center,
         Clone,
         Continue,
@@ -169,6 +171,7 @@ symbols! {
         Decoder,
         Default,
         Deref,
+        DiagnosticMessage,
         DirBuilder,
         Display,
         DoubleEndedIterator,
@@ -253,16 +256,20 @@ symbols! {
         RustcEncodable,
         Send,
         SeqCst,
+        SessionDiagnostic,
         SliceIndex,
         Some,
         String,
         StructuralEq,
         StructuralPartialEq,
+        SubdiagnosticMessage,
         Sync,
         Target,
         ToOwned,
         ToString,
         Try,
+        TryCaptureGeneric,
+        TryCapturePrintable,
         TryFrom,
         TryInto,
         Ty,
@@ -272,6 +279,7 @@ symbols! {
         UnsafeArg,
         Vec,
         VecDeque,
+        Wrapper,
         Yield,
         _DECLS,
         _Self,
@@ -354,6 +362,7 @@ symbols! {
         assert_receiver_is_total_eq,
         assert_uninit_valid,
         assert_zero_valid,
+        asserting,
         associated_const_equality,
         associated_consts,
         associated_type_bounds,
@@ -1184,7 +1193,6 @@ symbols! {
         rustc_const_unstable,
         rustc_conversion_suggestion,
         rustc_def_path,
-        rustc_deprecated,
         rustc_diagnostic_item,
         rustc_diagnostic_macros,
         rustc_dirty,
@@ -1205,6 +1213,7 @@ symbols! {
         rustc_layout_scalar_valid_range_end,
         rustc_layout_scalar_valid_range_start,
         rustc_legacy_const_generics,
+        rustc_lint_diagnostics,
         rustc_lint_query_instability,
         rustc_macro_transparency,
         rustc_main,
@@ -1432,6 +1441,7 @@ symbols! {
         truncf32,
         truncf64,
         try_blocks,
+        try_capture,
         try_from,
         try_into,
         try_trait_v2,
@@ -1494,6 +1504,7 @@ symbols! {
         unsized_tuple_coercion,
         unstable,
         untagged_unions,
+        unused_imports,
         unused_qualifications,
         unwind,
         unwind_attributes,
diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml
index b9751f0adb5..d5befa10e23 100644
--- a/compiler/rustc_symbol_mangling/Cargo.toml
+++ b/compiler/rustc_symbol_mangling/Cargo.toml
@@ -16,5 +16,4 @@ rustc_middle = { path = "../rustc_middle" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_target = { path = "../rustc_target" }
 rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_query_system = { path = "../rustc_query_system" }
 rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index b3773d5be28..f67b87a6a52 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -1,7 +1,6 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::CrateNum;
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
-use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::print::{PrettyPrinter, Print, Printer};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
@@ -30,6 +29,7 @@ pub(super) fn mangle<'tcx>(
         match key.disambiguated_data.data {
             DefPathData::TypeNs(_) | DefPathData::ValueNs(_) => {
                 instance_ty = tcx.type_of(ty_def_id);
+                debug!(?instance_ty);
                 break;
             }
             _ => {
@@ -228,9 +228,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
                 self.write_str("[")?;
                 self = self.print_type(ty)?;
                 self.write_str("; ")?;
-                if let Some(size) = size.val().try_to_bits(self.tcx().data_layout.pointer_size) {
+                if let Some(size) = size.kind().try_to_bits(self.tcx().data_layout.pointer_size) {
                     write!(self, "{}", size)?
-                } else if let ty::ConstKind::Param(param) = size.val() {
+                } else if let ty::ConstKind::Param(param) = size.kind() {
                     self = param.print(self)?
                 } else {
                     self.write_str("_")?
@@ -260,11 +260,8 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
 
     fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
         // only print integers
-        match (ct.val(), ct.ty().kind()) {
-            (
-                ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(scalar))),
-                ty::Int(_) | ty::Uint(_),
-            ) => {
+        match (ct.kind(), ct.ty().kind()) {
+            (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => {
                 // The `pretty_print_const` formatting depends on -Zverbose
                 // flag, so we cannot reuse it here.
                 let signed = matches!(ct.ty().kind(), ty::Int(_));
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 46f70bb1674..bed0e81e66e 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -155,6 +155,13 @@ pub fn typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>)
     v0::mangle_typeid_for_fnabi(tcx, fn_abi)
 }
 
+pub fn typeid_for_trait_ref<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyExistentialTraitRef<'tcx>,
+) -> String {
+    v0::mangle_typeid_for_trait_ref(tcx, trait_ref)
+}
+
 /// Computes the symbol name for the given instance. This function will call
 /// `compute_instantiating_crate` if it needs to factor the instantiating crate
 /// into the symbol name.
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index dc1946bcdc2..1036c5d941b 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -5,7 +5,6 @@ use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
-use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::print::{Print, Printer};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
@@ -95,6 +94,24 @@ pub(super) fn mangle_typeid_for_fnabi<'tcx>(
     format!("typeid{}", arg_count)
 }
 
+pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyExistentialTraitRef<'tcx>,
+) -> String {
+    // FIXME(flip1995): See comment in `mangle_typeid_for_fnabi`.
+    let mut cx = &mut SymbolMangler {
+        tcx,
+        start_offset: 0,
+        paths: FxHashMap::default(),
+        types: FxHashMap::default(),
+        consts: FxHashMap::default(),
+        binders: vec![],
+        out: String::new(),
+    };
+    cx = cx.print_def_path(trait_ref.def_id(), &[]).unwrap();
+    std::mem::take(&mut cx.out)
+}
+
 struct BinderLevel {
     /// The range of distances from the root of what's
     /// being printed, to the lifetimes in a binder.
@@ -582,7 +599,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
     fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
         // We only mangle a typed value if the const can be evaluated.
         let ct = ct.eval(self.tcx, ty::ParamEnv::reveal_all());
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Value(_) => {}
 
             // Placeholders (should be demangled as `_`).
@@ -604,16 +621,18 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         if let Some(&i) = self.consts.get(&ct) {
             return self.print_backref(i);
         }
+
         let start = self.out.len();
+        let ty = ct.ty();
 
-        match ct.ty().kind() {
+        match ty.kind() {
             ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
-                self = ct.ty().print(self)?;
+                self = ty.print(self)?;
 
-                let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty());
+                let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ty);
 
                 // Negative integer values are mangled using `n` as a "sign prefix".
-                if let ty::Int(ity) = ct.ty().kind() {
+                if let ty::Int(ity) = ty.kind() {
                     let val =
                         Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
                     if val < 0 {
@@ -625,46 +644,57 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                 let _ = write!(self.out, "{:x}_", bits);
             }
 
-            // HACK(eddyb) because `ty::Const` only supports sized values (for now),
-            // we can't use `deref_const` + supporting `str`, we have to specially
-            // handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
-            ty::Ref(_, ty, hir::Mutability::Not) if *ty == self.tcx.types.str_ => {
-                self.push("R");
-                match ct.val() {
-                    ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => {
-                        // NOTE(eddyb) the following comment was kept from `ty::print::pretty`:
-                        // The `inspect` here is okay since we checked the bounds, and there are no
-                        // relocations (we have an active `str` reference here). We don't use this
-                        // result to affect interpreter execution.
-                        let slice = data
-                            .inner()
-                            .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
-                        let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
-
-                        self.push("e");
-                        // FIXME(eddyb) use a specialized hex-encoding loop.
-                        for byte in s.bytes() {
-                            let _ = write!(self.out, "{:02x}", byte);
+            // FIXME(valtrees): Remove the special case for `str`
+            // here and fully support unsized constants.
+            ty::Ref(_, inner_ty, mutbl) => {
+                self.push(match mutbl {
+                    hir::Mutability::Not => "R",
+                    hir::Mutability::Mut => "Q",
+                });
+
+                match inner_ty.kind() {
+                    ty::Str if *mutbl == hir::Mutability::Not => {
+                        match ct.kind() {
+                            ty::ConstKind::Value(valtree) => {
+                                let slice =
+                                    valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
+                                        bug!(
+                                        "expected to get raw bytes from valtree {:?} for type {:}",
+                                        valtree, ty
+                                    )
+                                    });
+                                let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
+
+                                self.push("e");
+
+                                // FIXME(eddyb) use a specialized hex-encoding loop.
+                                for byte in s.bytes() {
+                                    let _ = write!(self.out, "{:02x}", byte);
+                                }
+
+                                self.push("_");
+                            }
+
+                            _ => {
+                                bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
+                            }
                         }
-                        self.push("_");
                     }
-
                     _ => {
-                        bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
+                        let pointee_ty = ct
+                            .ty()
+                            .builtin_deref(true)
+                            .expect("tried to dereference on non-ptr type")
+                            .ty;
+                        let dereferenced_const =
+                            self.tcx.mk_const(ty::ConstS { kind: ct.kind(), ty: pointee_ty });
+                        self = dereferenced_const.print(self)?;
                     }
                 }
             }
 
-            ty::Ref(_, _, mutbl) => {
-                self.push(match mutbl {
-                    hir::Mutability::Not => "R",
-                    hir::Mutability::Mut => "Q",
-                });
-                self = self.tcx.deref_const(ty::ParamEnv::reveal_all().and(ct)).print(self)?;
-            }
-
-            ty::Array(..) | ty::Tuple(..) | ty::Adt(..) => {
-                let contents = self.tcx.destructure_const(ty::ParamEnv::reveal_all().and(ct));
+            ty::Array(..) | ty::Tuple(..) | ty::Adt(..) | ty::Slice(_) => {
+                let contents = self.tcx.destructure_const(ct);
                 let fields = contents.fields.iter().copied();
 
                 let print_field_list = |mut this: Self| {
@@ -676,7 +706,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                 };
 
                 match *ct.ty().kind() {
-                    ty::Array(..) => {
+                    ty::Array(..) | ty::Slice(_) => {
                         self.push("A");
                         self = print_field_list(self)?;
                     }
@@ -723,7 +753,6 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                     _ => unreachable!(),
                 }
             }
-
             _ => {
                 bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty(), ct);
             }
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs
new file mode 100644
index 00000000000..3059f42140b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs
@@ -0,0 +1,38 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{FramePointer, Target, TargetOptions};
+
+pub fn target() -> Target {
+    let base = opts("watchos", Arch::Arm64_sim);
+
+    // Clang automatically chooses a more specific target based on
+    // WATCHOS_DEPLOYMENT_TARGET.
+    // This is required for the simulator target to pick the right
+    // MACH-O commands, so we do too.
+    let arch = "arm64";
+    let llvm_target = super::apple_base::watchos_sim_llvm_target(arch);
+
+    Target {
+        llvm_target: llvm_target.into(),
+        pointer_width: 64,
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
+        options: TargetOptions {
+            features: "+neon,+fp-armv8,+apple-a7".into(),
+            max_atomic_width: Some(128),
+            forces_embed_bitcode: true,
+            frame_pointer: FramePointer::NonLeaf,
+            // Taken from a clang build on Xcode 11.4.1.
+            // These arguments are not actually invoked - they just have
+            // to look right to pass App Store validation.
+            bitcode_llvm_cmdline: "-triple\0\
+                arm64-apple-watchos5.0-simulator\0\
+                -emit-obj\0\
+                -disable-llvm-passes\0\
+                -target-abi\0\
+                darwinpcs\0\
+                -Os\0"
+                .into(),
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 238d3f8bda5..e8460a509e2 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -114,3 +114,12 @@ pub fn ios_sim_llvm_target(arch: &str) -> String {
     let (major, minor) = ios_deployment_target();
     format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor)
 }
+
+fn watchos_deployment_target() -> (u32, u32) {
+    deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0))
+}
+
+pub fn watchos_sim_llvm_target(arch: &str) -> String {
+    let (major, minor) = watchos_deployment_target();
+    format!("{}-apple-watchos{}.{}.0-simulator", arch, major, minor)
+}
diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs
index e2d08955c08..ecb6cbd9f8a 100644
--- a/compiler/rustc_target/src/spec/apple_sdk_base.rs
+++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs
@@ -6,8 +6,10 @@ use Arch::*;
 #[derive(Copy, Clone)]
 pub enum Arch {
     Armv7,
+    Armv7k,
     Armv7s,
     Arm64,
+    Arm64_32,
     I386,
     X86_64,
     X86_64_macabi,
@@ -17,7 +19,7 @@ pub enum Arch {
 
 fn target_abi(arch: Arch) -> &'static str {
     match arch {
-        Armv7 | Armv7s | Arm64 | I386 | X86_64 => "",
+        Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "",
         X86_64_macabi | Arm64_macabi => "macabi",
         Arm64_sim => "sim",
     }
@@ -26,8 +28,10 @@ fn target_abi(arch: Arch) -> &'static str {
 fn target_cpu(arch: Arch) -> &'static str {
     match arch {
         Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
+        Armv7k => "cortex-a8",
         Armv7s => "cortex-a9",
         Arm64 => "apple-a7",
+        Arm64_32 => "apple-s4",
         I386 => "yonah",
         X86_64 => "core2",
         X86_64_macabi => "core2",
@@ -38,7 +42,7 @@ fn target_cpu(arch: Arch) -> &'static str {
 
 fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> {
     match arch {
-        Armv7 | Armv7s | Arm64 | I386 | X86_64 | Arm64_sim => {
+        Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 | Arm64_sim => {
             cvs!["MACOSX_DEPLOYMENT_TARGET"]
         }
         X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
new file mode 100644
index 00000000000..7b23fe1c482
--- /dev/null
+++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
@@ -0,0 +1,28 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    let base = opts("watchos", Arch::Arm64_32);
+    Target {
+        llvm_target: "arm64_32-apple-watchos".into(),
+        pointer_width: 32,
+        data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "aarch64".into(),
+        options: TargetOptions {
+            features: "+neon,+fp-armv8,+apple-a7".into(),
+            max_atomic_width: Some(64),
+            forces_embed_bitcode: true,
+            // These arguments are not actually invoked - they just have
+            // to look right to pass App Store validation.
+            bitcode_llvm_cmdline: "-triple\0\
+                arm64_32-apple-watchos5.0.0\0\
+                -emit-obj\0\
+                -disable-llvm-passes\0\
+                -target-abi\0\
+                darwinpcs\0\
+                -Os\0"
+                .into(),
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
index ffcd1a3f4df..67df73fa935 100644
--- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
@@ -37,7 +37,8 @@ pub fn target() -> Target {
             pre_link_args,
             exe_suffix: ".elf".into(),
             no_default_libraries: false,
-            has_thread_local: true,
+            // There are some issues in debug builds with this enabled in certain programs.
+            has_thread_local: false,
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
new file mode 100644
index 00000000000..af5d1c2ff45
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
@@ -0,0 +1,28 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    let base = opts("watchos", Arch::Armv7k);
+    Target {
+        llvm_target: "armv7k-apple-watchos".into(),
+        pointer_width: 32,
+        data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(),
+        arch: "arm".into(),
+        options: TargetOptions {
+            features: "+v7,+vfp4,+neon".into(),
+            max_atomic_width: Some(64),
+            forces_embed_bitcode: true,
+            // These arguments are not actually invoked - they just have
+            // to look right to pass App Store validation.
+            bitcode_llvm_cmdline: "-triple\0\
+                armv7k-apple-watchos3.0.0\0\
+                -emit-obj\0\
+                -disable-llvm-passes\0\
+                -target-abi\0\
+                darwinpcs\0\
+                -Os\0"
+                .into(),
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 4ede0677ab3..422af667875 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -928,6 +928,11 @@ supported_targets! {
     ("aarch64-apple-tvos", aarch64_apple_tvos),
     ("x86_64-apple-tvos", x86_64_apple_tvos),
 
+    ("armv7k-apple-watchos", armv7k_apple_watchos),
+    ("arm64_32-apple-watchos", arm64_32_apple_watchos),
+    ("x86_64-apple-watchos-sim", x86_64_apple_watchos_sim),
+    ("aarch64-apple-watchos-sim", aarch64_apple_watchos_sim),
+
     ("armebv7r-none-eabi", armebv7r_none_eabi),
     ("armebv7r-none-eabihf", armebv7r_none_eabihf),
     ("armv7r-none-eabi", armv7r_none_eabi),
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs
new file mode 100644
index 00000000000..4dff3c2f209
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs
@@ -0,0 +1,35 @@
+use super::apple_sdk_base::{opts, Arch};
+use crate::spec::{StackProbeType, Target, TargetOptions};
+
+pub fn target() -> Target {
+    let base = opts("watchos", Arch::X86_64);
+
+    let arch = "x86_64";
+    let llvm_target = super::apple_base::watchos_sim_llvm_target(arch);
+
+    Target {
+        llvm_target: llvm_target.into(),
+        pointer_width: 64,
+        data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .into(),
+        arch: "x86_64".into(),
+        options: TargetOptions {
+            max_atomic_width: Some(64),
+            // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+            stack_probes: StackProbeType::Call,
+            forces_embed_bitcode: true,
+            // Taken from a clang build on Xcode 11.4.1.
+            // These arguments are not actually invoked - they just have
+            // to look right to pass App Store validation.
+            bitcode_llvm_cmdline: "-triple\0\
+                x86_64-apple-watchos5.0-simulator\0\
+                -emit-obj\0\
+                -disable-llvm-passes\0\
+                -target-abi\0\
+                darwinpcs\0\
+                -Os\0"
+                .into(),
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index c1faa15d43c..9dd8588cece 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -209,7 +209,7 @@ fn check_opaque_type_parameter_valid(
             GenericArgKind::Lifetime(lt) => {
                 matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
             }
-            GenericArgKind::Const(ct) => matches!(ct.val(), ty::ConstKind::Param(_)),
+            GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
         };
 
         if arg_is_param {
@@ -452,7 +452,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
         trace!("checking const {:?}", ct);
         // Find a const parameter
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Param(..) => {
                 // Look it up in the substitution list.
                 match self.map.get(&ct.into()).map(|k| k.unpack()) {
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 4bcd3bdd1ef..a63790b594d 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -6,6 +6,7 @@ use super::*;
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::InferCtxt;
 use crate::traits::project::ProjectAndUnifyResult;
+use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{Region, RegionVid, Term};
 
@@ -828,13 +829,22 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 }
                 ty::PredicateKind::ConstEquate(c1, c2) => {
                     let evaluate = |c: ty::Const<'tcx>| {
-                        if let ty::ConstKind::Unevaluated(unevaluated) = c.val() {
+                        if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
                             match select.infcx().const_eval_resolve(
                                 obligation.param_env,
                                 unevaluated,
                                 Some(obligation.cause.span),
                             ) {
-                                Ok(val) => Ok(ty::Const::from_value(select.tcx(), val, c.ty())),
+                                Ok(Some(valtree)) => {
+                                    Ok(ty::Const::from_value(select.tcx(), valtree, c.ty()))
+                                }
+                                Ok(None) => {
+                                    let tcx = self.tcx;
+                                    let def_id = unevaluated.def.did;
+                                    let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit();
+
+                                    Err(ErrorHandled::Reported(reported))
+                                }
                                 Err(err) => Err(err),
                             }
                         } else {
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index e7f0e47f12c..b37db4b9e18 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -5,7 +5,7 @@
 //! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
 
 use crate::infer::outlives::env::OutlivesEnvironment;
-use crate::infer::{CombinedSnapshot, InferOk, RegionckMode};
+use crate::infer::{CombinedSnapshot, InferOk};
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::util::impl_subject_and_oblig;
 use crate::traits::SkipLeakCheck;
@@ -413,7 +413,7 @@ fn resolve_negative_obligation<'cx, 'tcx>(
         param_env,
     );
 
-    let errors = infcx.resolve_regions(region_context, &outlives_env, RegionckMode::default());
+    let errors = infcx.resolve_regions(region_context, &outlives_env);
 
     if !errors.is_empty() {
         return false;
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 0dea2c3d8bf..5d08ea99ac6 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -13,9 +13,7 @@ use rustc_hir::def::DefKind;
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::{
-    ConstValue, ErrorHandled, LitToConstError, LitToConstInput, Scalar,
-};
+use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
 use rustc_middle::thir;
 use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
 use rustc_middle::ty::subst::{Subst, SubstsRef};
@@ -144,7 +142,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                   .span_suggestion_verbose(
                       rustc_span::DUMMY_SP,
                       "consider enabling this feature",
-                      "#![feature(generic_const_exprs)]\n".to_string(),
+                      "#![feature(generic_const_exprs)]\n",
                       rustc_errors::Applicability::MaybeIncorrect,
                   )
                   .emit()
@@ -245,7 +243,7 @@ impl<'tcx> AbstractConst<'tcx> {
         tcx: TyCtxt<'tcx>,
         ct: ty::Const<'tcx>,
     ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
             ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported),
             _ => Ok(None),
@@ -414,7 +412,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
 
         for n in self.nodes.iter() {
             if let Node::Leaf(ct) = n {
-                if let ty::ConstKind::Unevaluated(ct) = ct.val() {
+                if let ty::ConstKind::Unevaluated(ct) = ct.kind() {
                     // `AbstractConst`s should not contain any promoteds as they require references which
                     // are not allowed.
                     assert_eq!(ct.promoted, None);
@@ -449,15 +447,14 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
                 self.nodes.push(Node::Leaf(constant))
             }
             &ExprKind::NonHirLiteral { lit , user_ty: _} => {
-                // FIXME Construct a Valtree from this ScalarInt when introducing Valtrees
-                let const_value = ConstValue::Scalar(Scalar::Int(lit));
-                self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, const_value, node.ty)))
+                let val = ty::ValTree::from_scalar_int(lit);
+                self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty)))
             }
             &ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
                 let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
 
                 let constant = self.tcx.mk_const(ty::ConstS {
-                                val: ty::ConstKind::Unevaluated(uneval),
+                                kind: ty::ConstKind::Unevaluated(uneval),
                                 ty: node.ty,
                             });
 
@@ -466,7 +463,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
 
             ExprKind::ConstParam {param, ..} => {
                 let const_param = self.tcx.mk_const(ty::ConstS {
-                        val: ty::ConstKind::Param(*param),
+                        kind: ty::ConstKind::Param(*param),
                         ty: node.ty,
                     });
                 self.nodes.push(Node::Leaf(const_param))
@@ -748,7 +745,7 @@ impl<'tcx> ConstUnifyCtxt<'tcx> {
                     return false;
                 }
 
-                match (a_ct.val(), b_ct.val()) {
+                match (a_ct.kind(), b_ct.kind()) {
                     // We can just unify errors with everything to reduce the amount of
                     // emitted errors here.
                     (ty::ConstKind::Error(_), _) | (_, ty::ConstKind::Error(_)) => true,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 2e7067fa710..2f999f5ffad 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -417,7 +417,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                                     span.shrink_to_lo(),
                                     "consider converting the `Option<T>` into a `Result<T, _>` \
                                      using `Option::ok_or` or `Option::ok_or_else`",
-                                    ".ok_or_else(|| /* error value */)".to_string(),
+                                    ".ok_or_else(|| /* error value */)",
                                     Applicability::HasPlaceholders,
                                 );
                             } else if should_convert_result_to_option {
@@ -425,7 +425,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                                     span.shrink_to_lo(),
                                     "consider converting the `Result<T, _>` into an `Option<T>` \
                                      using `Result::ok`",
-                                    ".ok()".to_string(),
+                                    ".ok()",
                                     Applicability::MachineApplicable,
                                 );
                             }
@@ -1084,11 +1084,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         let hir = self.tcx.hir();
         Some(match node {
             Node::Expr(&hir::Expr {
-                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
+                kind: hir::ExprKind::Closure { body, fn_decl_span, .. },
                 ..
             }) => (
-                sm.guess_head_span(span),
-                hir.body(id)
+                sm.guess_head_span(fn_decl_span),
+                hir.body(body)
                     .params
                     .iter()
                     .map(|arg| {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 4263a6fdf18..7c9ee64a0c2 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -103,10 +103,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 })
             }),
             hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
+                kind: hir::ExprKind::Closure { body, movability, .. },
                 ..
-            }) => self.describe_generator(*body_id).or_else(|| {
-                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
+            }) => self.describe_generator(*body).or_else(|| {
+                Some(if movability.is_some() { "an async closure" } else { "a closure" })
             }),
             hir::Node::Expr(hir::Expr { .. }) => {
                 let parent_hid = hir.get_parent_node(hir_id);
@@ -234,7 +234,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
             if let ty::Array(aty, len) = self_ty.kind() {
                 flags.push((sym::_Self, Some("[]".to_string())));
-                let len = len.val().try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx));
+                let len = len.kind().try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx));
                 flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
                 if let Some(n) = len {
                     flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));
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 353547a2fb8..09b73b982a0 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -701,7 +701,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         err.span_suggestion_verbose(
                             span.shrink_to_lo(),
                             "consider dereferencing here",
-                            "*".to_string(),
+                            "*",
                             Applicability::MachineApplicable,
                         );
                         return true;
@@ -785,14 +785,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         // Get the name of the callable and the arguments to be used in the suggestion.
         let (snippet, sugg) = match hir.get_if_local(def_id) {
             Some(hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
+                kind: hir::ExprKind::Closure { fn_decl, fn_decl_span, .. },
                 ..
             })) => {
-                err.span_label(*span, "consider calling this closure");
+                err.span_label(*fn_decl_span, "consider calling this closure");
                 let Some(name) = self.get_closure_name(def_id, err, &msg) else {
                     return false;
                 };
-                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
+                let args = fn_decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
                 let sugg = format!("({})", args);
                 (format!("{}{}", name, sugg), sugg)
             }
@@ -1002,7 +1002,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             &format!(
                 "consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`"
             ),
-            "&".to_string(),
+            "&",
             Applicability::MaybeIncorrect,
         );
     }
@@ -1059,12 +1059,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         format!("consider removing {} leading `&`-references", remove_refs)
                     };
 
-                    err.span_suggestion_short(
-                        sp,
-                        &msg,
-                        String::new(),
-                        Applicability::MachineApplicable,
-                    );
+                    err.span_suggestion_short(sp, &msg, "", Applicability::MachineApplicable);
                     suggested = true;
                     break;
                 }
@@ -1087,7 +1082,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     err.span_suggestion_verbose(
                         expr.span.shrink_to_hi().with_hi(span.hi()),
                         "remove the `.await`",
-                        String::new(),
+                        "",
                         Applicability::MachineApplicable,
                     );
                     // FIXME: account for associated `async fn`s.
@@ -1115,14 +1110,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                                 err.span_suggestion_verbose(
                                     span.shrink_to_lo(),
                                     &msg,
-                                    "async ".to_string(),
+                                    "async ",
                                     Applicability::MaybeIncorrect,
                                 );
                             } else {
                                 err.span_suggestion_verbose(
                                     vis_span.shrink_to_hi(),
                                     &msg,
-                                    " async".to_string(),
+                                    " async",
                                     Applicability::MaybeIncorrect,
                                 );
                             }
@@ -1190,7 +1185,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         err.span_suggestion_verbose(
                             sp,
                             "consider changing this borrow's mutability",
-                            "&mut ".to_string(),
+                            "&mut ",
                             Applicability::MachineApplicable,
                         );
                     } else {
@@ -1241,7 +1236,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             err.span_suggestion(
                 self.tcx.sess.source_map().end_point(stmt.span),
                 "remove this semicolon",
-                String::new(),
+                "",
                 Applicability::MachineApplicable
             );
             return true;
@@ -2275,7 +2270,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         err.span_suggestion_verbose(
                             span.shrink_to_lo(),
                             "consider borrowing here",
-                            "&".to_owned(),
+                            "&",
                             Applicability::MachineApplicable,
                         );
                         err.note("all local variables must have a statically known size");
@@ -2285,7 +2280,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             param.ty_span.shrink_to_lo(),
                             "function arguments must have a statically known size, borrowed types \
                             always have a known size",
-                            "&".to_owned(),
+                            "&",
                             Applicability::MachineApplicable,
                         );
                     }
@@ -2303,7 +2298,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         span.shrink_to_lo(),
                         "function arguments must have a statically known size, borrowed types \
                          always have a known size",
-                        "&".to_string(),
+                        "&",
                         Applicability::MachineApplicable,
                     );
                 } else {
@@ -2358,7 +2353,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 err.span_suggestion(
                     span.shrink_to_lo(),
                     "borrowed types always have a statically known size",
-                    "&".to_string(),
+                    "&",
                     Applicability::MachineApplicable,
                 );
                 err.multipart_suggestion(
@@ -2759,7 +2754,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     err.span_suggestion_verbose(
                         span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
                         "consider `await`ing on the `Future`",
-                        ".await".to_string(),
+                        ".await",
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -2785,7 +2780,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 err.span_suggestion_verbose(
                     rhs_span.shrink_to_hi(),
                     "consider using a floating-point literal by writing it with `.0`",
-                    String::from(".0"),
+                    ".0",
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -2965,7 +2960,7 @@ fn suggest_trait_object_return_type_alternatives(
         ret_ty,
         "use some type `T` that is `T: Sized` as the return type if all return paths have the \
             same type",
-        "T".to_string(),
+        "T",
         Applicability::MaybeIncorrect,
     );
     err.span_suggestion(
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 053e871c14f..70d8fdae651 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -578,7 +578,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
                         //
                         // Let's just see where this breaks :shrug:
                         if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
-                            (c1.val(), c2.val())
+                            (c1.kind(), c2.kind())
                         {
                             if infcx.try_unify_abstract_consts(
                                 a.shrink(),
@@ -593,23 +593,25 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
                     let stalled_on = &mut pending_obligation.stalled_on;
 
                     let mut evaluate = |c: Const<'tcx>| {
-                        if let ty::ConstKind::Unevaluated(unevaluated) = c.val() {
-                            match self.selcx.infcx().const_eval_resolve(
+                        if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
+                            match self.selcx.infcx().try_const_eval_resolve(
                                 obligation.param_env,
                                 unevaluated,
+                                c.ty(),
                                 Some(obligation.cause.span),
                             ) {
-                                Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty())),
-                                Err(ErrorHandled::TooGeneric) => {
-                                    stalled_on.extend(
-                                        unevaluated
-                                            .substs
-                                            .iter()
-                                            .filter_map(TyOrConstInferVar::maybe_from_generic_arg),
-                                    );
-                                    Err(ErrorHandled::TooGeneric)
-                                }
-                                Err(err) => Err(err),
+                                Ok(val) => Ok(val),
+                                Err(e) => match e {
+                                    ErrorHandled::TooGeneric => {
+                                        stalled_on.extend(
+                                            unevaluated.substs.iter().filter_map(
+                                                TyOrConstInferVar::maybe_from_generic_arg,
+                                            ),
+                                        );
+                                        Err(ErrorHandled::TooGeneric)
+                                    }
+                                    _ => Err(e),
+                                },
                             }
                         } else {
                             Ok(c)
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 03757b5447e..34b0f431b8e 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -23,7 +23,7 @@ mod util;
 pub mod wf;
 
 use crate::infer::outlives::env::OutlivesEnvironment;
-use crate::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
+use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::traits::error_reporting::InferCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_errors::ErrorGuaranteed;
@@ -240,11 +240,7 @@ fn do_normalize_predicates<'tcx>(
         // cares about declarations like `'a: 'b`.
         let outlives_env = OutlivesEnvironment::new(elaborated_env);
 
-        infcx.resolve_regions_and_report_errors(
-            region_context,
-            &outlives_env,
-            RegionckMode::default(),
-        );
+        infcx.resolve_regions_and_report_errors(region_context, &outlives_env);
 
         let predicates = match infcx.fully_resolve(predicates) {
             Ok(predicates) => predicates,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 7341ab0ab12..a72f90746ed 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -618,11 +618,14 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
         if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement {
             constant
         } else {
             let constant = constant.super_fold_with(self);
+            debug!(?constant);
+            debug!("self.param_env: {:?}", self.param_env);
             constant.eval(self.selcx.tcx(), self.param_env)
         }
     }
@@ -742,7 +745,7 @@ impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Bound(debruijn, _)
                 if debruijn.as_usize() + 1
                     > self.current_index.as_usize() + self.universe_indices.len() =>
@@ -758,7 +761,7 @@ impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
                 self.mapped_consts.insert(p, bound_const);
                 self.infcx
                     .tcx
-                    .mk_const(ty::ConstS { val: ty::ConstKind::Placeholder(p), ty: ct.ty() })
+                    .mk_const(ty::ConstS { kind: ty::ConstKind::Placeholder(p), ty: ct.ty() })
             }
             _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
             _ => ct,
@@ -878,7 +881,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if let ty::ConstKind::Placeholder(p) = ct.val() {
+        if let ty::ConstKind::Placeholder(p) = ct.kind() {
             let replace_var = self.mapped_consts.get(&p);
             match replace_var {
                 Some(replace_var) => {
@@ -891,7 +894,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
                         self.universe_indices.len() - index + self.current_index.as_usize() - 1,
                     );
                     self.tcx().mk_const(ty::ConstS {
-                        val: ty::ConstKind::Bound(db, *replace_var),
+                        kind: ty::ConstKind::Bound(db, *replace_var),
                         ty: ct.ty(),
                     })
                 }
@@ -2018,8 +2021,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
         let identity_substs =
             crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
         let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id);
-        let val = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, identity_substs));
-        tcx.mk_const(ty::ConstS { ty, val }).into()
+        let kind = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, identity_substs));
+        tcx.mk_const(ty::ConstS { ty, kind }).into()
     } else {
         ty.into()
     };
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index e9e2dca17e9..b80a27eb07d 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -100,7 +100,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
     }
 }
 
-/// Visitor to find the maximum escaping bound var
+// Visitor to find the maximum escaping bound var
 struct MaxEscapingBoundVarVisitor {
     // The index which would count as escaping
     outer_index: ty::DebruijnIndex,
@@ -141,7 +141,7 @@ impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor {
     }
 
     fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match ct.val() {
+        match ct.kind() {
             ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
                 self.escaping =
                     self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
@@ -336,12 +336,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
     ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
         Ok(match constant {
             mir::ConstantKind::Ty(c) => {
-                let const_folded = c.try_fold_with(self)?;
-                match const_folded.val() {
-                    ty::ConstKind::Value(cv) => {
-                        // FIXME With Valtrees we need to convert `cv: ValTree`
-                        // to a `ConstValue` here.
-                        mir::ConstantKind::Val(cv, const_folded.ty())
+                let const_folded = c.try_super_fold_with(self)?;
+                match const_folded.kind() {
+                    ty::ConstKind::Value(valtree) => {
+                        let tcx = self.infcx.tcx;
+                        let ty = const_folded.ty();
+                        let const_val = tcx.valtree_to_const_val((ty, valtree));
+                        debug!(?ty, ?valtree, ?const_val);
+
+                        mir::ConstantKind::Val(const_val, ty)
                     }
                     _ => mir::ConstantKind::Ty(const_folded),
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index cbf29af1c55..5942bb79d69 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -542,7 +542,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                 bound_vars.push(bound_var);
                                 tcx.mk_const(ty::ConstS {
                                     ty: tcx.type_of(param.def_id),
-                                    val: ty::ConstKind::Bound(
+                                    kind: ty::ConstKind::Bound(
                                         ty::INNERMOST,
                                         ty::BoundVar::from_usize(bound_vars.len() - 1),
                                     ),
@@ -989,7 +989,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // Lifetimes aren't allowed to change during unsizing.
                     GenericArgKind::Lifetime(_) => None,
 
-                    GenericArgKind::Const(ct) => match ct.val() {
+                    GenericArgKind::Const(ct) => match ct.kind() {
                         ty::ConstKind::Param(p) => Some(p.index),
                         _ => None,
                     },
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index a484b594418..ee2c8da5a00 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -622,7 +622,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         //
                         // Let's just see where this breaks :shrug:
                         if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
-                            (c1.val(), c2.val())
+                            (c1.kind(), c2.kind())
                         {
                             if self.infcx.try_unify_abstract_consts(
                                 a.shrink(),
@@ -635,14 +635,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     }
 
                     let evaluate = |c: ty::Const<'tcx>| {
-                        if let ty::ConstKind::Unevaluated(unevaluated) = c.val() {
-                            self.infcx
-                                .const_eval_resolve(
-                                    obligation.param_env,
-                                    unevaluated,
-                                    Some(obligation.cause.span),
-                                )
-                                .map(|val| ty::Const::from_value(self.tcx(), val, c.ty()))
+                        if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
+                            match self.infcx.try_const_eval_resolve(
+                                obligation.param_env,
+                                unevaluated,
+                                c.ty(),
+                                Some(obligation.cause.span),
+                            ) {
+                                Ok(val) => Ok(val),
+                                Err(e) => Err(e),
+                            }
                         } else {
                             Ok(c)
                         }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 2ce2a44d3db..8d666046ad9 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -41,7 +41,7 @@ pub fn obligations<'a, 'tcx>(
             .into()
         }
         GenericArgKind::Const(ct) => {
-            match ct.val() {
+            match ct.kind() {
                 ty::ConstKind::Infer(infer) => {
                     let resolved = infcx.shallow_resolve(infer);
                     if resolved == infer {
@@ -51,7 +51,7 @@ pub fn obligations<'a, 'tcx>(
 
                     infcx
                         .tcx
-                        .mk_const(ty::ConstS { val: ty::ConstKind::Infer(resolved), ty: ct.ty() })
+                        .mk_const(ty::ConstS { kind: ty::ConstKind::Infer(resolved), ty: ct.ty() })
                 }
                 _ => ct,
             }
@@ -437,7 +437,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                 GenericArgKind::Lifetime(_) => continue,
 
                 GenericArgKind::Const(constant) => {
-                    match constant.val() {
+                    match constant.kind() {
                         ty::ConstKind::Unevaluated(uv) => {
                             let obligations = self.nominal_obligations(uv.def.did, uv.substs);
                             self.out.extend(obligations);
@@ -460,7 +460,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                                 let cause = self.cause(traits::MiscObligation);
 
                                 let resolved_constant = self.infcx.tcx.mk_const(ty::ConstS {
-                                    val: ty::ConstKind::Infer(resolved),
+                                    kind: ty::ConstKind::Infer(resolved),
                                     ty: constant.ty(),
                                 });
                                 self.out.push(traits::Obligation::with_depth(
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 3de2fa2215b..497819ce5c5 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -736,7 +736,7 @@ fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx
 
         ty::GenericParamDefKind::Const { .. } => tcx
             .mk_const(ty::ConstS {
-                val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)),
+                kind: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)),
                 ty: tcx.type_of(param.def_id),
             })
             .into(),
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 4fd512d7b8d..e9f05ce9e06 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -514,7 +514,7 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
 impl<'tcx> LowerInto<'tcx, chalk_ir::Const<RustInterner<'tcx>>> for ty::Const<'tcx> {
     fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Const<RustInterner<'tcx>> {
         let ty = self.ty().lower_into(interner);
-        let value = match self.val() {
+        let value = match self.kind() {
             ty::ConstKind::Value(val) => {
                 chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: val })
             }
@@ -531,7 +531,7 @@ impl<'tcx> LowerInto<'tcx, ty::Const<'tcx>> for &chalk_ir::Const<RustInterner<'t
     fn lower_into(self, interner: RustInterner<'tcx>) -> ty::Const<'tcx> {
         let data = self.data(interner);
         let ty = data.ty.lower_into(interner);
-        let val = match data.value {
+        let kind = match data.value {
             chalk_ir::ConstValue::BoundVar(var) => ty::ConstKind::Bound(
                 ty::DebruijnIndex::from_u32(var.debruijn.depth()),
                 ty::BoundVar::from_u32(var.index as u32),
@@ -540,7 +540,7 @@ impl<'tcx> LowerInto<'tcx, ty::Const<'tcx>> for &chalk_ir::Const<RustInterner<'t
             chalk_ir::ConstValue::Placeholder(_p) => unimplemented!(),
             chalk_ir::ConstValue::Concrete(c) => ty::ConstKind::Value(c.interned),
         };
-        interner.tcx.mk_const(ty::ConstS { ty, val })
+        interner.tcx.mk_const(ty::ConstS { ty, kind })
     }
 }
 
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index a8a324dec97..5d394ed2263 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -25,7 +25,6 @@ pub(crate) fn provide(p: &mut Providers) {
     };
 }
 
-#[instrument(level = "debug", skip(tcx))]
 fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>(
     tcx: TyCtxt<'tcx>,
     goal: ParamEnvAnd<'tcx, T>,
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 7c89ce125e0..552db5406df 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -112,7 +112,6 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
     }
 }
 
-#[instrument(level = "debug", skip(tcx))]
 fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
@@ -141,7 +140,6 @@ fn resolve_instance_of_const_arg<'tcx>(
     )
 }
 
-#[instrument(level = "debug", skip(tcx))]
 fn inner_resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index a6a0d02c8ba..94072184399 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -14,7 +14,7 @@ use crate::UintTy;
 use self::TyKind::*;
 
 use rustc_data_structures::stable_hasher::HashStable;
-use rustc_serialize::{Decodable, Encodable};
+use rustc_serialize::{Decodable, Decoder, Encodable};
 
 /// Defines the kinds of types used by the type system.
 ///
@@ -833,56 +833,34 @@ where
     I::AllocId: Decodable<D>,
 {
     fn decode(d: &mut D) -> Self {
-        match rustc_serialize::Decoder::read_usize(d) {
+        match Decoder::read_usize(d) {
             0 => Bool,
             1 => Char,
-            2 => Int(rustc_serialize::Decodable::decode(d)),
-            3 => Uint(rustc_serialize::Decodable::decode(d)),
-            4 => Float(rustc_serialize::Decodable::decode(d)),
-            5 => Adt(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)),
-            6 => Foreign(rustc_serialize::Decodable::decode(d)),
+            2 => Int(Decodable::decode(d)),
+            3 => Uint(Decodable::decode(d)),
+            4 => Float(Decodable::decode(d)),
+            5 => Adt(Decodable::decode(d), Decodable::decode(d)),
+            6 => Foreign(Decodable::decode(d)),
             7 => Str,
-            8 => {
-                Array(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d))
-            }
-            9 => Slice(rustc_serialize::Decodable::decode(d)),
-            10 => RawPtr(rustc_serialize::Decodable::decode(d)),
-            11 => Ref(
-                rustc_serialize::Decodable::decode(d),
-                rustc_serialize::Decodable::decode(d),
-                rustc_serialize::Decodable::decode(d),
-            ),
-            12 => {
-                FnDef(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d))
-            }
-            13 => FnPtr(rustc_serialize::Decodable::decode(d)),
-            14 => Dynamic(
-                rustc_serialize::Decodable::decode(d),
-                rustc_serialize::Decodable::decode(d),
-            ),
-            15 => Closure(
-                rustc_serialize::Decodable::decode(d),
-                rustc_serialize::Decodable::decode(d),
-            ),
-            16 => Generator(
-                rustc_serialize::Decodable::decode(d),
-                rustc_serialize::Decodable::decode(d),
-                rustc_serialize::Decodable::decode(d),
-            ),
-            17 => GeneratorWitness(rustc_serialize::Decodable::decode(d)),
+            8 => Array(Decodable::decode(d), Decodable::decode(d)),
+            9 => Slice(Decodable::decode(d)),
+            10 => RawPtr(Decodable::decode(d)),
+            11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
+            12 => FnDef(Decodable::decode(d), Decodable::decode(d)),
+            13 => FnPtr(Decodable::decode(d)),
+            14 => Dynamic(Decodable::decode(d), Decodable::decode(d)),
+            15 => Closure(Decodable::decode(d), Decodable::decode(d)),
+            16 => Generator(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
+            17 => GeneratorWitness(Decodable::decode(d)),
             18 => Never,
-            19 => Tuple(rustc_serialize::Decodable::decode(d)),
-            20 => Projection(rustc_serialize::Decodable::decode(d)),
-            21 => {
-                Opaque(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d))
-            }
-            22 => Param(rustc_serialize::Decodable::decode(d)),
-            23 => {
-                Bound(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d))
-            }
-            24 => Placeholder(rustc_serialize::Decodable::decode(d)),
-            25 => Infer(rustc_serialize::Decodable::decode(d)),
-            26 => Error(rustc_serialize::Decodable::decode(d)),
+            19 => Tuple(Decodable::decode(d)),
+            20 => Projection(Decodable::decode(d)),
+            21 => Opaque(Decodable::decode(d), Decodable::decode(d)),
+            22 => Param(Decodable::decode(d)),
+            23 => Bound(Decodable::decode(d), Decodable::decode(d)),
+            24 => Placeholder(Decodable::decode(d)),
+            25 => Infer(Decodable::decode(d)),
+            26 => Error(Decodable::decode(d)),
             _ => panic!(
                 "{}",
                 format!(
diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs
index 8fe89c66389..d111008e82c 100644
--- a/compiler/rustc_typeck/src/astconv/errors.rs
+++ b/compiler/rustc_typeck/src/astconv/errors.rs
@@ -161,7 +161,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             err.span_suggestion(
                 assoc_name.span,
                 "there is an associated type with a similar name",
-                suggested_name.to_string(),
+                suggested_name,
                 Applicability::MaybeIncorrect,
             );
         } else {
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index b5025b794bb..32bbfd7e332 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -1589,7 +1589,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             err.span_suggestion(
                 span.shrink_to_lo(),
                 "you are looking for the module in `std`, not the primitive type",
-                "std::".to_string(),
+                "std::",
                 Applicability::MachineApplicable,
             );
         } else {
@@ -1820,7 +1820,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 err.span_suggestion_verbose(
                                     args_span,
                                     &format!("{type_name} doesn't have generic parameters"),
-                                    String::new(),
+                                    "",
                                     Applicability::MachineApplicable,
                                 );
                                 return;
@@ -1946,7 +1946,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         err.span_suggestion(
                             assoc_ident.span,
                             "there is a variant with a similar name",
-                            suggested_name.to_string(),
+                            suggested_name,
                             Applicability::MaybeIncorrect,
                         );
                     } else {
@@ -2422,7 +2422,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         err.span_suggestion_verbose(
                             ident.span.shrink_to_hi().to(args.span_ext),
                             "the `Self` type doesn't accept type parameters",
-                            String::new(),
+                            "",
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -2473,7 +2473,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 err.span_suggestion_verbose(
                                     segment.ident.span.shrink_to_hi().to(args.span_ext),
                                     "the `Self` type doesn't accept type parameters",
-                                    String::new(),
+                                    "",
                                     Applicability::MachineApplicable,
                                 );
                                 return;
@@ -2549,7 +2549,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             err.span_suggestion_verbose(
                                 segment.ident.span.shrink_to_hi().to(args.span_ext),
                                 &format!("primitive type `{name}` doesn't have generic parameters"),
-                                String::new(),
+                                "",
                                 Applicability::MaybeIncorrect,
                             );
                         }
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index 3632e14385f..bbdf1dae4a9 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -174,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.tool_only_span_suggestion(
                         semi_span,
                         "remove this semicolon",
-                        String::new(),
+                        "",
                         Applicability::MaybeIncorrect,
                     );
                 }),
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index af1288b6523..83a8c5ea021 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -283,11 +283,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let hir_id = self.tcx.hir().get_parent_node(hir_id);
         let parent_node = self.tcx.hir().get(hir_id);
         if let (
-            hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, _, _, sp, ..), .. }),
+            hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Closure { fn_decl_span, .. }, ..
+            }),
             hir::ExprKind::Block(..),
         ) = (parent_node, callee_node)
         {
-            let start = sp.shrink_to_lo();
+            let start = fn_decl_span.shrink_to_lo();
             let end = callee_span.shrink_to_hi();
             err.multipart_suggestion(
                 "if you meant to create this closure and immediately call it, surround the \
@@ -319,7 +321,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_suggestion(
                 start,
                 "consider separating array elements with a comma",
-                ",".to_string(),
+                ",",
                 Applicability::MaybeIncorrect,
             );
             return true;
@@ -406,7 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         &format!(
                             "`{path}` is a unit variant, you need to write it without the parentheses",
                         ),
-                        String::new(),
+                        "",
                         Applicability::MachineApplicable,
                     );
                 }
@@ -426,7 +428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             err.span_suggestion(
                                 callee_expr.span.shrink_to_hi(),
                                 "consider using a semicolon here",
-                                ";".to_owned(),
+                                ";",
                                 Applicability::MaybeIncorrect,
                             );
                         }
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 80abb28ee58..0425e7b074f 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -124,7 +124,7 @@ pub(super) fn check_fn<'a, 'tcx>(
                     ..
                 }) => Some(header),
                 // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
-                Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => None,
+                Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None,
                 node => bug!("Item being checked wasn't a function/closure: {:?}", node),
             };
 
@@ -539,7 +539,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
         }
 
         fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-            if let ty::ConstKind::Unevaluated(..) = c.val() {
+            if let ty::ConstKind::Unevaluated(..) = c.kind() {
                 // FIXME(#72219) We currently don't detect lifetimes within substs
                 // which would violate this check. Even though the particular substitution is not used
                 // within the const, this should still be fixed.
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index d6a8659d54b..43fc49c6801 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -1577,8 +1577,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         let parent_id = fcx.tcx.hir().get_parent_node(id);
         let parent = fcx.tcx.hir().get(parent_id);
         if let Some(expr) = expression
-            && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, _, body_id, ..), .. }) = parent
-            && !matches!(fcx.tcx.hir().get(body_id.hir_id), hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(..), .. }))
+            && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { body, .. }, .. }) = parent
+            && !matches!(fcx.tcx.hir().body(*body).value.kind, hir::ExprKind::Block(..))
         {
             fcx.suggest_missing_semicolon(&mut err, expr, expected, true);
         }
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index d4e17f27c92..acb2aa44ad5 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -354,7 +354,7 @@ fn compare_predicate_entailment<'tcx>(
                                         diag.span_suggestion_verbose(sp, msg, sugg, ap);
                                     }
                                     hir::FnRetTy::Return(hir_ty) => {
-                                        let sugg = trait_sig.output().to_string();
+                                        let sugg = trait_sig.output();
                                         diag.span_suggestion(hir_ty.span, msg, sugg, ap);
                                     }
                                 };
@@ -365,7 +365,7 @@ fn compare_predicate_entailment<'tcx>(
                         diag.span_suggestion(
                             impl_err_span,
                             "change the parameter type to match the trait",
-                            trait_ty.to_string(),
+                            trait_ty,
                             Applicability::MachineApplicable,
                         );
                     }
@@ -1379,7 +1379,7 @@ pub fn check_type_bounds<'tcx>(
             bound_vars.push(bound_var);
             tcx.mk_const(ty::ConstS {
                 ty: tcx.type_of(param.def_id),
-                val: ty::ConstKind::Bound(
+                kind: ty::ConstKind::Bound(
                     ty::INNERMOST,
                     ty::BoundVar::from_usize(bound_vars.len() - 1),
                 ),
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 419ccb5a73a..961bbc42661 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -483,7 +483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let param_parent = self.tcx.hir().get_parent_node(*param_hir_id);
         let Some(Node::Expr(hir::Expr {
             hir_id: expr_hir_id,
-            kind: hir::ExprKind::Closure(_, closure_fn_decl, ..),
+            kind: hir::ExprKind::Closure { fn_decl: closure_fn_decl, .. },
             ..
         })) = self.tcx.hir().find(param_parent) else {
             return None;
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index bf5bd744f62..dc9d76160c4 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -318,8 +318,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ExprKind::Match(discrim, arms, match_src) => {
                 self.check_match(expr, &discrim, arms, expected, match_src)
             }
-            ExprKind::Closure(capture, decl, body_id, _, gen) => {
-                self.check_expr_closure(expr, capture, &decl, body_id, gen, expected)
+            ExprKind::Closure { capture_clause, fn_decl, body, movability, .. } => {
+                self.check_expr_closure(expr, capture_clause, &fn_decl, body, movability, expected)
             }
             ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),
             ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected),
@@ -864,7 +864,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_suggestion_verbose(
                 expr.span.shrink_to_lo(),
                 "you might have meant to use pattern destructuring",
-                "let ".to_string(),
+                "let ",
                 Applicability::MachineApplicable,
             );
         });
@@ -1042,7 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.span_suggestion_verbose(
                         expr.span.shrink_to_lo(),
                         "you might have meant to use pattern matching",
-                        "let ".to_string(),
+                        "let ",
                         applicability,
                     );
                 };
@@ -1051,7 +1051,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 err.span_suggestion_verbose(
                     span,
                     "you might have meant to compare for equality",
-                    "==".to_string(),
+                    "==",
                     applicability,
                 );
             }
@@ -1086,7 +1086,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.span_suggestion_verbose(
                         lhs.span.shrink_to_lo(),
                         "consider dereferencing here to assign to the mutably borrowed value",
-                        "*".to_string(),
+                        "*",
                         Applicability::MachineApplicable,
                     );
                 }
@@ -1790,7 +1790,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_suggestion(
                 range_start.span.shrink_to_hi(),
                 &format!("to set the remaining fields{instead}, separate the last named field with a comma"),
-                ",".to_string(),
+                ",",
                 Applicability::MaybeIncorrect,
             );
         }
@@ -1912,7 +1912,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.span_suggestion(
                         field.ident.span,
                         "a field with a similar name exists",
-                        field_name.to_string(),
+                        field_name,
                         Applicability::MaybeIncorrect,
                     );
                 } else {
@@ -2158,7 +2158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.span_suggestion_verbose(
                         base.span.shrink_to_hi(),
                         "consider `await`ing on the `Future` and access the field of its `Output`",
-                        ".await".to_string(),
+                        ".await",
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -2358,7 +2358,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_suggestion(
                 field.span,
                 "a field with a similar name exists",
-                suggested_field_name.to_string(),
+                suggested_field_name,
                 Applicability::MaybeIncorrect,
             );
         } else {
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index c28c041e78d..ea7ebdf91d0 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -1310,7 +1310,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 err.span_suggestion(
                                     span,
                                     "use curly brackets",
-                                    String::from("Self { /* fields */ }"),
+                                    "Self { /* fields */ }",
                                     Applicability::HasPlaceholders,
                                 );
                             }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 0d0cc929839..93ca8e2237f 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -387,7 +387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     continue;
                 }
 
-                let is_closure = matches!(arg.kind, ExprKind::Closure(..));
+                let is_closure = matches!(arg.kind, ExprKind::Closure { .. });
                 if is_closure != check_closures {
                     continue;
                 }
@@ -1458,14 +1458,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 err.span_suggestion_verbose(
                     span_semi,
                     "consider removing this semicolon and boxing the expression",
-                    String::new(),
+                    "",
                     Applicability::HasPlaceholders,
                 );
             } else {
                 err.span_suggestion_short(
                     span_semi,
                     "remove this semicolon",
-                    String::new(),
+                    "",
                     Applicability::MachineApplicable,
                 );
             }
@@ -1774,10 +1774,10 @@ fn label_fn_like<'tcx>(
     } else {
         match tcx.hir().get_if_local(def_id) {
             Some(hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_, _, _, span, ..),
+                kind: hir::ExprKind::Closure { fn_decl_span, .. },
                 ..
             })) => {
-                let spans: MultiSpan = (*span).into();
+                let spans: MultiSpan = (*fn_decl_span).into();
 
                 // Note: We don't point to param spans here because they overlap
                 // with the closure span itself
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 99c766d54c8..03d91435e77 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -27,7 +27,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.span_suggestion_short(
             span.shrink_to_hi(),
             "consider using a semicolon here",
-            ";".to_string(),
+            ";",
             Applicability::MachineApplicable,
         );
     }
@@ -121,7 +121,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .join(", ");
                 }
                 Some(Node::Expr(hir::Expr {
-                    kind: ExprKind::Closure(_, _, body_id, _, _),
+                    kind: ExprKind::Closure { body: body_id, .. },
                     span: full_closure_span,
                     ..
                 })) => {
@@ -444,7 +444,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.span_suggestion(
                             fn_name.span,
                             "use `Box::pin` to pin and box this expression",
-                            "Box::pin".to_string(),
+                            "Box::pin",
                             Applicability::MachineApplicable,
                         );
                         true
@@ -507,7 +507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.span_suggestion(
                             expression.span.shrink_to_hi(),
                             "consider using a semicolon here",
-                            ";".to_string(),
+                            ";",
                             Applicability::MachineApplicable,
                         );
                     }
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
index 58b63804b4a..dbc309b29ff 100644
--- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
@@ -188,7 +188,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
             | ExprKind::If(..)
             | ExprKind::Loop(..)
             | ExprKind::Match(..)
-            | ExprKind::Closure(..)
+            | ExprKind::Closure { .. }
             | ExprKind::Block(..)
             | ExprKind::Assign(..)
             | ExprKind::AssignOp(..)
@@ -444,7 +444,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
             | ExprKind::Block(..)
             | ExprKind::Box(..)
             | ExprKind::Cast(..)
-            | ExprKind::Closure(..)
+            | ExprKind::Closure { .. }
             | ExprKind::ConstBlock(..)
             | ExprKind::DropTemps(..)
             | ExprKind::Err
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 5f6ddc1e1c9..8880049371e 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -330,7 +330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.span_suggestion(
                         span.shrink_to_lo(),
                         "you are looking for the module in `std`, not the primitive type",
-                        "std::".to_string(),
+                        "std::",
                         Applicability::MachineApplicable,
                     );
                 }
@@ -453,7 +453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.span_suggestion_short(
                             span,
                             msg,
-                            String::from("len"),
+                            "len",
                             Applicability::MachineApplicable,
                         );
                     } else {
@@ -893,7 +893,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 item_name.span,
                                 "because of the in-memory representation of `&str`, to obtain \
                                  an `Iterator` over each of its codepoint use method `chars`",
-                                String::from("chars"),
+                                "chars",
                                 Applicability::MachineApplicable,
                             );
                         }
@@ -1006,7 +1006,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.span_suggestion(
                             span,
                             "there is a variant with a similar name",
-                            suggestion.to_string(),
+                            suggestion,
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -1019,12 +1019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let call_expr =
                             self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
                         if let Some(span) = call_expr.span.trim_start(expr.span) {
-                            err.span_suggestion(
-                                span,
-                                msg,
-                                String::new(),
-                                Applicability::MachineApplicable,
-                            );
+                            err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
                             fallback_span = false;
                         }
                     }
@@ -1043,7 +1038,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 def_kind.article(),
                                 def_kind.descr(lev_candidate.def_id),
                             ),
-                            lev_candidate.name.to_string(),
+                            lev_candidate.name,
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -1164,7 +1159,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.span_suggestion(
                             span,
                             "remove the arguments",
-                            String::new(),
+                            "",
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -1418,7 +1413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             "use the `?` operator to extract the `{self_ty}` value, propagating \
                             {article} `{kind}::{variant}` value to the caller"
                         ),
-                        "?".to_owned(),
+                        "?",
                         Applicability::MachineApplicable,
                     );
                 } else {
@@ -1428,7 +1423,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
                              panicking if the value is {article} `{kind}::{variant}`"
                         ),
-                        ".expect(\"REASON\")".to_owned(),
+                        ".expect(\"REASON\")",
                         Applicability::HasPlaceholders,
                     );
                 }
@@ -1632,7 +1627,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_suggestion_verbose(
                 span.shrink_to_lo(),
                 "consider `await`ing on the `Future` and calling the method on its `Output`",
-                "await.".to_string(),
+                "await.",
                 Applicability::MaybeIncorrect,
             );
         }
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs
index 17a1f619ee1..c2f97a5051c 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_typeck/src/check/op.rs
@@ -446,7 +446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             err.span_suggestion_verbose(
                                 lhs_expr.span.shrink_to_lo(),
                                 msg,
-                                "*".to_string(),
+                                "*",
                                 rustc_errors::Applicability::MachineApplicable,
                             );
                         }
@@ -621,14 +621,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.span_suggestion_verbose(
                             lhs_expr.span.until(lhs_inner_expr.span),
                             rm_borrow_msg,
-                            "".to_owned(),
+                            "",
                             Applicability::MachineApplicable
                         );
                     } else {
                         err.span_suggestion_verbose(
                             lhs_expr.span.shrink_to_hi(),
                             to_owned_msg,
-                            ".to_owned()".to_owned(),
+                            ".to_owned()",
                             Applicability::MachineApplicable
                         );
                     }
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 5eba95b495d..f45b94bcdff 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -649,39 +649,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn borrow_pat_suggestion(
-        &self,
-        err: &mut Diagnostic,
-        pat: &Pat<'_>,
-        inner: &Pat<'_>,
-        expected: Ty<'tcx>,
-    ) {
+    // Precondition: pat is a Ref(_) pattern
+    fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>) {
         let tcx = self.tcx;
-        if let PatKind::Binding(..) = inner.kind {
+        if let PatKind::Ref(inner, mutbl) = pat.kind
+        && let PatKind::Binding(_, _, binding, ..) = inner.kind {
             let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id);
             let binding_parent = tcx.hir().get(binding_parent_id);
-            debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent);
+            debug!(?inner, ?pat, ?binding_parent);
+
+            let mutability = match mutbl {
+                ast::Mutability::Mut => "mut",
+                ast::Mutability::Not => "",
+            };
+
             match binding_parent {
-                hir::Node::Param(hir::Param { span, .. })
-                    if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) =>
-                {
-                    err.span_suggestion(
-                        *span,
-                        &format!("did you mean `{snippet}`"),
-                        format!(" &{expected}"),
-                        Applicability::MachineApplicable,
+                // Check that there is explicit type (ie this is not a closure param with inferred type)
+                // so we don't suggest moving something to the type that does not exist
+                hir::Node::Param(hir::Param { ty_span, .. }) if binding.span != *ty_span => {
+                    err.multipart_suggestion_verbose(
+                        format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"),
+                        vec![
+                            (pat.span.until(inner.span), "".to_owned()),
+                            (ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())),
+                        ],
+                        Applicability::MachineApplicable
                     );
                 }
-                hir::Node::Arm(_) | hir::Node::Pat(_) => {
+                hir::Node::Param(_) | hir::Node::Arm(_) | hir::Node::Pat(_) => {
                     // rely on match ergonomics or it might be nested `&&pat`
-                    if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
-                        err.span_suggestion(
-                            pat.span,
-                            "you can probably remove the explicit borrow",
-                            snippet,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
+                    err.span_suggestion_verbose(
+                        pat.span.until(inner.span),
+                        format!("consider removing `&{mutability}` from the pattern"),
+                        "",
+                        Applicability::MaybeIncorrect,
+                    );
                 }
                 _ => {} // don't provide suggestions in other cases #55175
             }
@@ -1150,14 +1152,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.span_suggestion_verbose(
                         all_fields_span,
                         "use `..` to ignore all fields",
-                        String::from(".."),
+                        "..",
                         Applicability::MaybeIncorrect,
                     );
                 } else {
                     err.span_suggestion_verbose(
                         tail_span,
                         "use `..` to ignore the rest of the fields",
-                        String::from(", .."),
+                        ", ..",
                         Applicability::MaybeIncorrect,
                     );
                 }
@@ -1428,7 +1430,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.span_suggestion_verbose(
             sp_comma,
             "add `..` at the end of the field list to ignore all other fields",
-            sugg.to_string(),
+            sugg,
             Applicability::MachineApplicable,
         );
         err.emit();
@@ -1502,7 +1504,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.span_suggestion(
                         pat_field.ident.span,
                         "a field with a similar name exists",
-                        suggested_name.to_string(),
+                        suggested_name,
                         Applicability::MaybeIncorrect,
                     );
 
@@ -1655,7 +1657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_suggestion_verbose(
                 field.span.shrink_to_hi(),
                 "ignore the inaccessible and unused fields",
-                ", ..".to_string(),
+                ", ..",
                 Applicability::MachineApplicable,
             );
         } else {
@@ -1670,7 +1672,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_suggestion_verbose(
                 span,
                 "ignore the inaccessible and unused fields",
-                " { .. }".to_string(),
+                " { .. }",
                 Applicability::MachineApplicable,
             );
         }
@@ -1836,6 +1838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         box_ty
     }
 
+    // Precondition: Pat is Ref(inner)
     fn check_pat_ref(
         &self,
         pat: &'tcx Pat<'tcx>,
@@ -1853,7 +1856,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             // Take region, inner-type from expected type if we can,
             // to avoid creating needless variables. This also helps with
-            // the bad  interactions of the given hack detailed in (note_1).
+            // the bad interactions of the given hack detailed in (note_1).
             debug!("check_pat_ref: expected={:?}", expected);
             match *expected.kind() {
                 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
@@ -1869,7 +1872,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // Look for a case like `fn foo(&foo: u32)` and suggest
                     // `fn foo(foo: &u32)`
                     if let Some(mut err) = err {
-                        self.borrow_pat_suggestion(&mut err, pat, inner, expected);
+                        self.borrow_pat_suggestion(&mut err, pat);
                         err.emit();
                     }
                     (rptr_ty, inner_ty)
diff --git a/compiler/rustc_typeck/src/check/region.rs b/compiler/rustc_typeck/src/check/region.rs
index 6c89c12b470..9f1368a3e07 100644
--- a/compiler/rustc_typeck/src/check/region.rs
+++ b/compiler/rustc_typeck/src/check/region.rs
@@ -335,7 +335,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
     match expr.kind {
         // Manually recurse over closures and inline consts, because they are the only
         // case of nested bodies that share the parent environment.
-        hir::ExprKind::Closure(.., body, _, _)
+        hir::ExprKind::Closure { body, .. }
         | hir::ExprKind::ConstBlock(hir::AnonConst { body, .. }) => {
             let body = visitor.tcx.hir().body(body);
             visitor.visit_body(body);
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
index 65b38b3f2e7..161ec31793d 100644
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ b/compiler/rustc_typeck/src/check/regionck.rs
@@ -82,7 +82,7 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::PatKind;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{self, InferCtxt, RegionObligation, RegionckMode};
+use rustc_infer::infer::{self, InferCtxt, RegionObligation};
 use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId};
 use rustc_middle::ty::adjustment;
 use rustc_middle::ty::{self, Ty};
@@ -163,7 +163,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             rcx.visit_body(body);
             rcx.visit_region_obligations(id);
         }
-        rcx.resolve_regions_and_report_errors(RegionckMode::Erase);
+        // Checked by NLL
+        rcx.fcx.skip_region_resolution();
     }
 
     /// Region checking during the WF phase for items. `wf_tys` are the
@@ -175,7 +176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
         rcx.outlives_environment.save_implied_bounds(item_id);
         rcx.visit_region_obligations(item_id);
-        rcx.resolve_regions_and_report_errors(RegionckMode::default());
+        rcx.resolve_regions_and_report_errors();
     }
 
     /// Region check a function body. Not invoked on closures, but
@@ -206,7 +207,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id));
         }
 
-        rcx.resolve_regions_and_report_errors(RegionckMode::Erase);
+        // Checked by NLL
+        rcx.fcx.skip_region_resolution();
     }
 }
 
@@ -361,7 +363,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
         self.select_all_obligations_or_error();
     }
 
-    fn resolve_regions_and_report_errors(&self, mode: RegionckMode) {
+    fn resolve_regions_and_report_errors(&self) {
         self.infcx.process_registered_region_obligations(
             self.outlives_environment.region_bound_pairs_map(),
             Some(self.tcx.lifetimes.re_root_empty),
@@ -371,7 +373,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
         self.fcx.resolve_regions_and_report_errors(
             self.subject_def_id.to_def_id(),
             &self.outlives_environment,
-            mode,
         );
     }
 
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index 8074ff368cc..0837d9c4a20 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -142,10 +142,10 @@ struct InferBorrowKindVisitor<'a, 'tcx> {
 impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         match expr.kind {
-            hir::ExprKind::Closure(cc, _, body_id, _, _) => {
+            hir::ExprKind::Closure { capture_clause, body: body_id, .. } => {
                 let body = self.fcx.tcx.hir().body(body_id);
                 self.visit_body(body);
-                self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc);
+                self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
             }
             hir::ExprKind::ConstBlock(anon_const) => {
                 let body = self.fcx.tcx.hir().body(anon_const.body);
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 362e034ba54..2db5f5d4071 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -15,8 +15,7 @@ use rustc_hir::ItemKind;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::outlives::obligations::TypeOutlives;
 use rustc_infer::infer::region_constraints::GenericKind;
-use rustc_infer::infer::{self, RegionckMode};
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
@@ -650,11 +649,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
 
         add_constraints(&infcx, region_bound_pairs);
 
-        let errors = infcx.resolve_regions(
-            id.expect_owner().to_def_id(),
-            &outlives_environment,
-            RegionckMode::default(),
-        );
+        let errors = infcx.resolve_regions(id.expect_owner().to_def_id(), &outlives_environment);
 
         debug!(?errors, "errors");
 
@@ -1387,7 +1382,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                 }
 
                 fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-                    if let ty::ConstKind::Param(param) = c.val() {
+                    if let ty::ConstKind::Param(param) = c.kind() {
                         self.params.insert(param.index);
                     }
                     c.super_visit_with(self)
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index dc135f002f4..9459cf5f8ca 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -262,7 +262,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
         self.fix_index_builtin_expr(e);
 
         match e.kind {
-            hir::ExprKind::Closure(_, _, body, _, _) => {
+            hir::ExprKind::Closure { body, .. } => {
                 let body = self.fcx.tcx.hir().body(body);
                 for param in body.params {
                     self.visit_node_id(e.span, param.hir_id);
diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs
index f28184c74d3..4a3cfa1ca37 100644
--- a/compiler/rustc_typeck/src/check_unused.rs
+++ b/compiler/rustc_typeck/src/check_unused.rs
@@ -122,7 +122,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
                         .span_suggestion_short(
                             span_with_attrs,
                             "remove it",
-                            String::new(),
+                            "",
                             Applicability::MachineApplicable,
                         )
                         .emit();
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
index 9f4e6a46d73..c647c2a4c1b 100644
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ b/compiler/rustc_typeck/src/coherence/builtin.rs
@@ -9,7 +9,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
 use rustc_infer::infer;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
 use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeFoldable};
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
@@ -349,11 +349,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did:
 
                     // Finally, resolve all regions.
                     let outlives_env = OutlivesEnvironment::new(param_env);
-                    infcx.resolve_regions_and_report_errors(
-                        impl_did.to_def_id(),
-                        &outlives_env,
-                        RegionckMode::default(),
-                    );
+                    infcx.resolve_regions_and_report_errors(impl_did.to_def_id(), &outlives_env);
                 }
             }
             _ => {
@@ -610,11 +606,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
 
         // Finally, resolve all regions.
         let outlives_env = OutlivesEnvironment::new(param_env);
-        infcx.resolve_regions_and_report_errors(
-            impl_did.to_def_id(),
-            &outlives_env,
-            RegionckMode::default(),
-        );
+        infcx.resolve_regions_and_report_errors(impl_did.to_def_id(), &outlives_env);
 
         CoerceUnsizedInfo { custom_kind: kind }
     })
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 5a70dc1e594..1f2e6ad86bd 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -295,7 +295,7 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
     }
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-        if let hir::ExprKind::Closure(..) = expr.kind {
+        if let hir::ExprKind::Closure { .. } = expr.kind {
             let def_id = self.tcx.hir().local_def_id(expr.hir_id);
             self.tcx.ensure().generics_of(def_id);
             // We do not call `type_of` for closures here as that
@@ -806,8 +806,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
                 hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id),
                 hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id),
                 hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => {
-                    // (#75889): Account for `const C: dyn Fn() -> _ = "";`
-                    if let hir::TyKind::TraitObject(..) = ty.kind {
+                    if !is_suggestable_infer_ty(ty) {
                         let mut visitor = HirPlaceholderCollector::default();
                         visitor.visit_item(it);
                         placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr());
@@ -1567,7 +1566,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                 }
             }
         }
-        Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
+        Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
             Some(tcx.typeck_root_def_id(def_id))
         }
         Node::Item(item) => match item.kind {
@@ -1718,7 +1717,9 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
     // provide junk type parameter defs - the only place that
     // cares about anything but the length is instantiation,
     // and we don't do that for closures.
-    if let Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), .. }) = node {
+    if let Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { movability: gen, .. }, .. }) =
+        node
+    {
         let dummy_args = if gen.is_some() {
             &["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
         } else {
@@ -1881,7 +1882,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
             ))
         }
 
-        Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
+        Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
             // Closure signatures are not like other function
             // signatures and cannot be accessed through `fn_sig`. For
             // example, a closure signature excludes the `self`
@@ -1930,7 +1931,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
                 diag.span_suggestion(
                     ty.span,
                     "replace with the correct return type",
-                    ret_ty.to_string(),
+                    ret_ty,
                     Applicability::MachineApplicable,
                 );
             } else if matches!(ret_ty.kind(), ty::FnDef(..)) {
@@ -1939,7 +1940,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
                     diag.span_suggestion(
                         ty.span,
                         "replace with the correct return type",
-                        fn_sig.to_string(),
+                        fn_sig,
                         Applicability::MachineApplicable,
                     );
                 }
@@ -2353,7 +2354,7 @@ fn const_evaluatable_predicates_of<'tcx>(
         fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
             let def_id = self.tcx.hir().local_def_id(c.hir_id);
             let ct = ty::Const::from_anon_const(self.tcx, def_id);
-            if let ty::ConstKind::Unevaluated(uv) = ct.val() {
+            if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
                 assert_eq!(uv.promoted, None);
                 let span = self.tcx.hir().span(c.hir_id);
                 self.preds.insert((
@@ -2567,9 +2568,9 @@ fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind> {
     match tcx.hir().get_if_local(def_id) {
         Some(Node::Expr(&rustc_hir::Expr {
-            kind: rustc_hir::ExprKind::Closure(_, _, body_id, _, _),
+            kind: rustc_hir::ExprKind::Closure { body, .. },
             ..
-        })) => tcx.hir().body(body_id).generator_kind(),
+        })) => tcx.hir().body(body).generator_kind(),
         Some(_) => None,
         _ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
     }
@@ -2584,7 +2585,7 @@ fn from_target_feature(
     let Some(list) = attr.meta_item_list() else { return };
     let bad_item = |span| {
         let msg = "malformed `target_feature` attribute input";
-        let code = "enable = \"..\"".to_owned();
+        let code = "enable = \"..\"";
         tcx.sess
             .struct_span_err(span, msg)
             .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 451a953691b..7011dd6e15c 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -405,7 +405,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
         Node::Field(field) => icx.to_ty(field.ty),
 
-        Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => tcx.typeck(def_id).node_type(hir_id),
+        Node::Expr(&Expr { kind: ExprKind::Closure{..}, .. }) => tcx.typeck(def_id).node_type(hir_id),
 
         Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
             // We defer to `type_of` of the corresponding parameter
@@ -593,7 +593,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
             self.tcx.hir()
         }
         fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
-            if let hir::ExprKind::Closure(..) = ex.kind {
+            if let hir::ExprKind::Closure { .. } = ex.kind {
                 let def_id = self.tcx.hir().local_def_id(ex.hir_id);
                 self.check(def_id);
             }
@@ -756,7 +756,7 @@ fn infer_placeholder_type<'a>(
                     diag.span_suggestion(
                         span,
                         "replace with the correct type",
-                        sugg_ty.to_string(),
+                        sugg_ty,
                         Applicability::MaybeIncorrect,
                     );
                 } else {
diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_typeck/src/constrained_generic_params.rs
index fc299057f4b..858cf63390a 100644
--- a/compiler/rustc_typeck/src/constrained_generic_params.rs
+++ b/compiler/rustc_typeck/src/constrained_generic_params.rs
@@ -80,7 +80,7 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
     }
 
     fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match c.val() {
+        match c.kind() {
             ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => {
                 // Constant expressions are not injective
                 return c.ty().visit_with(self);
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs
index 3ebb1dd83e1..920e3d578c8 100644
--- a/compiler/rustc_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_typeck/src/expr_use_visitor.rs
@@ -437,7 +437,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 self.consume_expr(base);
             }
 
-            hir::ExprKind::Closure(..) => {
+            hir::ExprKind::Closure { .. } => {
                 self.walk_captures(expr);
             }
 
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
index bb97d00be32..0ecc28e6054 100644
--- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
@@ -71,7 +71,7 @@ use crate::errors::SubstsOnOverriddenImpl;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::specialization_graph::Node;
 use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
@@ -164,7 +164,7 @@ fn get_impl_substs<'tcx>(
 
     // Conservatively use an empty `ParamEnv`.
     let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
-    infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env, RegionckMode::default());
+    infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
     let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
         tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
         return None;
diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_typeck/src/mem_categorization.rs
index 21916352532..9acae8d79e7 100644
--- a/compiler/rustc_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_typeck/src/mem_categorization.rs
@@ -359,7 +359,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
             | hir::ExprKind::Call(..)
             | hir::ExprKind::Assign(..)
             | hir::ExprKind::AssignOp(..)
-            | hir::ExprKind::Closure(..)
+            | hir::ExprKind::Closure { .. }
             | hir::ExprKind::Ret(..)
             | hir::ExprKind::Unary(..)
             | hir::ExprKind::Yield(..)
diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs
index 54a5037b575..14e3048cadc 100644
--- a/compiler/rustc_typeck/src/outlives/utils.rs
+++ b/compiler/rustc_typeck/src/outlives/utils.rs
@@ -21,7 +21,7 @@ pub fn insert_outlives_predicate<'tcx>(
 ) {
     // If the `'a` region is bound within the field type itself, we
     // don't want to propagate this constraint to the header.
-    if !is_free_region(tcx, outlived_region) {
+    if !is_free_region(outlived_region) {
         return;
     }
 
@@ -119,7 +119,7 @@ pub fn insert_outlives_predicate<'tcx>(
         }
 
         GenericArgKind::Lifetime(r) => {
-            if !is_free_region(tcx, r) {
+            if !is_free_region(r) {
                 return;
             }
             required_predicates.entry(ty::OutlivesPredicate(kind, outlived_region)).or_insert(span);
@@ -131,7 +131,7 @@ pub fn insert_outlives_predicate<'tcx>(
     }
 }
 
-fn is_free_region(tcx: TyCtxt<'_>, region: Region<'_>) -> bool {
+fn is_free_region(region: Region<'_>) -> bool {
     // First, screen for regions that might appear in a type header.
     match *region {
         // These correspond to `T: 'a` relationships:
@@ -144,13 +144,12 @@ fn is_free_region(tcx: TyCtxt<'_>, region: Region<'_>) -> bool {
         ty::ReEarlyBound(_) => true,
 
         // These correspond to `T: 'static` relationships which can be
-        // rather surprising. We are therefore putting this behind a
-        // feature flag:
+        // rather surprising.
         //
         //     struct Foo<'a, T> {
         //         field: &'static T, // this would generate a ReStatic
         //     }
-        ty::ReStatic => tcx.sess.features_untracked().infer_static_outlives_requirements,
+        ty::ReStatic => false,
 
         // Late-bound regions can appear in `fn` types:
         //
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
index c440e93fe0a..3224864e9b1 100644
--- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -715,7 +715,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             err.span_suggestion(
                 span_redundant_lt_args,
                 &msg_lifetimes,
-                String::new(),
+                "",
                 Applicability::MaybeIncorrect,
             );
         };
@@ -757,7 +757,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             err.span_suggestion(
                 span_redundant_type_or_const_args,
                 &msg_types_or_consts,
-                String::new(),
+                "",
                 Applicability::MaybeIncorrect,
             );
         };
@@ -797,7 +797,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
                 if self.gen_args.parenthesized { "parenthetical " } else { "" },
             );
 
-            err.span_suggestion(span, &msg, String::new(), Applicability::MaybeIncorrect);
+            err.span_suggestion(span, &msg, "", Applicability::MaybeIncorrect);
         } else if redundant_lifetime_args && redundant_type_or_const_args {
             remove_lifetime_args(err);
             remove_type_or_const_args(err);
diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs
index 690c362d853..a7dcbfff207 100644
--- a/compiler/rustc_typeck/src/variance/constraints.rs
+++ b/compiler/rustc_typeck/src/variance/constraints.rs
@@ -411,12 +411,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     fn add_constraints_from_const(
         &mut self,
         current: &CurrentItem,
-        val: ty::Const<'tcx>,
+        c: ty::Const<'tcx>,
         variance: VarianceTermPtr<'a>,
     ) {
-        debug!("add_constraints_from_const(val={:?}, variance={:?})", val, variance);
+        debug!("add_constraints_from_const(c={:?}, variance={:?})", c, variance);
 
-        match &val.val() {
+        match &c.kind() {
             ty::ConstKind::Unevaluated(uv) => {
                 self.add_constraints_from_invariant_substs(current, uv.substs, variance);
             }
diff --git a/library/alloc/src/collections/btree/fix.rs b/library/alloc/src/collections/btree/fix.rs
index c4861817dd0..fd73fde2acb 100644
--- a/library/alloc/src/collections/btree/fix.rs
+++ b/library/alloc/src/collections/btree/fix.rs
@@ -91,8 +91,8 @@ impl<K, V> Root<K, V> {
         }
     }
 
-    /// Stock up any underfull nodes on the right border of the tree.
-    /// The other nodes, those that are not the root nor a rightmost edge,
+    /// Stocks up any underfull nodes on the right border of the tree.
+    /// The other nodes, those that are neither the root nor a rightmost edge,
     /// must be prepared to have up to MIN_LEN elements stolen.
     pub fn fix_right_border_of_plentiful(&mut self) {
         let mut cur_node = self.borrow_mut();
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index cacd06b5df1..e2749aac694 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -315,7 +315,7 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
     pub fn insert(self, value: V) -> &'a mut V {
         let out_ptr = match self.handle {
             None => {
-                // SAFETY: We have consumed self.handle and the reference returned.
+                // SAFETY: There is no tree yet so no reference to it exists.
                 let map = unsafe { self.dormant_map.awaken() };
                 let mut root = NodeRef::new_leaf();
                 let val_ptr = root.borrow_mut().push(self.key, value) as *mut V;
@@ -325,16 +325,17 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
             }
             Some(handle) => match handle.insert_recursing(self.key, value) {
                 (None, val_ptr) => {
-                    // SAFETY: We have consumed self.handle and the handle returned.
+                    // SAFETY: We have consumed self.handle.
                     let map = unsafe { self.dormant_map.awaken() };
                     map.length += 1;
                     val_ptr
                 }
                 (Some(ins), val_ptr) => {
                     drop(ins.left);
-                    // SAFETY: We have consumed self.handle and the reference returned.
+                    // SAFETY: We have consumed self.handle and dropped the
+                    // remaining reference to the tree, ins.left.
                     let map = unsafe { self.dormant_map.awaken() };
-                    let root = map.root.as_mut().unwrap();
+                    let root = map.root.as_mut().unwrap(); // same as ins.left
                     root.push_internal_level().push(ins.kv.0, ins.kv.1, ins.right);
                     map.length += 1;
                     val_ptr
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index a38b8fb739a..93cdf121fbe 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -143,7 +143,8 @@ mod c_char_definition {
                     target_arch = "powerpc"
                 )
             ),
-            all(target_os = "fuchsia", target_arch = "aarch64")
+            all(target_os = "fuchsia", target_arch = "aarch64"),
+            target_os = "horizon"
         ))] {
             pub type c_char = u8;
             pub type NonZero_c_char = crate::num::NonZeroU8;
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 5223c43acc2..c4f2e283eb3 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -1632,6 +1632,7 @@ impl str {
     ///
     /// ```
     /// assert_eq!("cfg".split_once('='), None);
+    /// assert_eq!("cfg=".split_once('='), Some(("cfg", "")));
     /// assert_eq!("cfg=foo".split_once('='), Some(("cfg", "foo")));
     /// assert_eq!("cfg=foo=bar".split_once('='), Some(("cfg", "foo=bar")));
     /// ```
diff --git a/library/proc_macro/src/bridge/handle.rs b/library/proc_macro/src/bridge/handle.rs
index 7d6adda48ec..c219a9465d3 100644
--- a/library/proc_macro/src/bridge/handle.rs
+++ b/library/proc_macro/src/bridge/handle.rs
@@ -1,7 +1,7 @@
 //! Server-side handles and storage for per-handle data.
 
 use std::collections::{BTreeMap, HashMap};
-use std::hash::Hash;
+use std::hash::{BuildHasher, Hash};
 use std::num::NonZeroU32;
 use std::ops::{Index, IndexMut};
 use std::sync::atomic::{AtomicUsize, Ordering};
@@ -51,15 +51,31 @@ impl<T> IndexMut<Handle> for OwnedStore<T> {
     }
 }
 
+// HACK(eddyb) deterministic `std::collections::hash_map::RandomState` replacement
+// that doesn't require adding any dependencies to `proc_macro` (like `rustc-hash`).
+#[derive(Clone)]
+struct NonRandomState;
+
+impl BuildHasher for NonRandomState {
+    type Hasher = std::collections::hash_map::DefaultHasher;
+    #[inline]
+    fn build_hasher(&self) -> Self::Hasher {
+        Self::Hasher::new()
+    }
+}
+
 /// Like `OwnedStore`, but avoids storing any value more than once.
 pub(super) struct InternedStore<T: 'static> {
     owned: OwnedStore<T>,
-    interner: HashMap<T, Handle>,
+    interner: HashMap<T, Handle, NonRandomState>,
 }
 
 impl<T: Copy + Eq + Hash> InternedStore<T> {
     pub(super) fn new(counter: &'static AtomicUsize) -> Self {
-        InternedStore { owned: OwnedStore::new(counter), interner: HashMap::new() }
+        InternedStore {
+            owned: OwnedStore::new(counter),
+            interner: HashMap::with_hasher(NonRandomState),
+        }
     }
 
     pub(super) fn alloc(&mut self, x: T) -> Handle {
diff --git a/library/std/build.rs b/library/std/build.rs
index 43168e77296..bffbe802fd0 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -29,6 +29,7 @@ fn main() {
         || target.contains("asmjs")
         || target.contains("espidf")
         || target.contains("solid")
+        || target.contains("nintendo-3ds")
     {
         // These platforms don't have any special requirements.
     } else {
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 11ccdd9ea1c..d38fecc45b2 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -3140,6 +3140,7 @@ impl DefaultHasher {
     /// `DefaultHasher` instances, but is the same as all other `DefaultHasher`
     /// instances created through `new` or `default`.
     #[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
+    #[inline]
     #[allow(deprecated)]
     #[must_use]
     pub fn new() -> DefaultHasher {
@@ -3153,6 +3154,7 @@ impl Default for DefaultHasher {
     /// See its documentation for more.
     ///
     /// [`new`]: DefaultHasher::new
+    #[inline]
     fn default() -> DefaultHasher {
         DefaultHasher::new()
     }
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 247bdd95458..1212ff6f74a 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -45,6 +45,22 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// values, encoded in a less-strict variant of UTF-8. This is useful to
 /// understand when handling capacity and length values.
 ///
+/// # Capacity of `OsString`
+///
+/// Capacity uses units of UTF-8 bytes for OS strings which were created from valid unicode, and
+/// uses units of bytes in an unspecified encoding for other contents. On a given target, all
+/// `OsString` and `OsStr` values use the same units for capacity, so the following will work:
+/// ```
+/// use std::ffi::{OsStr, OsString};
+///
+/// fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
+///     let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
+///     ret.push(a); // This will not allocate further
+///     ret.push(b); // This will not allocate further
+///     ret
+/// }
+/// ```
+///
 /// # Creating an `OsString`
 ///
 /// **From a Rust string**: `OsString` implements
@@ -186,7 +202,7 @@ impl OsString {
     /// OS strings without reallocating. If `capacity` is 0, the string will not
     /// allocate.
     ///
-    /// See main `OsString` documentation information about encoding.
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Examples
     ///
@@ -229,7 +245,7 @@ impl OsString {
 
     /// Returns the capacity this `OsString` can hold without reallocating.
     ///
-    /// See `OsString` introduction for information about encoding.
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Examples
     ///
@@ -251,6 +267,8 @@ impl OsString {
     ///
     /// The collection may reserve more space to avoid frequent reallocations.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -272,6 +290,8 @@ impl OsString {
     /// greater than or equal to `self.len() + additional`. Does nothing if
     /// capacity is already sufficient.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Errors
     ///
     /// If the capacity overflows, or the allocator reports a failure, then an error
@@ -313,6 +333,8 @@ impl OsString {
     ///
     /// [`reserve`]: OsString::reserve
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -340,6 +362,8 @@ impl OsString {
     ///
     /// [`try_reserve`]: OsString::try_reserve
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Errors
     ///
     /// If the capacity overflows, or the allocator reports a failure, then an error
@@ -373,6 +397,8 @@ impl OsString {
 
     /// Shrinks the capacity of the `OsString` to match its length.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -399,6 +425,8 @@ impl OsString {
     ///
     /// If the current capacity is less than the lower limit, this is a no-op.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -773,6 +801,8 @@ impl OsStr {
     /// This number is simply useful for passing to other methods, like
     /// [`OsString::with_capacity`] to avoid reallocations.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs
index 13bb079194f..a456947534a 100644
--- a/library/std/src/os/fd/mod.rs
+++ b/library/std/src/os/fd/mod.rs
@@ -1,6 +1,6 @@
 //! Owned and borrowed Unix-like file descriptors.
 
-#![unstable(feature = "io_safety", issue = "87074")]
+#![stable(feature = "io_safety", since = "1.63.0")]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 // `RawFd`, `AsRawFd`, etc.
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index 53433823fbd..45b792039ef 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -1,6 +1,6 @@
 //! Owned and borrowed Unix-like file descriptors.
 
-#![unstable(feature = "io_safety", issue = "87074")]
+#![stable(feature = "io_safety", since = "1.63.0")]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
@@ -33,7 +33,7 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 // because c_int is 32 bits.
 #[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
 #[rustc_nonnull_optimization_guaranteed]
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub struct BorrowedFd<'fd> {
     fd: RawFd,
     _phantom: PhantomData<&'fd OwnedFd>,
@@ -54,7 +54,7 @@ pub struct BorrowedFd<'fd> {
 // because c_int is 32 bits.
 #[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
 #[rustc_nonnull_optimization_guaranteed]
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub struct OwnedFd {
     fd: RawFd,
 }
@@ -67,7 +67,8 @@ impl BorrowedFd<'_> {
     /// The resource pointed to by `fd` must remain open for the duration of
     /// the returned `BorrowedFd`, and it must not have the value `-1`.
     #[inline]
-    #[unstable(feature = "io_safety", issue = "87074")]
+    #[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
+    #[stable(feature = "io_safety", since = "1.63.0")]
     pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
         assert!(fd != u32::MAX as RawFd);
         // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
@@ -79,6 +80,7 @@ impl OwnedFd {
     /// Creates a new `OwnedFd` instance that shares the same underlying file handle
     /// as the existing `OwnedFd` instance.
     #[cfg(not(target_arch = "wasm32"))]
+    #[stable(feature = "io_safety", since = "1.63.0")]
     pub fn try_clone(&self) -> crate::io::Result<Self> {
         // We want to atomically duplicate this file descriptor and set the
         // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
@@ -98,6 +100,7 @@ impl OwnedFd {
     }
 
     #[cfg(target_arch = "wasm32")]
+    #[stable(feature = "io_safety", since = "1.63.0")]
     pub fn try_clone(&self) -> crate::io::Result<Self> {
         Err(crate::io::const_io_error!(
             crate::io::ErrorKind::Unsupported,
@@ -106,7 +109,7 @@ impl OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsRawFd for BorrowedFd<'_> {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
@@ -114,7 +117,7 @@ impl AsRawFd for BorrowedFd<'_> {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsRawFd for OwnedFd {
     #[inline]
     fn as_raw_fd(&self) -> RawFd {
@@ -122,7 +125,7 @@ impl AsRawFd for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl IntoRawFd for OwnedFd {
     #[inline]
     fn into_raw_fd(self) -> RawFd {
@@ -132,7 +135,7 @@ impl IntoRawFd for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl FromRawFd for OwnedFd {
     /// Constructs a new instance of `Self` from the given raw file descriptor.
     ///
@@ -148,7 +151,7 @@ impl FromRawFd for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl Drop for OwnedFd {
     #[inline]
     fn drop(&mut self) {
@@ -163,14 +166,14 @@ impl Drop for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl fmt::Debug for BorrowedFd<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("BorrowedFd").field("fd", &self.fd).finish()
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl fmt::Debug for OwnedFd {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("OwnedFd").field("fd", &self.fd).finish()
@@ -182,14 +185,13 @@ impl fmt::Debug for OwnedFd {
 /// This is only available on unix platforms and must be imported in order to
 /// call the method. Windows platforms have a corresponding `AsHandle` and
 /// `AsSocket` set of traits.
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub trait AsFd {
     /// Borrows the file descriptor.
     ///
     /// # Example
     ///
     /// ```rust,no_run
-    /// # #![feature(io_safety)]
     /// use std::fs::File;
     /// # use std::io;
     /// # #[cfg(target_os = "wasi")]
@@ -202,11 +204,11 @@ pub trait AsFd {
     /// let borrowed_fd: BorrowedFd<'_> = f.as_fd();
     /// # Ok::<(), io::Error>(())
     /// ```
-    #[unstable(feature = "io_safety", issue = "87074")]
+    #[stable(feature = "io_safety", since = "1.63.0")]
     fn as_fd(&self) -> BorrowedFd<'_>;
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<T: AsFd> AsFd for &T {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -214,7 +216,7 @@ impl<T: AsFd> AsFd for &T {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<T: AsFd> AsFd for &mut T {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -222,7 +224,7 @@ impl<T: AsFd> AsFd for &mut T {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for BorrowedFd<'_> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -230,7 +232,7 @@ impl AsFd for BorrowedFd<'_> {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for OwnedFd {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -241,7 +243,7 @@ impl AsFd for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for fs::File {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -249,7 +251,7 @@ impl AsFd for fs::File {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<fs::File> for OwnedFd {
     #[inline]
     fn from(file: fs::File) -> OwnedFd {
@@ -257,7 +259,7 @@ impl From<fs::File> for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedFd> for fs::File {
     #[inline]
     fn from(owned_fd: OwnedFd) -> Self {
@@ -265,7 +267,7 @@ impl From<OwnedFd> for fs::File {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for crate::net::TcpStream {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -273,7 +275,7 @@ impl AsFd for crate::net::TcpStream {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::net::TcpStream> for OwnedFd {
     #[inline]
     fn from(tcp_stream: crate::net::TcpStream) -> OwnedFd {
@@ -281,7 +283,7 @@ impl From<crate::net::TcpStream> for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedFd> for crate::net::TcpStream {
     #[inline]
     fn from(owned_fd: OwnedFd) -> Self {
@@ -291,7 +293,7 @@ impl From<OwnedFd> for crate::net::TcpStream {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for crate::net::TcpListener {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -299,7 +301,7 @@ impl AsFd for crate::net::TcpListener {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::net::TcpListener> for OwnedFd {
     #[inline]
     fn from(tcp_listener: crate::net::TcpListener) -> OwnedFd {
@@ -307,7 +309,7 @@ impl From<crate::net::TcpListener> for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedFd> for crate::net::TcpListener {
     #[inline]
     fn from(owned_fd: OwnedFd) -> Self {
@@ -317,7 +319,7 @@ impl From<OwnedFd> for crate::net::TcpListener {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for crate::net::UdpSocket {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -325,7 +327,7 @@ impl AsFd for crate::net::UdpSocket {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::net::UdpSocket> for OwnedFd {
     #[inline]
     fn from(udp_socket: crate::net::UdpSocket) -> OwnedFd {
@@ -333,7 +335,7 @@ impl From<crate::net::UdpSocket> for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedFd> for crate::net::UdpSocket {
     #[inline]
     fn from(owned_fd: OwnedFd) -> Self {
diff --git a/library/std/src/os/horizon/fs.rs b/library/std/src/os/horizon/fs.rs
new file mode 100644
index 00000000000..1325522105d
--- /dev/null
+++ b/library/std/src/os/horizon/fs.rs
@@ -0,0 +1,95 @@
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
+
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: crate::fs::Metadata
+#[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
+    }
+    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
+    }
+    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
+    }
+    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/horizon/mod.rs b/library/std/src/os/horizon/mod.rs
new file mode 100644
index 00000000000..326d0ae9cb9
--- /dev/null
+++ b/library/std/src/os/horizon/mod.rs
@@ -0,0 +1,6 @@
+//! Definitions for Horizon OS
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod fs;
+pub(crate) mod raw;
diff --git a/library/std/src/os/horizon/raw.rs b/library/std/src/os/horizon/raw.rs
new file mode 100644
index 00000000000..929fa7db1f9
--- /dev/null
+++ b/library/std/src/os/horizon/raw.rs
@@ -0,0 +1,70 @@
+//! Horizon OS raw type definitions
+
+#![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_long;
+use crate::os::unix::raw::{gid_t, uid_t};
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = libc::pthread_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blkcnt_t = libc::blkcnt_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blksize_t = libc::blksize_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type dev_t = libc::dev_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type ino_t = libc::ino_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type mode_t = libc::mode_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type nlink_t = libc::nlink_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type off_t = libc::off_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type time_t = libc::time_t;
+
+#[repr(C)]
+#[derive(Clone)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub struct stat {
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_dev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ino: ino_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mode: mode_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_nlink: nlink_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_uid: uid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gid: gid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_rdev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_size: off_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blksize: blksize_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blocks: blkcnt_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_spare4: [c_long; 2usize],
+}
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index 029f131c40b..a1df72a8a04 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -123,6 +123,8 @@ pub mod freebsd;
 pub mod fuchsia;
 #[cfg(target_os = "haiku")]
 pub mod haiku;
+#[cfg(target_os = "horizon")]
+pub mod horizon;
 #[cfg(target_os = "illumos")]
 pub mod illumos;
 #[cfg(target_os = "ios")]
diff --git a/library/std/src/os/unix/io/fd.rs b/library/std/src/os/unix/io/fd.rs
index 7795db7abc0..d4cb696459b 100644
--- a/library/std/src/os/unix/io/fd.rs
+++ b/library/std/src/os/unix/io/fd.rs
@@ -1,9 +1,8 @@
 //! Owned and borrowed file descriptors.
 
-#![unstable(feature = "io_safety", issue = "87074")]
-
 // Tests for this module
 #[cfg(test)]
 mod tests;
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub use crate::os::fd::owned::*;
diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs
index 0fd9591b016..e3a7cfc8d2a 100644
--- a/library/std/src/os/unix/io/mod.rs
+++ b/library/std/src/os/unix/io/mod.rs
@@ -51,7 +51,7 @@
 mod fd;
 mod raw;
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub use fd::*;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use raw::*;
diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs
index 7b8ca79eeb8..cef546487f3 100644
--- a/library/std/src/os/unix/mod.rs
+++ b/library/std/src/os/unix/mod.rs
@@ -51,6 +51,8 @@ mod platform {
     pub use crate::os::fuchsia::*;
     #[cfg(target_os = "haiku")]
     pub use crate::os::haiku::*;
+    #[cfg(target_os = "horizon")]
+    pub use crate::os::horizon::*;
     #[cfg(target_os = "illumos")]
     pub use crate::os::illumos::*;
     #[cfg(target_os = "ios")]
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index 0b1d9b07132..8008acfd1c9 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -962,7 +962,7 @@ impl IntoRawFd for UnixDatagram {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for UnixDatagram {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -970,7 +970,7 @@ impl AsFd for UnixDatagram {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<UnixDatagram> for OwnedFd {
     #[inline]
     fn from(unix_datagram: UnixDatagram) -> OwnedFd {
@@ -978,7 +978,7 @@ impl From<UnixDatagram> for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedFd> for UnixDatagram {
     #[inline]
     fn from(owned: OwnedFd) -> Self {
diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs
index 8e11d32f130..7c0d539504d 100644
--- a/library/std/src/os/unix/net/listener.rs
+++ b/library/std/src/os/unix/net/listener.rs
@@ -300,7 +300,7 @@ impl IntoRawFd for UnixListener {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for UnixListener {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -308,7 +308,7 @@ impl AsFd for UnixListener {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedFd> for UnixListener {
     #[inline]
     fn from(fd: OwnedFd) -> UnixListener {
@@ -316,7 +316,7 @@ impl From<OwnedFd> for UnixListener {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<UnixListener> for OwnedFd {
     #[inline]
     fn from(listener: UnixListener) -> OwnedFd {
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index 2a5790e9d5c..1d6083e66e1 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -683,7 +683,7 @@ impl IntoRawFd for UnixStream {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for UnixStream {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -691,7 +691,7 @@ impl AsFd for UnixStream {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<UnixStream> for OwnedFd {
     #[inline]
     fn from(unix_stream: UnixStream) -> OwnedFd {
@@ -699,7 +699,7 @@ impl From<UnixStream> for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedFd> for UnixStream {
     #[inline]
     fn from(owned: OwnedFd) -> Self {
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 9dca9b4a4a3..5065530e8d4 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -12,6 +12,16 @@ 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;
+
 /// Unix-specific extensions to the [`process::Command`] builder.
 ///
 /// This trait is sealed: it cannot be implemented outside the standard library.
@@ -22,29 +32,17 @@ pub trait CommandExt: Sealed {
     /// `setuid` call in the child process. Failure in the `setuid`
     /// call will cause the spawn to fail.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn uid(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
-    ) -> &mut process::Command;
+    fn uid(&mut self, id: UserId) -> &mut process::Command;
 
     /// Similar to `uid`, but sets the group ID of the child process. This has
     /// the same semantics as the `uid` field.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn gid(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
-    ) -> &mut process::Command;
+    fn gid(&mut self, id: GroupId) -> &mut process::Command;
 
     /// Sets the supplementary group IDs for the calling process. Translates to
     /// a `setgroups` call in the child process.
     #[unstable(feature = "setgroups", issue = "90747")]
-    fn groups(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] groups: &[u32],
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] groups: &[u16],
-    ) -> &mut process::Command;
+    fn groups(&mut self, groups: &[GroupId]) -> &mut process::Command;
 
     /// Schedules a closure to be run just before the `exec` function is
     /// invoked.
@@ -158,29 +156,17 @@ pub trait CommandExt: Sealed {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl CommandExt for process::Command {
-    fn uid(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
-    ) -> &mut process::Command {
+    fn uid(&mut self, id: UserId) -> &mut process::Command {
         self.as_inner_mut().uid(id);
         self
     }
 
-    fn gid(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
-    ) -> &mut process::Command {
+    fn gid(&mut self, id: GroupId) -> &mut process::Command {
         self.as_inner_mut().gid(id);
         self
     }
 
-    fn groups(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] groups: &[u32],
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] groups: &[u16],
-    ) -> &mut process::Command {
+    fn groups(&mut self, groups: &[GroupId]) -> &mut process::Command {
         self.as_inner_mut().groups(groups);
         self
     }
@@ -339,7 +325,7 @@ impl FromRawFd for process::Stdio {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedFd> for process::Stdio {
     #[inline]
     fn from(fd: OwnedFd) -> process::Stdio {
@@ -397,7 +383,7 @@ impl IntoRawFd for process::ChildStderr {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for crate::process::ChildStdin {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -405,7 +391,7 @@ impl AsFd for crate::process::ChildStdin {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::process::ChildStdin> for OwnedFd {
     #[inline]
     fn from(child_stdin: crate::process::ChildStdin) -> OwnedFd {
@@ -413,7 +399,7 @@ impl From<crate::process::ChildStdin> for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for crate::process::ChildStdout {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -421,7 +407,7 @@ impl AsFd for crate::process::ChildStdout {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::process::ChildStdout> for OwnedFd {
     #[inline]
     fn from(child_stdout: crate::process::ChildStdout) -> OwnedFd {
@@ -429,7 +415,7 @@ impl From<crate::process::ChildStdout> for OwnedFd {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for crate::process::ChildStderr {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -437,7 +423,7 @@ impl AsFd for crate::process::ChildStderr {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::process::ChildStderr> for OwnedFd {
     #[inline]
     fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs
index 90a5b7466fe..2f7c07c7910 100644
--- a/library/std/src/os/windows/io/handle.rs
+++ b/library/std/src/os/windows/io/handle.rs
@@ -1,6 +1,6 @@
 //! Owned and borrowed OS handles.
 
-#![unstable(feature = "io_safety", issue = "87074")]
+#![stable(feature = "io_safety", since = "1.63.0")]
 
 use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
 use crate::fmt;
@@ -38,7 +38,7 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks
 #[derive(Copy, Clone)]
 #[repr(transparent)]
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub struct BorrowedHandle<'handle> {
     handle: RawHandle,
     _phantom: PhantomData<&'handle OwnedHandle>,
@@ -66,7 +66,7 @@ pub struct BorrowedHandle<'handle> {
 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
 /// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks
 #[repr(transparent)]
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub struct OwnedHandle {
     handle: RawHandle,
 }
@@ -89,7 +89,7 @@ pub struct OwnedHandle {
 ///
 /// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks
 #[repr(transparent)]
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 #[derive(Debug)]
 pub struct HandleOrNull(OwnedHandle);
 
@@ -108,7 +108,7 @@ pub struct HandleOrNull(OwnedHandle);
 ///
 /// If holds a handle other than `INVALID_HANDLE_VALUE`, it will close the handle on drop.
 #[repr(transparent)]
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 #[derive(Debug)]
 pub struct HandleOrInvalid(OwnedHandle);
 
@@ -117,13 +117,21 @@ pub struct HandleOrInvalid(OwnedHandle);
 // `Send` or `Sync`).
 //
 // [`HANDLE`]: std::os::windows::raw::HANDLE
+#[stable(feature = "io_safety", since = "1.63.0")]
 unsafe impl Send for OwnedHandle {}
+#[stable(feature = "io_safety", since = "1.63.0")]
 unsafe impl Send for HandleOrNull {}
+#[stable(feature = "io_safety", since = "1.63.0")]
 unsafe impl Send for HandleOrInvalid {}
+#[stable(feature = "io_safety", since = "1.63.0")]
 unsafe impl Send for BorrowedHandle<'_> {}
+#[stable(feature = "io_safety", since = "1.63.0")]
 unsafe impl Sync for OwnedHandle {}
+#[stable(feature = "io_safety", since = "1.63.0")]
 unsafe impl Sync for HandleOrNull {}
+#[stable(feature = "io_safety", since = "1.63.0")]
 unsafe impl Sync for HandleOrInvalid {}
+#[stable(feature = "io_safety", since = "1.63.0")]
 unsafe impl Sync for BorrowedHandle<'_> {}
 
 impl BorrowedHandle<'_> {
@@ -142,12 +150,14 @@ impl BorrowedHandle<'_> {
     ///
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
-    #[unstable(feature = "io_safety", issue = "87074")]
+    #[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
+    #[stable(feature = "io_safety", since = "1.63.0")]
     pub const unsafe fn borrow_raw(handle: RawHandle) -> Self {
         Self { handle, _phantom: PhantomData }
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl TryFrom<HandleOrNull> for OwnedHandle {
     type Error = NullHandleError;
 
@@ -169,6 +179,7 @@ impl TryFrom<HandleOrNull> for OwnedHandle {
 impl OwnedHandle {
     /// Creates a new `OwnedHandle` instance that shares the same underlying file handle
     /// as the existing `OwnedHandle` instance.
+    #[stable(feature = "io_safety", since = "1.63.0")]
     pub fn try_clone(&self) -> crate::io::Result<Self> {
         self.duplicate(0, false, c::DUPLICATE_SAME_ACCESS)
     }
@@ -206,6 +217,7 @@ impl OwnedHandle {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl TryFrom<HandleOrInvalid> for OwnedHandle {
     type Error = InvalidHandleError;
 
@@ -227,29 +239,29 @@ impl TryFrom<HandleOrInvalid> for OwnedHandle {
 /// This is the error type used by [`HandleOrNull`] when attempting to convert
 /// into a handle, to indicate that the value is null.
 // The empty field prevents constructing this, and allows extending it in the future.
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct NullHandleError(());
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl fmt::Display for NullHandleError {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         "A HandleOrNull could not be converted to a handle because it was null".fmt(fmt)
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl crate::error::Error for NullHandleError {}
 
 /// This is the error type used by [`HandleOrInvalid`] when attempting to
 /// convert into a handle, to indicate that the value is
 /// `INVALID_HANDLE_VALUE`.
 // The empty field prevents constructing this, and allows extending it in the future.
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct InvalidHandleError(());
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl fmt::Display for InvalidHandleError {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         "A HandleOrInvalid could not be converted to a handle because it was INVALID_HANDLE_VALUE"
@@ -257,9 +269,10 @@ impl fmt::Display for InvalidHandleError {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl crate::error::Error for InvalidHandleError {}
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsRawHandle for BorrowedHandle<'_> {
     #[inline]
     fn as_raw_handle(&self) -> RawHandle {
@@ -267,6 +280,7 @@ impl AsRawHandle for BorrowedHandle<'_> {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsRawHandle for OwnedHandle {
     #[inline]
     fn as_raw_handle(&self) -> RawHandle {
@@ -274,6 +288,7 @@ impl AsRawHandle for OwnedHandle {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl IntoRawHandle for OwnedHandle {
     #[inline]
     fn into_raw_handle(self) -> RawHandle {
@@ -283,6 +298,7 @@ impl IntoRawHandle for OwnedHandle {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl FromRawHandle for OwnedHandle {
     #[inline]
     unsafe fn from_raw_handle(handle: RawHandle) -> Self {
@@ -305,6 +321,7 @@ impl HandleOrNull {
     /// Windows APIs use null for errors; see [here] for the full story.
     ///
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
+    #[stable(feature = "io_safety", since = "1.63.0")]
     #[inline]
     pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
         Self(OwnedHandle::from_raw_handle(handle))
@@ -327,12 +344,14 @@ impl HandleOrInvalid {
     /// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story.
     ///
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
+    #[stable(feature = "io_safety", since = "1.63.0")]
     #[inline]
     pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
         Self(OwnedHandle::from_raw_handle(handle))
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl Drop for OwnedHandle {
     #[inline]
     fn drop(&mut self) {
@@ -342,12 +361,14 @@ impl Drop for OwnedHandle {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl fmt::Debug for BorrowedHandle<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("BorrowedHandle").field("handle", &self.handle).finish()
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl fmt::Debug for OwnedHandle {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("OwnedHandle").field("handle", &self.handle).finish()
@@ -355,14 +376,13 @@ impl fmt::Debug for OwnedHandle {
 }
 
 /// A trait to borrow the handle from an underlying object.
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub trait AsHandle {
     /// Borrows the handle.
     ///
     /// # Example
     ///
     /// ```rust,no_run
-    /// # #![feature(io_safety)]
     /// use std::fs::File;
     /// # use std::io;
     /// use std::os::windows::io::{AsHandle, BorrowedHandle};
@@ -371,10 +391,11 @@ pub trait AsHandle {
     /// let borrowed_handle: BorrowedHandle<'_> = f.as_handle();
     /// # Ok::<(), io::Error>(())
     /// ```
+    #[stable(feature = "io_safety", since = "1.63.0")]
     fn as_handle(&self) -> BorrowedHandle<'_>;
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<T: AsHandle> AsHandle for &T {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -382,7 +403,7 @@ impl<T: AsHandle> AsHandle for &T {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<T: AsHandle> AsHandle for &mut T {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -390,6 +411,7 @@ impl<T: AsHandle> AsHandle for &mut T {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for BorrowedHandle<'_> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -397,6 +419,7 @@ impl AsHandle for BorrowedHandle<'_> {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for OwnedHandle {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -407,6 +430,7 @@ impl AsHandle for OwnedHandle {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for fs::File {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -414,6 +438,7 @@ impl AsHandle for fs::File {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<fs::File> for OwnedHandle {
     #[inline]
     fn from(file: fs::File) -> OwnedHandle {
@@ -421,6 +446,7 @@ impl From<fs::File> for OwnedHandle {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedHandle> for fs::File {
     #[inline]
     fn from(owned: OwnedHandle) -> Self {
@@ -428,6 +454,7 @@ impl From<OwnedHandle> for fs::File {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for crate::io::Stdin {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -435,6 +462,7 @@ impl AsHandle for crate::io::Stdin {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<'a> AsHandle for crate::io::StdinLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -442,6 +470,7 @@ impl<'a> AsHandle for crate::io::StdinLock<'a> {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for crate::io::Stdout {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -449,6 +478,7 @@ impl AsHandle for crate::io::Stdout {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<'a> AsHandle for crate::io::StdoutLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -456,6 +486,7 @@ impl<'a> AsHandle for crate::io::StdoutLock<'a> {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for crate::io::Stderr {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -463,6 +494,7 @@ impl AsHandle for crate::io::Stderr {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<'a> AsHandle for crate::io::StderrLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -470,6 +502,7 @@ impl<'a> AsHandle for crate::io::StderrLock<'a> {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for crate::process::ChildStdin {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -477,6 +510,7 @@ impl AsHandle for crate::process::ChildStdin {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::process::ChildStdin> for OwnedHandle {
     #[inline]
     fn from(child_stdin: crate::process::ChildStdin) -> OwnedHandle {
@@ -484,6 +518,7 @@ impl From<crate::process::ChildStdin> for OwnedHandle {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for crate::process::ChildStdout {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -491,6 +526,7 @@ impl AsHandle for crate::process::ChildStdout {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::process::ChildStdout> for OwnedHandle {
     #[inline]
     fn from(child_stdout: crate::process::ChildStdout) -> OwnedHandle {
@@ -498,6 +534,7 @@ impl From<crate::process::ChildStdout> for OwnedHandle {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for crate::process::ChildStderr {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -505,6 +542,7 @@ impl AsHandle for crate::process::ChildStderr {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::process::ChildStderr> for OwnedHandle {
     #[inline]
     fn from(child_stderr: crate::process::ChildStderr) -> OwnedHandle {
@@ -512,6 +550,7 @@ impl From<crate::process::ChildStderr> for OwnedHandle {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<T> AsHandle for crate::thread::JoinHandle<T> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -519,6 +558,7 @@ impl<T> AsHandle for crate::thread::JoinHandle<T> {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle {
     #[inline]
     fn from(join_handle: crate::thread::JoinHandle<T>) -> OwnedHandle {
diff --git a/library/std/src/os/windows/io/mod.rs b/library/std/src/os/windows/io/mod.rs
index 3325688e661..31545059707 100644
--- a/library/std/src/os/windows/io/mod.rs
+++ b/library/std/src/os/windows/io/mod.rs
@@ -48,11 +48,11 @@ mod handle;
 mod raw;
 mod socket;
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub use handle::*;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use raw::*;
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub use socket::*;
 
 #[cfg(test)]
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index e23e1cf8cee..c5a381c40d2 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -1,6 +1,6 @@
 //! Owned and borrowed OS sockets.
 
-#![unstable(feature = "io_safety", issue = "87074")]
+#![stable(feature = "io_safety", since = "1.63.0")]
 
 use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
 use crate::fmt;
@@ -36,7 +36,7 @@ use crate::sys::cvt;
     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
 )]
 #[rustc_nonnull_optimization_guaranteed]
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub struct BorrowedSocket<'socket> {
     socket: RawSocket,
     _phantom: PhantomData<&'socket OwnedSocket>,
@@ -59,7 +59,7 @@ pub struct BorrowedSocket<'socket> {
     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
 )]
 #[rustc_nonnull_optimization_guaranteed]
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub struct OwnedSocket {
     socket: RawSocket,
 }
@@ -73,7 +73,8 @@ impl BorrowedSocket<'_> {
     /// the returned `BorrowedSocket`, and it must not have the value
     /// `INVALID_SOCKET`.
     #[inline]
-    #[unstable(feature = "io_safety", issue = "87074")]
+    #[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
+    #[stable(feature = "io_safety", since = "1.63.0")]
     pub const unsafe fn borrow_raw(socket: RawSocket) -> Self {
         assert!(socket != c::INVALID_SOCKET as RawSocket);
         Self { socket, _phantom: PhantomData }
@@ -83,6 +84,7 @@ impl BorrowedSocket<'_> {
 impl OwnedSocket {
     /// Creates a new `OwnedSocket` instance that shares the same underlying socket
     /// as the existing `OwnedSocket` instance.
+    #[stable(feature = "io_safety", since = "1.63.0")]
     pub fn try_clone(&self) -> io::Result<Self> {
         let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() };
         let result = unsafe {
@@ -152,6 +154,7 @@ fn last_error() -> io::Error {
     io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() })
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsRawSocket for BorrowedSocket<'_> {
     #[inline]
     fn as_raw_socket(&self) -> RawSocket {
@@ -159,6 +162,7 @@ impl AsRawSocket for BorrowedSocket<'_> {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsRawSocket for OwnedSocket {
     #[inline]
     fn as_raw_socket(&self) -> RawSocket {
@@ -166,6 +170,7 @@ impl AsRawSocket for OwnedSocket {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl IntoRawSocket for OwnedSocket {
     #[inline]
     fn into_raw_socket(self) -> RawSocket {
@@ -175,6 +180,7 @@ impl IntoRawSocket for OwnedSocket {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl FromRawSocket for OwnedSocket {
     #[inline]
     unsafe fn from_raw_socket(socket: RawSocket) -> Self {
@@ -183,6 +189,7 @@ impl FromRawSocket for OwnedSocket {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl Drop for OwnedSocket {
     #[inline]
     fn drop(&mut self) {
@@ -192,12 +199,14 @@ impl Drop for OwnedSocket {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl fmt::Debug for BorrowedSocket<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("BorrowedSocket").field("socket", &self.socket).finish()
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl fmt::Debug for OwnedSocket {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("OwnedSocket").field("socket", &self.socket).finish()
@@ -205,13 +214,14 @@ impl fmt::Debug for OwnedSocket {
 }
 
 /// A trait to borrow the socket from an underlying object.
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 pub trait AsSocket {
     /// Borrows the socket.
+    #[stable(feature = "io_safety", since = "1.63.0")]
     fn as_socket(&self) -> BorrowedSocket<'_>;
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<T: AsSocket> AsSocket for &T {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
@@ -219,7 +229,7 @@ impl<T: AsSocket> AsSocket for &T {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<T: AsSocket> AsSocket for &mut T {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
@@ -227,6 +237,7 @@ impl<T: AsSocket> AsSocket for &mut T {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsSocket for BorrowedSocket<'_> {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
@@ -234,6 +245,7 @@ impl AsSocket for BorrowedSocket<'_> {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsSocket for OwnedSocket {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
@@ -244,6 +256,7 @@ impl AsSocket for OwnedSocket {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsSocket for crate::net::TcpStream {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
@@ -251,6 +264,7 @@ impl AsSocket for crate::net::TcpStream {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::net::TcpStream> for OwnedSocket {
     #[inline]
     fn from(tcp_stream: crate::net::TcpStream) -> OwnedSocket {
@@ -258,6 +272,7 @@ impl From<crate::net::TcpStream> for OwnedSocket {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedSocket> for crate::net::TcpStream {
     #[inline]
     fn from(owned: OwnedSocket) -> Self {
@@ -265,6 +280,7 @@ impl From<OwnedSocket> for crate::net::TcpStream {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsSocket for crate::net::TcpListener {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
@@ -272,6 +288,7 @@ impl AsSocket for crate::net::TcpListener {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::net::TcpListener> for OwnedSocket {
     #[inline]
     fn from(tcp_listener: crate::net::TcpListener) -> OwnedSocket {
@@ -279,6 +296,7 @@ impl From<crate::net::TcpListener> for OwnedSocket {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedSocket> for crate::net::TcpListener {
     #[inline]
     fn from(owned: OwnedSocket) -> Self {
@@ -286,6 +304,7 @@ impl From<OwnedSocket> for crate::net::TcpListener {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsSocket for crate::net::UdpSocket {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
@@ -293,6 +312,7 @@ impl AsSocket for crate::net::UdpSocket {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<crate::net::UdpSocket> for OwnedSocket {
     #[inline]
     fn from(udp_socket: crate::net::UdpSocket) -> OwnedSocket {
@@ -300,6 +320,7 @@ impl From<crate::net::UdpSocket> for OwnedSocket {
     }
 }
 
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedSocket> for crate::net::UdpSocket {
     #[inline]
     fn from(owned: OwnedSocket) -> Self {
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs
index 1c7e361c2a4..24b0888b112 100644
--- a/library/std/src/os/windows/process.rs
+++ b/library/std/src/os/windows/process.rs
@@ -22,7 +22,7 @@ impl FromRawHandle for process::Stdio {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<OwnedHandle> for process::Stdio {
     fn from(handle: OwnedHandle) -> process::Stdio {
         let handle = sys::handle::Handle::from_inner(handle);
@@ -39,7 +39,7 @@ impl AsRawHandle for process::Child {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for process::Child {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -54,7 +54,7 @@ impl IntoRawHandle for process::Child {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl From<process::Child> for OwnedHandle {
     fn from(child: process::Child) -> OwnedHandle {
         child.into_inner().into_handle().into_inner()
diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs
index 7c3d9573940..9d6567c9fb4 100644
--- a/library/std/src/sys/unix/alloc.rs
+++ b/library/std/src/sys/unix/alloc.rs
@@ -58,7 +58,8 @@ cfg_if::cfg_if! {
         target_os = "illumos",
         target_os = "redox",
         target_os = "solaris",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     ))] {
         #[inline]
         unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index ee5e3983ac2..79964e2b238 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -68,7 +68,8 @@ impl DoubleEndedIterator for Args {
     target_os = "l4re",
     target_os = "fuchsia",
     target_os = "redox",
-    target_os = "vxworks"
+    target_os = "vxworks",
+    target_os = "horizon"
 ))]
 mod imp {
     use super::Args;
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index 60551aeb3e7..4d8391656a4 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -119,6 +119,17 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "";
 }
 
+#[cfg(target_os = "horizon")]
+pub mod os {
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "horizon";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = ".elf";
+    pub const EXE_EXTENSION: &str = "elf";
+}
+
 #[cfg(all(target_os = "emscripten", target_arch = "asmjs"))]
 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 40a64585802..137ca3a7633 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -9,8 +9,6 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned
 use crate::sys::cvt;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
-use libc::{c_int, c_void};
-
 #[cfg(any(
     target_os = "android",
     target_os = "linux",
@@ -38,7 +36,7 @@ pub struct FileDesc(OwnedFd);
 // larger than or equal to INT_MAX. To handle both of these the read
 // size is capped on both platforms.
 #[cfg(target_os = "macos")]
-const READ_LIMIT: usize = c_int::MAX as usize - 1;
+const READ_LIMIT: usize = libc::c_int::MAX as usize - 1;
 #[cfg(not(target_os = "macos"))]
 const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
 
@@ -69,6 +67,7 @@ const fn max_iov() -> usize {
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
+    target_os = "horizon"
 )))]
 const fn max_iov() -> usize {
     16 // The minimum value required by POSIX.
@@ -79,33 +78,33 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::read(
                 self.as_raw_fd(),
-                buf.as_mut_ptr() as *mut c_void,
+                buf.as_mut_ptr() as *mut libc::c_void,
                 cmp::min(buf.len(), READ_LIMIT),
             )
         })?;
         Ok(ret as usize)
     }
 
-    #[cfg(not(target_os = "espidf"))]
+    #[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::readv(
                 self.as_raw_fd(),
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), max_iov()) as c_int,
+                cmp::min(bufs.len(), max_iov()) as libc::c_int,
             )
         })?;
         Ok(ret as usize)
     }
 
-    #[cfg(target_os = "espidf")]
+    #[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);
     }
 
     #[inline]
     pub fn is_read_vectored(&self) -> bool {
-        cfg!(not(target_os = "espidf"))
+        cfg!(not(any(target_os = "espidf", target_os = "horizon")))
     }
 
     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
@@ -122,7 +121,7 @@ impl FileDesc {
         unsafe {
             cvt(pread64(
                 self.as_raw_fd(),
-                buf.as_mut_ptr() as *mut c_void,
+                buf.as_mut_ptr() as *mut libc::c_void,
                 cmp::min(buf.len(), READ_LIMIT),
                 offset as off64_t,
             ))
@@ -134,7 +133,7 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::read(
                 self.as_raw_fd(),
-                buf.unfilled_mut().as_mut_ptr() as *mut c_void,
+                buf.unfilled_mut().as_mut_ptr() as *mut libc::c_void,
                 cmp::min(buf.remaining(), READ_LIMIT),
             )
         })?;
@@ -151,33 +150,33 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::write(
                 self.as_raw_fd(),
-                buf.as_ptr() as *const c_void,
+                buf.as_ptr() as *const libc::c_void,
                 cmp::min(buf.len(), READ_LIMIT),
             )
         })?;
         Ok(ret as usize)
     }
 
-    #[cfg(not(target_os = "espidf"))]
+    #[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::writev(
                 self.as_raw_fd(),
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), max_iov()) as c_int,
+                cmp::min(bufs.len(), max_iov()) as libc::c_int,
             )
         })?;
         Ok(ret as usize)
     }
 
-    #[cfg(target_os = "espidf")]
+    #[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);
     }
 
     #[inline]
     pub fn is_write_vectored(&self) -> bool {
-        cfg!(not(target_os = "espidf"))
+        cfg!(not(any(target_os = "espidf", target_os = "horizon")))
     }
 
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
@@ -189,7 +188,7 @@ impl FileDesc {
         unsafe {
             cvt(pwrite64(
                 self.as_raw_fd(),
-                buf.as_ptr() as *const c_void,
+                buf.as_ptr() as *const libc::c_void,
                 cmp::min(buf.len(), READ_LIMIT),
                 offset as off64_t,
             ))
@@ -221,7 +220,7 @@ impl FileDesc {
         }
     }
     #[cfg(any(
-        all(target_env = "newlib", not(target_os = "espidf")),
+        all(target_env = "newlib", not(any(target_os = "espidf", target_os = "horizon"))),
         target_os = "solaris",
         target_os = "illumos",
         target_os = "emscripten",
@@ -242,17 +241,17 @@ impl FileDesc {
             Ok(())
         }
     }
-    #[cfg(target_os = "espidf")]
+    #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     pub fn set_cloexec(&self) -> io::Result<()> {
-        // FD_CLOEXEC is not supported in ESP-IDF but there's no need to,
-        // because ESP-IDF does not support spawning processes either.
+        // FD_CLOEXEC is not supported in ESP-IDF and Horizon OS but there's no need to,
+        // because neither supports spawning processes.
         Ok(())
     }
 
     #[cfg(target_os = "linux")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         unsafe {
-            let v = nonblocking as c_int;
+            let v = nonblocking as libc::c_int;
             cvt(libc::ioctl(self.as_raw_fd(), libc::FIONBIO, &v))?;
             Ok(())
         }
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 5d0fb079003..8b0bbd6a55c 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -395,7 +395,7 @@ impl FileAttr {
 
 #[cfg(not(target_os = "netbsd"))]
 impl FileAttr {
-    #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
+    #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
     pub fn modified(&self) -> io::Result<SystemTime> {
         #[cfg(target_pointer_width = "32")]
         cfg_has_statx! {
@@ -412,7 +412,12 @@ impl FileAttr {
         Ok(SystemTime::new(self.stat.st_mtime as i64, 0))
     }
 
-    #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
+    #[cfg(target_os = "horizon")]
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(self.stat.st_mtim))
+    }
+
+    #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
     pub fn accessed(&self) -> io::Result<SystemTime> {
         #[cfg(target_pointer_width = "32")]
         cfg_has_statx! {
@@ -429,6 +434,11 @@ impl FileAttr {
         Ok(SystemTime::new(self.stat.st_atime as i64, 0))
     }
 
+    #[cfg(target_os = "horizon")]
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(self.stat.st_atim))
+    }
+
     #[cfg(any(
         target_os = "freebsd",
         target_os = "openbsd",
@@ -707,7 +717,8 @@ impl DirEntry {
         target_os = "fuchsia",
         target_os = "redox",
         target_os = "vxworks",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     ))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
@@ -1251,7 +1262,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
     let original = cstr(original)?;
     let link = cstr(link)?;
     cfg_if::cfg_if! {
-        if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf"))] {
+        if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon"))] {
             // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
             // it implementation-defined whether `link` follows symlinks, so rely on the
             // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
@@ -1549,14 +1560,14 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
 
 pub use remove_dir_impl::remove_dir_all;
 
-// Fallback for REDOX and ESP-IDF (and Miri)
-#[cfg(any(target_os = "redox", target_os = "espidf", miri))]
+// Fallback for REDOX, ESP-ID, Horizon, and Miri
+#[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", 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", miri)))]
+#[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri)))]
 mod remove_dir_impl {
     use super::{cstr, 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 61c28d696bc..78f10f0534c 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -47,7 +47,9 @@ impl Condvar {
     // So on that platform, init() should always be called
     // Moreover, that platform does not have pthread_condattr_setclock support,
     // hence that initialization should be skipped as well
-    #[cfg(target_os = "espidf")]
+    //
+    // Similar story for the 3DS (horizon).
+    #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     unsafe fn init(&mut self) {
         let r = libc::pthread_cond_init(self.inner.get(), crate::ptr::null());
         assert_eq!(r, 0);
@@ -59,7 +61,8 @@ impl Condvar {
         target_os = "l4re",
         target_os = "android",
         target_os = "redox",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     )))]
     unsafe fn init(&mut self) {
         use crate::mem::MaybeUninit;
@@ -100,7 +103,8 @@ impl Condvar {
         target_os = "macos",
         target_os = "ios",
         target_os = "android",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     )))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         use crate::mem;
@@ -132,7 +136,8 @@ impl Condvar {
         target_os = "macos",
         target_os = "ios",
         target_os = "android",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     ))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
         use crate::ptr;
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index ddec60961f0..34a023b02c4 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -88,6 +88,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
             target_os = "ios",
             target_os = "redox",
             target_os = "l4re",
+            target_os = "horizon",
         )))]
         'poll: {
             use crate::sys::os::errno;
@@ -131,6 +132,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
             target_os = "fuchsia",
             target_os = "vxworks",
             target_os = "l4re",
+            target_os = "horizon",
         )))]
         {
             use crate::sys::os::errno;
@@ -149,7 +151,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
     }
 
     unsafe fn reset_sigpipe() {
-        #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
+        #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
         rtassert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
     }
 }
@@ -344,7 +346,7 @@ cfg_if::cfg_if! {
     }
 }
 
-#[cfg(target_os = "espidf")]
+#[cfg(any(target_os = "espidf", target_os = "horizon"))]
 mod unsupported {
     use crate::io;
 
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 92bea9346d8..7252ad32184 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -446,7 +446,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     path.canonicalize()
 }
 
-#[cfg(target_os = "espidf")]
+#[cfg(any(target_os = "espidf", target_os = "horizon"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     super::unsupported::unsupported()
 }
@@ -601,7 +601,8 @@ pub fn home_dir() -> Option<PathBuf> {
         target_os = "emscripten",
         target_os = "redox",
         target_os = "vxworks",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     ))]
     unsafe fn fallback() -> Option<OsString> {
         None
@@ -612,7 +613,8 @@ pub fn home_dir() -> Option<PathBuf> {
         target_os = "emscripten",
         target_os = "redox",
         target_os = "vxworks",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     )))]
     unsafe fn fallback() -> Option<OsString> {
         let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
diff --git a/library/std/src/sys/unix/process/mod.rs b/library/std/src/sys/unix/process/mod.rs
index 0165ece849e..3701510f3a4 100644
--- a/library/std/src/sys/unix/process/mod.rs
+++ b/library/std/src/sys/unix/process/mod.rs
@@ -3,6 +3,7 @@ pub use self::process_inner::{ExitStatus, ExitStatusError, Process};
 pub use crate::ffi::OsString as EnvKey;
 pub use crate::sys_common::process::CommandEnvs;
 
+#[cfg_attr(any(target_os = "espidf", target_os = "horizon"), allow(unused))]
 mod process_common;
 
 cfg_if::cfg_if! {
@@ -13,7 +14,7 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "vxworks")] {
         #[path = "process_vxworks.rs"]
         mod process_inner;
-    } else if #[cfg(target_os = "espidf")] {
+    } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] {
         #[path = "process_unsupported.rs"]
         mod process_inner;
     } else {
diff --git a/library/std/src/sys/unix/process/process_unsupported.rs b/library/std/src/sys/unix/process/process_unsupported.rs
index 5db57ee9e9e..72f9f3f9ca7 100644
--- a/library/std/src/sys/unix/process/process_unsupported.rs
+++ b/library/std/src/sys/unix/process/process_unsupported.rs
@@ -1,10 +1,6 @@
 use crate::fmt;
 use crate::io;
-use crate::io::ErrorKind;
 use crate::num::NonZeroI32;
-use crate::sys;
-use crate::sys::cvt;
-use crate::sys::pipe::AnonPipe;
 use crate::sys::process::process_common::*;
 use crate::sys::unix::unsupported::*;
 use core::ffi::NonZero_c_int;
@@ -18,13 +14,13 @@ use libc::{c_int, pid_t};
 impl Command {
     pub fn spawn(
         &mut self,
-        default: Stdio,
-        needs_stdin: bool,
+        _default: Stdio,
+        _needs_stdin: bool,
     ) -> io::Result<(Process, StdioPipes)> {
         unsupported()
     }
 
-    pub fn exec(&mut self, default: Stdio) -> io::Error {
+    pub fn exec(&mut self, _default: Stdio) -> io::Error {
         unsupported_err()
     }
 }
@@ -34,7 +30,7 @@ impl Command {
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct Process {
-    handle: pid_t,
+    _handle: pid_t,
 }
 
 impl Process {
@@ -59,6 +55,7 @@ impl Process {
 pub struct ExitStatus(c_int);
 
 impl ExitStatus {
+    #[cfg_attr(target_os = "horizon", allow(unused))]
     pub fn success(&self) -> bool {
         self.code() == Some(0)
     }
diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs
index ea6df724713..56d01074c20 100644
--- a/library/std/src/sys/unix/rand.rs
+++ b/library/std/src/sys/unix/rand.rs
@@ -59,17 +59,27 @@ mod imp {
         unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
     }
 
-    #[cfg(target_os = "espidf")]
+    #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
         unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
     }
 
-    #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "espidf")))]
+    #[cfg(not(any(
+        target_os = "linux",
+        target_os = "android",
+        target_os = "espidf",
+        target_os = "horizon"
+    )))]
     fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
         false
     }
 
-    #[cfg(any(target_os = "linux", target_os = "android", target_os = "espidf"))]
+    #[cfg(any(
+        target_os = "linux",
+        target_os = "android",
+        target_os = "espidf",
+        target_os = "horizon"
+    ))]
     fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
         use crate::sync::atomic::{AtomicBool, Ordering};
         use crate::sys::os::errno;
diff --git a/library/std/src/sys/unix/stdio.rs b/library/std/src/sys/unix/stdio.rs
index e4d83ba0ffd..329f9433dba 100644
--- a/library/std/src/sys/unix/stdio.rs
+++ b/library/std/src/sys/unix/stdio.rs
@@ -92,7 +92,7 @@ pub fn panic_output() -> Option<impl io::Write> {
     Some(Stderr::new())
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for io::Stdin {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -100,7 +100,7 @@ impl AsFd for io::Stdin {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<'a> AsFd for io::StdinLock<'a> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -108,7 +108,7 @@ impl<'a> AsFd for io::StdinLock<'a> {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for io::Stdout {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -116,7 +116,7 @@ impl AsFd for io::Stdout {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<'a> AsFd for io::StdoutLock<'a> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -124,7 +124,7 @@ impl<'a> AsFd for io::StdoutLock<'a> {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl AsFd for io::Stderr {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
@@ -132,7 +132,7 @@ impl AsFd for io::Stderr {
     }
 }
 
-#[unstable(feature = "io_safety", issue = "87074")]
+#[stable(feature = "io_safety", since = "1.63.0")]
 impl<'a> AsFd for io::StderrLock<'a> {
     #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs
index c3f410353b9..6e8be2a91de 100644
--- a/library/std/src/sys/unix/thread_local_dtor.rs
+++ b/library/std/src/sys/unix/thread_local_dtor.rs
@@ -93,7 +93,7 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     }
 }
 
-#[cfg(target_os = "vxworks")]
+#[cfg(any(target_os = "vxworks", target_os = "horizon"))]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     use crate::sys_common::thread_local_dtor::register_dtor_fallback;
     register_dtor_fallback(t, dtor);
diff --git a/library/std/src/sys/unix/thread_parker.rs b/library/std/src/sys/unix/thread_parker.rs
index 30ed2ec7f54..76278ae30f1 100644
--- a/library/std/src/sys/unix/thread_parker.rs
+++ b/library/std/src/sys/unix/thread_parker.rs
@@ -115,7 +115,7 @@ impl Parker {
                 target_os = "redox"
             ))] {
                 addr_of_mut!((*parker).cvar).write(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER));
-            } else if #[cfg(target_os = "espidf")] {
+            } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] {
                 let r = libc::pthread_cond_init(addr_of_mut!((*parker).cvar).cast(), crate::ptr::null());
                 assert_eq!(r, 0);
             } else {
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index f99c453a3a8..d114af49d26 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -18,6 +18,7 @@ pub(in crate::sys::unix) struct Timespec {
 }
 
 impl SystemTime {
+    #[cfg_attr(target_os = "horizon", allow(unused))]
     pub fn new(tv_sec: i64, tv_nsec: i64) -> SystemTime {
         SystemTime { t: Timespec::new(tv_sec, tv_nsec) }
     }
@@ -303,9 +304,9 @@ mod inner {
         }
     }
 
-    #[cfg(not(any(target_os = "dragonfly", target_os = "espidf")))]
+    #[cfg(not(any(target_os = "dragonfly", target_os = "espidf", target_os = "horizon")))]
     pub type clock_t = libc::c_int;
-    #[cfg(any(target_os = "dragonfly", target_os = "espidf"))]
+    #[cfg(any(target_os = "dragonfly", target_os = "espidf", target_os = "horizon"))]
     pub type clock_t = libc::c_ulong;
 
     impl Timespec {
diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs
index c55df042003..ded97bb7eaa 100644
--- a/library/std/src/sys/windows/compat.rs
+++ b/library/std/src/sys/windows/compat.rs
@@ -102,21 +102,23 @@ macro_rules! compat_fn {
             }
 
             #[allow(dead_code)]
+            #[inline(always)]
             pub fn option() -> Option<F> {
-                unsafe { PTR }
+                unsafe {
+                    if cfg!(miri) {
+                        // Miri does not run `init`, so we just call `get_f` each time.
+                        get_f()
+                    } else {
+                        PTR
+                    }
+                }
             }
 
             #[allow(dead_code)]
             pub unsafe fn call($($argname: $argtype),*) -> $rettype {
-                if let Some(ptr) = PTR {
+                if let Some(ptr) = option() {
                     return ptr($($argname),*);
                 }
-                if cfg!(miri) {
-                    // Miri does not run `init`, so we just call `get_f` each time.
-                    if let Some(ptr) = get_f() {
-                        return ptr($($argname),*);
-                    }
-                }
                 $fallback_body
             }
         }
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 05425f4a362..f5730a2cea5 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -398,8 +398,20 @@ impl TcpListener {
         let (addrp, len) = addr.into_inner();
         cvt(unsafe { c::bind(sock.as_raw(), addrp, len as _) })?;
 
+        cfg_if::cfg_if! {
+            if #[cfg(target_os = "horizon")] {
+                // The 3DS doesn't support a big connection backlog. Sometimes
+                // it allows up to about 37, but other times it doesn't even
+                // accept 32. There may be a global limitation causing this.
+                let backlog = 20;
+            } else {
+                // The default for all other platforms
+                let backlog = 128;
+            }
+        }
+
         // Start listening
-        cvt(unsafe { c::listen(sock.as_raw(), 128) })?;
+        cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
         Ok(TcpListener { inner: sock })
     }
 
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 79f2338b7ab..e23498873f3 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -179,13 +179,13 @@ fn download_ci_llvm(builder: &Builder<'_>, llvm_sha: &str) {
     let filename = format!("rust-dev-nightly-{}.tar.xz", builder.build.build.triple);
     let tarball = rustc_cache.join(&filename);
     if !tarball.exists() {
-        let help_on_error = "error: failed to download llvm from ci\n
-\nhelp: old builds get deleted after a certain time
-\nhelp: if trying to compile an old commit of rustc, disable `download-ci-llvm` in config.toml:
-\n
-\n[llvm]
-\ndownload-ci-llvm = false
-\n
+        let help_on_error = "error: failed to download llvm from ci
+
+help: old builds get deleted after a certain time
+help: if trying to compile an old commit of rustc, disable `download-ci-llvm` in config.toml:
+
+[llvm]
+download-ci-llvm = false
 ";
         builder.download_component(base, &format!("{}/{}", url, filename), &tarball, help_on_error);
     }
@@ -315,8 +315,11 @@ impl Step for Llvm {
             cfg.define("LLVM_ENABLE_ZLIB", "OFF");
         }
 
-        // Are we compiling for iOS/tvOS?
-        if target.contains("apple-ios") || target.contains("apple-tvos") {
+        // Are we compiling for iOS/tvOS/watchOS?
+        if target.contains("apple-ios")
+            || target.contains("apple-tvos")
+            || target.contains("apple-watchos")
+        {
             // These two defines prevent CMake from automatically trying to add a MacOSX sysroot, which leads to a compiler error.
             cfg.define("CMAKE_OSX_SYSROOT", "/");
             cfg.define("CMAKE_OSX_DEPLOYMENT_TARGET", "");
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 8e2d44c1812..87dc5138539 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -16,6 +16,8 @@
     - [Target Tier Policy](target-tier-policy.md)
     - [Template for Target-specific Documentation](platform-support/TEMPLATE.md)
     - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
+    - [\*-apple-watchos\*](platform-support/apple-watchos.md)
+    - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md)
     - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
     - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
     - [\*-kmc-solid_\*](platform-support/kmc-solid.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 4ac09711b0a..eb985803266 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -207,6 +207,7 @@ target | std | host | notes
 -------|:---:|:----:|-------
 `aarch64-apple-ios-macabi` | ? |  | Apple Catalyst on ARM64
 `aarch64-apple-tvos` | * |  | ARM64 tvOS
+[`aarch64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ |  | ARM64 Apple WatchOS Simulator
 [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ |  | ARM64 SOLID with TOPPERS/ASP3
 [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
@@ -220,11 +221,12 @@ target | std | host | notes
 `aarch64-wrs-vxworks` | ? |  |
 `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
 `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
+[`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers
 `armv4t-unknown-linux-gnueabi` | ? |  |
 `armv5te-unknown-linux-uclibceabi` | ? |  | ARMv5TE Linux with uClibc
 `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
 `armv6-unknown-netbsd-eabihf` | ? |  |
-`armv6k-nintendo-3ds` | * |  | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
+[`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? |  | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
 `armv7-apple-ios` | ✓ |  | ARMv7 iOS, Cortex-a8
 [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7 Linux with uClibc, softfloat
 [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux with uClibc, hardfloat
@@ -234,6 +236,7 @@ target | std | host | notes
 [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ |  | ARM SOLID with TOPPERS/ASP3
 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ |  | ARM SOLID with TOPPERS/ASP3, hardfloat
 `armv7a-none-eabihf` | * | | ARM Cortex-A, hardfloat
+[`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS
 `armv7s-apple-ios` | ✓ |  |
 `avr-unknown-gnu-atmega328` | * |  | AVR. Requires `-Z build-std=core`
 `bpfeb-unknown-none` | * |  | BPF (big endian)
@@ -290,6 +293,7 @@ target | std | host | notes
 [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? |  | WebAssembly
 `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-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/apple-watchos.md b/src/doc/rustc/src/platform-support/apple-watchos.md
new file mode 100644
index 00000000000..fe4c7c0c88f
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/apple-watchos.md
@@ -0,0 +1,55 @@
+# *-apple-watchos
+- arm64_32-apple-watchos
+- armv7k-apple-watchos
+- aarch64-apple-watchos-sim
+- x86_64-apple-watchos-sim
+
+**Tier: 3**
+
+Apple WatchOS targets:
+- Apple WatchOS on Arm 64_32
+- Apple WatchOS on Arm v7k
+- Apple WatchOS Simulator on arm64
+- Apple WatchOS Simulator on x86_64
+
+## Target maintainers
+
+* [@deg4uss3r](https://github.com/deg4uss3r)
+* [@vladimir-ea](https://github.com/vladimir-ea)
+
+## Requirements
+
+These targets are cross-compiled.
+To build these targets Xcode 12 or higher on macOS is required.
+
+## Building the target
+
+The targets can be built by enabling them for a `rustc` build, for example:
+
+```toml
+[build]
+build-stage = 1
+target = ["aarch64-apple-watchos-sim"]
+```
+
+## Building Rust programs
+
+*Note: Building for this target requires the corresponding WatchOS SDK, as provided by Xcode 12+.*
+
+Rust programs can be built for these targets, if `rustc` has been built with support for them, for example:
+
+```text
+rustc --target aarch64-apple-watchos-sim your-code.rs
+```
+
+## Testing
+
+There is no support for running the Rust testsuite on WatchOS or the simulators.
+
+There is no easy way to run simple programs on WatchOS or the WatchOS simulators. Static library builds can be embedded into WatchOS applications.
+
+## Cross-compilation toolchains and C code
+
+This target can be cross-compiled from x86_64 or aarch64 macOS hosts.
+
+Other hosts are not supported for cross-compilation, but might work when also providing the required Xcode SDK.
diff --git a/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md b/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md
new file mode 100644
index 00000000000..215290e3898
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md
@@ -0,0 +1,130 @@
+# `armv6k-nintendo-3ds`
+
+**Tier: 3**
+
+The Nintendo 3DS platform, which has an ARMv6K processor, and its associated
+operating system (`horizon`).
+
+Rust support for this target is not affiliated with Nintendo, and is not derived
+from nor used with any official Nintendo SDK.
+
+## Target maintainers
+
+- [@Meziu](https://github.com/Meziu)
+- [@AzureMarker](https://github.com/AzureMarker)
+- [@ian-h-chamberlain](https://github.com/ian-h-chamberlain)
+
+## Requirements
+
+This target is cross-compiled. Dynamic linking is not supported.
+
+`#![no_std]` crates can be built using `build-std` to build `core` and optionally
+`alloc`, and either `panic_abort` or `panic_unwind`.
+
+`std` is partially supported, but mostly works. Some APIs are unimplemented
+and will simply return an error, such as `std::process`. An allocator is provided
+by default.
+
+In order to support some APIs, binaries must be linked against `libc` written
+for the target, using a linker for the target. These are provided by the
+devkitARM toolchain. See
+[Cross-compilation toolchains and C code](#cross-compilation-toolchains-and-c-code)
+for more details.
+
+Additionally, some helper crates provide implementations of some `libc` functions
+use by `std` that may otherwise be missing. These, or an alternate implementation
+of the relevant functions, are required to use `std`:
+
+- [`pthread-3ds`](https://github.com/Meziu/pthread-3ds) provides pthread APIs for `std::thread`.
+- [`linker-fix-3ds`](https://github.com/Meziu/rust-linker-fix-3ds) fulfills some other missing libc APIs.
+
+Binaries built for this target should be compatible with all variants of the
+3DS (and 2DS) hardware and firmware, but testing is limited and some versions may
+not work correctly.
+
+This target generates binaries in the ELF format.
+
+## Building the target
+
+You can build Rust with support for the target by adding it to the `target`
+list in `config.toml` and providing paths to the devkitARM toolchain.
+
+```toml
+[build]
+build-stage = 1
+target = ["armv6k-nintendo-3ds"]
+
+[target.armv6k-nintendo-3ds]
+cc = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-gcc"
+cxx = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-g++"
+ar = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-ar"
+ranlib = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-ranlib"
+linker = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-gcc"
+```
+
+Also, to build `compiler_builtins` for the target, export these flags before
+building the Rust toolchain:
+
+```sh
+export CFLAGS_armv6k_nintendo_3ds="-mfloat-abi=hard -mtune=mpcore -mtp=soft -march=armv6k"
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target.
+
+The recommended way to build binaries is by using the
+[cargo-3ds](https://github.com/Meziu/cargo-3ds) tool, which uses `build-std`
+and provides commands that work like the usual `cargo run`, `cargo build`, etc.
+
+You can also build Rust with the target enabled (see
+[Building the target](#building-the-target) above).
+
+As mentioned in [Requirements](#requirements), programs that use `std` must link
+against both the devkitARM toolchain and libraries providing the `libc` APIs used
+in `std`.  There is a general-purpose utility crate for working with nonstandard
+APIs provided by the OS: [`ctru-rs`](https://github.com/Meziu/ctru-rs).
+Add it to Cargo.toml to use it in your program:
+
+```toml
+[dependencies]
+ctru-rs = { git = "https://github.com/Meziu/ctru-rs.git" }
+```
+
+Using this library's `init()` function ensures the symbols needed to link
+against `std` are present (as mentioned in [Requirements](#requirements)
+above), as well as providing a runtime suitable for `std`:
+
+```rust,ignore (requires-3rd-party-library)
+fn main() {
+    ctru::init();
+}
+```
+
+## Testing
+
+Binaries built for this target can be run in an emulator (most commonly
+[Citra](https://citra-emu.org/)), or sent to a device through
+the use of a tool like devkitARM's `3dslink`. They may also simply be copied
+to an SD card to be inserted in the device.
+
+The `cargo-3ds` tool mentioned in [Building Rust programs](#building-rust-programs)
+supports the use of `3dslink` with `cargo 3ds run`. The default Rust test runner
+is not supported, but
+[custom test frameworks](https://doc.rust-lang.org/beta/unstable-book/language-features/custom-test-frameworks.html)
+can be used with `cargo 3ds test` to run unit tests on a device.
+
+The Rust test suite for `library/std` is not yet supported.
+
+## Cross-compilation toolchains and C code
+
+C code can be built for this target using the
+[devkitARM toolchain](https://devkitpro.org/wiki/Getting_Started).
+This toolchain provides `arm-none-eabi-gcc` as the linker used to link Rust
+programs as well.
+
+The toolchain also provides a `libc` implementation, which is required by `std`
+for many of its APIs, and a helper library `libctru` which is used by several
+of the helper crates listed in [Requirements](#requirements).
+This toolchain does not, however, include all of the APIs expected by `std`,
+and the remaining APIs are implemented by `pthread-3ds` and `linker-fix-3ds`.
diff --git a/src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md b/src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md
new file mode 100644
index 00000000000..c6516d838dd
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md
@@ -0,0 +1,39 @@
+# `virtual-function-elimination`
+
+This option controls whether LLVM runs the Virtual Function Elimination (VFE)
+optimization. This optimization in only available with LTO, so this flag can
+only be passed if [`-Clto`][Clto] is also passed.
+
+VFE makes it possible to remove functions from vtables that are never
+dynamically called by the rest of the code. Without this flag, LLVM makes the
+really conservative assumption, that if any function in a vtable is called, no
+function that is referenced by this vtable can be removed. With this flag
+additional information are given to LLVM, so that it can determine which
+functions are actually called and remove the unused functions.
+
+## Limitations
+
+At the time of writing this flag may remove vtable functions too eagerly. One
+such example is in this code:
+
+```rust
+trait Foo { fn foo(&self) { println!("foo") } }
+
+impl Foo for usize {}
+
+pub struct FooBox(Box<dyn Foo>);
+
+pub fn make_foo() -> FooBox { FooBox(Box::new(0)) }
+
+#[inline]
+pub fn f(a: FooBox) { a.0.foo() }
+```
+
+In the above code the `Foo` trait is private, so an assumption is made that its
+functions can only be seen/called from the current crate and can therefore get
+optimized out, if unused. However, with `make_foo` you can produce a wrapped
+`dyn Foo` type outside of the current crate, which can then be used in `f`. Due
+to inlining of `f`, `Foo::foo` can then be called from a foreign crate. This can
+lead to miscompilations.
+
+[Clto]: https://doc.rust-lang.org/rustc/codegen-options/index.html#lto
diff --git a/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md b/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md
deleted file mode 100644
index 5f3f1b4dd8a..00000000000
--- a/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# `infer_static_outlives_requirements`
-
-The tracking issue for this feature is: [#54185]
-
-[#54185]: https://github.com/rust-lang/rust/issues/54185
-
-------------------------
-The `infer_static_outlives_requirements` feature indicates that certain
-`'static` outlives requirements can be inferred by the compiler rather than
-stating them explicitly.
-
-Note: It is an accompanying feature to `infer_outlives_requirements`,
-which must be enabled to infer outlives requirements.
-
-For example, currently generic struct definitions that contain
-references, require where-clauses of the form T: 'static. By using
-this feature the outlives predicates will be inferred, although
-they may still be written explicitly.
-
-```rust,ignore (pseudo-Rust)
-struct Foo<U> where U: 'static { // <-- currently required
-    bar: Bar<U>
-}
-struct Bar<T: 'static> {
-    x: T,
-}
-```
-
-
-## Examples:
-
-```rust,ignore (pseudo-Rust)
-#![feature(infer_outlives_requirements)]
-#![feature(infer_static_outlives_requirements)]
-
-#[rustc_outlives]
-// Implicitly infer U: 'static
-struct Foo<U> {
-    bar: Bar<U>
-}
-struct Bar<T: 'static> {
-    x: T,
-}
-```
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index caea2544b54..41ab0e9377d 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -15,6 +15,7 @@ use rustc_data_structures::thin_vec::ThinVec;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 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};
@@ -234,7 +235,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
 }
 
 pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
-    match n.val() {
+    match n.kind() {
         ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
             let mut s = if let Some(def) = def.as_local() {
                 let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
@@ -270,7 +271,7 @@ pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<St
             (_, &ty::Ref(..)) => None,
             (ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
             (ConstValue::Scalar(_), _) => {
-                let const_ = ty::Const::from_value(tcx, val, ty);
+                let const_ = mir::ConstantKind::from_value(val, ty);
                 Some(print_const_with_custom_print_scalar(tcx, const_))
             }
             _ => None,
@@ -304,19 +305,18 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
         .collect()
 }
 
-fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: ty::Const<'_>) -> String {
+fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: mir::ConstantKind<'_>) -> String {
     // Use a slightly different format for integer types which always shows the actual value.
     // For all other types, fallback to the original `pretty_print_const`.
-    match (ct.val(), ct.ty().kind()) {
-        (ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Uint(ui)) => {
+    match (ct, ct.ty().kind()) {
+        (mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Uint(ui)) => {
             format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
         }
-        (ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Int(i)) => {
+        (mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Int(i)) => {
             let ty = tcx.lift(ct.ty()).unwrap();
             let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
             let data = int.assert_bits(size);
             let sign_extended_data = size.sign_extend(data) as i128;
-
             format!(
                 "{}{}",
                 format_integer_with_underscore_sep(&sign_extended_data.to_string()),
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index b7789493df6..394db2d0cda 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -886,9 +886,9 @@ fn fmt_type<'cx>(
                 primitive_link(f, PrimitiveType::Slice, &format!("[{name}]"), cx)
             }
             _ => {
-                primitive_link(f, PrimitiveType::Slice, "[", cx)?;
+                write!(f, "[")?;
                 fmt::Display::fmt(&t.print(cx), f)?;
-                primitive_link(f, PrimitiveType::Slice, "]", cx)
+                write!(f, "]")
             }
         },
         clean::Array(ref t, ref n) => {
@@ -926,31 +926,6 @@ fn fmt_type<'cx>(
             let m = mutability.print_with_space();
             let amp = if f.alternate() { "&".to_string() } else { "&amp;".to_string() };
             match **ty {
-                clean::Slice(ref bt) => {
-                    // `BorrowedRef{ ... Slice(T) }` is `&[T]`
-                    match **bt {
-                        clean::Generic(name) => primitive_link(
-                            f,
-                            PrimitiveType::Slice,
-                            &format!("{amp}{lt}{m}[{name}]"),
-                            cx,
-                        ),
-                        _ => {
-                            primitive_link(
-                                f,
-                                PrimitiveType::Slice,
-                                &format!("{}{}{}[", amp, lt, m),
-                                cx,
-                            )?;
-                            if f.alternate() {
-                                write!(f, "{:#}", bt.print(cx))?;
-                            } else {
-                                write!(f, "{}", bt.print(cx))?;
-                            }
-                            primitive_link(f, PrimitiveType::Slice, "]", cx)
-                        }
-                    }
-                }
                 clean::DynTrait(ref bounds, ref trait_lt)
                     if bounds.len() > 1 || trait_lt.is_some() =>
                 {
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index f338050bee0..0964b757e74 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -181,15 +181,44 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         let name = item.name;
         let item_id = item.item_id;
         if let Some(mut new_item) = self.convert_item(item) {
-            if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
-                t.implementations = self.get_trait_implementors(item_id.expect_def_id())
-            } else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
-                s.impls = self.get_impls(item_id.expect_def_id())
-            } else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
-                e.impls = self.get_impls(item_id.expect_def_id())
-            } else if let types::ItemEnum::Union(ref mut u) = new_item.inner {
-                u.impls = self.get_impls(item_id.expect_def_id())
-            }
+            let can_be_ignored = match new_item.inner {
+                types::ItemEnum::Trait(ref mut t) => {
+                    t.implementations = self.get_trait_implementors(item_id.expect_def_id());
+                    false
+                }
+                types::ItemEnum::Struct(ref mut s) => {
+                    s.impls = self.get_impls(item_id.expect_def_id());
+                    false
+                }
+                types::ItemEnum::Enum(ref mut e) => {
+                    e.impls = self.get_impls(item_id.expect_def_id());
+                    false
+                }
+                types::ItemEnum::Union(ref mut u) => {
+                    u.impls = self.get_impls(item_id.expect_def_id());
+                    false
+                }
+
+                types::ItemEnum::Method(_)
+                | types::ItemEnum::AssocConst { .. }
+                | types::ItemEnum::AssocType { .. } => true,
+                types::ItemEnum::Module(_)
+                | types::ItemEnum::ExternCrate { .. }
+                | types::ItemEnum::Import(_)
+                | types::ItemEnum::StructField(_)
+                | types::ItemEnum::Variant(_)
+                | types::ItemEnum::Function(_)
+                | types::ItemEnum::TraitAlias(_)
+                | types::ItemEnum::Impl(_)
+                | types::ItemEnum::Typedef(_)
+                | types::ItemEnum::OpaqueTy(_)
+                | types::ItemEnum::Constant(_)
+                | types::ItemEnum::Static(_)
+                | types::ItemEnum::ForeignType
+                | types::ItemEnum::Macro(_)
+                | types::ItemEnum::ProcMacro(_)
+                | types::ItemEnum::PrimitiveType(_) => false,
+            };
             let removed = self
                 .index
                 .borrow_mut()
@@ -199,7 +228,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
             // to make sure the items are unique. The main place this happens is when an item, is
             // reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod`
             if let Some(old_item) = removed {
-                assert_eq!(old_item, new_item);
+                // In case of generic implementations (like `impl<T> Trait for T {}`), all the
+                // inner items will be duplicated so we can ignore if they are slightly different.
+                if !can_be_ignored {
+                    assert_eq!(old_item, new_item);
+                }
             }
         }
 
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 9cc006b10ff..e3b349af661 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -122,7 +122,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
                     diag.span_suggestion(
                         sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
                         explanation,
-                        String::from("text"),
+                        "text",
                         Applicability::MachineApplicable,
                     );
                 }
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 242f926967c..da09ae9dd06 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -17,7 +17,7 @@ use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_serialize::{
-    opaque::{Decoder, FileEncoder},
+    opaque::{FileEncoder, MemDecoder},
     Decodable, Encodable, Encoder,
 };
 use rustc_session::getopts;
@@ -336,7 +336,7 @@ pub(crate) fn load_call_locations(
         let mut all_calls: AllCallLocations = FxHashMap::default();
         for path in with_examples {
             let bytes = fs::read(&path).map_err(|e| format!("{} (for path {})", e, path))?;
-            let mut decoder = Decoder::new(&bytes, 0);
+            let mut decoder = MemDecoder::new(&bytes, 0);
             let calls = AllCallLocations::decode(&mut decoder);
 
             for (function, fn_calls) in calls.into_iter() {
diff --git a/src/test/codegen/issue-96497-slice-size-nowrap.rs b/src/test/codegen/issue-96497-slice-size-nowrap.rs
new file mode 100644
index 00000000000..a5dbef93460
--- /dev/null
+++ b/src/test/codegen/issue-96497-slice-size-nowrap.rs
@@ -0,0 +1,29 @@
+// This test case checks that LLVM is aware that computing the size of a slice cannot wrap.
+// The possibility of wrapping results in an additional branch when dropping boxed slices
+// in some situations, see https://github.com/rust-lang/rust/issues/96497#issuecomment-1112865218
+
+// compile-flags: -O
+// min-llvm-version: 14.0
+
+#![crate_type="lib"]
+
+// CHECK-LABEL: @simple_size_of_nowrap
+#[no_mangle]
+pub fn simple_size_of_nowrap(x: &[u32]) -> usize {
+    // Make sure the shift used to compute the size has a nowrap flag.
+
+    // CHECK: [[A:%.*]] = shl nsw {{.*}}, 2
+    // CHECK-NEXT: ret {{.*}} [[A]]
+    core::mem::size_of_val(x)
+}
+
+// CHECK-LABEL: @drop_write
+#[no_mangle]
+pub fn drop_write(mut x: Box<[u32]>) {
+    // Check that this write is optimized out.
+    // This depends on the size calculation not wrapping,
+    // since otherwise LLVM can't tell that the memory is always deallocated if the slice len > 0.
+
+    // CHECK-NOT: store i32 42
+    x[1] = 42;
+}
diff --git a/src/test/codegen/virtual-function-elimination-32bit.rs b/src/test/codegen/virtual-function-elimination-32bit.rs
new file mode 100644
index 00000000000..6f963363a99
--- /dev/null
+++ b/src/test/codegen/virtual-function-elimination-32bit.rs
@@ -0,0 +1,35 @@
+// compile-flags: -Zvirtual-function-elimination -Clto -O -Csymbol-mangling-version=v0
+// ignore-64bit
+
+// CHECK: @vtable.0 = {{.*}}, !type ![[TYPE0:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
+
+#![crate_type = "lib"]
+
+trait T {
+    // CHECK-LABEL: ; <virtual_function_elimination_32bit::S as virtual_function_elimination_32bit::T>::used
+    fn used(&self) -> i32 {
+        1
+    }
+    // CHECK-LABEL-NOT: {{.*}}::unused
+    fn unused(&self) -> i32 {
+        2
+    }
+}
+
+#[derive(Copy, Clone)]
+struct S;
+
+impl T for S {}
+
+fn taking_t(t: &dyn T) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 12, metadata !"[[MANGLED_TYPE0:[0-9a-zA-Z_]+]]")
+    t.used()
+}
+
+pub fn main() {
+    let s = S;
+    taking_t(&s);
+}
+
+// CHECK: ![[TYPE0]] = !{i32 0, !"[[MANGLED_TYPE0]]"}
+// CHECK: ![[VCALL_VIS0]] = !{i64 2}
diff --git a/src/test/codegen/virtual-function-elimination.rs b/src/test/codegen/virtual-function-elimination.rs
new file mode 100644
index 00000000000..4cf7e12fee2
--- /dev/null
+++ b/src/test/codegen/virtual-function-elimination.rs
@@ -0,0 +1,100 @@
+// compile-flags: -Zvirtual-function-elimination -Clto -O -Csymbol-mangling-version=v0
+// ignore-32bit
+
+// CHECK: @vtable.0 = {{.*}}, !type ![[TYPE0:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
+// CHECK: @vtable.1 = {{.*}}, !type ![[TYPE1:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
+// CHECK: @vtable.2 = {{.*}}, !type ![[TYPE2:[0-9]+]], !vcall_visibility ![[VCALL_VIS2:[0-9]+]]
+
+#![crate_type = "lib"]
+#![allow(incomplete_features)]
+#![feature(unsized_locals)]
+
+use std::rc::Rc;
+
+trait T {
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::T>::used
+    fn used(&self) -> i32 {
+        1
+    }
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::T>::used_through_sub_trait
+    fn used_through_sub_trait(&self) -> i32 {
+        3
+    }
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::T>::by_rc
+    fn by_rc(self: Rc<Self>) -> i32 {
+        self.used() + self.used()
+    }
+    // CHECK-LABEL-NOT: {{.*}}::unused
+    fn unused(&self) -> i32 {
+        2
+    }
+    // CHECK-LABEL-NOT: {{.*}}::by_rc_unused
+    fn by_rc_unused(self: Rc<Self>) -> i32 {
+        self.by_rc()
+    }
+}
+
+trait U: T {
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::U>::subtrait_used
+    fn subtrait_used(&self) -> i32 {
+        4
+    }
+    // CHECK-LABEL-NOT: {{.*}}::subtrait_unused
+    fn subtrait_unused(&self) -> i32 {
+        5
+    }
+}
+
+pub trait V {
+    // CHECK-LABEL: ; <virtual_function_elimination::S as virtual_function_elimination::V>::public_function
+    fn public_function(&self) -> i32;
+}
+
+#[derive(Copy, Clone)]
+struct S;
+
+impl T for S {}
+
+impl U for S {}
+
+impl V for S {
+    fn public_function(&self) -> i32 {
+        6
+    }
+}
+
+fn taking_t(t: &dyn T) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"[[MANGLED_TYPE0:[0-9a-zA-Z_]+]]")
+    t.used()
+}
+
+fn taking_rc_t(t: Rc<dyn T>) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 40, metadata !"[[MANGLED_TYPE0:[0-9a-zA-Z_]+]]")
+    t.by_rc()
+}
+
+fn taking_u(u: &dyn U) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 64, metadata !"[[MANGLED_TYPE1:[0-9a-zA-Z_]+]]")
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"[[MANGLED_TYPE1:[0-9a-zA-Z_]+]]")
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 32, metadata !"[[MANGLED_TYPE1:[0-9a-zA-Z_]+]]")
+    u.subtrait_used() + u.used() + u.used_through_sub_trait()
+}
+
+pub fn taking_v(v: &dyn V) -> i32 {
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtCsfRpWlKdQPZn_28virtual_function_elimination1V")
+    v.public_function()
+}
+
+pub fn main() {
+    let s = S;
+    taking_t(&s);
+    taking_rc_t(Rc::new(s));
+    taking_u(&s);
+    taking_v(&s);
+}
+
+// CHECK: ![[TYPE0]] = !{i64 0, !"[[MANGLED_TYPE0]]"}
+// CHECK: ![[VCALL_VIS0]] = !{i64 2}
+// CHECK: ![[TYPE1]] = !{i64 0, !"[[MANGLED_TYPE1]]"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"NtCsfRpWlKdQPZn_28virtual_function_elimination1V"}
+// CHECK: ![[VCALL_VIS2]] = !{i64 1}
diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs
index 73e34d4bb32..60fb06d409c 100644
--- a/src/test/debuginfo/function-names.rs
+++ b/src/test/debuginfo/function-names.rs
@@ -37,7 +37,7 @@
 // Const generic parameter
 // gdb-command:info functions -q function_names::const_generic_fn.*
 // gdb-check:[...]static fn function_names::const_generic_fn_bool<false>();
-// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#3fcd7c34c1555be6}>();
+// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#6348c650c7b26618}>();
 // gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>();
 // gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>();
 
@@ -76,7 +76,7 @@
 // Const generic parameter
 // cdb-command:x a!function_names::const_generic_fn*
 // cdb-check:[...] a!function_names::const_generic_fn_bool<false> (void)
-// cdb-check:[...] a!function_names::const_generic_fn_non_int<CONST$3fcd7c34c1555be6> (void)
+// cdb-check:[...] a!function_names::const_generic_fn_non_int<CONST$6348c650c7b26618> (void)
 // cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void)
 // cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void)
 
diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs
index 9e449de0cf5..806c8415259 100644
--- a/src/test/incremental/issue-54242.rs
+++ b/src/test/incremental/issue-54242.rs
@@ -14,7 +14,7 @@ impl Tr for str {
     type Arr = [u8; 8];
     #[cfg(cfail)]
     type Arr = [u8; Self::C];
-    //[cfail]~^ ERROR cycle detected when simplifying constant
+    //[cfail]~^ ERROR cycle detected when evaluating type-level constant
 }
 
 fn main() {}
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
index 8b5ad40c9f9..432aac9ccdf 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
@@ -21,41 +21,41 @@ fn main() -> () {
 }
 
 alloc1 (static: FOO, size: 8, align: 4) {
-    ╾─alloc28─╼ 03 00 00 00                         │ ╾──╼....
+    ╾─alloc22─╼ 03 00 00 00                         │ ╾──╼....
 }
 
-alloc28 (size: 48, align: 4) {
-    0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc13─╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc18─╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc26─╼ 03 00 00 00 │ ....*...╾──╼....
+alloc22 (size: 48, align: 4) {
+    0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 00 00 00 00 │ ....░░░░╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc14─╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc20─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
-alloc13 (size: 0, align: 4) {}
+alloc9 (size: 0, align: 4) {}
 
-alloc18 (size: 8, align: 4) {
-    ╾─alloc16─╼ ╾─alloc17─╼                         │ ╾──╼╾──╼
+alloc14 (size: 8, align: 4) {
+    ╾─alloc12─╼ ╾─alloc13─╼                         │ ╾──╼╾──╼
 }
 
-alloc16 (size: 1, align: 1) {
+alloc12 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc17 (size: 1, align: 1) {
+alloc13 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc26 (size: 12, align: 4) {
-    ╾─a22+0x3─╼ ╾─alloc23─╼ ╾─a25+0x2─╼             │ ╾──╼╾──╼╾──╼
+alloc20 (size: 12, align: 4) {
+    ╾─a17+0x3─╼ ╾─alloc18─╼ ╾─a19+0x2─╼             │ ╾──╼╾──╼╾──╼
 }
 
-alloc22 (size: 4, align: 1) {
+alloc17 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc23 (size: 1, align: 1) {
+alloc18 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc25 (size: 4, align: 1) {
+alloc19 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
index ef651f01c9b..e2acd610b80 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
@@ -21,44 +21,44 @@ fn main() -> () {
 }
 
 alloc1 (static: FOO, size: 16, align: 8) {
-    ╾───────alloc28───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    ╾───────alloc22───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc28 (size: 72, align: 8) {
-    0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc13───────╼ │ ....░░░░╾──────╼
+alloc22 (size: 72, align: 8) {
+    0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc9────────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc18───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc26───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc14───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc20───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
-alloc13 (size: 0, align: 8) {}
+alloc9 (size: 0, align: 8) {}
 
-alloc18 (size: 16, align: 8) {
-    ╾───────alloc16───────╼ ╾───────alloc17───────╼ │ ╾──────╼╾──────╼
+alloc14 (size: 16, align: 8) {
+    ╾───────alloc12───────╼ ╾───────alloc13───────╼ │ ╾──────╼╾──────╼
 }
 
-alloc16 (size: 1, align: 1) {
+alloc12 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc17 (size: 1, align: 1) {
+alloc13 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc26 (size: 24, align: 8) {
-    0x00 │ ╾─────alloc22+0x3─────╼ ╾───────alloc23───────╼ │ ╾──────╼╾──────╼
-    0x10 │ ╾─────alloc25+0x2─────╼                         │ ╾──────╼
+alloc20 (size: 24, align: 8) {
+    0x00 │ ╾─────alloc17+0x3─────╼ ╾───────alloc18───────╼ │ ╾──────╼╾──────╼
+    0x10 │ ╾─────alloc19+0x2─────╼                         │ ╾──────╼
 }
 
-alloc22 (size: 4, align: 1) {
+alloc17 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc23 (size: 1, align: 1) {
+alloc18 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc25 (size: 4, align: 1) {
+alloc19 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff
index c19cbe3e5b0..5b2b9f7e3a9 100644
--- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff
+++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff
@@ -36,7 +36,7 @@
 +         StorageLive(_7);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         _7 = &mut (*_5);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         StorageLive(_8);                 // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+         _8 = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         _8 = const alloc::raw_vec::RawVec::<u32>::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
                                            // mir::Constant
 -                                          // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
 -                                          // + user_ty: UserType(1)
@@ -46,7 +46,7 @@
 -     bb2: {
 +                                          // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +                                          // + user_ty: UserType(0)
-+                                          // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Value(ByRef(..)) }
++                                          // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
 +         Deinit((*_7));                   // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +         ((*_7).0: alloc::raw_vec::RawVec<u32>) = move _8; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +         ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff
index c19cbe3e5b0..5b2b9f7e3a9 100644
--- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff
+++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff
@@ -36,7 +36,7 @@
 +         StorageLive(_7);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         _7 = &mut (*_5);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         StorageLive(_8);                 // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+         _8 = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         _8 = const alloc::raw_vec::RawVec::<u32>::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
                                            // mir::Constant
 -                                          // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
 -                                          // + user_ty: UserType(1)
@@ -46,7 +46,7 @@
 -     bb2: {
 +                                          // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +                                          // + user_ty: UserType(0)
-+                                          // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Value(ByRef(..)) }
++                                          // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
 +         Deinit((*_7));                   // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +         ((*_7).0: alloc::raw_vec::RawVec<u32>) = move _8; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +         ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index f79e2705ad2..7d9e012bb29 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
@@ -23,7 +23,7 @@
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
-    let mut _1: [usize; Const { ty: usize, val: Value(Scalar(0x00000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
+    let mut _1: [usize; Const { ty: usize, kind: Value(Leaf(0x00000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
     let _3: usize;                       // in scope 0 at $DIR/region-subtyping-basic.rs:18:16: 18:17
     let mut _4: usize;                   // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
     let mut _5: bool;                    // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
@@ -63,7 +63,7 @@ fn main() -> () {
         FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
-        switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
+        switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
     }
 
     bb2: {
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 162cacef8a5..c555e0441f4 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
@@ -23,7 +23,7 @@
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
-    let mut _1: [usize; Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
+    let mut _1: [usize; Const { ty: usize, kind: Value(Leaf(0x0000000000000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
     let _3: usize;                       // in scope 0 at $DIR/region-subtyping-basic.rs:18:16: 18:17
     let mut _4: usize;                   // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
     let mut _5: bool;                    // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
@@ -63,7 +63,7 @@ fn main() -> () {
         FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
-        switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
+        switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
     }
 
     bb2: {
diff --git a/src/test/rustdoc-json/generic_impl.rs b/src/test/rustdoc-json/generic_impl.rs
new file mode 100644
index 00000000000..ac68ba578b6
--- /dev/null
+++ b/src/test/rustdoc-json/generic_impl.rs
@@ -0,0 +1,24 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/97986>.
+
+// @has generic_impl.json
+// @has - "$.index[*][?(@.name=='f')]"
+// @has - "$.index[*][?(@.name=='AssocTy')]"
+// @has - "$.index[*][?(@.name=='AssocConst')]"
+
+pub mod m {
+    pub struct S;
+}
+
+pub trait F {
+    type AssocTy;
+    const AssocConst: usize;
+    fn f() -> m::S;
+}
+
+impl<T> F for T {
+    type AssocTy = u32;
+    const AssocConst: usize = 0;
+    fn f() -> m::S {
+        m::S
+    }
+}
diff --git a/src/test/rustdoc/slice-links.link_box_u32.html b/src/test/rustdoc/slice-links.link_box_u32.html
index 42fd721a4ac..7bec7582df7 100644
--- a/src/test/rustdoc/slice-links.link_box_u32.html
+++ b/src/test/rustdoc/slice-links.link_box_u32.html
@@ -1 +1 @@
-<code>pub fn gamma() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;<a class="primitive" href="{{channel}}/core/primitive.slice.html">[</a><a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a><a class="primitive" href="{{channel}}/core/primitive.slice.html">]</a>&gt;</code>
\ No newline at end of file
+<code>pub fn gamma() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;[<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>]&gt;</code>
\ No newline at end of file
diff --git a/src/test/rustdoc/slice-links.link_slice_generic.html b/src/test/rustdoc/slice-links.link_slice_generic.html
index fe79ca7a82d..1d0f2bf75a2 100644
--- a/src/test/rustdoc/slice-links.link_slice_generic.html
+++ b/src/test/rustdoc/slice-links.link_slice_generic.html
@@ -1 +1 @@
-<code>pub fn beta&lt;T&gt;() -&gt; <a class="primitive" href="{{channel}}/core/primitive.slice.html">&amp;'static [T]</a></code>
\ No newline at end of file
+<code>pub fn beta&lt;T&gt;() -&gt; &amp;'static <a class="primitive" href="{{channel}}/core/primitive.slice.html">[T]</a></code>
\ No newline at end of file
diff --git a/src/test/rustdoc/slice-links.link_slice_u32.html b/src/test/rustdoc/slice-links.link_slice_u32.html
index c7e430b0607..c86d3830426 100644
--- a/src/test/rustdoc/slice-links.link_slice_u32.html
+++ b/src/test/rustdoc/slice-links.link_slice_u32.html
@@ -1 +1 @@
-<code>pub fn alpha() -&gt; <a class="primitive" href="{{channel}}/core/primitive.slice.html">&amp;'static [</a><a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a><a class="primitive" href="{{channel}}/core/primitive.slice.html">]</a></code>
\ No newline at end of file
+<code>pub fn alpha() -&gt; &amp;'static [<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>]</code>
\ No newline at end of file
diff --git a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs
index a09deeec4f1..4ad4ef60a52 100644
--- a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs
+++ b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs
@@ -7,7 +7,7 @@ extern crate rustc_macros;
 extern crate rustc_serialize;
 
 use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque;
+use rustc_serialize::opaque::{MemDecoder, MemEncoder};
 use rustc_serialize::{Decodable, Encodable, Encoder};
 
 #[derive(Encodable, Decodable)]
@@ -18,11 +18,11 @@ struct A {
 fn main() {
     let obj = A { foo: Box::new([true, false]) };
 
-    let mut encoder = opaque::Encoder::new();
+    let mut encoder = MemEncoder::new();
     obj.encode(&mut encoder);
     let data = encoder.finish().unwrap();
 
-    let mut decoder = opaque::Decoder::new(&data, 0);
+    let mut decoder = MemDecoder::new(&data, 0);
     let obj2 = A::decode(&mut decoder);
 
     assert_eq!(obj.foo, obj2.foo);
diff --git a/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs b/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs
index 9b6fb0e5806..3ac3abae692 100644
--- a/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs
+++ b/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs
@@ -9,7 +9,7 @@ extern crate rustc_macros;
 extern crate rustc_serialize;
 
 use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque;
+use rustc_serialize::opaque::{MemDecoder, MemEncoder};
 use rustc_serialize::{Decodable, Encodable, Encoder};
 use std::cell::{Cell, RefCell};
 
@@ -27,11 +27,11 @@ struct B {
 fn main() {
     let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) };
 
-    let mut encoder = opaque::Encoder::new();
+    let mut encoder = MemEncoder::new();
     obj.encode(&mut encoder);
     let data = encoder.finish().unwrap();
 
-    let mut decoder = opaque::Decoder::new(&data, 0);
+    let mut decoder = MemDecoder::new(&data, 0);
     let obj2 = B::decode(&mut decoder);
 
     assert_eq!(obj.foo.get(), obj2.foo.get());
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
new file mode 100644
index 00000000000..817d8531da9
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
@@ -0,0 +1,73 @@
+// compile-flags: -Z unstable-options
+
+#![crate_type = "lib"]
+#![feature(rustc_private)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
+extern crate rustc_errors;
+extern crate rustc_macros;
+extern crate rustc_session;
+extern crate rustc_span;
+
+use rustc_errors::{AddSubdiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, fluent};
+use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_session::{parse::ParseSess, SessionDiagnostic};
+use rustc_span::Span;
+
+#[derive(SessionDiagnostic)]
+#[error(slug = "parser-expect-path")]
+struct DeriveSessionDiagnostic {
+    #[primary_span]
+    span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[note(slug = "note")]
+struct Note {
+    #[primary_span]
+    span: Span,
+}
+
+pub struct UntranslatableInSessionDiagnostic;
+
+impl<'a> SessionDiagnostic<'a, ErrorGuaranteed> for UntranslatableInSessionDiagnostic {
+    fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+        sess.struct_err("untranslatable diagnostic")
+        //~^ ERROR diagnostics should be created using translatable messages
+    }
+}
+
+pub struct TranslatableInSessionDiagnostic;
+
+impl<'a> SessionDiagnostic<'a, ErrorGuaranteed> for TranslatableInSessionDiagnostic {
+    fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+        sess.struct_err(fluent::parser::expect_path)
+    }
+}
+
+pub struct UntranslatableInAddSubdiagnostic;
+
+impl AddSubdiagnostic for UntranslatableInAddSubdiagnostic {
+    fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+        diag.note("untranslatable diagnostic");
+        //~^ ERROR diagnostics should be created using translatable messages
+    }
+}
+
+pub struct TranslatableInAddSubdiagnostic;
+
+impl AddSubdiagnostic for TranslatableInAddSubdiagnostic {
+    fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+        diag.note(fluent::typeck::note);
+    }
+}
+
+pub fn make_diagnostics<'a>(sess: &'a ParseSess) {
+    let _diag = sess.struct_err(fluent::parser::expect_path);
+    //~^ ERROR diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
+
+    let _diag = sess.struct_err("untranslatable diagnostic");
+    //~^ ERROR diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
+    //~^^ ERROR diagnostics should be created using translatable messages
+}
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.stderr b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr
new file mode 100644
index 00000000000..bae78ffdc02
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr
@@ -0,0 +1,44 @@
+error: diagnostics should be created using translatable messages
+  --> $DIR/diagnostics.rs:36:14
+   |
+LL |         sess.struct_err("untranslatable diagnostic")
+   |              ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/diagnostics.rs:5:9
+   |
+LL | #![deny(rustc::untranslatable_diagnostic)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: diagnostics should be created using translatable messages
+  --> $DIR/diagnostics.rs:53:14
+   |
+LL |         diag.note("untranslatable diagnostic");
+   |              ^^^^
+
+error: diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
+  --> $DIR/diagnostics.rs:67:22
+   |
+LL |     let _diag = sess.struct_err(fluent::parser::expect_path);
+   |                      ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/diagnostics.rs:6:9
+   |
+LL | #![deny(rustc::diagnostic_outside_of_impl)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
+  --> $DIR/diagnostics.rs:70:22
+   |
+LL |     let _diag = sess.struct_err("untranslatable diagnostic");
+   |                      ^^^^^^^^^^
+
+error: diagnostics should be created using translatable messages
+  --> $DIR/diagnostics.rs:70:22
+   |
+LL |     let _diag = sess.struct_err("untranslatable diagnostic");
+   |                      ^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.rs b/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.rs
new file mode 100644
index 00000000000..99f99ffcd35
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Z unstable-options
+
+#![feature(rustc_attrs)]
+
+#[rustc_lint_diagnostics]
+//~^ ERROR attribute should be applied to a function
+struct Foo;
+
+impl Foo {
+    #[rustc_lint_diagnostics(a)]
+    //~^ ERROR malformed `rustc_lint_diagnostics`
+    fn bar() {}
+}
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.stderr b/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.stderr
new file mode 100644
index 00000000000..46c206f3bf9
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.stderr
@@ -0,0 +1,17 @@
+error: malformed `rustc_lint_diagnostics` attribute input
+  --> $DIR/diagnostics_incorrect.rs:10:5
+   |
+LL |     #[rustc_lint_diagnostics(a)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_lint_diagnostics]`
+
+error: attribute should be applied to a function
+  --> $DIR/diagnostics_incorrect.rs:5:1
+   |
+LL | #[rustc_lint_diagnostics]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | struct Foo;
+   | ----------- not a function
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui-fulldeps/issue-14021.rs b/src/test/ui-fulldeps/issue-14021.rs
index 4241456367e..b7b6e1b860d 100644
--- a/src/test/ui-fulldeps/issue-14021.rs
+++ b/src/test/ui-fulldeps/issue-14021.rs
@@ -8,7 +8,7 @@ extern crate rustc_macros;
 extern crate rustc_serialize;
 
 use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque;
+use rustc_serialize::opaque::{MemDecoder, MemEncoder};
 use rustc_serialize::{Decodable, Encodable, Encoder};
 
 #[derive(Encodable, Decodable, PartialEq, Debug)]
@@ -17,11 +17,11 @@ struct UnitLikeStruct;
 pub fn main() {
     let obj = UnitLikeStruct;
 
-    let mut encoder = opaque::Encoder::new();
+    let mut encoder = MemEncoder::new();
     obj.encode(&mut encoder);
     let data = encoder.finish().unwrap();
 
-    let mut decoder = opaque::Decoder::new(&data, 0);
+    let mut decoder = MemDecoder::new(&data, 0);
     let obj2 = UnitLikeStruct::decode(&mut decoder);
 
     assert_eq!(obj, obj2);
diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.rs b/src/test/ui/associated-consts/defaults-cyclic-fail.rs
index 2f1858d39b3..a1c6840a0f1 100644
--- a/src/test/ui/associated-consts/defaults-cyclic-fail.rs
+++ b/src/test/ui/associated-consts/defaults-cyclic-fail.rs
@@ -1,9 +1,9 @@
 // build-fail
-//~^ ERROR cycle detected when normalizing `<() as Tr>::A` [E0391]
 
 // Cyclic assoc. const defaults don't error unless *used*
 trait Tr {
     const A: u8 = Self::B;
+    //~^ cycle detected when const-evaluating + checking `Tr::A`
 
     const B: u8 = Self::A;
 }
diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr
index 3fb4ab72fe6..c4cd9c2a49f 100644
--- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr
+++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr
@@ -1,42 +1,20 @@
-error[E0391]: cycle detected when normalizing `<() as Tr>::A`
-   |
-note: ...which requires simplifying constant for the type system `Tr::A`...
-  --> $DIR/defaults-cyclic-fail.rs:6:5
-   |
-LL |     const A: u8 = Self::B;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `Tr::A`...
-  --> $DIR/defaults-cyclic-fail.rs:6:5
-   |
-LL |     const A: u8 = Self::B;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `Tr::A`...
-  --> $DIR/defaults-cyclic-fail.rs:6:5
+error[E0391]: cycle detected when const-evaluating + checking `Tr::A`
+  --> $DIR/defaults-cyclic-fail.rs:5:5
    |
 LL |     const A: u8 = Self::B;
    |     ^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `<() as Tr>::B`...
-note: ...which requires simplifying constant for the type system `Tr::B`...
-  --> $DIR/defaults-cyclic-fail.rs:8:5
    |
-LL |     const B: u8 = Self::A;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `Tr::B`...
-  --> $DIR/defaults-cyclic-fail.rs:8:5
-   |
-LL |     const B: u8 = Self::A;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `Tr::B`...
   --> $DIR/defaults-cyclic-fail.rs:8:5
    |
 LL |     const B: u8 = Self::A;
    |     ^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle
+   = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle
 note: cycle used when const-evaluating + checking `main::promoted[1]`
-  --> $DIR/defaults-cyclic-fail.rs:14:1
+  --> $DIR/defaults-cyclic-fail.rs:16:16
    |
-LL | fn main() {
-   | ^^^^^^^^^
+LL |     assert_eq!(<() as Tr>::A, 0);
+   |                ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
index 3d696bb049c..b4dc730d863 100644
--- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
+++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
@@ -1,16 +1,10 @@
 error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`
-  --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
+  --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:22
    |
 LL |     const BAR: u32 = IMPL_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: ...which requires normalizing `IMPL_REF_BAR`...
-note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
+   |                      ^^^^^^^^^^^^
    |
-LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
+note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
    |
 LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
@@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
    |
 LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
-note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
-   |
-LL |     const BAR: u32 = IMPL_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
-   |
-LL |     const BAR: u32 = IMPL_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
    |
diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
index 71e26245e16..97ede6ad388 100644
--- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
+++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
@@ -1,16 +1,10 @@
 error[E0391]: cycle detected when elaborating drops for `FooDefault::BAR`
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
+  --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:22
    |
 LL |     const BAR: u32 = DEFAULT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: ...which requires normalizing `DEFAULT_REF_BAR`...
-note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
+   |                      ^^^^^^^^^^^^^^^
    |
-LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
+note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
    |
 LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
@@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
    |
 LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `<GlobalDefaultRef as FooDefault>::BAR`...
-note: ...which requires simplifying constant for the type system `FooDefault::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
-   |
-LL |     const BAR: u32 = DEFAULT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `FooDefault::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
-   |
-LL |     const BAR: u32 = DEFAULT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `FooDefault::BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
    |
diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
index 020d758e153..bd97c31229e 100644
--- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
+++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
@@ -1,16 +1,10 @@
 error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
+  --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:22
    |
 LL |     const BAR: u32 = TRAIT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: ...which requires normalizing `TRAIT_REF_BAR`...
-note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
+   |                      ^^^^^^^^^^^^^
    |
-LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
+note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
    |
 LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
@@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
    |
 LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `<GlobalTraitRef as Foo>::BAR`...
-note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
-   |
-LL |     const BAR: u32 = TRAIT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
-   |
-LL |     const BAR: u32 = TRAIT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
    |
diff --git a/src/test/ui/borrowck/issue-81899.rs b/src/test/ui/borrowck/issue-81899.rs
index 356517745ff..9b60612037d 100644
--- a/src/test/ui/borrowck/issue-81899.rs
+++ b/src/test/ui/borrowck/issue-81899.rs
@@ -2,6 +2,8 @@
 // The `panic!()` below is important to trigger the fixed ICE.
 
 const _CONST: &[u8] = &f(&[], |_| {});
+//~^ ERROR any use of this value
+//~| WARNING this was previously
 
 const fn f<F>(_: &[u8], _: F) -> &[u8]
 where
diff --git a/src/test/ui/borrowck/issue-81899.stderr b/src/test/ui/borrowck/issue-81899.stderr
index 59bf00d0012..92ebd5a220d 100644
--- a/src/test/ui/borrowck/issue-81899.stderr
+++ b/src/test/ui/borrowck/issue-81899.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-81899.rs:10:5
+  --> $DIR/issue-81899.rs:12:5
    |
 LL | const _CONST: &[u8] = &f(&[], |_| {});
    |                        -------------- inside `_CONST` at $DIR/issue-81899.rs:4:24
@@ -7,11 +7,23 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
 LL |     panic!()
    |     ^^^^^^^^
    |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:10:5
+   |     the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:12:5
    |     inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to previous error
+error: any use of this value will cause an error
+  --> $DIR/issue-81899.rs:4:23
+   |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   | ----------------------^^^^^^^^^^^^^^^-
+   |                       |
+   |                       referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.rs b/src/test/ui/borrowck/issue-88434-minimal-example.rs
index 632f8dc3ad6..7618d001e86 100644
--- a/src/test/ui/borrowck/issue-88434-minimal-example.rs
+++ b/src/test/ui/borrowck/issue-88434-minimal-example.rs
@@ -1,6 +1,8 @@
 // Regression test related to issue 88434
 
 const _CONST: &() = &f(&|_| {});
+//~^ ERROR any use of this value
+//~| WARNING this was previously
 
 const fn f<F>(_: &F)
 where
diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr
index d9635e1ee46..d46cd862e34 100644
--- a/src/test/ui/borrowck/issue-88434-minimal-example.stderr
+++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-88434-minimal-example.rs:9:5
+  --> $DIR/issue-88434-minimal-example.rs:11:5
    |
 LL | const _CONST: &() = &f(&|_| {});
    |                      ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22
@@ -7,11 +7,23 @@ LL | const _CONST: &() = &f(&|_| {});
 LL |     panic!()
    |     ^^^^^^^^
    |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:9:5
+   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:11:5
    |     inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to previous error
+error: any use of this value will cause an error
+  --> $DIR/issue-88434-minimal-example.rs:3:21
+   |
+LL | const _CONST: &() = &f(&|_| {});
+   | --------------------^^^^^^^^^^^-
+   |                     |
+   |                     referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs
index f0a6dcd4eb3..b1fc1615ece 100644
--- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs
+++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs
@@ -1,6 +1,8 @@
 // Regression test for issue 88434
 
 const _CONST: &[u8] = &f(&[], |_| {});
+//~^ ERROR any use of this value will cause an error
+//~| WARNING this was previously
 
 const fn f<F>(_: &[u8], _: F) -> &[u8]
 where
diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
index 44e244ae9cc..e6b07aba74d 100644
--- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
+++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-88434-removal-index-should-be-less.rs:9:5
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:11:5
    |
 LL | const _CONST: &[u8] = &f(&[], |_| {});
    |                        -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24
@@ -7,11 +7,23 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
 LL |     panic!()
    |     ^^^^^^^^
    |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:9:5
+   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:11:5
    |     inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to previous error
+error: any use of this value will cause an error
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:3:23
+   |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   | ----------------------^^^^^^^^^^^^^^^-
+   |                       |
+   |                       referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr
index a1f7e17d778..24ce2280c8a 100644
--- a/src/test/ui/check-cfg/well-known-values.stderr
+++ b/src/test/ui/check-cfg/well-known-values.stderr
@@ -7,7 +7,7 @@ LL | #[cfg(target_os = "linuz")]
    |                   help: did you mean: `"linux"`
    |
    = note: `#[warn(unexpected_cfgs)]` on by default
-   = note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, windows, xous
+   = note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous
 
 warning: unexpected `cfg` condition value
   --> $DIR/well-known-values.rs:14:7
diff --git a/src/test/ui/const-generics/different_generic_args_array.stderr b/src/test/ui/const-generics/different_generic_args_array.stderr
index c0709a996ce..f0b9035357d 100644
--- a/src/test/ui/const-generics/different_generic_args_array.stderr
+++ b/src/test/ui/const-generics/different_generic_args_array.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/different_generic_args_array.rs:9:9
    |
 LL |     x = Const::<{ [4] }> {};
-   |         ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+   |         ^^^^^^^^^^^^^^^^^^^ expected `[3_usize]`, found `[4_usize]`
    |
    = note: expected struct `Const<[3_usize]>`
               found struct `Const<[4_usize]>`
diff --git a/src/test/ui/const-generics/issue-97007.rs b/src/test/ui/const-generics/issue-97007.rs
new file mode 100644
index 00000000000..7036834c4b1
--- /dev/null
+++ b/src/test/ui/const-generics/issue-97007.rs
@@ -0,0 +1,88 @@
+// check-pass
+
+#![feature(adt_const_params, generic_const_exprs)]
+#![allow(incomplete_features)]
+
+mod lib {
+    const N_ISLANDS: usize = 4;
+    const N_BRIDGES: usize = 7;
+    const BRIDGES: [(usize, usize); 7] = [(0, 1), (0, 1), (0, 2), (0, 3), (0, 3), (1, 2), (2, 3)];
+
+    pub type Matrix = [[usize; N_ISLANDS]; N_ISLANDS];
+
+    const EMPTY_MATRIX: Matrix = [[0; N_ISLANDS]; N_ISLANDS];
+
+    const fn build(mut matrix: Matrix, (to, from): (usize, usize)) -> Matrix {
+        matrix[to][from] += 1;
+        matrix[from][to] += 1;
+        matrix
+    }
+
+    pub const fn walk(mut matrix: Matrix, from: usize, to: usize) -> Matrix {
+        matrix[from][to] -= 1;
+        matrix[to][from] -= 1;
+        matrix
+    }
+
+    const fn to_matrix(bridges: [(usize, usize); N_BRIDGES]) -> Matrix {
+        let matrix = EMPTY_MATRIX;
+
+        let matrix = build(matrix, bridges[0]);
+        let matrix = build(matrix, bridges[1]);
+        let matrix = build(matrix, bridges[2]);
+        let matrix = build(matrix, bridges[3]);
+        let matrix = build(matrix, bridges[4]);
+        let matrix = build(matrix, bridges[5]);
+        let matrix = build(matrix, bridges[6]);
+
+        matrix
+    }
+
+    const BRIDGE_MATRIX: [[usize; N_ISLANDS]; N_ISLANDS] = to_matrix(BRIDGES);
+
+    pub struct Walk<const CURRENT: usize, const REMAINING: Matrix> {
+        _p: (),
+    }
+
+    impl Walk<0, BRIDGE_MATRIX> {
+        pub const fn new() -> Self {
+            Self { _p: () }
+        }
+    }
+
+    impl<const CURRENT: usize, const REMAINING: Matrix> Walk<CURRENT, REMAINING> {
+        pub fn proceed_to<const NEXT: usize>(
+            self,
+        ) -> Walk<NEXT, { walk(REMAINING, CURRENT, NEXT) }> {
+            Walk { _p: () }
+        }
+    }
+
+    pub struct Trophy {
+        _p: (),
+    }
+
+    impl<const CURRENT: usize> Walk<CURRENT, EMPTY_MATRIX> {
+        pub fn collect_prize(self) -> Trophy {
+            Trophy { _p: () }
+        }
+    }
+}
+
+pub use lib::{Trophy, Walk};
+
+fn main() {
+    // Example, taking the first step
+    let _ = Walk::new().proceed_to::<1>();
+
+    // Don't be so eager to collect the trophy
+    // let trophy = Walk::new()
+    //     .proceed_to::<1>()
+    //     .proceed_to::<0>()
+    //     .collect_prize();
+
+    // Can't just make a Trophy out of thin air, you must earn it
+    // let trophy: Trophy = Trophy { _p: () };
+
+    // Can you collect the Trophy?
+}
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.full.stderr b/src/test/ui/const-generics/issues/issue-67945-3.full.stderr
new file mode 100644
index 00000000000..d3d9452d316
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-67945-3.full.stderr
@@ -0,0 +1,16 @@
+error: overly complex generic constant
+  --> $DIR/issue-67945-3.rs:10:13
+   |
+LL |       A: [(); {
+   |  _____________^
+LL | |         let x: Option<S> = None;
+LL | |
+LL | |         0
+LL | |     }],
+   | |_____^ blocks are not supported in generic constant
+   |
+   = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.min.stderr b/src/test/ui/const-generics/issues/issue-67945-3.min.stderr
new file mode 100644
index 00000000000..8e6b4b20409
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-67945-3.min.stderr
@@ -0,0 +1,21 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-3.rs:11:23
+   |
+LL |         let x: Option<S> = None;
+   |                       ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-3.rs:9: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 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.rs b/src/test/ui/const-generics/issues/issue-67945-3.rs
new file mode 100644
index 00000000000..fd8a393effe
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-67945-3.rs
@@ -0,0 +1,17 @@
+// Regression test for
+// https://github.com/rust-lang/rust/issues/67945#issuecomment-572617285
+// Make sure we don't emit an E0277 error.
+
+// revisions: full min
+#![cfg_attr(full, feature(generic_const_exprs))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+struct Bug<S> { //[min]~ ERROR: parameter `S` is never used
+    A: [(); { //[full]~ ERROR: overly complex generic constant
+        let x: Option<S> = None;
+        //[min]~^ ERROR: generic parameters may not be used in const operations
+        0
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67945-4.full.stderr b/src/test/ui/const-generics/issues/issue-67945-4.full.stderr
new file mode 100644
index 00000000000..9604eb35d02
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-67945-4.full.stderr
@@ -0,0 +1,16 @@
+error: overly complex generic constant
+  --> $DIR/issue-67945-4.rs:9:13
+   |
+LL |       A: [(); {
+   |  _____________^
+LL | |         let x: Option<Box<S>> = None;
+LL | |
+LL | |         0
+LL | |     }],
+   | |_____^ blocks are not supported in generic constant
+   |
+   = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-67945-4.min.stderr b/src/test/ui/const-generics/issues/issue-67945-4.min.stderr
new file mode 100644
index 00000000000..f9520872ddd
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-67945-4.min.stderr
@@ -0,0 +1,21 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-67945-4.rs:10:27
+   |
+LL |         let x: Option<Box<S>> = None;
+   |                           ^ cannot perform const operation using `S`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error[E0392]: parameter `S` is never used
+  --> $DIR/issue-67945-4.rs:8: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 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/issues/issue-67945-4.rs b/src/test/ui/const-generics/issues/issue-67945-4.rs
new file mode 100644
index 00000000000..9a27bf09f88
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-67945-4.rs
@@ -0,0 +1,16 @@
+// Regression test for
+// https://github.com/rust-lang/rust/issues/67945#issuecomment-572617285
+
+// revisions: full min
+#![cfg_attr(full, feature(generic_const_exprs))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+struct Bug<S> { //[min]~ ERROR: parameter `S` is never used
+    A: [(); { //[full]~ ERROR: overly complex generic constant
+        let x: Option<Box<S>> = None;
+        //[min]~^ ERROR: generic parameters may not be used in const operations
+        0
+    }],
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr
index 8705a39fa4b..98931a3936f 100644
--- a/src/test/ui/const-generics/issues/issue-83765.stderr
+++ b/src/test/ui/const-generics/issues/issue-83765.stderr
@@ -10,7 +10,11 @@ note: ...which requires checking if `TensorDimension` fulfills its obligations..
 LL | trait TensorDimension {
    | ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle
-   = note: cycle used when normalizing `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`
+note: cycle used when checking if `TensorDimension` fulfills its obligations
+  --> $DIR/issue-83765.rs:4:1
+   |
+LL | trait TensorDimension {
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
index 5b0b9aa9666..023d5ea34d8 100644
--- a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
+++ b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
@@ -243,7 +243,7 @@ error[E0080]: could not evaluate static initializer
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+   |                  ptr_offset_from_unsigned called on pointers into different allocations
    |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
   ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
@@ -262,7 +262,7 @@ error[E0080]: could not evaluate static initializer
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+   |                  ptr_offset_from_unsigned called on pointers into different allocations
    |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
   ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
index b75e6c50246..ed89c253d53 100644
--- a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
+++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
@@ -243,7 +243,7 @@ error[E0080]: could not evaluate static initializer
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+   |                  ptr_offset_from_unsigned called on pointers into different allocations
    |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
   ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
@@ -262,7 +262,7 @@ error[E0080]: could not evaluate static initializer
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+   |                  ptr_offset_from_unsigned called on pointers into different allocations
    |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
   ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr
index 678714d0e05..52b173c4d04 100644
--- a/src/test/ui/const-ptr/out_of_bounds_read.stderr
+++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr
@@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |         |
-   |         memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
   ::: $DIR/out_of_bounds_read.rs:12:33
@@ -18,7 +18,7 @@ error[E0080]: evaluation of constant value failed
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |         |
-   |         memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
   ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -37,7 +37,7 @@ error[E0080]: evaluation of constant value failed
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |         |
-   |         memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
   ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.rs b/src/test/ui/consts/const-eval/const-eval-query-stack.rs
index e73e54ff5f1..c9460498951 100644
--- a/src/test/ui/consts/const-eval/const-eval-query-stack.rs
+++ b/src/test/ui/consts/const-eval/const-eval-query-stack.rs
@@ -1,5 +1,4 @@
 // compile-flags: -Ztreat-err-as-bug=2
-//~^ ERROR 1:1: 1:1: ty::ConstKind::Error constructed but no error reported
 // build-fail
 // failure-status: 101
 // rustc-env:RUST_BACKTRACE=1
@@ -23,5 +22,7 @@ const X: i32 = 1 / 0; //~WARN any use of this value will cause an error
 fn main() {
     let x: &'static i32 = &X;
     //~^ ERROR evaluation of constant value failed
+    //~| ERROR erroneous constant used
+    //~| WARNING this was previously accepted by the compiler
     println!("x={}", x);
 }
diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
index 8bd5c08dc46..b74d5a2722b 100644
--- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
@@ -1,5 +1,5 @@
 warning: any use of this value will cause an error
-  --> $DIR/const-eval-query-stack.rs:20:16
+  --> $DIR/const-eval-query-stack.rs:19:16
    |
 LL | const X: i32 = 1 / 0;
    | ---------------^^^^^-
@@ -7,7 +7,7 @@ LL | const X: i32 = 1 / 0;
    |                attempt to divide `1_i32` by zero
    |
 note: the lint level is defined here
-  --> $DIR/const-eval-query-stack.rs:19:8
+  --> $DIR/const-eval-query-stack.rs:18:8
    |
 LL | #[warn(const_err)]
    |        ^^^^^^^^^
@@ -15,13 +15,23 @@ LL | #[warn(const_err)]
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-eval-query-stack.rs:24:28
+  --> $DIR/const-eval-query-stack.rs:23:28
    |
 LL |     let x: &'static i32 = &X;
    |                            ^ referenced constant has errors
+
+error: erroneous constant used
+  --> $DIR/const-eval-query-stack.rs:23:27
+   |
+LL |     let x: &'static i32 = &X;
+   |                           ^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 query stack during panic:
-#0 [try_normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]`
-#1 [mir_drops_elaborated_and_const_checked] elaborating drops for `main`
-#2 [optimized_mir] optimizing MIR for `main`
-#3 [collect_and_partition_mono_items] collect_and_partition_mono_items
+#0 [mir_drops_elaborated_and_const_checked] elaborating drops for `main`
+#1 [optimized_mir] optimizing MIR for `main`
+#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
 end of query stack
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
index a5e3d078bd0..a78cff11589 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
@@ -149,8 +149,19 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
                ╾─allocN─╼                                     │ ╾──╼
            }
 
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:87:40
+   |
+LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
+   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                        |
+   |                                        referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:93:1
+  --> $DIR/ub-wide-ptr.rs:95:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered 0x03, but expected a boolean
@@ -160,8 +171,19 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3
                ╾allocN─╼                                     │ ╾──╼
            }
 
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:95:42
+   |
+LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                          |
+   |                                          referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:96:1
+  --> $DIR/ub-wide-ptr.rs:100:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.1[0]: encountered 0x03, but expected a boolean
@@ -171,8 +193,19 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran
                ╾allocN─╼                                     │ ╾──╼
            }
 
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:100:42
+   |
+LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                          |
+   |                                          referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:103:1
+  --> $DIR/ub-wide-ptr.rs:109:1
    |
 LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
 LL | |
@@ -187,7 +220,7 @@ LL | | };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:111:1
+  --> $DIR/ub-wide-ptr.rs:117:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
@@ -198,7 +231,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:114:1
+  --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
@@ -209,7 +242,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:117:1
+  --> $DIR/ub-wide-ptr.rs:123:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer
@@ -220,7 +253,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:119:1
+  --> $DIR/ub-wide-ptr.rs:125:1
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer
@@ -231,7 +264,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:121:1
+  --> $DIR/ub-wide-ptr.rs:127:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -242,7 +275,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:123:1
+  --> $DIR/ub-wide-ptr.rs:129:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -253,7 +286,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:125:1
+  --> $DIR/ub-wide-ptr.rs:131:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -264,7 +297,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:129:1
+  --> $DIR/ub-wide-ptr.rs:135:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
@@ -275,7 +308,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:133:1
+  --> $DIR/ub-wide-ptr.rs:139:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer
@@ -286,7 +319,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:135:1
+  --> $DIR/ub-wide-ptr.rs:141:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
@@ -297,17 +330,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:141:5
+  --> $DIR/ub-wide-ptr.rs:147:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:145:5
+  --> $DIR/ub-wide-ptr.rs:151:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 12 bytes starting at offset N is out-of-bounds
 
-error: aborting due to 29 previous errors
+error: aborting due to 32 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
index a3ba62ca87b..69a61d9caed 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
@@ -149,8 +149,19 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
                ╾───────allocN───────╼                         │ ╾──────╼
            }
 
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:87:40
+   |
+LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
+   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                        |
+   |                                        referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:93:1
+  --> $DIR/ub-wide-ptr.rs:95:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered 0x03, but expected a boolean
@@ -160,8 +171,19 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3
                ╾──────allocN───────╼                         │ ╾──────╼
            }
 
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:95:42
+   |
+LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                          |
+   |                                          referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:96:1
+  --> $DIR/ub-wide-ptr.rs:100:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.1[0]: encountered 0x03, but expected a boolean
@@ -171,8 +193,19 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran
                ╾──────allocN───────╼                         │ ╾──────╼
            }
 
+error: any use of this value will cause an error
+  --> $DIR/ub-wide-ptr.rs:100:42
+   |
+LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
+   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                          |
+   |                                          referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:103:1
+  --> $DIR/ub-wide-ptr.rs:109:1
    |
 LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
 LL | |
@@ -187,7 +220,7 @@ LL | | };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:111:1
+  --> $DIR/ub-wide-ptr.rs:117:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
@@ -198,7 +231,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:114:1
+  --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
@@ -209,7 +242,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:117:1
+  --> $DIR/ub-wide-ptr.rs:123:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer
@@ -220,7 +253,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:119:1
+  --> $DIR/ub-wide-ptr.rs:125:1
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer
@@ -231,7 +264,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:121:1
+  --> $DIR/ub-wide-ptr.rs:127:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -242,7 +275,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:123:1
+  --> $DIR/ub-wide-ptr.rs:129:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -253,7 +286,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:125:1
+  --> $DIR/ub-wide-ptr.rs:131:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -264,7 +297,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:129:1
+  --> $DIR/ub-wide-ptr.rs:135:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
@@ -275,7 +308,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:133:1
+  --> $DIR/ub-wide-ptr.rs:139:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer
@@ -286,7 +319,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:135:1
+  --> $DIR/ub-wide-ptr.rs:141:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
@@ -297,17 +330,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:141:5
+  --> $DIR/ub-wide-ptr.rs:147:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:145:5
+  --> $DIR/ub-wide-ptr.rs:151:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 24 bytes starting at offset N is out-of-bounds
 
-error: aborting due to 29 previous errors
+error: aborting due to 32 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
index 763e6ba2967..f2e5738f88c 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
@@ -86,15 +86,21 @@ const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
 // bad data *inside* the slice
 const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
 //~^ ERROR it is undefined behavior to use this value
+//~| ERROR any use of this value will cause an error
+//~| WARNING this was previously accepted
 
 // good MySliceBool
 const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]);
 // bad: sized field is not okay
 const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
 //~^ ERROR it is undefined behavior to use this value
+//~| ERROR any use of this value will cause an error
+//~| WARNING this was previously accepted
 // bad: unsized part is not okay
 const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
 //~^ ERROR it is undefined behavior to use this value
+//~| ERROR any use of this value will cause an error
+//~| WARNING this was previously accepted
 
 // # raw slice
 const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok
diff --git a/src/test/ui/consts/const-float-bits-reject-conv.rs b/src/test/ui/consts/const-float-bits-reject-conv.rs
index 122f5b97eee..b156ded4a6c 100644
--- a/src/test/ui/consts/const-float-bits-reject-conv.rs
+++ b/src/test/ui/consts/const-float-bits-reject-conv.rs
@@ -28,14 +28,22 @@ fn f32() {
     const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
 
     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+    //~^ ERROR any use of this value will cause an error
+    //~| WARNING this was previously accepted
     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+    //~^ ERROR any use of this value will cause an error
+    //~| WARNING this was previously accepted
 
     // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
     // In practice, this seems to only cause a problem on x86, since the most widely used calling
     // convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
     if !cfg!(target_arch = "x86") {
         const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+        //~^ ERROR any use of this value will cause an error
+        //~| WARNING this was previously accepted
         const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+        //~^ ERROR any use of this value will cause an error
+        //~| WARNING this was previously accepted
     }
 }
 
@@ -47,12 +55,20 @@ fn f64() {
     const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
 
     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+    //~^ ERROR any use of this value will cause an error
+    //~| WARNING this was previously accepted
     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+    //~^ ERROR any use of this value will cause an error
+    //~| WARNING this was previously accepted
 
     // See comment above.
     if !cfg!(target_arch = "x86") {
         const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+        //~^ ERROR any use of this value will cause an error
+        //~| WARNING this was previously accepted
         const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+        //~^ ERROR any use of this value will cause an error
+        //~| WARNING this was previously accepted
     }
 }
 
diff --git a/src/test/ui/consts/const-float-bits-reject-conv.stderr b/src/test/ui/consts/const-float-bits-reject-conv.stderr
index b39e8819701..f3fd098e848 100644
--- a/src/test/ui/consts/const-float-bits-reject-conv.stderr
+++ b/src/test/ui/consts/const-float-bits-reject-conv.stderr
@@ -56,6 +56,55 @@ LL |     const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:30:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:33:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:41:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:44:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
@@ -78,10 +127,10 @@ LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 LL |     called_in_const.call_once(arg)
    |     ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:46:30
+  ::: $DIR/const-float-bits-reject-conv.rs:54:30
    |
 LL |     const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
-   |                              ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:46:30
+   |                              ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:54:30
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -107,13 +156,61 @@ LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 LL |     called_in_const.call_once(arg)
    |     ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:47:30
+  ::: $DIR/const-float-bits-reject-conv.rs:55:30
    |
 LL |     const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
-   |                              ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:47:30
+   |                              ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:55:30
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 4 previous errors
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:57:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:60:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:66:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:69:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-integer-bool-ops.rs b/src/test/ui/consts/const-integer-bool-ops.rs
index 35915a7a606..6924956bdf7 100644
--- a/src/test/ui/consts/const-integer-bool-ops.rs
+++ b/src/test/ui/consts/const-integer-bool-ops.rs
@@ -6,6 +6,7 @@ const X: usize = 42 && 39;
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR: [i32; X] = [99; 34];
+//~^ ERROR evaluation of constant value failed
 
 const X1: usize = 42 || 39;
 //~^ ERROR mismatched types
@@ -15,6 +16,7 @@ const X1: usize = 42 || 39;
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR1: [i32; X1] = [99; 47];
+//~^ ERROR evaluation of constant value failed
 
 const X2: usize = -42 || -39;
 //~^ ERROR mismatched types
@@ -24,6 +26,7 @@ const X2: usize = -42 || -39;
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR2: [i32; X2] = [99; 18446744073709551607];
+//~^ ERROR evaluation of constant value failed
 
 const X3: usize = -42 && -39;
 //~^ ERROR mismatched types
@@ -33,36 +36,43 @@ const X3: usize = -42 && -39;
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR3: [i32; X3] = [99; 6];
+//~^ ERROR evaluation of constant value failed
 
 const Y: usize = 42.0 == 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR: [i32; Y] = [99; 1];
+//~^ ERROR evaluation of constant value failed
 
 const Y1: usize = 42.0 >= 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR1: [i32; Y1] = [99; 1];
+//~^ ERROR evaluation of constant value failed
 
 const Y2: usize = 42.0 <= 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR2: [i32; Y2] = [99; 1];
+//~^ ERROR evaluation of constant value failed
 
 const Y3: usize = 42.0 > 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR3: [i32; Y3] = [99; 0];
+//~^ ERROR evaluation of constant value failed
 
 const Y4: usize = 42.0 < 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR4: [i32; Y4] = [99; 0];
+//~^ ERROR evaluation of constant value failed
 
 const Y5: usize = 42.0 != 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR5: [i32; Y5] = [99; 0];
+//~^ ERROR evaluation of constant value failed
 
 fn main() {
     let _ = ARR;
diff --git a/src/test/ui/consts/const-integer-bool-ops.stderr b/src/test/ui/consts/const-integer-bool-ops.stderr
index 4e503e5a5c0..9001fefd102 100644
--- a/src/test/ui/consts/const-integer-bool-ops.stderr
+++ b/src/test/ui/consts/const-integer-bool-ops.stderr
@@ -16,96 +16,157 @@ error[E0308]: mismatched types
 LL | const X: usize = 42 && 39;
    |                  ^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:8:18
+   |
+LL | const ARR: [i32; X] = [99; 34];
+   |                  ^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:10:19
+  --> $DIR/const-integer-bool-ops.rs:11:19
    |
 LL | const X1: usize = 42 || 39;
    |                   ^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:10:25
+  --> $DIR/const-integer-bool-ops.rs:11:25
    |
 LL | const X1: usize = 42 || 39;
    |                         ^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:10:19
+  --> $DIR/const-integer-bool-ops.rs:11:19
    |
 LL | const X1: usize = 42 || 39;
    |                   ^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:18:19
+   |
+LL | const ARR1: [i32; X1] = [99; 47];
+   |                   ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:19:19
+  --> $DIR/const-integer-bool-ops.rs:21:19
    |
 LL | const X2: usize = -42 || -39;
    |                   ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:19:26
+  --> $DIR/const-integer-bool-ops.rs:21:26
    |
 LL | const X2: usize = -42 || -39;
    |                          ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:19:19
+  --> $DIR/const-integer-bool-ops.rs:21:19
    |
 LL | const X2: usize = -42 || -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
-error[E0308]: mismatched types
+error[E0080]: evaluation of constant value failed
   --> $DIR/const-integer-bool-ops.rs:28:19
    |
+LL | const ARR2: [i32; X2] = [99; 18446744073709551607];
+   |                   ^^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:31:19
+   |
 LL | const X3: usize = -42 && -39;
    |                   ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:28:26
+  --> $DIR/const-integer-bool-ops.rs:31:26
    |
 LL | const X3: usize = -42 && -39;
    |                          ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:28:19
+  --> $DIR/const-integer-bool-ops.rs:31:19
    |
 LL | const X3: usize = -42 && -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:38:19
+   |
+LL | const ARR3: [i32; X3] = [99; 6];
+   |                   ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:37:18
+  --> $DIR/const-integer-bool-ops.rs:41:18
    |
 LL | const Y: usize = 42.0 == 42.0;
    |                  ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:44:19
+   |
+LL | const ARRR: [i32; Y] = [99; 1];
+   |                   ^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:42:19
+  --> $DIR/const-integer-bool-ops.rs:47:19
    |
 LL | const Y1: usize = 42.0 >= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:50:20
+   |
+LL | const ARRR1: [i32; Y1] = [99; 1];
+   |                    ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:47:19
+  --> $DIR/const-integer-bool-ops.rs:53:19
    |
 LL | const Y2: usize = 42.0 <= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:56:20
+   |
+LL | const ARRR2: [i32; Y2] = [99; 1];
+   |                    ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:52:19
+  --> $DIR/const-integer-bool-ops.rs:59:19
    |
 LL | const Y3: usize = 42.0 > 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:62:20
+   |
+LL | const ARRR3: [i32; Y3] = [99; 0];
+   |                    ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:57:19
+  --> $DIR/const-integer-bool-ops.rs:65:19
    |
 LL | const Y4: usize = 42.0 < 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:68:20
+   |
+LL | const ARRR4: [i32; Y4] = [99; 0];
+   |                    ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:62:19
+  --> $DIR/const-integer-bool-ops.rs:71:19
    |
 LL | const Y5: usize = 42.0 != 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-error: aborting due to 18 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:74:20
+   |
+LL | const ARRR5: [i32; Y5] = [99; 0];
+   |                    ^^ referenced constant has errors
+
+error: aborting due to 28 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0080, E0308.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr
index 61b00be345f..0f420ae1b6b 100644
--- a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr
+++ b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr
@@ -19,7 +19,13 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
 LL | const S: &'static mut str = &mut " hello ";
    |                             ^^^^^^^^^^^^^^ cannot borrow as mutable
 
-error: aborting due to 3 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-76510.rs:11:70
+   |
+LL |         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+   |                                                                      ^ referenced constant has errors
+
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0596, E0658, E0764.
-For more information about an error, try `rustc --explain E0596`.
+Some errors have detailed explanations: E0080, E0596, E0658, E0764.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr
index 61b00be345f..0f420ae1b6b 100644
--- a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr
+++ b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr
@@ -19,7 +19,13 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
 LL | const S: &'static mut str = &mut " hello ";
    |                             ^^^^^^^^^^^^^^ cannot borrow as mutable
 
-error: aborting due to 3 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-76510.rs:11:70
+   |
+LL |         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+   |                                                                      ^ referenced constant has errors
+
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0596, E0658, E0764.
-For more information about an error, try `rustc --explain E0596`.
+Some errors have detailed explanations: E0080, E0596, E0658, E0764.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs
index 143d2fb6b9a..08cf64ee330 100644
--- a/src/test/ui/consts/const-mut-refs/issue-76510.rs
+++ b/src/test/ui/consts/const-mut-refs/issue-76510.rs
@@ -9,6 +9,7 @@ const S: &'static mut str = &mut " hello ";
 
 const fn trigger() -> [(); unsafe {
         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+        //~^ ERROR evaluation of constant value failed
         0
     }] {
     [(); 0]
diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr
index 1067eb003f7..46f02ce8a45 100644
--- a/src/test/ui/consts/const-size_of-cycle.stderr
+++ b/src/test/ui/consts/const-size_of-cycle.stderr
@@ -1,10 +1,10 @@
-error[E0391]: cycle detected when simplifying constant for the type system `Foo::bytes::{constant#0}`
+error[E0391]: cycle detected when evaluating type-level constant
   --> $DIR/const-size_of-cycle.rs:4:17
    |
 LL |     bytes: [u8; std::mem::size_of::<Foo>()]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: ...which requires simplifying constant for the type system `Foo::bytes::{constant#0}`...
+note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
   --> $DIR/const-size_of-cycle.rs:4:17
    |
 LL |     bytes: [u8; std::mem::size_of::<Foo>()]
@@ -17,7 +17,7 @@ LL |     bytes: [u8; std::mem::size_of::<Foo>()]
    = note: ...which requires computing layout of `Foo`...
    = note: ...which requires computing layout of `[u8; _]`...
    = note: ...which requires normalizing `[u8; _]`...
-   = note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
+   = note: ...which again requires evaluating type-level constant, completing the cycle
 note: cycle used when checking that `Foo` is well-formed
   --> $DIR/const-size_of-cycle.rs:3:1
    |
diff --git a/src/test/ui/consts/const-tup-index-span.rs b/src/test/ui/consts/const-tup-index-span.rs
index 8057d64369a..763263c6aeb 100644
--- a/src/test/ui/consts/const-tup-index-span.rs
+++ b/src/test/ui/consts/const-tup-index-span.rs
@@ -4,6 +4,7 @@ const TUP: (usize,) = 5usize << 64;
 //~^ ERROR mismatched types
 //~| expected tuple, found `usize`
 const ARR: [i32; TUP.0] = [];
+//~^ ERROR evaluation of constant value failed
 
 fn main() {
 }
diff --git a/src/test/ui/consts/const-tup-index-span.stderr b/src/test/ui/consts/const-tup-index-span.stderr
index d301f8c4054..b178e05e27a 100644
--- a/src/test/ui/consts/const-tup-index-span.stderr
+++ b/src/test/ui/consts/const-tup-index-span.stderr
@@ -11,6 +11,13 @@ help: use a trailing comma to create a tuple with one element
 LL | const TUP: (usize,) = (5usize << 64,);
    |                       +            ++
 
-error: aborting due to previous error
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-tup-index-span.rs:6:18
+   |
+LL | const ARR: [i32; TUP.0] = [];
+   |                  ^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0080, E0308.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr
index 884ae71197b..38c38d1ae67 100644
--- a/src/test/ui/consts/invalid-union.32bit.stderr
+++ b/src/test/ui/consts/invalid-union.32bit.stderr
@@ -6,7 +6,7 @@ LL | fn main() {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc8──╼                                     │ ╾──╼
+               ╾─alloc7──╼                                     │ ╾──╼
            }
 
 error: erroneous constant used
diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr
index 9df1a89694e..6bfa97a2fde 100644
--- a/src/test/ui/consts/invalid-union.64bit.stderr
+++ b/src/test/ui/consts/invalid-union.64bit.stderr
@@ -6,7 +6,7 @@ LL | fn main() {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc8────────╼                         │ ╾──────╼
+               ╾───────alloc7────────╼                         │ ╾──────╼
            }
 
 error: erroneous constant used
diff --git a/src/test/ui/consts/issue-36163.stderr b/src/test/ui/consts/issue-36163.stderr
index 113f86cf0f9..9ac6c984cb0 100644
--- a/src/test/ui/consts/issue-36163.stderr
+++ b/src/test/ui/consts/issue-36163.stderr
@@ -1,48 +1,20 @@
-error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}`
+error[E0391]: cycle detected when const-evaluating + checking `Foo::B::{constant#0}`
   --> $DIR/issue-36163.rs:4:9
    |
 LL |     B = A,
    |         ^
    |
-note: ...which requires simplifying constant for the type system `Foo::B::{constant#0}`...
-  --> $DIR/issue-36163.rs:4:9
-   |
-LL |     B = A,
-   |         ^
-note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`...
-  --> $DIR/issue-36163.rs:4:9
-   |
-LL |     B = A,
-   |         ^
-   = note: ...which requires normalizing `A`...
-note: ...which requires simplifying constant for the type system `A`...
-  --> $DIR/issue-36163.rs:1:1
-   |
-LL | const A: isize = Foo::B as isize;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `A`...
-  --> $DIR/issue-36163.rs:1:1
-   |
-LL | const A: isize = Foo::B as isize;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `A`...
   --> $DIR/issue-36163.rs:1:1
    |
 LL | const A: isize = Foo::B as isize;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `A`...
-   = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-36163.rs:1:1
+   = note: ...which again requires const-evaluating + checking `Foo::B::{constant#0}`, completing the cycle
+note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}`
+  --> $DIR/issue-36163.rs:4:9
    |
-LL | / const A: isize = Foo::B as isize;
-LL | |
-LL | | enum Foo {
-LL | |     B = A,
-LL | | }
-LL | |
-LL | | fn main() {}
-   | |____________^
+LL |     B = A,
+   |         ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-39974.rs b/src/test/ui/consts/issue-39974.rs
index 503647ef4a8..503647ef4a8 100644
--- a/src/test/ui/issues/issue-39974.rs
+++ b/src/test/ui/consts/issue-39974.rs
diff --git a/src/test/ui/issues/issue-39974.stderr b/src/test/ui/consts/issue-39974.stderr
index 56365e51e0a..56365e51e0a 100644
--- a/src/test/ui/issues/issue-39974.stderr
+++ b/src/test/ui/consts/issue-39974.stderr
diff --git a/src/test/ui/consts/issue-44415.rs b/src/test/ui/consts/issue-44415.rs
index 71e764620d1..d93b451be45 100644
--- a/src/test/ui/consts/issue-44415.rs
+++ b/src/test/ui/consts/issue-44415.rs
@@ -4,7 +4,7 @@ use std::intrinsics;
 
 struct Foo {
     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-    //~^ ERROR cycle detected when simplifying constant for the type system
+    //~^ ERROR cycle detected when evaluating type-level constant
     x: usize,
 }
 
diff --git a/src/test/ui/consts/issue-44415.stderr b/src/test/ui/consts/issue-44415.stderr
index 9e3db5ce9a4..c085beb0ea5 100644
--- a/src/test/ui/consts/issue-44415.stderr
+++ b/src/test/ui/consts/issue-44415.stderr
@@ -1,10 +1,10 @@
-error[E0391]: cycle detected when simplifying constant for the type system `Foo::bytes::{constant#0}`
+error[E0391]: cycle detected when evaluating type-level constant
   --> $DIR/issue-44415.rs:6:17
    |
 LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
    |                 ^^^^^^
    |
-note: ...which requires simplifying constant for the type system `Foo::bytes::{constant#0}`...
+note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
   --> $DIR/issue-44415.rs:6:17
    |
 LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
@@ -17,7 +17,7 @@ LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
    = note: ...which requires computing layout of `Foo`...
    = note: ...which requires computing layout of `[u8; _]`...
    = note: ...which requires normalizing `[u8; _]`...
-   = note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
+   = note: ...which again requires evaluating type-level constant, completing the cycle
 note: cycle used when checking that `Foo` is well-formed
   --> $DIR/issue-44415.rs:5:1
    |
diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs
index f604f57e39d..10e368ba133 100644
--- a/src/test/ui/consts/offset_from_ub.rs
+++ b/src/test/ui/consts/offset_from_ub.rs
@@ -15,7 +15,7 @@ pub const DIFFERENT_ALLOC: usize = {
     let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
     let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
     let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed
-    //~| ptr_offset_from cannot compute offset of pointers into different allocations.
+    //~| pointers into different allocations
     offset as usize
 };
 
@@ -41,7 +41,7 @@ pub const DIFFERENT_INT: isize = { // offset_from with two different integers: l
     let ptr1 = 8 as *const u8;
     let ptr2 = 16 as *const u8;
     unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
-    //~| 0x10 is not a valid pointer
+    //~| 0x8 is not a valid pointer
 };
 
 const OUT_OF_BOUNDS_1: isize = {
@@ -50,7 +50,7 @@ const OUT_OF_BOUNDS_1: isize = {
     let end_ptr = (start_ptr).wrapping_add(length);
     // First ptr is out of bounds
     unsafe { ptr_offset_from(end_ptr, start_ptr) } //~ERROR evaluation of constant value failed
-    //~| pointer at offset 10 is out-of-bounds
+    //~| pointer to 10 bytes starting at offset 0 is out-of-bounds
 };
 
 const OUT_OF_BOUNDS_2: isize = {
@@ -59,7 +59,7 @@ const OUT_OF_BOUNDS_2: isize = {
     let end_ptr = (start_ptr).wrapping_add(length);
     // Second ptr is out of bounds
     unsafe { ptr_offset_from(start_ptr, end_ptr) } //~ERROR evaluation of constant value failed
-    //~| pointer at offset 10 is out-of-bounds
+    //~| pointer to 10 bytes starting at offset 0 is out-of-bounds
 };
 
 const OUT_OF_BOUNDS_SAME: isize = {
@@ -76,7 +76,7 @@ pub const DIFFERENT_ALLOC_UNSIGNED: usize = {
     let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
     let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
     let offset = unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed
-    //~| ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+    //~| pointers into different allocations
     offset as usize
 };
 
@@ -84,7 +84,7 @@ const WRONG_ORDER_UNSIGNED: usize = {
     let a = ['a', 'b', 'c'];
     let p = a.as_ptr();
     unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } //~ERROR evaluation of constant value failed
-    //~| cannot compute a negative offset, but 0 < 8
+    //~| first pointer has smaller offset than second: 0 < 8
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr
index 4c98fd72cac..eb7f1d7a6b2 100644
--- a/src/test/ui/consts/offset_from_ub.stderr
+++ b/src/test/ui/consts/offset_from_ub.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:17:27
    |
 LL |     let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from cannot compute offset of pointers into different allocations.
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from called on pointers into different allocations
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -10,7 +10,7 @@ error[E0080]: evaluation of constant value failed
 LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  out-of-bounds offset_from: 0x2a is not a valid pointer
+   |                  ptr_offset_from called on pointers into different allocations
    |                  inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
   ::: $DIR/offset_from_ub.rs:23:14
@@ -34,19 +34,19 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:43:14
    |
 LL |     unsafe { ptr_offset_from(ptr2, ptr1) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: 0x10 is not a valid pointer
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: 0x8 is not a valid pointer
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:52:14
    |
 LL |     unsafe { ptr_offset_from(end_ptr, start_ptr) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc20 has size 4, so pointer at offset 10 is out-of-bounds
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:61:14
    |
 LL |     unsafe { ptr_offset_from(start_ptr, end_ptr) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc23 has size 4, so pointer at offset 10 is out-of-bounds
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc23 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:69:14
@@ -58,13 +58,13 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:78:27
    |
 LL |     let offset = unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) };
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from_unsigned cannot compute offset of pointers into different allocations.
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from_unsigned called on pointers into different allocations
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:86:14
    |
 LL |     unsafe { ptr_offset_from_unsigned(p, p.add(2) ) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from_unsigned cannot compute a negative offset, but 0 < 8
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from_unsigned called when first pointer has smaller offset than second: 0 < 8
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/deprecation/rustc_deprecated.rs b/src/test/ui/deprecation/rustc_deprecated.rs
deleted file mode 100644
index b87bd069c60..00000000000
--- a/src/test/ui/deprecation/rustc_deprecated.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile-flags: --crate-type=lib
-
-#![feature(staged_api)]
-#![stable(since = "1.0.0", feature = "rust1")]
-
-#[rustc_deprecated( //~ ERROR `#[rustc_deprecated]` has been removed
-    //~^ HELP use `#[deprecated]` instead
-    since = "1.100.0",
-    reason = "text" //~ ERROR `reason` has been renamed
-    //~^ HELP use `note` instead
-)]
-#[stable(feature = "rust1", since = "1.0.0")]
-fn foo() {}
diff --git a/src/test/ui/deprecation/rustc_deprecated.stderr b/src/test/ui/deprecation/rustc_deprecated.stderr
deleted file mode 100644
index 4413e196f09..00000000000
--- a/src/test/ui/deprecation/rustc_deprecated.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error: `#[rustc_deprecated]` has been removed
-  --> $DIR/rustc_deprecated.rs:6:1
-   |
-LL | / #[rustc_deprecated(
-LL | |
-LL | |     since = "1.100.0",
-LL | |     reason = "text"
-LL | |
-LL | | )]
-   | |__^
-   |
-   = help: use `#[deprecated]` instead
-
-error: `reason` has been renamed
-  --> $DIR/rustc_deprecated.rs:9:5
-   |
-LL |     reason = "text"
-   |     ^^^^^^^^^^^^^^^ help: use `note` instead: `note = "text"`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/destructure-trait-ref.stderr b/src/test/ui/destructure-trait-ref.stderr
index 302917ca02e..1291517928e 100644
--- a/src/test/ui/destructure-trait-ref.stderr
+++ b/src/test/ui/destructure-trait-ref.stderr
@@ -23,10 +23,14 @@ LL |     let &&x = &1isize as &dyn T;
    |          ^^   ----------------- this expression has type `&dyn T`
    |          |
    |          expected trait object `dyn T`, found reference
-   |          help: you can probably remove the explicit borrow: `x`
    |
    = note: expected trait object `dyn T`
                  found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let &&x = &1isize as &dyn T;
+LL +     let &x = &1isize as &dyn T;
+   | 
 
 error[E0308]: mismatched types
   --> $DIR/destructure-trait-ref.rs:36:11
@@ -35,10 +39,14 @@ LL |     let &&&x = &(&1isize as &dyn T);
    |           ^^   -------------------- this expression has type `&&dyn T`
    |           |
    |           expected trait object `dyn T`, found reference
-   |           help: you can probably remove the explicit borrow: `x`
    |
    = note: expected trait object `dyn T`
                  found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let &&&x = &(&1isize as &dyn T);
+LL +     let &&x = &(&1isize as &dyn T);
+   | 
 
 error[E0308]: mismatched types
   --> $DIR/destructure-trait-ref.rs:40:13
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
index 609a5efd46f..3ccc14bba54 100644
--- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
+++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
@@ -25,10 +25,16 @@ LL |         println!("Then when?");
 error: expected `{`, found `;`
   --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:31
    |
-LL |     if not  // lack of braces is [sic]
-   |     -- this `if` expression has a condition, but no block
 LL |         println!("Then when?");
    |                               ^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:19:8
+   |
+LL |       if not  // lack of braces is [sic]
+   |  ________^
+LL | |         println!("Then when?");
+   | |______________________________^
 
 error: unexpected `2` after identifier
   --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24
diff --git a/src/test/ui/expr/if/if-without-block.rs b/src/test/ui/expr/if/if-without-block.rs
index 8a4c59f3261..5add9dfda4b 100644
--- a/src/test/ui/expr/if/if-without-block.rs
+++ b/src/test/ui/expr/if/if-without-block.rs
@@ -1,9 +1,7 @@
 fn main() {
     let n = 1;
     if 5 == {
-    //~^ NOTE this `if` expression has a condition, but no block
+    //~^ ERROR this `if` expression is missing a block after the condition
         println!("five");
     }
 }
-//~^ ERROR expected `{`, found `}`
-//~| NOTE expected `{`
diff --git a/src/test/ui/expr/if/if-without-block.stderr b/src/test/ui/expr/if/if-without-block.stderr
index d3f6ca07617..2d1ee04ce09 100644
--- a/src/test/ui/expr/if/if-without-block.stderr
+++ b/src/test/ui/expr/if/if-without-block.stderr
@@ -1,17 +1,14 @@
-error: expected `{`, found `}`
-  --> $DIR/if-without-block.rs:7:1
+error: this `if` expression is missing a block after the condition
+  --> $DIR/if-without-block.rs:3:5
    |
 LL |     if 5 == {
-   |     -- this `if` expression has a condition, but no block
-...
-LL | }
-   | ^ expected `{`
+   |     ^^
    |
-help: maybe you forgot the right operand of the condition?
-  --> $DIR/if-without-block.rs:3:10
+help: this binary operation is possibly unfinished
+  --> $DIR/if-without-block.rs:3:8
    |
 LL |     if 5 == {
-   |          ^^
+   |        ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.rs b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.rs
deleted file mode 100644
index 65792a74ea4..00000000000
--- a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Needs an explicit where clause stating outlives condition. (RFC 2093)
-
-// Type T needs to outlive lifetime 'static.
-struct Foo<U> {
-    bar: Bar<U> //~ ERROR the parameter type `U` may not live long enough [E0310]
-}
-struct Bar<T: 'static> {
-    x: T,
-}
-
-
-fn main() { }
diff --git a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
deleted file mode 100644
index 7ffebab4153..00000000000
--- a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0310]: the parameter type `U` may not live long enough
-  --> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:10
-   |
-LL |     bar: Bar<U>
-   |          ^^^^^^ ...so that the type `U` will meet its required lifetime bounds...
-   |
-note: ...that is required by this bound
-  --> $DIR/feature-gate-infer_static_outlives_requirements.rs:7:15
-   |
-LL | struct Bar<T: 'static> {
-   |               ^^^^^^^
-help: consider adding an explicit lifetime bound...
-   |
-LL | struct Foo<U: 'static> {
-   |             +++++++++
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index d8d2eca570e..8db12e55d25 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -69,7 +69,6 @@
 #![link_section = "1800"]
 //~^ WARN attribute should be applied to a function or static
 //~^^ WARN this was previously accepted by the compiler
-// see issue-43106-gating-of-rustc_deprecated.rs
 #![must_use]
 //~^ WARN `#[must_use]` has no effect
 // see issue-43106-gating-of-stable.rs
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index 06e1bd84c8b..3f838fcf523 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -1,5 +1,5 @@
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:400:17
    |
 LL |     mod inner { #![macro_escape] }
    |                 ^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     mod inner { #![macro_escape] }
    = help: try an outer attribute: `#[macro_use]`
 
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:397:1
    |
 LL | #[macro_escape]
    | ^^^^^^^^^^^^^^^
@@ -43,151 +43,151 @@ LL | #![deny(x5100)]
    |         ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:106:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:105:8
    |
 LL | #[warn(x5400)]
    |        ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:109:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:108:25
    |
 LL |     mod inner { #![warn(x5400)] }
    |                         ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:112:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:111:12
    |
 LL |     #[warn(x5400)] fn f() { }
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:115:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:12
    |
 LL |     #[warn(x5400)] struct S;
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:118:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:12
    |
 LL |     #[warn(x5400)] type T = S;
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:121:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12
    |
 LL |     #[warn(x5400)] impl S { }
    |            ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:124:9
    |
 LL | #[allow(x5300)]
    |         ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:128:26
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:127:26
    |
 LL |     mod inner { #![allow(x5300)] }
    |                          ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:131:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:130:13
    |
 LL |     #[allow(x5300)] fn f() { }
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:134:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:13
    |
 LL |     #[allow(x5300)] struct S;
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:137:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:13
    |
 LL |     #[allow(x5300)] type T = S;
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:140:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13
    |
 LL |     #[allow(x5300)] impl S { }
    |             ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:10
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:143:10
    |
 LL | #[forbid(x5200)]
    |          ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:147:27
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:146:27
    |
 LL |     mod inner { #![forbid(x5200)] }
    |                           ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:150:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:149:14
    |
 LL |     #[forbid(x5200)] fn f() { }
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:153:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:14
    |
 LL |     #[forbid(x5200)] struct S;
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:156:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:14
    |
 LL |     #[forbid(x5200)] type T = S;
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:159:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14
    |
 LL |     #[forbid(x5200)] impl S { }
    |              ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:162:8
    |
 LL | #[deny(x5100)]
    |        ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:166:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:165:25
    |
 LL |     mod inner { #![deny(x5100)] }
    |                         ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:169:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:168:12
    |
 LL |     #[deny(x5100)] fn f() { }
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:172:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:12
    |
 LL |     #[deny(x5100)] struct S;
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:175:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:12
    |
 LL |     #[deny(x5100)] type T = S;
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:178:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12
    |
 LL |     #[deny(x5100)] impl S { }
    |            ^^^^^
 
 warning: use of deprecated attribute `crate_id`: no longer used.
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:85:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:84:1
    |
 LL | #![crate_id = "10"]
    | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute
@@ -195,13 +195,13 @@ LL | #![crate_id = "10"]
    = note: `#[warn(deprecated)]` on by default
 
 warning: use of deprecated attribute `no_start`: no longer used.
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:95:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:94:1
    |
 LL | #![no_start]
    | ^^^^^^^^^^^^ help: remove this attribute
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:199:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:1
    |
 LL | #[macro_export]
    | ^^^^^^^^^^^^^^^
@@ -213,13 +213,13 @@ LL | #![warn(unused_attributes, unknown_lints)]
    |         ^^^^^^^^^^^^^^^^^
 
 warning: `#[automatically_derived]` only has an effect on items
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:267:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:1
    |
 LL | #[automatically_derived]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:285:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:1
    |
 LL |   #[no_mangle]
    |   ^^^^^^^^^^^^
@@ -236,31 +236,31 @@ LL | | }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:1
    |
 LL | #[should_panic]
    | ^^^^^^^^^^^^^^^
 
 warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:343:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:1
    |
 LL | #[ignore]
    | ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:378:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:1
    |
 LL | #[reexport_test_harness_main = "2900"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:1
    |
 LL | #[no_std]
    | ^^^^^^^^^
 
 warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:453:1
    |
 LL |   #[cold]
    |   ^^^^^^^
@@ -277,7 +277,7 @@ LL | | }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:482:1
    |
 LL |   #[link_name = "1900"]
    |   ^^^^^^^^^^^^^^^^^^^^^
@@ -294,7 +294,7 @@ LL | | }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:1
    |
 LL |   #[link_section = "1800"]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -311,7 +311,7 @@ LL | | }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:554:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:553:1
    |
 LL |   #[link()]
    |   ^^^^^^^^^
@@ -328,55 +328,55 @@ LL | | }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: `#[must_use]` has no effect when applied to a module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:605:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:604:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:618:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617:1
    |
 LL | #[windows_subsystem = "windows"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:1
    |
 LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:658:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:677:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:1
    |
 LL | #[no_main]
    | ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:1
    |
 LL | #[no_builtins]
    | ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -432,115 +432,115 @@ LL | #![link_section = "1800"]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: `#[must_use]` has no effect when applied to a module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:73:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
    |
 LL | #![must_use]
    | ^^^^^^^^^^^^
 
 warning: `#[macro_use]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:186:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:5
    |
 LL |     #[macro_use] fn f() { }
    |     ^^^^^^^^^^^^
 
 warning: `#[macro_use]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:189:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:188:5
    |
 LL |     #[macro_use] struct S;
    |     ^^^^^^^^^^^^
 
 warning: `#[macro_use]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5
    |
 LL |     #[macro_use] type T = S;
    |     ^^^^^^^^^^^^
 
 warning: `#[macro_use]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:195:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:194:5
    |
 LL |     #[macro_use] impl S { }
    |     ^^^^^^^^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:202:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:17
    |
 LL |     mod inner { #![macro_export] }
    |                 ^^^^^^^^^^^^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:205:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5
    |
 LL |     #[macro_export] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:208:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:5
    |
 LL |     #[macro_export] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:211:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:210:5
    |
 LL |     #[macro_export] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:214:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5
    |
 LL |     #[macro_export] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[path]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:254:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5
    |
 LL |     #[path = "3800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^
 
 warning: `#[path]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:257:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5
    |
 LL |     #[path = "3800"]  struct S;
    |     ^^^^^^^^^^^^^^^^
 
 warning: `#[path]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5
    |
 LL |     #[path = "3800"] type T = S;
    |     ^^^^^^^^^^^^^^^^
 
 warning: `#[path]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:262:5
    |
 LL |     #[path = "3800"] impl S { }
    |     ^^^^^^^^^^^^^^^^
 
 warning: `#[automatically_derived]` only has an effect on items
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:270:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:17
    |
 LL |     mod inner { #![automatically_derived] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[automatically_derived]` only has an effect on items
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:273:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:272:5
    |
 LL |     #[automatically_derived] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[automatically_derived]` only has an effect on items
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:276:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:275:5
    |
 LL |     #[automatically_derived] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[automatically_derived]` only has an effect on items
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:279:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:278:5
    |
 LL |     #[automatically_derived] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:290:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:289:17
    |
 LL |     mod inner { #![no_mangle] }
    |     ------------^^^^^^^^^^^^^-- not a free function, impl method or static
@@ -548,7 +548,7 @@ LL |     mod inner { #![no_mangle] }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:297:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:296:5
    |
 LL |     #[no_mangle] struct S;
    |     ^^^^^^^^^^^^ --------- not a free function, impl method or static
@@ -556,7 +556,7 @@ LL |     #[no_mangle] struct S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:302:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:5
    |
 LL |     #[no_mangle] type T = S;
    |     ^^^^^^^^^^^^ ----------- not a free function, impl method or static
@@ -564,7 +564,7 @@ LL |     #[no_mangle] type T = S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:307:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:306:5
    |
 LL |     #[no_mangle] impl S { }
    |     ^^^^^^^^^^^^ ---------- not a free function, impl method or static
@@ -572,7 +572,7 @@ LL |     #[no_mangle] impl S { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:313:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:312:9
    |
 LL |         #[no_mangle] fn foo();
    |         ^^^^^^^^^^^^ --------- not a free function, impl method or static
@@ -580,7 +580,7 @@ LL |         #[no_mangle] fn foo();
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:318:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:317:9
    |
 LL |         #[no_mangle] fn bar() {}
    |         ^^^^^^^^^^^^ ----------- not a free function, impl method or static
@@ -588,163 +588,163 @@ LL |         #[no_mangle] fn bar() {}
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:328:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:327:17
    |
 LL |     mod inner { #![should_panic] }
    |                 ^^^^^^^^^^^^^^^^
 
 warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:5
    |
 LL |     #[should_panic] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5
    |
 LL |     #[should_panic] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:339:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:5
    |
 LL |     #[should_panic] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:346:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:17
    |
 LL |     mod inner { #![ignore] }
    |                 ^^^^^^^^^^
 
 warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:351:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5
    |
 LL |     #[ignore] struct S;
    |     ^^^^^^^^^
 
 warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:354:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:353:5
    |
 LL |     #[ignore] type T = S;
    |     ^^^^^^^^^
 
 warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:357:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:356:5
    |
 LL |     #[ignore] impl S { }
    |     ^^^^^^^^^
 
 warning: `#[no_implicit_prelude]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:5
    |
 LL |     #[no_implicit_prelude] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[no_implicit_prelude]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:5
    |
 LL |     #[no_implicit_prelude] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[no_implicit_prelude]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5
    |
 LL |     #[no_implicit_prelude] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[no_implicit_prelude]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5
    |
 LL |     #[no_implicit_prelude] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:381:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:17
    |
 LL |     mod inner { #![reexport_test_harness_main="2900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:5
    |
 LL |     #[reexport_test_harness_main = "2900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:5
    |
 LL |     #[reexport_test_harness_main = "2900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5
    |
 LL |     #[reexport_test_harness_main = "2900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:5
    |
 LL |     #[reexport_test_harness_main = "2900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: `#[macro_escape]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:405:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5
    |
 LL |     #[macro_escape] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[macro_escape]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:5
    |
 LL |     #[macro_escape] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[macro_escape]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:410:5
    |
 LL |     #[macro_escape] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[macro_escape]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:413:5
    |
 LL |     #[macro_escape] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:17
    |
 LL |     mod inner { #![no_std] }
    |                 ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:424:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5
    |
 LL |     #[no_std] fn f() { }
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5
    |
 LL |     #[no_std] struct S;
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5
    |
 LL |     #[no_std] type T = S;
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5
    |
 LL |     #[no_std] impl S { }
    |     ^^^^^^^^^
 
 warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:460:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:459:17
    |
 LL |     mod inner { #![cold] }
    |     ------------^^^^^^^^-- not a function
@@ -752,7 +752,7 @@ LL |     mod inner { #![cold] }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5
    |
 LL |     #[cold] struct S;
    |     ^^^^^^^ --------- not a function
@@ -760,7 +760,7 @@ LL |     #[cold] struct S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:472:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:5
    |
 LL |     #[cold] type T = S;
    |     ^^^^^^^ ----------- not a function
@@ -768,7 +768,7 @@ LL |     #[cold] type T = S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:5
    |
 LL |     #[cold] impl S { }
    |     ^^^^^^^ ---------- not a function
@@ -776,7 +776,7 @@ LL |     #[cold] impl S { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5
    |
 LL |     #[link_name = "1900"]
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -786,13 +786,13 @@ LL |     extern "C" { }
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 help: try `#[link(name = "1900")]` instead
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5
    |
 LL |     #[link_name = "1900"]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:17
    |
 LL |     mod inner { #![link_name="1900"] }
    |     ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static
@@ -800,7 +800,7 @@ LL |     mod inner { #![link_name="1900"] }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:501:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:5
    |
 LL |     #[link_name = "1900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
@@ -808,7 +808,7 @@ LL |     #[link_name = "1900"] fn f() { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:506:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
    |
 LL |     #[link_name = "1900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static
@@ -816,7 +816,7 @@ LL |     #[link_name = "1900"] struct S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:511:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:5
    |
 LL |     #[link_name = "1900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static
@@ -824,7 +824,7 @@ LL |     #[link_name = "1900"] type T = S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:5
    |
 LL |     #[link_name = "1900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
@@ -832,7 +832,7 @@ LL |     #[link_name = "1900"] impl S { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:17
    |
 LL |     mod inner { #![link_section="1800"] }
    |     ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static
@@ -840,7 +840,7 @@ LL |     mod inner { #![link_section="1800"] }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:534:5
    |
 LL |     #[link_section = "1800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static
@@ -848,7 +848,7 @@ LL |     #[link_section = "1800"] struct S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:539:5
    |
 LL |     #[link_section = "1800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static
@@ -856,7 +856,7 @@ LL |     #[link_section = "1800"] type T = S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:545:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
    |
 LL |     #[link_section = "1800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static
@@ -864,7 +864,7 @@ LL |     #[link_section = "1800"] impl S { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:560:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:17
    |
 LL |     mod inner { #![link()] }
    |     ------------^^^^^^^^^^-- not an `extern` block
@@ -872,7 +872,7 @@ LL |     mod inner { #![link()] }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:565:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:564:5
    |
 LL |     #[link()] fn f() { }
    |     ^^^^^^^^^ ---------- not an `extern` block
@@ -880,7 +880,7 @@ LL |     #[link()] fn f() { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:570:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:569:5
    |
 LL |     #[link()] struct S;
    |     ^^^^^^^^^ --------- not an `extern` block
@@ -888,7 +888,7 @@ LL |     #[link()] struct S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:575:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:574:5
    |
 LL |     #[link()] type T = S;
    |     ^^^^^^^^^ ----------- not an `extern` block
@@ -896,7 +896,7 @@ LL |     #[link()] type T = S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:580:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:579:5
    |
 LL |     #[link()] impl S { }
    |     ^^^^^^^^^ ---------- not an `extern` block
@@ -904,7 +904,7 @@ LL |     #[link()] impl S { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:585:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:584:5
    |
 LL |     #[link()] extern "Rust" {}
    |     ^^^^^^^^^
@@ -912,265 +912,265 @@ LL |     #[link()] extern "Rust" {}
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: `#[must_use]` has no effect when applied to a module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:607:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:606:17
    |
 LL |     mod inner { #![must_use] }
    |                 ^^^^^^^^^^^^
 
 warning: `#[must_use]` has no effect when applied to a type alias
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:613:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:612:5
    |
 LL |     #[must_use] type T = S;
    |     ^^^^^^^^^^^
 
 warning: `#[must_use]` has no effect when applied to an item
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:615:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:5
    |
 LL |     #[must_use] impl S { }
    |     ^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:621:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:17
    |
 LL |     mod inner { #![windows_subsystem="windows"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:624:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623:5
    |
 LL |     #[windows_subsystem = "windows"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:627:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:5
    |
 LL |     #[windows_subsystem = "windows"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:630:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:629:5
    |
 LL |     #[windows_subsystem = "windows"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:633:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:632:5
    |
 LL |     #[windows_subsystem = "windows"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:17
    |
 LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:645:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:5
    |
 LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:648:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5
    |
 LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5
    |
 LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:653:5
    |
 LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:661:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:666:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:670:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:680:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:686:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:689:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:17
    |
 LL |     mod inner { #![no_main] }
    |                 ^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5
    |
 LL |     #[no_main] fn f() { }
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5
    |
 LL |     #[no_main] struct S;
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
    |
 LL |     #[no_main] type T = S;
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5
    |
 LL |     #[no_main] impl S { }
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:17
    |
 LL |     mod inner { #![no_builtins] }
    |                 ^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
    |
 LL |     #[no_builtins] fn f() { }
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5
    |
 LL |     #[no_builtins] struct S;
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
    |
 LL |     #[no_builtins] type T = S;
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5
    |
 LL |     #[no_builtins] impl S { }
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:766:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:91:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:12
    |
 LL | #![feature(rust1)]
    |            ^^^^^
diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr
index 1148577016a..4856418ed60 100644
--- a/src/test/ui/issues/issue-17252.stderr
+++ b/src/test/ui/issues/issue-17252.stderr
@@ -1,21 +1,10 @@
-error[E0391]: cycle detected when normalizing `FOO`
-   |
-note: ...which requires simplifying constant for the type system `FOO`...
-  --> $DIR/issue-17252.rs:1:1
-   |
-LL | const FOO: usize = FOO;
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `FOO`...
+error[E0391]: cycle detected when const-evaluating + checking `FOO`
   --> $DIR/issue-17252.rs:1:1
    |
 LL | const FOO: usize = FOO;
    | ^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `FOO`...
-  --> $DIR/issue-17252.rs:1:1
    |
-LL | const FOO: usize = FOO;
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires normalizing `FOO`, completing the cycle
+   = note: ...which immediately requires const-evaluating + checking `FOO` again
 note: cycle used when const-evaluating + checking `main::{constant#0}`
   --> $DIR/issue-17252.rs:4:18
    |
diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr
index d3a1993536a..9366050d7ec 100644
--- a/src/test/ui/issues/issue-23302-1.stderr
+++ b/src/test/ui/issues/issue-23302-1.stderr
@@ -1,26 +1,15 @@
-error[E0391]: cycle detected when simplifying constant for the type system `X::A::{constant#0}`
+error[E0391]: cycle detected when const-evaluating + checking `X::A::{constant#0}`
   --> $DIR/issue-23302-1.rs:4:9
    |
 LL |     A = X::A as isize,
    |         ^^^^^^^^^^^^^
    |
-note: ...which requires simplifying constant for the type system `X::A::{constant#0}`...
+   = note: ...which immediately requires const-evaluating + checking `X::A::{constant#0}` again
+note: cycle used when simplifying constant for the type system `X::A::{constant#0}`
   --> $DIR/issue-23302-1.rs:4:9
    |
 LL |     A = X::A as isize,
    |         ^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `X::A::{constant#0}`...
-  --> $DIR/issue-23302-1.rs:4:9
-   |
-LL |     A = X::A as isize,
-   |         ^^^^^^^^^^^^^
-   = note: ...which requires normalizing `X::A as isize`...
-   = note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-23302-1.rs:3:1
-   |
-LL | enum X {
-   | ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr
index d3b78ea1af5..b97ae287a47 100644
--- a/src/test/ui/issues/issue-23302-2.stderr
+++ b/src/test/ui/issues/issue-23302-2.stderr
@@ -1,26 +1,15 @@
-error[E0391]: cycle detected when simplifying constant for the type system `Y::A::{constant#0}`
+error[E0391]: cycle detected when const-evaluating + checking `Y::A::{constant#0}`
   --> $DIR/issue-23302-2.rs:4:9
    |
 LL |     A = Y::B as isize,
    |         ^^^^^^^^^^^^^
    |
-note: ...which requires simplifying constant for the type system `Y::A::{constant#0}`...
+   = note: ...which immediately requires const-evaluating + checking `Y::A::{constant#0}` again
+note: cycle used when simplifying constant for the type system `Y::A::{constant#0}`
   --> $DIR/issue-23302-2.rs:4:9
    |
 LL |     A = Y::B as isize,
    |         ^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `Y::A::{constant#0}`...
-  --> $DIR/issue-23302-2.rs:4:9
-   |
-LL |     A = Y::B as isize,
-   |         ^^^^^^^^^^^^^
-   = note: ...which requires normalizing `Y::B as isize`...
-   = note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-23302-2.rs:3:1
-   |
-LL | enum Y {
-   | ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr
index 5233b832ecc..1a07d4a95bc 100644
--- a/src/test/ui/issues/issue-23302-3.stderr
+++ b/src/test/ui/issues/issue-23302-3.stderr
@@ -1,38 +1,20 @@
-error[E0391]: cycle detected when simplifying constant for the type system `A`
+error[E0391]: cycle detected when const-evaluating + checking `A`
   --> $DIR/issue-23302-3.rs:1:1
    |
 LL | const A: i32 = B;
    | ^^^^^^^^^^^^^^^^^
    |
-note: ...which requires simplifying constant for the type system `A`...
-  --> $DIR/issue-23302-3.rs:1:1
-   |
-LL | const A: i32 = B;
-   | ^^^^^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `A`...
-  --> $DIR/issue-23302-3.rs:1:1
-   |
-LL | const A: i32 = B;
-   | ^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `B`...
-note: ...which requires simplifying constant for the type system `B`...
-  --> $DIR/issue-23302-3.rs:3:1
-   |
-LL | const B: i32 = A;
-   | ^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `B`...
+note: ...which requires const-evaluating + checking `B`...
   --> $DIR/issue-23302-3.rs:3:1
    |
 LL | const B: i32 = A;
    | ^^^^^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `B`...
-  --> $DIR/issue-23302-3.rs:3:1
+   = note: ...which again requires const-evaluating + checking `A`, completing the cycle
+note: cycle used when simplifying constant for the type system `A`
+  --> $DIR/issue-23302-3.rs:1:1
    |
-LL | const B: i32 = A;
+LL | const A: i32 = B;
    | ^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `A`...
-   = note: ...which again requires simplifying constant for the type system `A`, completing the cycle
-   = note: cycle used when running analysis passes on this crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-39848.stderr b/src/test/ui/issues/issue-39848.stderr
index feabe3814dc..387ef0776ff 100644
--- a/src/test/ui/issues/issue-39848.stderr
+++ b/src/test/ui/issues/issue-39848.stderr
@@ -2,13 +2,19 @@ error: expected `{`, found `foo`
   --> $DIR/issue-39848.rs:3:21
    |
 LL |         if $tgt.has_$field() {}
-   |         --          ^^^^^^ expected `{`
-   |         |
-   |         this `if` expression has a condition, but no block
+   |                     ^^^^^^ expected `{`
 ...
 LL |     get_opt!(bar, foo);
    |     ------------------ in this macro invocation
    |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/issue-39848.rs:3:12
+   |
+LL |         if $tgt.has_$field() {}
+   |            ^^^^^^^^^
+...
+LL |     get_opt!(bar, foo);
+   |     ------------------ in this macro invocation
    = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: try placing this code inside a block
    |
diff --git a/src/test/ui/issues/issue-41394.rs b/src/test/ui/issues/issue-41394.rs
index 06a33081340..64873ac35a0 100644
--- a/src/test/ui/issues/issue-41394.rs
+++ b/src/test/ui/issues/issue-41394.rs
@@ -5,6 +5,7 @@ enum Foo {
 
 enum Bar {
     A = Foo::A as isize
+    //~^ ERROR evaluation of constant value failed
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-41394.stderr b/src/test/ui/issues/issue-41394.stderr
index fa95ca9c18a..47a24547d45 100644
--- a/src/test/ui/issues/issue-41394.stderr
+++ b/src/test/ui/issues/issue-41394.stderr
@@ -6,6 +6,13 @@ LL |     A = "" + 1
    |         |
    |         &str
 
-error: aborting due to previous error
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-41394.rs:7:9
+   |
+LL |     A = Foo::A as isize
+   |         ^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0369`.
+Some errors have detailed explanations: E0080, E0369.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/issues/issue-54954.rs
index 42a4d5b674b..ddd39141541 100644
--- a/src/test/ui/issues/issue-54954.rs
+++ b/src/test/ui/issues/issue-54954.rs
@@ -9,6 +9,8 @@ trait Tt {
 }
 
 fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
+  //~^ ERROR evaluation of constant value failed
+  //~| ERROR evaluation of constant value failed
     z
 }
 
diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr
index efe2ef504a2..6e8d3cac9a7 100644
--- a/src/test/ui/issues/issue-54954.stderr
+++ b/src/test/ui/issues/issue-54954.stderr
@@ -12,7 +12,19 @@ LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
    |
    = note: cannot satisfy `_: Tt`
 
-error: aborting due to 2 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-54954.rs:11:15
+   |
+LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
+   |               ^^^^^^^ referenced constant has errors
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-54954.rs:11:34
+   |
+LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
+   |                                  ^^^^^^^ referenced constant has errors
+
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0283, E0379.
-For more information about an error, try `rustc --explain E0283`.
+Some errors have detailed explanations: E0080, E0283, E0379.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs
index 2c5257ce063..6851b67cb3b 100644
--- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs
+++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs
@@ -19,4 +19,5 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA`
 
 fn main() {
     let _ = [0; B::VALUE];
+    //~^ ERROR evaluation of constant value failed
 }
diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr
index 8ae0f8b804c..cb5b397849c 100644
--- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr
+++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr
@@ -13,7 +13,13 @@ LL |     type MyA: TraitA;
 LL | impl TraitB for B {
    | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation
 
-error: aborting due to 2 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17
+   |
+LL |     let _ = [0; B::VALUE];
+   |                 ^^^^^^^^ referenced constant has errors
+
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0046, E0437.
+Some errors have detailed explanations: E0046, E0080, E0437.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/issues/issue-17728.rs b/src/test/ui/lifetimes/issue-17728.rs
index 6aca159c47e..6aca159c47e 100644
--- a/src/test/ui/issues/issue-17728.rs
+++ b/src/test/ui/lifetimes/issue-17728.rs
diff --git a/src/test/ui/issues/issue-17728.stderr b/src/test/ui/lifetimes/issue-17728.stderr
index 3b25902d757..3b25902d757 100644
--- a/src/test/ui/issues/issue-17728.stderr
+++ b/src/test/ui/lifetimes/issue-17728.stderr
diff --git a/src/test/ui/issues/issue-55796.rs b/src/test/ui/lifetimes/issue-55796.rs
index a7b27a99929..a7b27a99929 100644
--- a/src/test/ui/issues/issue-55796.rs
+++ b/src/test/ui/lifetimes/issue-55796.rs
diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/lifetimes/issue-55796.stderr
index 5809a56cd4b..5809a56cd4b 100644
--- a/src/test/ui/issues/issue-55796.stderr
+++ b/src/test/ui/lifetimes/issue-55796.stderr
diff --git a/src/test/ui/issues/issue-11154.rs b/src/test/ui/lto/issue-11154.rs
index e11cdc82f32..e11cdc82f32 100644
--- a/src/test/ui/issues/issue-11154.rs
+++ b/src/test/ui/lto/issue-11154.rs
diff --git a/src/test/ui/issues/issue-11154.stderr b/src/test/ui/lto/issue-11154.stderr
index 8eec8b37c85..8eec8b37c85 100644
--- a/src/test/ui/issues/issue-11154.stderr
+++ b/src/test/ui/lto/issue-11154.stderr
diff --git a/src/test/ui/macros/assert-trailing-junk.rs b/src/test/ui/macros/assert-trailing-junk.rs
index cd7faf9bf8b..da725e19e2a 100644
--- a/src/test/ui/macros/assert-trailing-junk.rs
+++ b/src/test/ui/macros/assert-trailing-junk.rs
@@ -1,3 +1,6 @@
+// revisions: with-generic-asset without-generic-asset
+// [with-generic-asset] compile-flags: --cfg feature="generic_assert"
+
 // Ensure assert macro does not ignore trailing garbage.
 //
 // See https://github.com/rust-lang/rust/issues/60024 for details.
diff --git a/src/test/ui/macros/assert-trailing-junk.stderr b/src/test/ui/macros/assert-trailing-junk.with-generic-asset.stderr
index eb001429c55..09dd16a0b0d 100644
--- a/src/test/ui/macros/assert-trailing-junk.stderr
+++ b/src/test/ui/macros/assert-trailing-junk.with-generic-asset.stderr
@@ -1,17 +1,17 @@
 error: expected one of `,`, `.`, `?`, or an operator, found `some`
-  --> $DIR/assert-trailing-junk.rs:6:18
+  --> $DIR/assert-trailing-junk.rs:9:18
    |
 LL |     assert!(true some extra junk, "whatever");
    |                  ^^^^ expected one of `,`, `.`, `?`, or an operator
 
 error: expected one of `,`, `.`, `?`, or an operator, found `some`
-  --> $DIR/assert-trailing-junk.rs:9:18
+  --> $DIR/assert-trailing-junk.rs:12:18
    |
 LL |     assert!(true some extra junk);
    |                  ^^^^ expected one of `,`, `.`, `?`, or an operator
 
 error: no rules expected the token `blah`
-  --> $DIR/assert-trailing-junk.rs:12:30
+  --> $DIR/assert-trailing-junk.rs:15:30
    |
 LL |     assert!(true, "whatever" blah);
    |                             -^^^^ no rules expected this token in macro call
@@ -19,7 +19,7 @@ LL |     assert!(true, "whatever" blah);
    |                             help: missing comma here
 
 error: unexpected string literal
-  --> $DIR/assert-trailing-junk.rs:15:18
+  --> $DIR/assert-trailing-junk.rs:18:18
    |
 LL |     assert!(true "whatever" blah);
    |                 -^^^^^^^^^^
@@ -27,7 +27,7 @@ LL |     assert!(true "whatever" blah);
    |                 help: try adding a comma
 
 error: no rules expected the token `blah`
-  --> $DIR/assert-trailing-junk.rs:15:29
+  --> $DIR/assert-trailing-junk.rs:18:29
    |
 LL |     assert!(true "whatever" blah);
    |                            -^^^^ no rules expected this token in macro call
@@ -35,7 +35,7 @@ LL |     assert!(true "whatever" blah);
    |                            help: missing comma here
 
 error: macro requires an expression as an argument
-  --> $DIR/assert-trailing-junk.rs:19:5
+  --> $DIR/assert-trailing-junk.rs:22:5
    |
 LL |     assert!(true;);
    |     ^^^^^^^^^^^^-^
@@ -43,7 +43,7 @@ LL |     assert!(true;);
    |                 help: try removing semicolon
 
 error: unexpected string literal
-  --> $DIR/assert-trailing-junk.rs:22:27
+  --> $DIR/assert-trailing-junk.rs:25:27
    |
 LL |     assert!(false || true "error message");
    |                          -^^^^^^^^^^^^^^^
diff --git a/src/test/ui/macros/assert-trailing-junk.without-generic-asset.stderr b/src/test/ui/macros/assert-trailing-junk.without-generic-asset.stderr
new file mode 100644
index 00000000000..09dd16a0b0d
--- /dev/null
+++ b/src/test/ui/macros/assert-trailing-junk.without-generic-asset.stderr
@@ -0,0 +1,54 @@
+error: expected one of `,`, `.`, `?`, or an operator, found `some`
+  --> $DIR/assert-trailing-junk.rs:9:18
+   |
+LL |     assert!(true some extra junk, "whatever");
+   |                  ^^^^ expected one of `,`, `.`, `?`, or an operator
+
+error: expected one of `,`, `.`, `?`, or an operator, found `some`
+  --> $DIR/assert-trailing-junk.rs:12:18
+   |
+LL |     assert!(true some extra junk);
+   |                  ^^^^ expected one of `,`, `.`, `?`, or an operator
+
+error: no rules expected the token `blah`
+  --> $DIR/assert-trailing-junk.rs:15:30
+   |
+LL |     assert!(true, "whatever" blah);
+   |                             -^^^^ no rules expected this token in macro call
+   |                             |
+   |                             help: missing comma here
+
+error: unexpected string literal
+  --> $DIR/assert-trailing-junk.rs:18:18
+   |
+LL |     assert!(true "whatever" blah);
+   |                 -^^^^^^^^^^
+   |                 |
+   |                 help: try adding a comma
+
+error: no rules expected the token `blah`
+  --> $DIR/assert-trailing-junk.rs:18:29
+   |
+LL |     assert!(true "whatever" blah);
+   |                            -^^^^ no rules expected this token in macro call
+   |                            |
+   |                            help: missing comma here
+
+error: macro requires an expression as an argument
+  --> $DIR/assert-trailing-junk.rs:22:5
+   |
+LL |     assert!(true;);
+   |     ^^^^^^^^^^^^-^
+   |                 |
+   |                 help: try removing semicolon
+
+error: unexpected string literal
+  --> $DIR/assert-trailing-junk.rs:25:27
+   |
+LL |     assert!(false || true "error message");
+   |                          -^^^^^^^^^^^^^^^
+   |                          |
+   |                          help: try adding a comma
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/macros/assert.rs b/src/test/ui/macros/assert.rs
index 71b0dbb19e2..a314db907b8 100644
--- a/src/test/ui/macros/assert.rs
+++ b/src/test/ui/macros/assert.rs
@@ -1,3 +1,6 @@
+// revisions: with-generic-asset without-generic-asset
+// [with-generic-asset] compile-flags: --cfg feature="generic_assert"
+
 fn main() {
     assert!();  //~ ERROR requires a boolean expression
     assert!(struct); //~ ERROR expected expression
diff --git a/src/test/ui/macros/assert.stderr b/src/test/ui/macros/assert.with-generic-asset.stderr
index 57e5c77a566..51d8f28a35c 100644
--- a/src/test/ui/macros/assert.stderr
+++ b/src/test/ui/macros/assert.with-generic-asset.stderr
@@ -1,17 +1,17 @@
 error: macro requires a boolean expression as an argument
-  --> $DIR/assert.rs:2:5
+  --> $DIR/assert.rs:5:5
    |
 LL |     assert!();
    |     ^^^^^^^^^ boolean expression required
 
 error: expected expression, found keyword `struct`
-  --> $DIR/assert.rs:3:13
+  --> $DIR/assert.rs:6:13
    |
 LL |     assert!(struct);
    |             ^^^^^^ expected expression
 
 error: macro requires a boolean expression as an argument
-  --> $DIR/assert.rs:4:5
+  --> $DIR/assert.rs:7:5
    |
 LL |     debug_assert!();
    |     ^^^^^^^^^^^^^^^ boolean expression required
@@ -19,7 +19,7 @@ LL |     debug_assert!();
    = note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected expression, found keyword `struct`
-  --> $DIR/assert.rs:5:19
+  --> $DIR/assert.rs:8:19
    |
 LL |     debug_assert!(struct);
    |                   ^^^^^^ expected expression
diff --git a/src/test/ui/macros/assert.without-generic-asset.stderr b/src/test/ui/macros/assert.without-generic-asset.stderr
new file mode 100644
index 00000000000..51d8f28a35c
--- /dev/null
+++ b/src/test/ui/macros/assert.without-generic-asset.stderr
@@ -0,0 +1,28 @@
+error: macro requires a boolean expression as an argument
+  --> $DIR/assert.rs:5:5
+   |
+LL |     assert!();
+   |     ^^^^^^^^^ boolean expression required
+
+error: expected expression, found keyword `struct`
+  --> $DIR/assert.rs:6:13
+   |
+LL |     assert!(struct);
+   |             ^^^^^^ expected expression
+
+error: macro requires a boolean expression as an argument
+  --> $DIR/assert.rs:7:5
+   |
+LL |     debug_assert!();
+   |     ^^^^^^^^^^^^^^^ boolean expression required
+   |
+   = note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected expression, found keyword `struct`
+  --> $DIR/assert.rs:8:19
+   |
+LL |     debug_assert!(struct);
+   |                   ^^^^^^ expected expression
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
new file mode 100644
index 00000000000..c0e9f29fdbc
--- /dev/null
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
@@ -0,0 +1,143 @@
+// edition:2021
+// ignore-tidy-linelength
+// only-x86_64
+// run-pass
+
+#![allow(path_statements, unused_allocation)]
+#![feature(box_syntax, core_intrinsics, generic_assert, generic_assert_internals)]
+
+macro_rules! test {
+  (
+    let mut $elem_ident:ident = $elem_expr:expr;
+    [ $($assert:tt)* ] => $msg:literal
+  ) => {
+    {
+      #[allow(unused_assignments, unused_mut, unused_variables)]
+      let rslt = std::panic::catch_unwind(|| {
+        let mut $elem_ident = $elem_expr;
+        assert!($($assert)*);
+      });
+      let err = rslt.unwrap_err();
+      if let Some(elem) = err.downcast_ref::<String>() {
+        assert_eq!(elem, &$msg);
+      }
+      else if let Some(elem) = err.downcast_ref::<&str>() {
+        assert_eq!(elem, &$msg);
+      }
+      else {
+        panic!("assert!( ... ) should return a string");
+      }
+    }
+  }
+}
+
+macro_rules! tests {
+  (
+    let mut $elem_ident:ident = $elem_expr:expr;
+
+    $(
+      [ $($elem_assert:tt)* ] => $elem_msg:literal
+    )+
+  ) => {
+    $(
+      test!(
+        let mut $elem_ident = $elem_expr;
+        [ $($elem_assert)* ] => $elem_msg
+      );
+    )+
+  }
+}
+
+const FOO: Foo = Foo { bar: 1 };
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+struct Foo {
+  bar: i32
+}
+
+fn main() {
+  // ***** Allowed *****
+
+  tests!(
+    let mut elem = 1i32;
+
+    // binary
+    [ elem + 1 == 3 ] => "Assertion failed: elem + 1 == 3\nWith captures:\n  elem = 1\n"
+  );
+
+  // ***** Disallowed *****
+
+  tests!(
+    let mut elem = 1i32;
+
+    // assign
+    [ { let local = elem; local } == 3 ] => "Assertion failed: { let local = elem; local } == 3"
+
+    // assign op
+    [ { elem += 1; elem } == 3 ] => "Assertion failed: { elem += 1; elem } == 3"
+
+    // async
+    [ { let _ = async { elem }; elem } == 3 ] => "Assertion failed: { let _ = async { elem }; elem } == 3"
+
+    // await
+
+    // block
+    [ { elem } == 3 ] => "Assertion failed: { elem } == 3"
+
+    // box
+    [ box elem == box 3 ] => "Assertion failed: box elem == box 3"
+
+    // break
+    [ loop { break elem; } ==  3 ] => "Assertion failed: loop { break elem; } == 3"
+
+    // closure
+    [(|| elem)() ==  3 ] => "Assertion failed: (|| elem)() == 3"
+
+    // const block
+
+    // continue
+
+    // err
+
+    // field
+    [ FOO.bar ==  3 ] => "Assertion failed: FOO.bar == 3"
+
+    // for loop
+    [ { for _ in 0..elem { elem; } elem } ==  3 ] => "Assertion failed: { for _ in 0..elem { elem; } elem } == 3"
+
+    // if
+    [ if true { elem } else { elem } == 3 ] => "Assertion failed: if true { elem } else { elem } == 3"
+
+    // inline asm
+
+    // let
+    [ if let true = true { elem } else { elem } == 3 ] => "Assertion failed: if let true = true { elem } else { elem } == 3"
+
+    // lit
+
+    // loop
+    [ loop { elem; break elem; } == 3 ] => "Assertion failed: loop { elem; break elem; } == 3"
+
+    // mac call
+
+    // match
+    [ match elem { _ => elem } == 3 ] => "Assertion failed: match elem { _ => elem, } == 3"
+
+    // ret
+    [ (|| { return elem; })() == 3 ] => "Assertion failed: (|| { return elem; })() == 3"
+
+    // try
+    [ (|| { Some(Some(elem)?) })() == Some(3) ] => "Assertion failed: (|| { Some(Some(elem)?) })() == Some(3)"
+
+    // try block
+
+    // underscore
+
+    // while
+    [ { while false { elem; break; } elem } == 3 ] => "Assertion failed: { while false { elem; break; } elem } == 3"
+
+    // yeet
+
+    // yield
+  );
+}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
new file mode 100644
index 00000000000..86697c58fbc
--- /dev/null
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
@@ -0,0 +1,43 @@
+// aux-build:common.rs
+// ignore-tidy-linelength
+// only-x86_64
+// run-pass
+
+#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+
+extern crate common;
+
+#[derive(Clone, Copy, PartialEq)]
+struct CopyNoDebug(i32);
+
+#[derive(Debug, PartialEq)]
+struct NoCopyDebug(i32);
+
+#[derive(PartialEq)]
+struct NoCopyNoDebug(i32);
+
+fn main() {
+  // Has Copy but does not have Debug
+  common::test!(
+    let mut copy_no_debug = CopyNoDebug(1);
+    [ copy_no_debug == CopyNoDebug(3) ] => "Assertion failed: copy_no_debug == CopyNoDebug(3)\nWith captures:\n  copy_no_debug = N/A\n"
+  );
+
+  // Does not have Copy but has Debug
+  common::test!(
+    let mut no_copy_debug = NoCopyDebug(1);
+    [ no_copy_debug == NoCopyDebug(3) ] => "Assertion failed: no_copy_debug == NoCopyDebug(3)\nWith captures:\n  no_copy_debug = N/A\n"
+  );
+
+  // Does not have Copy and does not have Debug
+  common::test!(
+    let mut no_copy_no_debug = NoCopyNoDebug(1);
+    [ no_copy_no_debug == NoCopyNoDebug(3) ] => "Assertion failed: no_copy_no_debug == NoCopyNoDebug(3)\nWith captures:\n  no_copy_no_debug = N/A\n"
+  );
+
+  // Unevaluated (Expression short-circuited)
+  common::test!(
+    let mut elem = true;
+    [ false && elem ] => "Assertion failed: false && elem\nWith captures:\n  elem = N/A\n"
+  );
+}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
new file mode 100644
index 00000000000..6a1435f792b
--- /dev/null
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
@@ -0,0 +1,13 @@
+// compile-flags: --test
+// run-pass
+
+#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+
+#[should_panic(expected = "Custom user message")]
+#[test]
+fn test() {
+  assert!(1 == 3, "Custom user message");
+}
+
+fn main() {
+}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
new file mode 100644
index 00000000000..06c4993ec30
--- /dev/null
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
@@ -0,0 +1,14 @@
+// aux-build:common.rs
+// only-x86_64
+// run-pass
+
+#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+
+extern crate common;
+
+fn main() {
+  common::test!(
+    let mut _nothing = ();
+    [ 1 == 3 ] => "Assertion failed: 1 == 3"
+  );
+}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
new file mode 100644
index 00000000000..903ed507c2e
--- /dev/null
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
@@ -0,0 +1,25 @@
+#[macro_export]
+macro_rules! test {
+  (
+    let mut $elem_ident:ident = $elem_expr:expr;
+    [ $($assert:tt)* ] => $msg:literal
+  ) => {
+    {
+      #[allow(unused_assignments, unused_mut, unused_variables)]
+      let rslt = std::panic::catch_unwind(|| {
+        let mut $elem_ident = $elem_expr;
+        assert!($($assert)*);
+      });
+      let err = rslt.unwrap_err();
+      if let Some(elem) = err.downcast_ref::<String>() {
+        assert_eq!(elem, &$msg);
+      }
+      else if let Some(elem) = err.downcast_ref::<&str>() {
+        assert_eq!(elem, &$msg);
+      }
+      else {
+        panic!("assert!( ... ) should return a string");
+      }
+    }
+  }
+}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs
new file mode 100644
index 00000000000..1db9d33c72a
--- /dev/null
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs
@@ -0,0 +1,9 @@
+// check-pass
+// compile-flags: -Z unpretty=expanded
+
+#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+
+fn main() {
+    let elem = 1i32;
+    assert!(elem == 1);
+}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout
new file mode 100644
index 00000000000..a590eb32232
--- /dev/null
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout
@@ -0,0 +1,29 @@
+#![feature(prelude_import)]
+#![no_std]
+// check-pass
+// compile-flags: -Z unpretty=expanded
+
+#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+fn main() {
+    let elem = 1i32;
+    {
+        #[allow(unused_imports)]
+        use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+        let mut __capture0 = ::core::asserting::Capture::new();
+        let __local_bind0 = &elem;
+        if !(*{
+                                (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+                                __local_bind0
+                            } == 1) {
+                {
+                    ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n  elem = ",
+                                        "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+                }
+            }
+    };
+}
diff --git a/src/test/ui/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
index f70ca87e304..01860adaac2 100644
--- a/src/test/ui/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
@@ -1,8 +1,7 @@
 // compile-flags: --test
+// ignore-tidy-linelength
 // run-pass
 
-// `generic_assert` is completely unimplemented and doesn't generate any logic, thus the
-// reason why this test currently passes
 #![feature(core_intrinsics, generic_assert, generic_assert_internals)]
 
 use std::fmt::{Debug, Formatter};
@@ -16,10 +15,11 @@ impl Debug for CopyDebug {
   }
 }
 
+#[should_panic(expected = "Assertion failed: copy_debug == CopyDebug(3)\nWith captures:\n  copy_debug = With great power comes great electricity bills\n")]
 #[test]
 fn test() {
-  let _copy_debug = CopyDebug(1);
-  assert!(_copy_debug == CopyDebug(3));
+  let copy_debug = CopyDebug(1);
+  assert!(copy_debug == CopyDebug(3));
 }
 
 fn main() {
diff --git a/src/test/ui/mismatched_types/issue-38371-unfixable.rs b/src/test/ui/mismatched_types/issue-38371-unfixable.rs
new file mode 100644
index 00000000000..c4316bfdd18
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-38371-unfixable.rs
@@ -0,0 +1,5 @@
+fn ugh(&[bar]: &u32) {} //~ ERROR expected an array or slice
+
+fn bgh(&&bar: u32) {} //~ ERROR mismatched types
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/issue-38371-unfixable.stderr b/src/test/ui/mismatched_types/issue-38371-unfixable.stderr
new file mode 100644
index 00000000000..3c5e765abfb
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-38371-unfixable.stderr
@@ -0,0 +1,21 @@
+error[E0529]: expected an array or slice, found `u32`
+  --> $DIR/issue-38371-unfixable.rs:1:9
+   |
+LL | fn ugh(&[bar]: &u32) {}
+   |         ^^^^^ pattern cannot match with input type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-38371-unfixable.rs:3:8
+   |
+LL | fn bgh(&&bar: u32) {}
+   |        ^^^^^  --- expected due to this
+   |        |
+   |        expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0529.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/issue-38371.fixed b/src/test/ui/mismatched_types/issue-38371.fixed
new file mode 100644
index 00000000000..0e20835bef0
--- /dev/null
+++ b/src/test/ui/mismatched_types/issue-38371.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+// see also issue-38371-unfixable.rs
+#![allow(dead_code)]
+
+#[derive(Copy, Clone)]
+struct Foo {}
+
+fn foo(_a: &Foo) {} //~ ERROR mismatched types
+
+fn bar(_a: Foo) {}
+
+fn qux(_a: &Foo) {}
+
+fn zar(&_a: &Foo) {}
+
+fn agh(&_a: &u32) {} //~ ERROR mismatched types
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/issue-38371.rs b/src/test/ui/mismatched_types/issue-38371.rs
index d2cd2b88ab7..fb9e4c173e7 100644
--- a/src/test/ui/mismatched_types/issue-38371.rs
+++ b/src/test/ui/mismatched_types/issue-38371.rs
@@ -1,27 +1,18 @@
-struct Foo {
-}
+// run-rustfix
+// see also issue-38371-unfixable.rs
+#![allow(dead_code)]
 
-fn foo(&foo: Foo) { //~ ERROR mismatched types
-}
+#[derive(Copy, Clone)]
+struct Foo {}
 
-fn bar(foo: Foo) {
-}
+fn foo(&_a: Foo) {} //~ ERROR mismatched types
 
-fn qux(foo: &Foo) {
-}
+fn bar(_a: Foo) {}
 
-fn zar(&foo: &Foo) {
-}
+fn qux(_a: &Foo) {}
 
-// The somewhat unexpected help message in this case is courtesy of
-// match_default_bindings.
-fn agh(&&bar: &u32) { //~ ERROR mismatched types
-}
+fn zar(&_a: &Foo) {}
 
-fn bgh(&&bar: u32) { //~ ERROR mismatched types
-}
-
-fn ugh(&[bar]: &u32) { //~ ERROR expected an array or slice
-}
+fn agh(&&_a: &u32) {} //~ ERROR mismatched types
 
 fn main() {}
diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr
index 5d2ce9302ec..003f17cda15 100644
--- a/src/test/ui/mismatched_types/issue-38371.stderr
+++ b/src/test/ui/mismatched_types/issue-38371.stderr
@@ -1,46 +1,35 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-38371.rs:4:8
+  --> $DIR/issue-38371.rs:8:8
    |
-LL | fn foo(&foo: Foo) {
-   |        ^^^^-----
-   |        |     |
-   |        |     expected due to this
+LL | fn foo(&_a: Foo) {}
+   |        ^^^  --- expected due to this
+   |        |
    |        expected struct `Foo`, found reference
-   |        help: did you mean `foo`: `&Foo`
    |
    = note: expected struct `Foo`
            found reference `&_`
+help: to take parameter `_a` by reference, move `&` to the type
+   |
+LL - fn foo(&_a: Foo) {}
+LL + fn foo(_a: &Foo) {}
+   | 
 
 error[E0308]: mismatched types
-  --> $DIR/issue-38371.rs:18:9
+  --> $DIR/issue-38371.rs:16:9
    |
-LL | fn agh(&&bar: &u32) {
-   |         ^^^^  ---- expected due to this
+LL | fn agh(&&_a: &u32) {}
+   |         ^^^  ---- expected due to this
    |         |
    |         expected `u32`, found reference
-   |         help: you can probably remove the explicit borrow: `bar`
-   |
-   = note:   expected type `u32`
-           found reference `&_`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-38371.rs:21:8
-   |
-LL | fn bgh(&&bar: u32) {
-   |        ^^^^^  --- expected due to this
-   |        |
-   |        expected `u32`, found reference
    |
    = note:   expected type `u32`
            found reference `&_`
-
-error[E0529]: expected an array or slice, found `u32`
-  --> $DIR/issue-38371.rs:24:9
+help: consider removing `&` from the pattern
    |
-LL | fn ugh(&[bar]: &u32) {
-   |         ^^^^^ pattern cannot match with input type `u32`
+LL - fn agh(&&_a: &u32) {}
+LL + fn agh(&_a: &u32) {}
+   | 
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0529.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.fixed b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed
new file mode 100644
index 00000000000..ab8483eef49
--- /dev/null
+++ b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed
@@ -0,0 +1,24 @@
+// run-rustfix
+
+fn _f0(_a: &u32) {} //~ ERROR mismatched types
+fn _f1(_a: &mut u32) {} //~ ERROR mismatched types
+fn _f2(&_a: &u32) {} //~ ERROR mismatched types
+fn _f3(&mut _a: &mut u32) {} //~ ERROR mismatched types
+fn _f4(&_a: &u32) {} //~ ERROR mismatched types
+fn _f5(&mut _a: &mut u32) {} //~ ERROR mismatched types
+
+fn main() {
+    let _: fn(u32) = |_a| (); //~ ERROR mismatched types
+    let _: fn(u32) = |_a| (); //~ ERROR mismatched types
+    let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types
+    let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types
+    let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types
+    let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types
+
+    let _ = |_a: &u32| (); //~ ERROR mismatched types
+    let _ = |_a: &mut u32| (); //~ ERROR mismatched types
+    let _ = |&_a: &u32| (); //~ ERROR mismatched types
+    let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types
+    let _ = |&_a: &u32| (); //~ ERROR mismatched types
+    let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.rs b/src/test/ui/mismatched_types/ref-pat-suggestions.rs
new file mode 100644
index 00000000000..7e55539aa3d
--- /dev/null
+++ b/src/test/ui/mismatched_types/ref-pat-suggestions.rs
@@ -0,0 +1,24 @@
+// run-rustfix
+
+fn _f0(&_a: u32) {} //~ ERROR mismatched types
+fn _f1(&mut _a: u32) {} //~ ERROR mismatched types
+fn _f2(&&_a: &u32) {} //~ ERROR mismatched types
+fn _f3(&mut &_a: &mut u32) {} //~ ERROR mismatched types
+fn _f4(&&mut _a: &u32) {} //~ ERROR mismatched types
+fn _f5(&mut &mut _a: &mut u32) {} //~ ERROR mismatched types
+
+fn main() {
+    let _: fn(u32) = |&_a| (); //~ ERROR mismatched types
+    let _: fn(u32) = |&mut _a| (); //~ ERROR mismatched types
+    let _: fn(&u32) = |&&_a| (); //~ ERROR mismatched types
+    let _: fn(&mut u32) = |&mut &_a| (); //~ ERROR mismatched types
+    let _: fn(&u32) = |&&mut _a| (); //~ ERROR mismatched types
+    let _: fn(&mut u32) = |&mut &mut _a| (); //~ ERROR mismatched types
+
+    let _ = |&_a: u32| (); //~ ERROR mismatched types
+    let _ = |&mut _a: u32| (); //~ ERROR mismatched types
+    let _ = |&&_a: &u32| (); //~ ERROR mismatched types
+    let _ = |&mut &_a: &mut u32| (); //~ ERROR mismatched types
+    let _ = |&&mut _a: &u32| (); //~ ERROR mismatched types
+    let _ = |&mut &mut _a: &mut u32| (); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr
new file mode 100644
index 00000000000..0516bad49ab
--- /dev/null
+++ b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr
@@ -0,0 +1,297 @@
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:3:8
+   |
+LL | fn _f0(&_a: u32) {}
+   |        ^^^  --- expected due to this
+   |        |
+   |        expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: to take parameter `_a` by reference, move `&` to the type
+   |
+LL - fn _f0(&_a: u32) {}
+LL + fn _f0(_a: &u32) {}
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:4:8
+   |
+LL | fn _f1(&mut _a: u32) {}
+   |        ^^^^^^^  --- expected due to this
+   |        |
+   |        expected `u32`, found `&mut _`
+   |
+   = note:           expected type `u32`
+           found mutable reference `&mut _`
+help: to take parameter `_a` by reference, move `&mut` to the type
+   |
+LL - fn _f1(&mut _a: u32) {}
+LL + fn _f1(_a: &mut u32) {}
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:5:9
+   |
+LL | fn _f2(&&_a: &u32) {}
+   |         ^^^  ---- expected due to this
+   |         |
+   |         expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL - fn _f2(&&_a: &u32) {}
+LL + fn _f2(&_a: &u32) {}
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:6:13
+   |
+LL | fn _f3(&mut &_a: &mut u32) {}
+   |             ^^^  -------- expected due to this
+   |             |
+   |             expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL - fn _f3(&mut &_a: &mut u32) {}
+LL + fn _f3(&mut _a: &mut u32) {}
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:7:9
+   |
+LL | fn _f4(&&mut _a: &u32) {}
+   |         ^^^^^^^  ---- expected due to this
+   |         |
+   |         expected `u32`, found `&mut _`
+   |
+   = note:           expected type `u32`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL - fn _f4(&&mut _a: &u32) {}
+LL + fn _f4(&_a: &u32) {}
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:8:13
+   |
+LL | fn _f5(&mut &mut _a: &mut u32) {}
+   |             ^^^^^^^  -------- expected due to this
+   |             |
+   |             expected `u32`, found `&mut _`
+   |
+   = note:           expected type `u32`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL - fn _f5(&mut &mut _a: &mut u32) {}
+LL + fn _f5(&mut _a: &mut u32) {}
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:11:23
+   |
+LL |     let _: fn(u32) = |&_a| ();
+   |                       ^--
+   |                       ||
+   |                       |expected due to this
+   |                       expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let _: fn(u32) = |&_a| ();
+LL +     let _: fn(u32) = |_a| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:12:23
+   |
+LL |     let _: fn(u32) = |&mut _a| ();
+   |                       ^^^^^--
+   |                       |    |
+   |                       |    expected due to this
+   |                       expected `u32`, found `&mut _`
+   |
+   = note:           expected type `u32`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let _: fn(u32) = |&mut _a| ();
+LL +     let _: fn(u32) = |_a| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:13:25
+   |
+LL |     let _: fn(&u32) = |&&_a| ();
+   |                         ^--
+   |                         ||
+   |                         |expected due to this
+   |                         expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let _: fn(&u32) = |&&_a| ();
+LL +     let _: fn(&u32) = |&_a| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:14:33
+   |
+LL |     let _: fn(&mut u32) = |&mut &_a| ();
+   |                                 ^--
+   |                                 ||
+   |                                 |expected due to this
+   |                                 expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let _: fn(&mut u32) = |&mut &_a| ();
+LL +     let _: fn(&mut u32) = |&mut _a| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:15:25
+   |
+LL |     let _: fn(&u32) = |&&mut _a| ();
+   |                         ^^^^^--
+   |                         |    |
+   |                         |    expected due to this
+   |                         expected `u32`, found `&mut _`
+   |
+   = note:           expected type `u32`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let _: fn(&u32) = |&&mut _a| ();
+LL +     let _: fn(&u32) = |&_a| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:16:33
+   |
+LL |     let _: fn(&mut u32) = |&mut &mut _a| ();
+   |                                 ^^^^^--
+   |                                 |    |
+   |                                 |    expected due to this
+   |                                 expected `u32`, found `&mut _`
+   |
+   = note:           expected type `u32`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let _: fn(&mut u32) = |&mut &mut _a| ();
+LL +     let _: fn(&mut u32) = |&mut _a| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:18:14
+   |
+LL |     let _ = |&_a: u32| ();
+   |              ^^^  --- expected due to this
+   |              |
+   |              expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: to take parameter `_a` by reference, move `&` to the type
+   |
+LL -     let _ = |&_a: u32| ();
+LL +     let _ = |_a: &u32| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:19:14
+   |
+LL |     let _ = |&mut _a: u32| ();
+   |              ^^^^^^^  --- expected due to this
+   |              |
+   |              expected `u32`, found `&mut _`
+   |
+   = note:           expected type `u32`
+           found mutable reference `&mut _`
+help: to take parameter `_a` by reference, move `&mut` to the type
+   |
+LL -     let _ = |&mut _a: u32| ();
+LL +     let _ = |_a: &mut u32| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:20:15
+   |
+LL |     let _ = |&&_a: &u32| ();
+   |               ^^^  ---- expected due to this
+   |               |
+   |               expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let _ = |&&_a: &u32| ();
+LL +     let _ = |&_a: &u32| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:21:19
+   |
+LL |     let _ = |&mut &_a: &mut u32| ();
+   |                   ^^^  -------- expected due to this
+   |                   |
+   |                   expected `u32`, found reference
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let _ = |&mut &_a: &mut u32| ();
+LL +     let _ = |&mut _a: &mut u32| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:22:15
+   |
+LL |     let _ = |&&mut _a: &u32| ();
+   |               ^^^^^^^  ---- expected due to this
+   |               |
+   |               expected `u32`, found `&mut _`
+   |
+   = note:           expected type `u32`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let _ = |&&mut _a: &u32| ();
+LL +     let _ = |&_a: &u32| ();
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/ref-pat-suggestions.rs:23:19
+   |
+LL |     let _ = |&mut &mut _a: &mut u32| ();
+   |                   ^^^^^^^  -------- expected due to this
+   |                   |
+   |                   expected `u32`, found `&mut _`
+   |
+   = note:           expected type `u32`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let _ = |&mut &mut _a: &mut u32| ();
+LL +     let _ = |&mut _a: &mut u32| ();
+   | 
+
+error: aborting due to 18 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/missing/missing-block-hint.stderr b/src/test/ui/missing/missing-block-hint.stderr
index 148e214e58e..16954223a45 100644
--- a/src/test/ui/missing/missing-block-hint.stderr
+++ b/src/test/ui/missing/missing-block-hint.stderr
@@ -2,18 +2,25 @@ error: expected `{`, found `=>`
   --> $DIR/missing-block-hint.rs:3:18
    |
 LL |         if (foo) => {}
-   |         --       ^^ expected `{`
-   |         |
-   |         this `if` expression has a condition, but no block
+   |                  ^^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/missing-block-hint.rs:3:12
+   |
+LL |         if (foo) => {}
+   |            ^^^^^
 
 error: expected `{`, found `bar`
   --> $DIR/missing-block-hint.rs:7:13
    |
-LL |         if (foo)
-   |         -- this `if` expression has a condition, but no block
 LL |             bar;
    |             ^^^ expected `{`
    |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/missing-block-hint.rs:6:12
+   |
+LL |         if (foo)
+   |            ^^^^^
 help: try placing this code inside a block
    |
 LL |             { bar; }
diff --git a/src/test/ui/issues/issue-46023.rs b/src/test/ui/nll/issue-46023.rs
index a923eb24421..a923eb24421 100644
--- a/src/test/ui/issues/issue-46023.rs
+++ b/src/test/ui/nll/issue-46023.rs
diff --git a/src/test/ui/issues/issue-46023.stderr b/src/test/ui/nll/issue-46023.stderr
index ca19c250120..ca19c250120 100644
--- a/src/test/ui/issues/issue-46023.stderr
+++ b/src/test/ui/nll/issue-46023.stderr
diff --git a/src/test/ui/parser/bad-if-statements.rs b/src/test/ui/parser/bad-if-statements.rs
new file mode 100644
index 00000000000..2c501e3a5b3
--- /dev/null
+++ b/src/test/ui/parser/bad-if-statements.rs
@@ -0,0 +1,38 @@
+fn a() {
+    if {}
+    //~^ ERROR missing condition for `if` expression
+}
+
+fn b() {
+    if true && {}
+    //~^ ERROR this `if` expression is missing a block after the condition
+}
+
+fn c() {
+    let x = {};
+    if true x
+    //~^ ERROR expected `{`, found `x`
+}
+
+fn a2() {
+    if {} else {}
+    //~^ ERROR missing condition for `if` expression
+}
+
+fn b2() {
+    if true && {} else {}
+    //~^ ERROR this `if` expression is missing a block after the condition
+}
+
+fn c2() {
+    let x = {};
+    if true x else {}
+    //~^ ERROR expected `{`, found `x`
+}
+
+fn d() {
+    if true else {}
+    //~^ ERROR this `if` expression is missing a block after the condition
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/bad-if-statements.stderr b/src/test/ui/parser/bad-if-statements.stderr
new file mode 100644
index 00000000000..ee839db6455
--- /dev/null
+++ b/src/test/ui/parser/bad-if-statements.stderr
@@ -0,0 +1,86 @@
+error: missing condition for `if` expression
+  --> $DIR/bad-if-statements.rs:2:7
+   |
+LL |     if {}
+   |       ^- if this block is the condition of the `if` expression, then it must be followed by another block
+   |       |
+   |       expected condition here
+
+error: this `if` expression is missing a block after the condition
+  --> $DIR/bad-if-statements.rs:7:5
+   |
+LL |     if true && {}
+   |     ^^
+   |
+help: this binary operation is possibly unfinished
+  --> $DIR/bad-if-statements.rs:7:8
+   |
+LL |     if true && {}
+   |        ^^^^^^^
+
+error: expected `{`, found `x`
+  --> $DIR/bad-if-statements.rs:13:13
+   |
+LL |     if true x
+   |             ^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/bad-if-statements.rs:13:8
+   |
+LL |     if true x
+   |        ^^^^
+help: try placing this code inside a block
+   |
+LL |     if true { x }
+   |             +   +
+
+error: missing condition for `if` expression
+  --> $DIR/bad-if-statements.rs:18:7
+   |
+LL |     if {} else {}
+   |       ^- if this block is the condition of the `if` expression, then it must be followed by another block
+   |       |
+   |       expected condition here
+
+error: this `if` expression is missing a block after the condition
+  --> $DIR/bad-if-statements.rs:23:5
+   |
+LL |     if true && {} else {}
+   |     ^^
+   |
+help: this binary operation is possibly unfinished
+  --> $DIR/bad-if-statements.rs:23:8
+   |
+LL |     if true && {} else {}
+   |        ^^^^^^^
+
+error: expected `{`, found `x`
+  --> $DIR/bad-if-statements.rs:29:13
+   |
+LL |     if true x else {}
+   |             ^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/bad-if-statements.rs:29:8
+   |
+LL |     if true x else {}
+   |        ^^^^
+help: try placing this code inside a block
+   |
+LL |     if true { x } else {}
+   |             +   +
+
+error: this `if` expression is missing a block after the condition
+  --> $DIR/bad-if-statements.rs:34:5
+   |
+LL |     if true else {}
+   |     ^^
+   |
+help: add a block here
+  --> $DIR/bad-if-statements.rs:34:12
+   |
+LL |     if true else {}
+   |            ^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/parser/can-begin-expr-check.rs b/src/test/ui/parser/can-begin-expr-check.rs
index 8974d9f48c1..e5be8de79a9 100644
--- a/src/test/ui/parser/can-begin-expr-check.rs
+++ b/src/test/ui/parser/can-begin-expr-check.rs
@@ -16,5 +16,5 @@ pub fn main() {
         return break as ();
     }
 
-    return enum; //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found keyword `enum`
+    return enum; //~ ERROR expected one of `;`, `}`, or an operator, found keyword `enum`
 }
diff --git a/src/test/ui/parser/can-begin-expr-check.stderr b/src/test/ui/parser/can-begin-expr-check.stderr
index d674fc36bc2..9569ababad8 100644
--- a/src/test/ui/parser/can-begin-expr-check.stderr
+++ b/src/test/ui/parser/can-begin-expr-check.stderr
@@ -1,8 +1,8 @@
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found keyword `enum`
+error: expected one of `;`, `}`, or an operator, found keyword `enum`
   --> $DIR/can-begin-expr-check.rs:19:12
    |
 LL |     return enum;
-   |            ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
+   |            ^^^^ expected one of `;`, `}`, or an operator
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs
index 32aeee29472..54955944c7d 100644
--- a/src/test/ui/parser/duplicate-visibility.rs
+++ b/src/test/ui/parser/duplicate-visibility.rs
@@ -2,8 +2,8 @@ fn main() {}
 
 extern "C" { //~ NOTE while parsing this item list starting here
     pub pub fn foo();
-    //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub`
-    //~| NOTE expected one of 9 possible tokens
+    //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub`
+    //~| NOTE expected one of 8 possible tokens
     //~| HELP there is already a visibility modifier, remove one
     //~| NOTE explicit visibility first seen here
 } //~ NOTE the item list ends here
diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr
index 97144ac2f64..8ecebf01f17 100644
--- a/src/test/ui/parser/duplicate-visibility.stderr
+++ b/src/test/ui/parser/duplicate-visibility.stderr
@@ -1,4 +1,4 @@
-error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub`
+error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub`
   --> $DIR/duplicate-visibility.rs:4:9
    |
 LL | extern "C" {
@@ -6,7 +6,7 @@ LL | extern "C" {
 LL |     pub pub fn foo();
    |         ^^^
    |         |
-   |         expected one of 9 possible tokens
+   |         expected one of 8 possible tokens
    |         help: there is already a visibility modifier, remove one
 ...
 LL | }
diff --git a/src/test/ui/parser/if-block-unreachable-expr.rs b/src/test/ui/parser/if-block-unreachable-expr.rs
new file mode 100644
index 00000000000..4063a337084
--- /dev/null
+++ b/src/test/ui/parser/if-block-unreachable-expr.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+// This regressed from 1.20 -> 1.21 -- the condition is unreachable,
+// but it's still an expression, and should parse fine.
+
+fn main() {
+    if { if true { return; } else { return; }; } {}
+}
diff --git a/src/test/ui/parser/issue-61858.stderr b/src/test/ui/parser/issue-61858.stderr
index 8b95d9c6ae4..03f51c6e3a8 100644
--- a/src/test/ui/parser/issue-61858.stderr
+++ b/src/test/ui/parser/issue-61858.stderr
@@ -2,9 +2,13 @@ error: expected `{`, found `)`
   --> $DIR/issue-61858.rs:2:15
    |
 LL |     (if foobar)
-   |      --       ^ expected `{`
-   |      |
-   |      this `if` expression has a condition, but no block
+   |               ^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/issue-61858.rs:2:9
+   |
+LL |     (if foobar)
+   |         ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs b/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs
index 00f90cc73b3..57d36feb37b 100644
--- a/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs
+++ b/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs
@@ -1,7 +1,8 @@
 macro_rules! x {
     ($($c:tt)*) => {
-        $($c)ö* {} //~ ERROR missing condition for `if` expression
-    };             //~| ERROR mismatched types
+        $($c)ö* {}
+        //~^ ERROR missing condition for `if` expression
+    };
 }
 
 fn main() {
diff --git a/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr b/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr
index cdd4c670500..6674b924e9c 100644
--- a/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr
+++ b/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr
@@ -2,19 +2,9 @@ error: missing condition for `if` expression
   --> $DIR/issue-68091-unicode-ident-after-if.rs:3:14
    |
 LL |         $($c)ö* {}
-   |              ^ expected if condition here
+   |              ^  - if this block is the condition of the `if` expression, then it must be followed by another block
+   |              |
+   |              expected condition here
 
-error[E0308]: mismatched types
-  --> $DIR/issue-68091-unicode-ident-after-if.rs:3:17
-   |
-LL |         $($c)ö* {}
-   |                 ^^ expected `bool`, found `()`
-...
-LL |     x!(if);
-   |     ------ in this macro invocation
-   |
-   = note: this error originates in the macro `x` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-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/src/test/ui/parser/issue-91421.rs b/src/test/ui/parser/issue-91421.rs
index 9959df56638..8bba27f3724 100644
--- a/src/test/ui/parser/issue-91421.rs
+++ b/src/test/ui/parser/issue-91421.rs
@@ -2,9 +2,8 @@
 
 fn main() {
     let value = if true && {
-    //~^ ERROR: this `if` expression has a condition, but no block
-    //~| HELP: maybe you forgot the right operand of the condition?
+    //~^ ERROR: this `if` expression is missing a block after the condition
+    //~| HELP: this binary operation is possibly unfinished
         3
-        //~^ ERROR: mismatched types [E0308]
     } else { 4 };
 }
diff --git a/src/test/ui/parser/issue-91421.stderr b/src/test/ui/parser/issue-91421.stderr
index 04284d5e3b2..2d9652051dd 100644
--- a/src/test/ui/parser/issue-91421.stderr
+++ b/src/test/ui/parser/issue-91421.stderr
@@ -1,21 +1,14 @@
-error: this `if` expression has a condition, but no block
+error: this `if` expression is missing a block after the condition
   --> $DIR/issue-91421.rs:4:17
    |
 LL |     let value = if true && {
    |                 ^^
    |
-help: maybe you forgot the right operand of the condition?
-  --> $DIR/issue-91421.rs:4:25
+help: this binary operation is possibly unfinished
+  --> $DIR/issue-91421.rs:4:20
    |
 LL |     let value = if true && {
-   |                         ^^
+   |                    ^^^^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/issue-91421.rs:7:9
-   |
-LL |         3
-   |         ^ expected `bool`, found integer
-
-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/src/test/ui/parser/issues/issue-13483.rs b/src/test/ui/parser/issues/issue-13483.rs
index a2fd9264b15..4e32fcab3f0 100644
--- a/src/test/ui/parser/issues/issue-13483.rs
+++ b/src/test/ui/parser/issues/issue-13483.rs
@@ -1,15 +1,15 @@
 fn main() {
     if true {
-    } else if { //~ ERROR missing condition
-    //~^ ERROR mismatched types
+    } else if {
+    //~^ ERROR missing condition for `if` expression
     } else {
     }
 }
 
 fn foo() {
     if true {
-    } else if { //~ ERROR missing condition
-    //~^ ERROR mismatched types
+    } else if {
+    //~^ ERROR missing condition for `if` expression
     }
     bar();
 }
diff --git a/src/test/ui/parser/issues/issue-13483.stderr b/src/test/ui/parser/issues/issue-13483.stderr
index 5fd05b18ce0..f5534090f18 100644
--- a/src/test/ui/parser/issues/issue-13483.stderr
+++ b/src/test/ui/parser/issues/issue-13483.stderr
@@ -2,32 +2,17 @@ error: missing condition for `if` expression
   --> $DIR/issue-13483.rs:3:14
    |
 LL |     } else if {
-   |              ^ expected if condition here
+   |              ^- if this block is the condition of the `if` expression, then it must be followed by another block
+   |              |
+   |              expected condition here
 
 error: missing condition for `if` expression
   --> $DIR/issue-13483.rs:11:14
    |
 LL |     } else if {
-   |              ^ expected if condition here
+   |              ^- if this block is the condition of the `if` expression, then it must be followed by another block
+   |              |
+   |              expected condition here
 
-error[E0308]: mismatched types
-  --> $DIR/issue-13483.rs:3:15
-   |
-LL |       } else if {
-   |  _______________^
-LL | |
-LL | |     } else {
-   | |_____^ expected `bool`, found `()`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-13483.rs:11:15
-   |
-LL |       } else if {
-   |  _______________^
-LL | |
-LL | |     }
-   | |_____^ expected `bool`, found `()`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issues/issue-20616-2.rs b/src/test/ui/parser/issues/issue-20616-2.rs
index f108ae5de14..2f2c6903a9f 100644
--- a/src/test/ui/parser/issues/issue-20616-2.rs
+++ b/src/test/ui/parser/issues/issue-20616-2.rs
@@ -9,7 +9,7 @@ type Type_1_<'a, T> = &'a T;
 //type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
 
 
-type Type_2 = Type_1_<'static ()>; //~ error: expected one of `,`, `:`, `=`, or `>`, found `(`
+type Type_2 = Type_1_<'static ()>; //~ error: expected one of `,` or `>`, found `(`
 
 
 //type Type_3<T> = Box<T,,>; // error: expected type, found `,`
diff --git a/src/test/ui/parser/issues/issue-20616-2.stderr b/src/test/ui/parser/issues/issue-20616-2.stderr
index 13e6aa7d605..42059685c5c 100644
--- a/src/test/ui/parser/issues/issue-20616-2.stderr
+++ b/src/test/ui/parser/issues/issue-20616-2.stderr
@@ -1,8 +1,8 @@
-error: expected one of `,`, `:`, `=`, or `>`, found `(`
+error: expected one of `,` or `>`, found `(`
   --> $DIR/issue-20616-2.rs:12:31
    |
 LL | type Type_2 = Type_1_<'static ()>;
-   |                               ^ expected one of `,`, `:`, `=`, or `>`
+   |                               ^ expected one of `,` or `>`
    |
 help: you might have meant to end the type parameters here
    |
diff --git a/src/test/ui/parser/issues/issue-51602.stderr b/src/test/ui/parser/issues/issue-51602.stderr
index d800890bca3..4a5653fdb51 100644
--- a/src/test/ui/parser/issues/issue-51602.stderr
+++ b/src/test/ui/parser/issues/issue-51602.stderr
@@ -2,9 +2,13 @@ error: expected `{`, found keyword `in`
   --> $DIR/issue-51602.rs:2:10
    |
 LL |     if i in 1..10 {
-   |     --   ^^ expected `{`
-   |     |
-   |     this `if` expression has a condition, but no block
+   |          ^^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/issue-51602.rs:2:8
+   |
+LL |     if i in 1..10 {
+   |        ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-62554.stderr b/src/test/ui/parser/issues/issue-62554.stderr
index 3589016e1dc..9e62572e388 100644
--- a/src/test/ui/parser/issues/issue-62554.stderr
+++ b/src/test/ui/parser/issues/issue-62554.stderr
@@ -57,10 +57,13 @@ 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 `{`
-   |                 |
-   |                 this `if` expression has a condition, but no block
+   |                       ^^^^^^^^^^^ 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 { }
diff --git a/src/test/ui/parser/issues/issue-62660.rs b/src/test/ui/parser/issues/issue-62660.rs
index 4f866b78976..33c8a9fa328 100644
--- a/src/test/ui/parser/issues/issue-62660.rs
+++ b/src/test/ui/parser/issues/issue-62660.rs
@@ -5,7 +5,7 @@ struct Foo;
 
 impl Foo {
     pub fn foo(_: i32, self: Box<Self) {}
-    //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `)`
+    //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `)`
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/issues/issue-62660.stderr b/src/test/ui/parser/issues/issue-62660.stderr
index be0b9a524df..14c0bdcb111 100644
--- a/src/test/ui/parser/issues/issue-62660.stderr
+++ b/src/test/ui/parser/issues/issue-62660.stderr
@@ -1,8 +1,8 @@
-error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `)`
+error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `)`
   --> $DIR/issue-62660.rs:7:38
    |
 LL |     pub fn foo(_: i32, self: Box<Self) {}
-   |                                      ^ expected one of 9 possible tokens
+   |                                      ^ expected one of 7 possible tokens
    |
 help: you might have meant to end the type parameters here
    |
diff --git a/src/test/ui/parser/issues/issue-84117.rs b/src/test/ui/parser/issues/issue-84117.rs
index 919585877cf..c9ebf133588 100644
--- a/src/test/ui/parser/issues/issue-84117.rs
+++ b/src/test/ui/parser/issues/issue-84117.rs
@@ -6,4 +6,4 @@ fn main() {
     //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
     //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
 }
-//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `}`
+//~^ ERROR expected one of `,` or `>`, found `}`
diff --git a/src/test/ui/parser/issues/issue-84117.stderr b/src/test/ui/parser/issues/issue-84117.stderr
index a2407affeef..237bc11bd06 100644
--- a/src/test/ui/parser/issues/issue-84117.stderr
+++ b/src/test/ui/parser/issues/issue-84117.stderr
@@ -21,11 +21,11 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, fo
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
    |                                                                 ^ expected one of 8 possible tokens
 
-error: expected one of `,`, `:`, `=`, or `>`, found `}`
+error: expected one of `,` or `>`, found `}`
   --> $DIR/issue-84117.rs:8:1
    |
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
-   |         ----------- while parsing the type for `outer_local`       - expected one of `,`, `:`, `=`, or `>`
+   |         ----------- while parsing the type for `outer_local`       - expected one of `,` or `>`
 ...
 LL | }
    | ^ unexpected token
diff --git a/src/test/ui/parser/issues/issue-93282.stderr b/src/test/ui/parser/issues/issue-93282.stderr
index 900f21a7cce..ee554784b3a 100644
--- a/src/test/ui/parser/issues/issue-93282.stderr
+++ b/src/test/ui/parser/issues/issue-93282.stderr
@@ -4,11 +4,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
 LL |     f<'a,>
    |         ^ expected `while`, `for`, `loop` or `{` after a label
 
-error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `{`, `}`, or an operator, found `,`
+error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `}`, or an operator, found `,`
   --> $DIR/issue-93282.rs:2:9
    |
 LL |     f<'a,>
-   |         ^ expected one of 10 possible tokens
+   |         ^ expected one of 9 possible tokens
    |
 help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
    |
diff --git a/src/test/ui/parser/issues/issue-93867.rs b/src/test/ui/parser/issues/issue-93867.rs
new file mode 100644
index 00000000000..50744792391
--- /dev/null
+++ b/src/test/ui/parser/issues/issue-93867.rs
@@ -0,0 +1,10 @@
+pub struct Entry<'a, K, V> {
+    k: &'a mut K,
+    v: V,
+}
+
+pub fn entry<'a, K, V>() -> Entry<'a K, V> {
+//                                  ^ missing comma
+//~^^ expected one of `,` or `>`, found `K`
+    unimplemented!()
+}
diff --git a/src/test/ui/parser/issues/issue-93867.stderr b/src/test/ui/parser/issues/issue-93867.stderr
new file mode 100644
index 00000000000..ee0cb4efd74
--- /dev/null
+++ b/src/test/ui/parser/issues/issue-93867.stderr
@@ -0,0 +1,13 @@
+error: expected one of `,` or `>`, found `K`
+  --> $DIR/issue-93867.rs:6:38
+   |
+LL | pub fn entry<'a, K, V>() -> Entry<'a K, V> {
+   |                                      ^ expected one of `,` or `>`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | pub fn entry<'a, K, V>() -> Entry<'a> K, V> {
+   |                                     +
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/lifetime-semicolon.fixed b/src/test/ui/parser/lifetime-semicolon.fixed
index 89e87fe9988..482b7704695 100644
--- a/src/test/ui/parser/lifetime-semicolon.fixed
+++ b/src/test/ui/parser/lifetime-semicolon.fixed
@@ -5,6 +5,6 @@ struct Foo<'a, 'b> {
 }
 
 fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {}
-//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `;`
+//~^ ERROR expected one of `,` or `>`, found `;`
 
 fn main() {}
diff --git a/src/test/ui/parser/lifetime-semicolon.rs b/src/test/ui/parser/lifetime-semicolon.rs
index 744c93fc7c7..21c8b0a7f88 100644
--- a/src/test/ui/parser/lifetime-semicolon.rs
+++ b/src/test/ui/parser/lifetime-semicolon.rs
@@ -5,6 +5,6 @@ struct Foo<'a, 'b> {
 }
 
 fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {}
-//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `;`
+//~^ ERROR expected one of `,` or `>`, found `;`
 
 fn main() {}
diff --git a/src/test/ui/parser/lifetime-semicolon.stderr b/src/test/ui/parser/lifetime-semicolon.stderr
index 5de7a5f2d5d..ee486c2366c 100644
--- a/src/test/ui/parser/lifetime-semicolon.stderr
+++ b/src/test/ui/parser/lifetime-semicolon.stderr
@@ -1,8 +1,8 @@
-error: expected one of `,`, `:`, `=`, or `>`, found `;`
+error: expected one of `,` or `>`, found `;`
   --> $DIR/lifetime-semicolon.rs:7:31
    |
 LL | fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {}
-   |                               ^ expected one of `,`, `:`, `=`, or `>`
+   |                               ^ expected one of `,` or `>`
    |
 help: use a comma to separate type parameters
    |
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
index 92d700753dc..0bf52854ec2 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
@@ -59,11 +59,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
 LL |     let _ = f<'_, i8>();
    |                 ^ expected `while`, `for`, `loop` or `{` after a label
 
-error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, `{`, or an operator, found `,`
+error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, or an operator, found `,`
   --> $DIR/require-parens-for-chained-comparison.rs:22:17
    |
 LL |     let _ = f<'_, i8>();
-   |                 ^ expected one of 10 possible tokens
+   |                 ^ expected one of 9 possible tokens
    |
 help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
    |
diff --git a/src/test/ui/pattern/for-loop-bad-item.stderr b/src/test/ui/pattern/for-loop-bad-item.stderr
index 9410e4da8d2..886d815d70b 100644
--- a/src/test/ui/pattern/for-loop-bad-item.stderr
+++ b/src/test/ui/pattern/for-loop-bad-item.stderr
@@ -5,10 +5,14 @@ LL |     for ((_, _), (&mut c, _)) in &mut map {
    |                   ^^^^^^         -------- this is an iterator with items of type `(&(char, char), &mut (char, char))`
    |                   |
    |                   expected `char`, found `&mut _`
-   |                   help: you can probably remove the explicit borrow: `c`
    |
    = note:           expected type `char`
            found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     for ((_, _), (&mut c, _)) in &mut map {
+LL +     for ((_, _), (c, _)) in &mut map {
+   | 
 
 error[E0308]: mismatched types
   --> $DIR/for-loop-bad-item.rs:14:14
diff --git a/src/test/ui/privacy/macro-private-reexport.rs b/src/test/ui/privacy/macro-private-reexport.rs
new file mode 100644
index 00000000000..d0aab528ed4
--- /dev/null
+++ b/src/test/ui/privacy/macro-private-reexport.rs
@@ -0,0 +1,17 @@
+// edition:2021
+
+#![feature(decl_macro)]
+
+mod foo {
+    macro_rules! bar {
+        () => {};
+    }
+
+    pub use bar as _; //~ ERROR `bar` is only public within the crate, and cannot be re-exported outside
+
+    macro baz() {}
+
+    pub use baz as _; //~ ERROR `baz` is private, and cannot be re-exported
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/macro-private-reexport.stderr b/src/test/ui/privacy/macro-private-reexport.stderr
new file mode 100644
index 00000000000..b8768f3612e
--- /dev/null
+++ b/src/test/ui/privacy/macro-private-reexport.stderr
@@ -0,0 +1,29 @@
+error[E0364]: `bar` is only public within the crate, and cannot be re-exported outside
+  --> $DIR/macro-private-reexport.rs:10:13
+   |
+LL |     pub use bar as _;
+   |             ^^^^^^^^
+   |
+help: consider adding a `#[macro_export]` to the macro in the imported module
+  --> $DIR/macro-private-reexport.rs:6:5
+   |
+LL | /     macro_rules! bar {
+LL | |         () => {};
+LL | |     }
+   | |_____^
+
+error[E0364]: `baz` is private, and cannot be re-exported
+  --> $DIR/macro-private-reexport.rs:14:13
+   |
+LL |     pub use baz as _;
+   |             ^^^^^^^^
+   |
+note: consider marking `baz` as `pub` in the imported module
+  --> $DIR/macro-private-reexport.rs:14:13
+   |
+LL |     pub use baz as _;
+   |             ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0364`.
diff --git a/src/test/ui/resolve/filter-intrinsics.rs b/src/test/ui/resolve/filter-intrinsics.rs
new file mode 100644
index 00000000000..c0956ef85af
--- /dev/null
+++ b/src/test/ui/resolve/filter-intrinsics.rs
@@ -0,0 +1,10 @@
+fn main() {
+    // Should suggest only `std::mem::size_of`
+    let _ = size_of::<usize>();
+    //~^ ERROR cannot find
+
+    // Should suggest `std::intrinsics::fabsf64`,
+    // since there is no non-intrinsic to suggest.
+    let _ = fabsf64(1.0);
+    //~^ ERROR cannot find
+}
diff --git a/src/test/ui/resolve/filter-intrinsics.stderr b/src/test/ui/resolve/filter-intrinsics.stderr
new file mode 100644
index 00000000000..955070891fb
--- /dev/null
+++ b/src/test/ui/resolve/filter-intrinsics.stderr
@@ -0,0 +1,25 @@
+error[E0425]: cannot find function `size_of` in this scope
+  --> $DIR/filter-intrinsics.rs:3:13
+   |
+LL |     let _ = size_of::<usize>();
+   |             ^^^^^^^ not found in this scope
+   |
+help: consider importing this function
+   |
+LL | use std::mem::size_of;
+   |
+
+error[E0425]: cannot find function `fabsf64` in this scope
+  --> $DIR/filter-intrinsics.rs:8:13
+   |
+LL |     let _ = fabsf64(1.0);
+   |             ^^^^^^^ not found in this scope
+   |
+help: consider importing this function
+   |
+LL | use std::intrinsics::fabsf64;
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/issue-50599.rs b/src/test/ui/resolve/issue-50599.rs
index 00588735b9a..78a20cf8ebb 100644
--- a/src/test/ui/resolve/issue-50599.rs
+++ b/src/test/ui/resolve/issue-50599.rs
@@ -2,4 +2,5 @@ fn main() {
     const N: u32 = 1_000;
     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; //~ ERROR cannot find value
     let mut digits = [0u32; M];
+    //~^ ERROR evaluation of constant value failed
 }
diff --git a/src/test/ui/resolve/issue-50599.stderr b/src/test/ui/resolve/issue-50599.stderr
index 4cc035cb11e..f0cb784f56c 100644
--- a/src/test/ui/resolve/issue-50599.stderr
+++ b/src/test/ui/resolve/issue-50599.stderr
@@ -16,6 +16,13 @@ LL -     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
 LL +     const M: usize = (f64::from(N) * LOG10_2) as usize;
    | 
 
-error: aborting due to previous error
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-50599.rs:4:29
+   |
+LL |     let mut digits = [0u32; M];
+   |                             ^ referenced constant has errors
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0425`.
+Some errors have detailed explanations: E0080, E0425.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs
index 5297d0d9842..d3940b13b11 100644
--- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs
+++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs
@@ -1,7 +1,5 @@
 /*
- * We don't infer `T: 'static` outlives relationships by default.
- * Instead an additional feature gate `infer_static_outlives_requirements`
- * is required.
+ * We don't infer `T: 'static` outlives relationships.
  */
 
 struct Foo<U> {
diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
index 950ffd6c89b..0c388f5fe41 100644
--- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
@@ -1,11 +1,11 @@
 error[E0310]: the parameter type `U` may not live long enough
-  --> $DIR/dont-infer-static.rs:8:10
+  --> $DIR/dont-infer-static.rs:6:10
    |
 LL |     bar: Bar<U>
    |          ^^^^^^ ...so that the type `U` will meet its required lifetime bounds...
    |
 note: ...that is required by this bound
-  --> $DIR/dont-infer-static.rs:10:15
+  --> $DIR/dont-infer-static.rs:8:15
    |
 LL | struct Bar<T: 'static> {
    |               ^^^^^^^
diff --git a/src/test/ui/rfc-2093-infer-outlives/infer-static.rs b/src/test/ui/rfc-2093-infer-outlives/infer-static.rs
deleted file mode 100644
index bd778e3b136..00000000000
--- a/src/test/ui/rfc-2093-infer-outlives/infer-static.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#![feature(rustc_attrs)]
-#![feature(infer_static_outlives_requirements)]
-
-#[rustc_outlives]
-struct Foo<U> { //~ ERROR rustc_outlives
-    bar: Bar<U>
-}
-struct Bar<T: 'static> {
-    x: T,
-}
-
-fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/infer-static.stderr
deleted file mode 100644
index 6fbb7cf4cb8..00000000000
--- a/src/test/ui/rfc-2093-infer-outlives/infer-static.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error: rustc_outlives
-  --> $DIR/infer-static.rs:5:1
-   |
-LL | / struct Foo<U> {
-LL | |     bar: Bar<U>
-LL | | }
-   | |_^
-   |
-   = note: U: 'static
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
index e24649ea044..e66caa19ec9 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
@@ -21,15 +21,15 @@ fn main() {
     };
 
     if let Some(n) = opt else {
-    //~^ ERROR missing condition for `if` expression
+    //~^ ERROR this `if` expression is missing a block after the condition
         return;
     };
     if let Some(n) = opt && n == 1 else {
-    //~^ ERROR missing condition for `if` expression
+    //~^ ERROR this `if` expression is missing a block after the condition
         return;
     };
     if let Some(n) = opt && let another = n else {
-    //~^ ERROR missing condition for `if` expression
+    //~^ ERROR this `if` expression is missing a block after the condition
         return;
     };
 
diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
index aebfc1a72b7..eea8ed0c963 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
@@ -20,23 +20,41 @@ help: wrap the expression in parentheses
 LL |     let Some(n) = (opt && let another = n) else {
    |                   +                      +
 
-error: missing condition for `if` expression
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:7
+error: this `if` expression is missing a block after the condition
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:5
    |
 LL |     if let Some(n) = opt else {
-   |       ^ expected if condition here
+   |     ^^
+   |
+help: add a block here
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:25
+   |
+LL |     if let Some(n) = opt else {
+   |                         ^
 
-error: missing condition for `if` expression
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:7
+error: this `if` expression is missing a block after the condition
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:5
    |
 LL |     if let Some(n) = opt && n == 1 else {
-   |       ^ expected if condition here
+   |     ^^
+   |
+help: add a block here
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:35
+   |
+LL |     if let Some(n) = opt && n == 1 else {
+   |                                   ^
 
-error: missing condition for `if` expression
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:7
+error: this `if` expression is missing a block after the condition
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:5
+   |
+LL |     if let Some(n) = opt && let another = n else {
+   |     ^^
+   |
+help: add a block here
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:44
    |
 LL |     if let Some(n) = opt && let another = n else {
-   |       ^ expected if condition here
+   |                                            ^
 
 error: expected `{`, found keyword `else`
   --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:37:33
diff --git a/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr b/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr
index 9e48e26b1df..9f8c928c32c 100644
--- a/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/macro-rules.stderr
@@ -4,11 +4,11 @@ error[E0364]: `legacy_macro` is only public within the crate, and cannot be re-e
 LL |     pub use legacy_macro as _;
    |             ^^^^^^^^^^^^^^^^^
    |
-note: consider marking `legacy_macro` as `pub` in the imported module
-  --> $DIR/macro-rules.rs:11:13
+help: consider adding a `#[macro_export]` to the macro in the imported module
+  --> $DIR/macro-rules.rs:7:5
    |
-LL |     pub use legacy_macro as _;
-   |             ^^^^^^^^^^^^^^^^^
+LL |     macro_rules! legacy_macro { () => () }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0659]: `legacy_macro` is ambiguous
   --> $DIR/macro-rules.rs:31:13
diff --git a/src/test/ui/suggestions/match-ergonomics.stderr b/src/test/ui/suggestions/match-ergonomics.stderr
index 4eab2df3080..a9342f9fc30 100644
--- a/src/test/ui/suggestions/match-ergonomics.stderr
+++ b/src/test/ui/suggestions/match-ergonomics.stderr
@@ -4,13 +4,15 @@ error[E0308]: mismatched types
 LL |     match &x[..] {
    |           ------ this expression has type `&[i32]`
 LL |         [&v] => {},
-   |          ^^
-   |          |
-   |          expected `i32`, found reference
-   |          help: you can probably remove the explicit borrow: `v`
+   |          ^^ expected `i32`, found reference
    |
    = note:   expected type `i32`
            found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -         [&v] => {},
+LL +         [v] => {},
+   | 
 
 error[E0529]: expected an array or slice, found `Vec<i32>`
   --> $DIR/match-ergonomics.rs:8:9
@@ -34,13 +36,15 @@ error[E0308]: mismatched types
 LL |     match y {
    |           - this expression has type `i32`
 LL |         &v => {},
-   |         ^^
-   |         |
-   |         expected `i32`, found reference
-   |         help: you can probably remove the explicit borrow: `v`
+   |         ^^ expected `i32`, found reference
    |
    = note:   expected type `i32`
            found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -         &v => {},
+LL +         v => {},
+   | 
 
 error[E0308]: mismatched types
   --> $DIR/match-ergonomics.rs:40:13
@@ -49,10 +53,14 @@ LL |     if let [&v] = &x[..] {}
    |             ^^    ------ this expression has type `&[i32]`
    |             |
    |             expected `i32`, found reference
-   |             help: you can probably remove the explicit borrow: `v`
    |
    = note:   expected type `i32`
            found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let [&v] = &x[..] {}
+LL +     if let [v] = &x[..] {}
+   | 
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/issues/issue-18400.rs b/src/test/ui/traits/issue-18400.rs
index fdd11512da3..fdd11512da3 100644
--- a/src/test/ui/issues/issue-18400.rs
+++ b/src/test/ui/traits/issue-18400.rs
diff --git a/src/test/ui/issues/issue-18400.stderr b/src/test/ui/traits/issue-18400.stderr
index 92e0f60079f..92e0f60079f 100644
--- a/src/test/ui/issues/issue-18400.stderr
+++ b/src/test/ui/traits/issue-18400.stderr
diff --git a/src/test/ui/issues/issue-18412.rs b/src/test/ui/traits/issue-18412.rs
index fe1cfb3dffa..fe1cfb3dffa 100644
--- a/src/test/ui/issues/issue-18412.rs
+++ b/src/test/ui/traits/issue-18412.rs
diff --git a/src/test/ui/issues/issue-35869.rs b/src/test/ui/traits/issue-35869.rs
index b9b4c972e58..b9b4c972e58 100644
--- a/src/test/ui/issues/issue-35869.rs
+++ b/src/test/ui/traits/issue-35869.rs
diff --git a/src/test/ui/issues/issue-35869.stderr b/src/test/ui/traits/issue-35869.stderr
index 0780109b843..0780109b843 100644
--- a/src/test/ui/issues/issue-35869.stderr
+++ b/src/test/ui/traits/issue-35869.stderr
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.rs b/src/test/ui/type/type-dependent-def-issue-49241.rs
index 4b6bc6124db..f37f093d9ed 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.rs
+++ b/src/test/ui/type/type-dependent-def-issue-49241.rs
@@ -2,4 +2,5 @@ fn main() {
     let v = vec![0];
     const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
     let s: [u32; l] = v.into_iter().collect();
+    //~^ERROR evaluation of constant value failed
 }
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr
index 64c7687f7a8..02f267c6c8d 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.stderr
+++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr
@@ -6,6 +6,13 @@ LL |     const l: usize = v.count();
    |     |
    |     help: consider using `let` instead of `const`: `let l`
 
-error: aborting due to previous error
+error[E0080]: evaluation of constant value failed
+  --> $DIR/type-dependent-def-issue-49241.rs:4:18
+   |
+LL |     let s: [u32; l] = v.into_iter().collect();
+   |                  ^ referenced constant has errors
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0435`.
+Some errors have detailed explanations: E0080, E0435.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-29124.rs b/src/test/ui/typeck/issue-29124.rs
index dd278484175..dd278484175 100644
--- a/src/test/ui/issues/issue-29124.rs
+++ b/src/test/ui/typeck/issue-29124.rs
diff --git a/src/test/ui/issues/issue-29124.stderr b/src/test/ui/typeck/issue-29124.stderr
index c5d2ec08409..c5d2ec08409 100644
--- a/src/test/ui/issues/issue-29124.stderr
+++ b/src/test/ui/typeck/issue-29124.stderr
diff --git a/src/test/ui/typeck/issue-74086.rs b/src/test/ui/typeck/issue-74086.rs
index 44ca256b051..9b7c0d7cc6e 100644
--- a/src/test/ui/typeck/issue-74086.rs
+++ b/src/test/ui/typeck/issue-74086.rs
@@ -1,4 +1,5 @@
 fn main() {
     static BUG: fn(_) -> u8 = |_| 8;
     //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions [E0121]
+    //~| ERROR the placeholder `_` is not allowed within types on item signatures for static items
 }
diff --git a/src/test/ui/typeck/issue-74086.stderr b/src/test/ui/typeck/issue-74086.stderr
index e7aea33758c..95ebf9a906c 100644
--- a/src/test/ui/typeck/issue-74086.stderr
+++ b/src/test/ui/typeck/issue-74086.stderr
@@ -4,6 +4,12 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
 LL |     static BUG: fn(_) -> u8 = |_| 8;
    |                    ^ not allowed in type signatures
 
-error: aborting due to previous error
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items
+  --> $DIR/issue-74086.rs:2:20
+   |
+LL |     static BUG: fn(_) -> u8 = |_| 8;
+   |                    ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/typeck/issue-81885.rs b/src/test/ui/typeck/issue-81885.rs
index 8935535fb7e..fb3949478a4 100644
--- a/src/test/ui/typeck/issue-81885.rs
+++ b/src/test/ui/typeck/issue-81885.rs
@@ -1,8 +1,9 @@
 const TEST4: fn() -> _ = 42;
                   //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
+                  //~| ERROR the placeholder `_` is not allowed within types on item signatures for constant items
 
 fn main() {
     const TEST5: fn() -> _ = 42;
                       //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
-
+                      //~| ERROR the placeholder `_` is not allowed within types on item signatures for constant items
 }
diff --git a/src/test/ui/typeck/issue-81885.stderr b/src/test/ui/typeck/issue-81885.stderr
index 3ff4375cd8d..91c08bd8235 100644
--- a/src/test/ui/typeck/issue-81885.stderr
+++ b/src/test/ui/typeck/issue-81885.stderr
@@ -4,12 +4,24 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
 LL | const TEST4: fn() -> _ = 42;
    |                      ^ not allowed in type signatures
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items
+  --> $DIR/issue-81885.rs:1:22
+   |
+LL | const TEST4: fn() -> _ = 42;
+   |                      ^ not allowed in type signatures
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/issue-81885.rs:5:26
+  --> $DIR/issue-81885.rs:6:26
+   |
+LL |     const TEST5: fn() -> _ = 42;
+   |                          ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items
+  --> $DIR/issue-81885.rs:6:26
    |
 LL |     const TEST5: fn() -> _ = 42;
    |                          ^ not allowed in type signatures
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/typeck/issue-88643.rs b/src/test/ui/typeck/issue-88643.rs
new file mode 100644
index 00000000000..4435cba0207
--- /dev/null
+++ b/src/test/ui/typeck/issue-88643.rs
@@ -0,0 +1,19 @@
+// Regression test for the ICE described in #88643. Specifically:
+// https://github.com/rust-lang/rust/issues/88643#issuecomment-913128893
+// and https://github.com/rust-lang/rust/issues/88643#issuecomment-913171935
+// and https://github.com/rust-lang/rust/issues/88643#issuecomment-913765984
+
+use std::collections::HashMap;
+
+pub trait T {}
+
+static CALLBACKS: HashMap<*const dyn T, dyn FnMut(&mut _) + 'static> = HashMap::new();
+//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static items [E0121]
+
+static CALLBACKS2: Vec<dyn Fn(& _)> = Vec::new();
+//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static items [E0121]
+
+static CALLBACKS3: Option<dyn Fn(& _)> = None;
+//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static items [E0121]
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-88643.stderr b/src/test/ui/typeck/issue-88643.stderr
new file mode 100644
index 00000000000..d5d596b6f42
--- /dev/null
+++ b/src/test/ui/typeck/issue-88643.stderr
@@ -0,0 +1,21 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items
+  --> $DIR/issue-88643.rs:10:56
+   |
+LL | static CALLBACKS: HashMap<*const dyn T, dyn FnMut(&mut _) + 'static> = HashMap::new();
+   |                                                        ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items
+  --> $DIR/issue-88643.rs:13:33
+   |
+LL | static CALLBACKS2: Vec<dyn Fn(& _)> = Vec::new();
+   |                                 ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items
+  --> $DIR/issue-88643.rs:16:36
+   |
+LL | static CALLBACKS3: Option<dyn Fn(& _)> = None;
+   |                                    ^ not allowed in type signatures
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.rs b/src/test/ui/typeck/typeck_type_placeholder_item_help.rs
index 53f31b683c1..c459d8c3cdc 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item_help.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.rs
@@ -12,6 +12,7 @@ const TEST3: _ = Some(42);
 
 const TEST4: fn() -> _ = 42;
 //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
+//~| ERROR the placeholder `_` is not allowed within types on item signatures for constant items
 
 trait Test5 {
     const TEST5: _ = 42;
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
index e8191832318..07a5dbd93c7 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
@@ -31,8 +31,14 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
 LL | const TEST4: fn() -> _ = 42;
    |                      ^ not allowed in type signatures
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items
+  --> $DIR/typeck_type_placeholder_item_help.rs:13:22
+   |
+LL | const TEST4: fn() -> _ = 42;
+   |                      ^ not allowed in type signatures
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item_help.rs:17:18
+  --> $DIR/typeck_type_placeholder_item_help.rs:18:18
    |
 LL |     const TEST5: _ = 42;
    |                  ^
@@ -41,7 +47,7 @@ LL |     const TEST5: _ = 42;
    |                  help: replace with the correct type: `i32`
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item_help.rs:24:18
+  --> $DIR/typeck_type_placeholder_item_help.rs:25:18
    |
 LL |     const TEST6: _ = 13;
    |                  ^
@@ -49,6 +55,6 @@ LL |     const TEST6: _ = 13;
    |                  not allowed in type signatures
    |                  help: replace with the correct type: `i32`
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0121`.
diff --git a/src/test/ui/variance/variance-object-types.rs b/src/test/ui/variance/variance-object-types.rs
index 14e11f681b1..6ded24cd1e9 100644
--- a/src/test/ui/variance/variance-object-types.rs
+++ b/src/test/ui/variance/variance-object-types.rs
@@ -1,9 +1,5 @@
-// Test that Cell is considered invariant with respect to its
-// type.
-
 #![feature(rustc_attrs)]
 
-use std::cell::Cell;
 
 // For better or worse, associated types are invariant, and hence we
 // get an invariant result for `'a`.
diff --git a/src/test/ui/variance/variance-object-types.stderr b/src/test/ui/variance/variance-object-types.stderr
index d97d222e711..2a5d8f91e1e 100644
--- a/src/test/ui/variance/variance-object-types.stderr
+++ b/src/test/ui/variance/variance-object-types.stderr
@@ -1,5 +1,5 @@
 error[E0208]: [o]
-  --> $DIR/variance-object-types.rs:11:1
+  --> $DIR/variance-object-types.rs:7:1
    |
 LL | / struct Foo<'a> {
 LL | |     x: Box<dyn Fn(i32) -> &'a i32 + 'static>
diff --git a/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs
index b364a370efa..59a7c535400 100644
--- a/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs
+++ b/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs
@@ -90,7 +90,7 @@ fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg
                     diag.span_suggestion(
                         span,
                         "use an inclusive range",
-                        sugg.to_owned(),
+                        sugg,
                         Applicability::MaybeIncorrect,
                     );
                 }
diff --git a/src/tools/clippy/clippy_lints/src/as_underscore.rs b/src/tools/clippy/clippy_lints/src/as_underscore.rs
index 464be4218dd..0bdef9d0a7e 100644
--- a/src/tools/clippy/clippy_lints/src/as_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/as_underscore.rs
@@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for AsUnderscore {
                     diag.span_suggestion(
                         ty.span,
                         "consider giving the type explicitly",
-                        format!("{}", ty_resolved),
+                        ty_resolved,
                         Applicability::MachineApplicable,
                     );
             }
diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
index 5bd7a342389..4b3a04f1255 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
@@ -51,7 +51,7 @@ struct ExVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::Closure(_, _, eid, _, _) = expr.kind {
+        if let ExprKind::Closure { body, .. } = expr.kind {
             // do not lint if the closure is called using an iterator (see #1141)
             if_chain! {
                 if let Some(parent) = get_parent_expr(self.cx, expr);
@@ -64,7 +64,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
                 }
             }
 
-            let body = self.cx.tcx.hir().body(eid);
+            let body = self.cx.tcx.hir().body(body);
             let ex = &body.value;
             if let ExprKind::Block(block, _) = ex.kind {
                 if !body.value.span.from_expansion() && !block.stmts.is_empty() {
diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs
index bfdbaf2413a..4e530256321 100644
--- a/src/tools/clippy/clippy_lints/src/bytecount.rs
+++ b/src/tools/clippy/clippy_lints/src/bytecount.rs
@@ -51,8 +51,8 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount {
             if count.ident.name == sym::count;
             if let ExprKind::MethodCall(filter, [filter_recv, filter_arg], _) = count_recv.kind;
             if filter.ident.name == sym!(filter);
-            if let ExprKind::Closure(_, _, body_id, _, _) = filter_arg.kind;
-            let body = cx.tcx.hir().body(body_id);
+            if let ExprKind::Closure { body, .. } = filter_arg.kind;
+            let body = cx.tcx.hir().body(body);
             if let [param] = body.params;
             if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind;
             if let ExprKind::Binary(ref op, l, r) = body.value.kind;
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 8288f7a8b9b..527529965a9 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -498,7 +498,7 @@ fn is_linted_explicit_deref_position(parent: Option<Node<'_>>, child_id: HirId,
         | ExprKind::Loop(..)
         | ExprKind::Match(..)
         | ExprKind::Let(..)
-        | ExprKind::Closure(..)
+        | ExprKind::Closure{..}
         | ExprKind::Block(..)
         | ExprKind::Assign(..)
         | ExprKind::AssignOp(..)
diff --git a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
index 8430e7b4c82..08bf80a4229 100644
--- a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
@@ -44,7 +44,7 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
                     diagnostic.span_suggestion_hidden(
                         span_after_ident,
                         "remove the brackets",
-                        ";".to_string(),
+                        ";",
                         Applicability::MachineApplicable);
                     },
             );
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index 10be245b362..da67888827d 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -50,8 +50,8 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
                         .tcx
                         .const_eval_poly(def_id.to_def_id())
                         .ok()
-                        .map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
-                    if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) {
+                        .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty));
+                    if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) {
                         if let ty::Adt(adt, _) = ty.kind() {
                             if adt.is_enum() {
                                 ty = adt.repr().discr_type().to_ty(cx.tcx);
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 530d6d4de35..197cac86a57 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
             return;
         }
         let body = match expr.kind {
-            ExprKind::Closure(_, _, id, _, _) => cx.tcx.hir().body(id),
+            ExprKind::Closure { body, .. } => cx.tcx.hir().body(body),
             _ => return,
         };
         if body.value.span.from_expansion() {
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index b2b9889f5dc..41e1fc4e3c2 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -158,8 +158,8 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
                 }
             }
             if method.ident.name == sym!(flat_map) && args.len() == 2 {
-                if let ExprKind::Closure(_, _, body_id, _, _) = args[1].kind {
-                    let body = cx.tcx.hir().body(body_id);
+                if let ExprKind::Closure { body, .. } = args[1].kind {
+                    let body = cx.tcx.hir().body(body);
                     return is_infinite(cx, &body.value);
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index 27db6388136..e10993ba7dd 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -3,7 +3,6 @@ use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -53,8 +52,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
             if let ItemKind::Const(hir_ty, _) = &item.kind;
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
             if let ty::Array(element_type, cst) = ty.kind();
-            if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.val();
-            if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
+            if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
+            if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
             if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
             if self.maximum_allowed_size < element_count * element_size;
 
@@ -75,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
                         diag.span_suggestion(
                             sugg_span,
                             "make this a static item",
-                            "static".to_string(),
+                            "static",
                             Applicability::MachineApplicable,
                         );
                     }
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
index 57b0d709acd..0acbd81aec3 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -3,7 +3,6 @@ use clippy_utils::source::snippet;
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -43,8 +42,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
         if_chain! {
             if let ExprKind::Repeat(_, _) = expr.kind;
             if let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind();
-            if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.val();
-            if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
+            if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
+            if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
             if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
             if self.maximum_allowed_size < element_count * element_size;
             then {
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index a348bb465c8..0b6d9adb553 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -369,8 +369,8 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
                     self.visit_expr(expr);
                 }
             },
-            ExprKind::Closure(_, _, body_id, ..) => {
-                let body = self.cx.tcx.hir().body(body_id);
+            ExprKind::Closure { body, .. } => {
+                let body = self.cx.tcx.hir().body(body);
                 self.visit_expr(&body.value);
             },
             _ => walk_expr(self, expr),
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 c025f5972d5..99d21466935 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -182,7 +182,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
             .fold(NeverLoopResult::Otherwise, combine_both),
         ExprKind::Struct(_, _, None)
         | ExprKind::Yield(_, _)
-        | ExprKind::Closure(_, _, _, _, _)
+        | ExprKind::Closure { .. }
         | ExprKind::Path(_)
         | ExprKind::ConstBlock(_)
         | ExprKind::Lit(_)
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index 82760607ba2..a5715975066 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -220,7 +220,7 @@ fn uses_iter<'tcx>(cx: &LateContext<'tcx>, iter_expr: &IterExpr, container: &'tc
                 if let Some(e) = e {
                     self.visit_expr(e);
                 }
-            } else if let ExprKind::Closure(_, _, id, _, _) = e.kind {
+            } else if let ExprKind::Closure { body: id, .. } = e.kind {
                 if is_res_used(self.cx, self.iter_expr.path, id) {
                     self.uses_iter = true;
                 }
@@ -260,7 +260,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
                     if let Some(e) = e {
                         self.visit_expr(e);
                     }
-                } else if let ExprKind::Closure(_, _, id, _, _) = e.kind {
+                } else if let ExprKind::Closure { body: id, .. } = e.kind {
                     self.used_iter = is_res_used(self.cx, self.iter_expr.path, id);
                 } else {
                     walk_expr(self, e);
@@ -307,7 +307,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
                     if let Some(e) = e {
                         self.visit_expr(e);
                     }
-                } else if let ExprKind::Closure(_, _, id, _, _) = e.kind {
+                } else if let ExprKind::Closure { body: id, .. } = e.kind {
                     self.used_after = is_res_used(self.cx, self.iter_expr.path, id);
                 } else {
                     walk_expr(self, e);
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index babc6fab3c0..d7d8a592152 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -86,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
                                 diag.span_suggestion(
                                     block.span,
                                     "move the body of the async block to the enclosing function",
-                                    body_snip.to_string(),
+                                    body_snip,
                                     Applicability::MachineApplicable
                                 );
                             }
@@ -177,8 +177,8 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
         if let Some(block_expr) = block.expr;
         if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR);
         if args.len() == 1;
-        if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0];
-        let closure_body = cx.tcx.hir().body(body_id);
+        if let Expr{kind: ExprKind::Closure { body, .. }, ..} = args[0];
+        let closure_body = cx.tcx.hir().body(body);
         if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
         then {
             return Some(closure_body);
diff --git a/src/tools/clippy/clippy_lints/src/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/manual_ok_or.rs
index bf4ab29d908..18cfd003767 100644
--- a/src/tools/clippy/clippy_lints/src/manual_ok_or.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_ok_or.rs
@@ -88,8 +88,8 @@ fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
         }
     }
     if_chain! {
-        if let ExprKind::Closure(_, _, body_id, ..) = map_expr.kind;
-        let body = cx.tcx.hir().body(body_id);
+        if let ExprKind::Closure { body, .. } = map_expr.kind;
+        let body = cx.tcx.hir().body(body);
         if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind;
         if let ExprKind::Call(Expr { kind: ExprKind::Path(ok_path), .. }, &[ref ok_arg]) = body.value.kind;
         if is_lang_ctor(cx, ok_path, ResultOk);
diff --git a/src/tools/clippy/clippy_lints/src/map_clone.rs b/src/tools/clippy/clippy_lints/src/map_clone.rs
index a13d191375b..3533de54a1e 100644
--- a/src/tools/clippy/clippy_lints/src/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/map_clone.rs
@@ -67,9 +67,9 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
             if method.ident.name == sym::map;
             let ty = cx.typeck_results().expr_ty(&args[0]);
             if is_type_diagnostic_item(cx, ty, sym::Option) || is_trait_method(cx, e, sym::Iterator);
-            if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind;
+            if let hir::ExprKind::Closure { body, .. } = args[1].kind;
             then {
-                let closure_body = cx.tcx.hir().body(body_id);
+                let closure_body = cx.tcx.hir().body(body);
                 let closure_expr = peel_blocks(&closure_body.value);
                 match closure_body.params[0].pat.kind {
                     hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding(
diff --git a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
index e3a42de0b7c..0c221441048 100644
--- a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
+++ b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
@@ -117,12 +117,19 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
             // only work if the method name is `map_err` and there are only 2 arguments (e.g. x.map_err(|_|[1]
             // Enum::Variant[2]))
             if method.ident.as_str() == "map_err" && args.len() == 2 {
-                // make sure the first argument is a closure, and grab the CaptureRef, body_id, and body_span fields
-                if let ExprKind::Closure(capture, _, body_id, body_span, _) = args[1].kind {
+                // make sure the first argument is a closure, and grab the CaptureRef, BodyId, and fn_decl_span
+                // fields
+                if let ExprKind::Closure {
+                    capture_clause,
+                    body,
+                    fn_decl_span,
+                    ..
+                } = args[1].kind
+                {
                     // check if this is by Reference (meaning there's no move statement)
-                    if capture == CaptureBy::Ref {
+                    if capture_clause == CaptureBy::Ref {
                         // Get the closure body to check the parameters and values
-                        let closure_body = cx.tcx.hir().body(body_id);
+                        let closure_body = cx.tcx.hir().body(body);
                         // make sure there's only one parameter (`|_|`)
                         if closure_body.params.len() == 1 {
                             // make sure that parameter is the wild token (`_`)
@@ -132,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
                                 span_lint_and_help(
                                     cx,
                                     MAP_ERR_IGNORE,
-                                    body_span,
+                                    fn_decl_span,
                                     "`map_err(|_|...` wildcard pattern discards the original error",
                                     None,
                                     "consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
index f552d5c1afa..663246b4c86 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -169,12 +169,12 @@ fn unit_closure<'tcx>(
     expr: &hir::Expr<'_>,
 ) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> {
     if_chain! {
-        if let hir::ExprKind::Closure(_, decl, inner_expr_id, _, _) = expr.kind;
-        let body = cx.tcx.hir().body(inner_expr_id);
+        if let hir::ExprKind::Closure { fn_decl, body, .. } = expr.kind;
+        let body = cx.tcx.hir().body(body);
         let body_expr = &body.value;
-        if decl.inputs.len() == 1;
+        if fn_decl.inputs.len() == 1;
         if is_unit_expression(cx, body_expr);
-        if let Some(binding) = iter_input_pats(decl, body).next();
+        if let Some(binding) = iter_input_pats(fn_decl, body).next();
         then {
             return Some((binding, body_expr));
         }
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index a96a7fe55f3..4f8baf7efb0 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -113,7 +113,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
                     diag.span_suggestion(
                         arm1.span,
                         "try removing the arm",
-                        String::new(),
+                        "",
                         Applicability::MaybeIncorrect,
                     )
                     .help("or try changing either arm body")
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
index a59711d4cac..9df2db45dcf 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
@@ -177,7 +177,7 @@ fn sugg_with_curlies<'a>(
 
     let (mut cbrace_start, mut cbrace_end) = (String::new(), String::new());
     if let Some(parent_expr) = get_parent_expr(cx, match_expr) {
-        if let ExprKind::Closure(..) = parent_expr.kind {
+        if let ExprKind::Closure { .. } = parent_expr.kind {
             cbrace_end = format!("\n{}}}", indent);
             // Fix body indent due to the closure
             indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index c0b3e95b185..ae69ca8a339 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_note;
 use core::cmp::Ordering;
 use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
 use rustc_lint::LateContext;
+use rustc_middle::mir;
 use rustc_middle::ty::Ty;
 use rustc_span::Span;
 
@@ -34,11 +35,25 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                 if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
                     let lhs_const = match lhs {
                         Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
-                        None => miri_to_const(ty.numeric_min_val(cx.tcx)?)?,
+                        None => {
+                            let min_val_const = ty.numeric_min_val(cx.tcx)?;
+                            let min_constant = mir::ConstantKind::from_value(
+                                cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())),
+                                ty,
+                            );
+                            miri_to_const(cx.tcx, min_constant)?
+                        },
                     };
                     let rhs_const = match rhs {
                         Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
-                        None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
+                        None => {
+                            let max_val_const = ty.numeric_max_val(cx.tcx)?;
+                            let max_constant = mir::ConstantKind::from_value(
+                                cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())),
+                                ty,
+                            );
+                            miri_to_const(cx.tcx, max_constant)?
+                        },
                     };
                     let lhs_val = lhs_const.int_value(cx, ty)?;
                     let rhs_val = rhs_const.int_value(cx, ty)?;
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index a211dc18f9e..dcaf6f865de 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -305,7 +305,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
             ExprKind::Break(_, _) |
             ExprKind::Cast(_, _) |
             // Don't want to check the closure itself, only invocation, which is covered by MethodCall
-            ExprKind::Closure(_, _, _, _, _) |
+            ExprKind::Closure { .. } |
             ExprKind::ConstBlock(_) |
             ExprKind::Continue(_) |
             ExprKind::DropTemps(_) |
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 b88ec0963f2..d31b736982b 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
@@ -150,11 +150,11 @@ pub(crate) trait BindInsteadOfMap {
         }
 
         match arg.kind {
-            hir::ExprKind::Closure(_, _, body_id, closure_args_span, _) => {
-                let closure_body = cx.tcx.hir().body(body_id);
+            hir::ExprKind::Closure { body, fn_decl_span, .. } => {
+                let closure_body = cx.tcx.hir().body(body);
                 let closure_expr = peel_blocks(&closure_body.value);
 
-                if Self::lint_closure_autofixable(cx, expr, recv, closure_expr, closure_args_span) {
+                if Self::lint_closure_autofixable(cx, expr, recv, closure_expr, fn_decl_span) {
                     true
                 } else {
                     Self::lint_closure(cx, expr, closure_expr)
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
index 558cb6bd64e..3efccd703a6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -22,8 +22,8 @@ fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy
         hir::ExprKind::Path(QPath::Resolved(_, segments)) => {
             segments.segments.last().unwrap().ident.name == method_name
         },
-        hir::ExprKind::Closure(_, _, c, _, _) => {
-            let body = cx.tcx.hir().body(*c);
+        hir::ExprKind::Closure { body, .. } => {
+            let body = cx.tcx.hir().body(*body);
             let closure_expr = peel_blocks(&body.value);
             let arg_id = body.params[0].pat.hir_id;
             match closure_expr.kind {
@@ -106,7 +106,7 @@ pub(super) fn check<'tcx>(
             if is_trait_method(cx, map_recv, sym::Iterator);
 
             // filter(|x| ...is_some())...
-            if let ExprKind::Closure(_, _, filter_body_id, ..) = filter_arg.kind;
+            if let ExprKind::Closure { body: filter_body_id, .. } = filter_arg.kind;
             let filter_body = cx.tcx.hir().body(filter_body_id);
             if let [filter_param] = filter_body.params;
             // optional ref pattern: `filter(|&x| ..)`
@@ -129,7 +129,7 @@ pub(super) fn check<'tcx>(
             if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
 
             // ...map(|x| ...unwrap())
-            if let ExprKind::Closure(_, _, map_body_id, ..) = map_arg.kind;
+            if let ExprKind::Closure { body: map_body_id, .. } = map_arg.kind;
             let map_body = cx.tcx.hir().body(map_body_id);
             if let [map_param] = map_body.params;
             if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index b50a173d835..912499bf96b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -51,8 +51,8 @@ pub(super) fn check<'tcx>(
             .map_or(false, |fun_def_id| {
                 deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
             }),
-        hir::ExprKind::Closure(_, _, body_id, _, _) => {
-            let closure_body = cx.tcx.hir().body(body_id);
+        hir::ExprKind::Closure { body, .. } => {
+            let closure_body = cx.tcx.hir().body(body);
             let closure_expr = peel_blocks(&closure_body.value);
 
             match &closure_expr.kind {
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 8989db54f6c..2d71bd6f240 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
@@ -71,27 +71,26 @@ pub(super) fn check<'tcx>(
     if is_option {
         let self_snippet = snippet(cx, recv.span, "..");
         if_chain! {
-        if let hir::ExprKind::Closure(_, _, id, span, _) = map_arg.kind;
-            let arg_snippet = snippet(cx, span, "..");
-            let body = cx.tcx.hir().body(id);
-                if let Some((func, [arg_char])) = reduce_unit_expression(&body.value);
-                if let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id));
-                if Some(id) == cx.tcx.lang_items().option_some_variant();
-                then {
-                    let func_snippet = snippet(cx, arg_char.span, "..");
-                    let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
-                       `map(..)` instead";
-                    return span_lint_and_sugg(
-                        cx,
-                        OPTION_MAP_OR_NONE,
-                        expr.span,
-                        msg,
-                        "try using `map` instead",
-                        format!("{0}.map({1} {2})", self_snippet, arg_snippet,func_snippet),
-                        Applicability::MachineApplicable,
-                    );
-                }
-
+            if let hir::ExprKind::Closure { body, fn_decl_span, .. } = map_arg.kind;
+            let arg_snippet = snippet(cx, fn_decl_span, "..");
+            let body = cx.tcx.hir().body(body);
+            if let Some((func, [arg_char])) = reduce_unit_expression(&body.value);
+            if let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id));
+            if Some(id) == cx.tcx.lang_items().option_some_variant();
+            then {
+                let func_snippet = snippet(cx, arg_char.span, "..");
+                let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
+                   `map(..)` instead";
+                return span_lint_and_sugg(
+                    cx,
+                    OPTION_MAP_OR_NONE,
+                    expr.span,
+                    msg,
+                    "try using `map` instead",
+                    format!("{0}.map({1} {2})", self_snippet, arg_snippet,func_snippet),
+                    Applicability::MachineApplicable,
+                );
+            }
         }
 
         let func_snippet = snippet(cx, map_arg.span, "..");
diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
index 5ed4ba94884..b11f4531a91 100644
--- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
@@ -41,8 +41,8 @@ pub(super) fn check<'tcx>(
             let mut applicability = Applicability::MachineApplicable;
             let any_search_snippet = if_chain! {
                 if search_method == "find";
-                if let hir::ExprKind::Closure(_, _, body_id, ..) = search_arg.kind;
-                let closure_body = cx.tcx.hir().body(body_id);
+                if let hir::ExprKind::Closure { body, .. } = search_arg.kind;
+                let closure_body = cx.tcx.hir().body(body);
                 if let Some(closure_arg) = closure_body.params.get(0);
                 then {
                     if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 90651a6ba04..4ac738272d0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -176,13 +176,13 @@ fn check_manual_split_once_indirect(
             diag.span_suggestion(
                 first.span,
                 &remove_msg,
-                String::new(),
+                "",
                 app,
             );
             diag.span_suggestion(
                 second.span,
                 &remove_msg,
-                String::new(),
+                "",
                 app,
             );
         });
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index 2fda254ca98..a405467f5e8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -18,8 +18,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
         return;
     }
 
-    if let hir::ExprKind::Closure(_, _, body_id, ..) = arg.kind {
-        let body = cx.tcx.hir().body(body_id);
+    if let hir::ExprKind::Closure { body, .. } = arg.kind {
+        let body = cx.tcx.hir().body(body);
         let arg_id = body.params[0].pat.hir_id;
         let mutates_arg =
             mutated_variables(&body.value, cx).map_or(true, |used_mutably| used_mutably.contains(&arg_id));
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index 47a81199608..913c4dbedc3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -29,8 +29,8 @@ pub(super) fn check(
     ) {
         if_chain! {
             // Extract the body of the closure passed to fold
-            if let hir::ExprKind::Closure(_, _, body_id, _, _) = acc.kind;
-            let closure_body = cx.tcx.hir().body(body_id);
+            if let hir::ExprKind::Closure { body, .. } = acc.kind;
+            let closure_body = cx.tcx.hir().body(body);
             let closure_expr = peel_blocks(&closure_body.value);
 
             // Check if the closure body is of the form `acc <op> some_expr(x)`
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 7a39557ad57..19037093e20 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -85,7 +85,7 @@ pub fn check_for_loop_iter(
                         match addr_of_expr.kind {
                             ExprKind::AddrOf(_, _, referent) => {
                                 let span = addr_of_expr.span.with_hi(referent.span.lo());
-                                diag.span_suggestion(span, "remove this `&`", String::new(), applicability);
+                                diag.span_suggestion(span, "remove this `&`", "", applicability);
                             }
                             _ => unreachable!(),
                         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index 2369be70812..865f6d0318e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -22,8 +22,8 @@ pub(super) fn check<'tcx>(
     let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
 
     if is_option || is_result {
-        if let hir::ExprKind::Closure(_, _, eid, _, _) = arg.kind {
-            let body = cx.tcx.hir().body(eid);
+        if let hir::ExprKind::Closure { body, .. } = arg.kind {
+            let body = cx.tcx.hir().body(body);
             let body_expr = &body.value;
 
             if usage::BindingUsageFinder::are_params_used(cx, body) {
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index 024bd076071..c3b850fbb9d 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -112,7 +112,7 @@ struct DivergenceVisitor<'a, 'tcx> {
 impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
     fn maybe_walk_expr(&mut self, e: &'tcx Expr<'_>) {
         match e.kind {
-            ExprKind::Closure(..) => {},
+            ExprKind::Closure { .. } => {},
             ExprKind::Match(e, arms, _) => {
                 self.visit_expr(e);
                 for arm in arms {
@@ -243,7 +243,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr<'_>) -
                 walk_expr(vis, expr);
             }
         },
-        ExprKind::Closure(_, _, _, _, _) => {
+        ExprKind::Closure { .. } => {
             // Either
             //
             // * `var` is defined in the closure body, in which case we've reached the top of the enclosing
@@ -315,7 +315,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
             // We're about to descend a closure. Since we don't know when (or
             // if) the closure will be evaluated, any reads in it might not
             // occur here (or ever). Like above, bail to avoid false positives.
-            ExprKind::Closure(_, _, _, _, _) |
+            ExprKind::Closure{..} |
 
             // We want to avoid a false positive when a variable name occurs
             // only to have its address taken, so we stop here. Technically,
diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
index 6cf513b214e..48ac695f2ac 100644
--- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
@@ -72,8 +72,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
             if has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some();
             // Skip the lint if the body is not block because this is simpler than `for` loop.
             // e.g. `v.iter().for_each(f)` is simpler and clearer than using `for` loop.
-            if let ExprKind::Closure(_, _, body_id, ..) = for_each_arg.kind;
-            let body = cx.tcx.hir().body(body_id);
+            if let ExprKind::Closure { body, .. } = for_each_arg.kind;
+            let body = cx.tcx.hir().body(body);
             if let ExprKind::Block(..) = body.value.kind;
             then {
                 let mut ret_collector = RetCollector::default();
diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
index 26c694a71fe..1f8c4c85cc2 100644
--- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
@@ -281,7 +281,7 @@ fn check<'tcx>(
                     diag.tool_only_span_suggestion(
                         local_stmt.span,
                         "remove the local",
-                        String::new(),
+                        "",
                         Applicability::MachineApplicable,
                     );
 
@@ -318,7 +318,7 @@ fn check<'tcx>(
                         diag.span_suggestion(
                             usage.stmt.span.shrink_to_hi(),
                             "add a semicolon after the `if` expression",
-                            ";".to_string(),
+                            ";",
                             applicability,
                         );
                     }
@@ -353,7 +353,7 @@ fn check<'tcx>(
                         diag.span_suggestion(
                             usage.stmt.span.shrink_to_hi(),
                             "add a semicolon after the `match` expression",
-                            ";".to_string(),
+                            ";",
                             applicability,
                         );
                     }
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 f423be4b67a..8b273aca7d0 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
@@ -258,7 +258,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                                 diag.span_suggestion(
                                     input.span,
                                     "consider changing the type to",
-                                    "&str".to_string(),
+                                    "&str",
                                     Applicability::Unspecified,
                                 );
 
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 5bf8a1ba1ca..6598413c77e 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -116,7 +116,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         return false;
     }
     match peel_blocks(expr).kind {
-        ExprKind::Lit(..) | ExprKind::Closure(..) => true,
+        ExprKind::Lit(..) | ExprKind::Closure { .. } => true,
         ExprKind::Path(..) => !has_drop(cx, cx.typeck_results().expr_ty(expr)),
         ExprKind::Index(a, b) | ExprKind::Binary(_, a, b) => has_no_effect(cx, a) && has_no_effect(cx, b),
         ExprKind::Array(v) | ExprKind::Tup(v) => v.iter().all(|val| has_no_effect(cx, val)),
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 8db41ba6ee2..7163cfe5e3a 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -13,9 +13,10 @@ use rustc_hir::{
     BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass, Lint};
+use rustc_middle::mir;
 use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
 use rustc_middle::ty::adjustment::Adjust;
-use rustc_middle::ty::{self, Const, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{InnerSpan, Span, DUMMY_SP};
 use rustc_typeck::hir_ty_to_ty;
@@ -136,19 +137,18 @@ fn is_value_unfrozen_raw<'tcx>(
     result: Result<ConstValue<'tcx>, ErrorHandled>,
     ty: Ty<'tcx>,
 ) -> bool {
-    fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool {
+    fn inner<'tcx>(cx: &LateContext<'tcx>, val: mir::ConstantKind<'tcx>) -> bool {
         match val.ty().kind() {
             // the fact that we have to dig into every structs to search enums
             // leads us to the point checking `UnsafeCell` directly is the only option.
             ty::Adt(ty_def, ..) if Some(ty_def.did()) == cx.tcx.lang_items().unsafe_cell_type() => true,
             ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
-                let val = cx.tcx.destructure_const(cx.param_env.and(val));
+                let val = cx.tcx.destructure_mir_constant(cx.param_env, val);
                 val.fields.iter().any(|field| inner(cx, *field))
             },
             _ => false,
         }
     }
-
     result.map_or_else(
         |err| {
             // Consider `TooGeneric` cases as being unfrozen.
@@ -174,7 +174,7 @@ fn is_value_unfrozen_raw<'tcx>(
             // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
             err == ErrorHandled::TooGeneric
         },
-        |val| inner(cx, Const::from_value(cx.tcx, val, ty)),
+        |val| inner(cx, mir::ConstantKind::from_value(val, ty)),
     )
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index d66698f8adc..de5f77f3ad9 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -298,8 +298,8 @@ impl<'tcx> Visitor<'tcx> for SideEffectVisit<'tcx> {
             },
             ExprKind::Match(expr, arms, _) => self.visit_match(expr, arms),
             // since analysing the closure is not easy, just set all variables in it to side-effect
-            ExprKind::Closure(_, _, body_id, _, _) => {
-                let body = self.tcx.hir().body(body_id);
+            ExprKind::Closure { body, .. } => {
+                let body = self.tcx.hir().body(body);
                 self.visit_body(body);
                 let vars = std::mem::take(&mut self.ret_vars);
                 self.add_side_effect(vars);
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index 249f11f9850..3b11cbc3760 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -255,7 +255,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                         diag.span_suggestion(
                             sugg_span,
                             "remove this",
-                            String::new(),
+                            "",
                             app,
                         );
                         if clone_usage.cloned_used {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 5a25008e95e..4c2016fe3f7 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
             if_chain! {
                 if let hir::StmtKind::Local(local) = w[0].kind;
                 if let Option::Some(t) = local.init;
-                if let hir::ExprKind::Closure(..) = t.kind;
+                if let hir::ExprKind::Closure { .. } = t.kind;
                 if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind;
                 if let hir::StmtKind::Semi(second) = w[1].kind;
                 if let hir::ExprKind::Assign(_, call, _) = second.kind;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
index d5ef86dc4e5..1bde977cfa2 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -55,7 +55,7 @@ pub(super) fn check<'tcx>(
                         sugg
                     };
 
-                    diag.span_suggestion(e.span, "consider using", sugg.to_string(), Applicability::Unspecified);
+                    diag.span_suggestion(e.span, "consider using", sugg, Applicability::Unspecified);
                 },
             );
             true
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
index d712b33de9e..31a9b69ca15 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
@@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(
                 |diag| {
                     if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
                         let sugg = arg.as_ty(cx.tcx.mk_ptr(*to_ty));
-                        diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified);
+                        diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
                     }
                 },
             );
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
index 786e7bfc56f..707a11d361c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
@@ -73,7 +73,7 @@ pub(super) fn check<'tcx>(
                             diag.span_suggestion(
                                 e.span,
                                 "try",
-                                sugg.to_string(),
+                                sugg,
                                 Applicability::Unspecified,
                             );
                         },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
index a0d104e2390..fc9227b76f0 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
@@ -46,7 +46,7 @@ pub(super) fn check<'tcx>(
                                 arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty)
                             };
 
-                            diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified);
+                            diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
                         }
                     },
                 );
@@ -64,7 +64,7 @@ pub(super) fn check<'tcx>(
                         diag.span_suggestion(
                             e.span,
                             "try",
-                            arg.as_ty(&to_ty.to_string()).to_string(),
+                            arg.as_ty(&to_ty.to_string()),
                             Applicability::Unspecified,
                         );
                     }
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index 7c39a08a336..f58da7ce9b4 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -116,13 +116,13 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
 
 fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Span, Option<Span>)> {
     if_chain! {
-        if let ExprKind::Closure(_, _fn_decl, body_id, span, _) = arg.kind;
+        if let ExprKind::Closure { body, fn_decl_span, .. } = arg.kind;
         if let ty::Closure(_def_id, substs) = &cx.typeck_results().node_type(arg.hir_id).kind();
         let ret_ty = substs.as_closure().sig().output();
         let ty = cx.tcx.erase_late_bound_regions(ret_ty);
         if ty.is_unit();
         then {
-            let body = cx.tcx.hir().body(body_id);
+            let body = cx.tcx.hir().body(body);
             if_chain! {
                 if let ExprKind::Block(block, _) = body.value.kind;
                 if block.expr.is_none();
@@ -131,9 +131,9 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa
                 then {
                     let data = stmt.span.data();
                     // Make a span out of the semicolon for the help message
-                    Some((span, Some(data.with_lo(data.hi-BytePos(1)))))
+                    Some((fn_decl_span, Some(data.with_lo(data.hi-BytePos(1)))))
                 } else {
-                    Some((span, None))
+                    Some((fn_decl_span, None))
                 }
             }
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
index d371cafb16b..7d4373b2a57 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
@@ -155,7 +155,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
         if let ExprKind::MethodCall(name_ident, args, _) = &expr.kind;
         if let name = name_ident.ident.name.to_ident_string();
         if name == "sort_by" || name == "sort_unstable_by";
-        if let [vec, Expr { kind: ExprKind::Closure(_, _, closure_body_id, _, _), .. }] = args;
+        if let [vec, Expr { kind: ExprKind::Closure{ body: closure_body_id, .. }, .. }] = args;
         if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(vec), sym::Vec);
         if let closure_body = cx.tcx.hir().body(*closure_body_id);
         if let &[
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 3f4d0fd199d..2c8820eb7e1 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -466,7 +466,13 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 self.expr(scrutinee);
                 self.slice(arms, |arm| self.arm(arm));
             },
-            ExprKind::Closure(capture_by, fn_decl, body_id, _, movability) => {
+            ExprKind::Closure {
+                capture_clause,
+                fn_decl,
+                body: body_id,
+                movability,
+                ..
+            } => {
                 let movability = OptionPat::new(movability.map(|m| format!("Movability::{m:?}")));
 
                 let ret_ty = match fn_decl.output {
@@ -475,7 +481,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 };
 
                 bind!(self, fn_decl, body_id);
-                kind!("Closure(CaptureBy::{capture_by:?}, {fn_decl}, {body_id}, _, {movability})");
+                kind!("Closure(CaptureBy::{capture_clause:?}, {fn_decl}, {body_id}, _, {movability})");
                 out!("if let {ret_ty} = {fn_decl}.output;");
                 self.body(body_id);
             },
diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs
index 49318849d58..186bba09d20 100644
--- a/src/tools/clippy/clippy_utils/src/attrs.rs
+++ b/src/tools/clippy/clippy_utils/src/attrs.rs
@@ -92,7 +92,7 @@ pub fn get_attr<'a>(
                                 diag.span_suggestion(
                                     attr_segments[1].ident.span,
                                     "consider using",
-                                    new_name.to_string(),
+                                    new_name,
                                     Applicability::MachineApplicable,
                                 );
                                 diag.emit();
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index d487868cafe..5d0ce6cc620 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -7,6 +7,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
 use rustc_lint::LateContext;
+use rustc_middle::mir;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
@@ -429,8 +430,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                         None,
                     )
                     .ok()
-                    .map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
-                let result = miri_to_const(result);
+                    .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
+                let result = miri_to_const(self.lcx.tcx, result);
                 if result.is_some() {
                     self.needed_resolution = true;
                 }
@@ -580,10 +581,10 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     }
 }
 
-pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
+pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant> {
     use rustc_middle::mir::interpret::ConstValue;
-    match result.val() {
-        ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(int))) => {
+    match result {
+        mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => {
             match result.ty().kind() {
                 ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
                 ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
@@ -603,7 +604,7 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
                 _ => None,
             }
         },
-        ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty().kind() {
+        mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() {
             ty::Ref(_, tam, _) => match tam.kind() {
                 ty::Str => String::from_utf8(
                     data.inner()
@@ -616,10 +617,10 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
             },
             _ => None,
         },
-        ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty().kind() {
+        mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
             ty::Array(sub_type, len) => match sub_type.kind() {
-                ty::Float(FloatTy::F32) => match miri_to_const(*len) {
-                    Some(Constant::Int(len)) => alloc
+                ty::Float(FloatTy::F32) => match len.to_valtree().try_to_machine_usize(tcx) {
+                    Some(len) => alloc
                         .inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize))
                         .to_owned()
@@ -633,8 +634,8 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
                         .map(Constant::Vec),
                     _ => None,
                 },
-                ty::Float(FloatTy::F64) => match miri_to_const(*len) {
-                    Some(Constant::Int(len)) => alloc
+                ty::Float(FloatTy::F64) => match len.to_valtree().try_to_machine_usize(tcx) {
+                    Some(len) => alloc
                         .inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize))
                         .to_owned()
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 1a784b6cdda..730724b95b9 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -198,7 +198,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                 | ExprKind::Let(..)
                 | ExprKind::If(..)
                 | ExprKind::Match(..)
-                | ExprKind::Closure(..)
+                | ExprKind::Closure { .. }
                 | ExprKind::Field(..)
                 | ExprKind::Path(_)
                 | ExprKind::AddrOf(..)
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 0603471c343..12931c56df6 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -622,10 +622,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_expr(e);
                 self.hash_ty(ty);
             },
-            ExprKind::Closure(cap, _, eid, _, _) => {
-                std::mem::discriminant(&cap).hash(&mut self.s);
+            ExprKind::Closure {
+                capture_clause, body, ..
+            } => {
+                std::mem::discriminant(&capture_clause).hash(&mut self.s);
                 // closures inherit TypeckResults
-                self.hash_expr(&self.cx.tcx.hir().body(eid).value);
+                self.hash_expr(&self.cx.tcx.hir().body(body).value);
             },
             ExprKind::Field(e, ref f) => {
                 self.hash_expr(e);
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 5f051e3f444..0cf23ca626c 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -962,7 +962,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
                         self.captures.entry(l).and_modify(|e| *e |= cap).or_insert(cap);
                     }
                 },
-                ExprKind::Closure(..) => {
+                ExprKind::Closure { .. } => {
                     let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id).to_def_id();
                     for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) {
                         let local_id = match capture.place.base {
@@ -1200,7 +1200,7 @@ pub fn get_enclosing_loop_or_closure<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -
         match node {
             Node::Expr(
                 e @ Expr {
-                    kind: ExprKind::Loop(..) | ExprKind::Closure(..),
+                    kind: ExprKind::Loop(..) | ExprKind::Closure { .. },
                     ..
                 },
             ) => return Some(e),
@@ -1693,7 +1693,7 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t
         _,
         &[
             Expr {
-                kind: ExprKind::Closure(_, _, body, _, _),
+                kind: ExprKind::Closure { body, .. },
                 ..
             },
         ],
@@ -1780,7 +1780,7 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool
     }
 
     match expr.kind {
-        ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
+        ExprKind::Closure { body, .. } => is_body_identity_function(cx, cx.tcx.hir().body(body)),
         _ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)),
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 4f3757f1ec6..4d21ba8bd1d 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -134,7 +134,7 @@ impl<'a> Sugg<'a> {
             | hir::ExprKind::Box(..)
             | hir::ExprKind::If(..)
             | hir::ExprKind::Let(..)
-            | hir::ExprKind::Closure(..)
+            | hir::ExprKind::Closure { .. }
             | hir::ExprKind::Unary(..)
             | hir::ExprKind::Match(..) => Sugg::MaybeParen(get_snippet(expr.span)),
             hir::ExprKind::Continue(..)
@@ -188,7 +188,7 @@ impl<'a> Sugg<'a> {
         match expr.kind {
             ast::ExprKind::AddrOf(..)
             | ast::ExprKind::Box(..)
-            | ast::ExprKind::Closure(..)
+            | ast::ExprKind::Closure { .. }
             | ast::ExprKind::If(..)
             | ast::ExprKind::Let(..)
             | ast::ExprKind::Unary(..)
@@ -790,8 +790,8 @@ pub struct DerefClosure {
 ///
 /// note: this only works on single line immutable closures with exactly one input parameter.
 pub fn deref_closure_args<'tcx>(cx: &LateContext<'_>, closure: &'tcx hir::Expr<'_>) -> Option<DerefClosure> {
-    if let hir::ExprKind::Closure(_, fn_decl, body_id, ..) = closure.kind {
-        let closure_body = cx.tcx.hir().body(body_id);
+    if let hir::ExprKind::Closure { fn_decl, body, .. } = closure.kind {
+        let closure_body = cx.tcx.hir().body(body);
         // is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
         // a type annotation is present if param `kind` is different from `TyKind::Infer`
         let closure_arg_is_type_annotated_double_ref = if let TyKind::Rptr(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index 9819778540c..3af5dfb62f9 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -185,7 +185,7 @@ pub fn local_used_after_expr(cx: &LateContext<'_>, local_id: HirId, after: &Expr
             matches!(
                 node,
                 Node::Expr(Expr {
-                    kind: ExprKind::Loop(..) | ExprKind::Closure(..),
+                    kind: ExprKind::Loop(..) | ExprKind::Closure { .. },
                     ..
                 })
             )
diff --git a/src/tools/compiletest/src/raise_fd_limit.rs b/src/tools/compiletest/src/raise_fd_limit.rs
index faded7c8024..bc2946e2c13 100644
--- a/src/tools/compiletest/src/raise_fd_limit.rs
+++ b/src/tools/compiletest/src/raise_fd_limit.rs
@@ -4,7 +4,7 @@
 /// on the number of cores available.
 ///
 /// This fixes issue #7772.
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
 #[allow(non_camel_case_types)]
 pub unsafe fn raise_fd_limit() {
     use std::cmp;
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index bed509d77be..215af347f17 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -31,6 +31,7 @@ const OS_TABLE: &[(&str, &str)] = &[
     ("redox", "redox"),
     ("sgx", "sgx"),
     ("solaris", "solaris"),
+    ("watchos", "watchos"),
     ("win32", "windows"),
     ("windows", "windows"),
     ("vxworks", "vxworks"),
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 4d6eca1c081dac022a887a134691cc7718cad94
+Subproject 4c1f50bf2bef7b25613a4c42322de87ffcf8c92
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject ad6810e90bf89a4ef0ae21349d077050bc2a4fa
+Subproject 366bd7242ed00c65f293497a26eb81c7510ac68
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index a79290e7a6b..992a2e83f63 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -73,6 +73,7 @@ features = [
 [dependencies]
 bstr = { version = "0.2.13", features = ["default"] }
 byteorder = { version = "1", features = ['default', 'std'] }
+clap = { version = "3.1.1", features = ["lazy_static", "derive", "clap_derive"]}
 curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
 crossbeam-utils = { version = "0.8.0", features = ["nightly"] }
 libc = { version = "0.2.79", features = ["align"] }
diff --git a/src/tools/rustfmt/.github/workflows/integration.yml b/src/tools/rustfmt/.github/workflows/integration.yml
index b79221d0543..4d8899b434b 100644
--- a/src/tools/rustfmt/.github/workflows/integration.yml
+++ b/src/tools/rustfmt/.github/workflows/integration.yml
@@ -69,7 +69,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
       # Run build
     - name: install rustup
diff --git a/src/tools/rustfmt/.github/workflows/linux.yml b/src/tools/rustfmt/.github/workflows/linux.yml
index 45f63b83c05..6a3f9d89d98 100644
--- a/src/tools/rustfmt/.github/workflows/linux.yml
+++ b/src/tools/rustfmt/.github/workflows/linux.yml
@@ -26,7 +26,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
       # Run build
     - name: install rustup
diff --git a/src/tools/rustfmt/.github/workflows/mac.yml b/src/tools/rustfmt/.github/workflows/mac.yml
index 55e1cc9539b..7dfda3142ca 100644
--- a/src/tools/rustfmt/.github/workflows/mac.yml
+++ b/src/tools/rustfmt/.github/workflows/mac.yml
@@ -23,7 +23,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
       # Run build
     - name: install rustup
diff --git a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml
index ca96d30f586..cd0c3218971 100644
--- a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml
+++ b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml
@@ -11,7 +11,7 @@ jobs:
     name: rustdoc check
     steps:
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
     - name: install rustup
       run: |
diff --git a/src/tools/rustfmt/.github/workflows/upload-assets.yml b/src/tools/rustfmt/.github/workflows/upload-assets.yml
index f4dd3944453..25699234a1e 100644
--- a/src/tools/rustfmt/.github/workflows/upload-assets.yml
+++ b/src/tools/rustfmt/.github/workflows/upload-assets.yml
@@ -31,7 +31,7 @@ jobs:
             target: x86_64-pc-windows-msvc
     runs-on: ${{ matrix.os }}
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
 
         # Run build
       - name: install rustup
diff --git a/src/tools/rustfmt/.github/workflows/windows.yml b/src/tools/rustfmt/.github/workflows/windows.yml
index dcb08b5412e..4ebc2963849 100644
--- a/src/tools/rustfmt/.github/workflows/windows.yml
+++ b/src/tools/rustfmt/.github/workflows/windows.yml
@@ -33,7 +33,7 @@ jobs:
     - name: disable git eol translation
       run: git config --global core.autocrlf false
     - name: checkout
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
       # Run build
     - name: Install Rustup using win.rustup.rs
diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md
index 5b233608583..bfc155cd656 100644
--- a/src/tools/rustfmt/CHANGELOG.md
+++ b/src/tools/rustfmt/CHANGELOG.md
@@ -2,9 +2,82 @@
 
 ## [Unreleased]
 
-### Fixed
+## [1.5.0] 2022-06-13
+
+### Changed
+
+- Simplify the rustfmt help text by eliding the full path to the rustfmt binary path from the usage string when running `rustfmt --help` [#5214](https://github.com/rust-lang/rustfmt/issues/5214)
+
+### Fixed
+
+- Remove duplicate imports when `imports_granularity` is set to `Item` [#4725](https://github.com/rust-lang/rustfmt/issues/4725)
+- Properly handle stdin input containing an inner skip attribute [#5368](https://github.com/rust-lang/rustfmt/issues/5368)
+- Maintain attributes on imports when `imports_granularity` is set to `Item` [#5030](https://github.com/rust-lang/rustfmt/issues/5030)
+- Format empty trait definitions as a single line when both `empty_item_single_line` is enabled and `brace_style` is set to `AlwaysNextLine` [#5047](https://github.com/rust-lang/rustfmt/issues/5047)
+- Don't change granularity of imports containing comments with `imports_granularity` if doing so could lose or misplace those comments [#5311](https://github.com/rust-lang/rustfmt/pull/5311)
+- Prevent rustfmt from removing trailing comments at the end of files annotated with inner `#![rustfmt::skip]` attributes [#5033](https://github.com/rust-lang/rustfmt/issues/5033)
+- Fixed various `error[internal]: left behind trailing whitespace"` issues:
+  - Remove trailing whitespace when formatting a where clause who's bounds have an empty right hand side [#5012](https://github.com/rust-lang/rustfmt/issues/5012) [#4850](https://github.com/rust-lang/rustfmt/issues/4850)
+  - Prevent rustfmt from adding an empty comment line when rewriting markdown lists at the start of doc comments. This issue was triggered when `wrap_comments=true` [#5088](https://github.com/rust-lang/rustfmt/issues/5088)
+- Prevent adding a block indented newline before a function parameter with a complex type that was formatted over multiple lines [#5125](https://github.com/rust-lang/rustfmt/issues/5125)
+- Fix various module resolution issues preventing rustfmt from finding modules that should be formatted:
+  - Handle external mods imported via external->inline load hierarchy [#5063](https://github.com/rust-lang/rustfmt/issues/5063)
+  - Resolve sub modules of integration tests [#5119](https://github.com/rust-lang/rustfmt/issues/5119)
+  - Module resolution will fallback to the current search directory if a relative directory search results in a `FileNotFound` error [#5198](https://github.com/rust-lang/rustfmt/issues/5198)
+- Give users a clearer error message when resolving a module who's file path is ambiguous (e.g `x.rs` and `x/mod.rs`). Before users were given a `File not found` error message which was confusing [#5167](https://github.com/rust-lang/rustfmt/issues/5167)
+- Fix various issues related to type aliases:
+  - Prevent rustfmt from adding `= impl` to associated types defined in macro bodies [#4823](https://github.com/rust-lang/rustfmt/issues/4823)
+  - Properly block indent type alias impl traits (TAITs) that wrap to the next line when `version=Two` is set. Before any trait bounds that wrapped to the next line would not be indented [#5027](https://github.com/rust-lang/rustfmt/issues/5027)
+  - Prevent rustfmt from adding an `impl Trait` definition into types [#5086](https://github.com/rust-lang/rustfmt/issues/5086)
+- Fix cases where `normalize_comments=true` would de-normalizes some comments by changing inline comments into block comments [#4909](https://github.com/rust-lang/rustfmt/issues/4909)
+- Prevent rustfmt from wrapping the content of markdown [reference-style links](https://www.markdownguide.org/basic-syntax/#reference-style-links) in doc comments [#5095](https://github.com/rust-lang/rustfmt/issues/5095) [#4933](https://github.com/rust-lang/rustfmt/issues/4933)
+- Don't format files annotated with inner `#![rustfmt::skip]` attribute [PR #5094](https://github.com/rust-lang/rustfmt/pull/5094)
+- Prevent duplicate comma when struct pattern ends with `..` and `trailing_comma=Always`. For example, `let Foo { a, .. } = b;` would become `let Foo { a,, .. } = b;` [#5066](https://github.com/rust-lang/rustfmt/issues/5066)
+- Fix the order of `static` and `async` keywords when rewriting static async closures. The correct order is `static` and then `async` (e.g `static async || {}`) [#5149](https://github.com/rust-lang/rustfmt/issues/5149)
+- Retain the fully qualified path segment when rewriting struct literals in expression position. Now `<Struct as Trait>::Type` is not rewritten as `Trait::Type` [#5151](https://github.com/rust-lang/rustfmt/issues/5151)
+- Do not remove match arm braces from a match arm with a single `ast::ExprKind::Block` that has leading attributes. Removing the braces could lead to code that does not compile. Now rustfmt will leave the outer `{}` in place when formatting `=> {#[allow(unsafe_code)]unsafe {}}` [#4109](https://github.com/rust-lang/rustfmt/issues/4109)
+- Backport json emitter and stdin changes [PR #5054](https://github.com/rust-lang/rustfmt/pull/5054)
+  - Make `--check` work when running rustfmt with input from stdin [PR #3896](https://github.com/rust-lang/rustfmt/pull/3896)
+  - Fix `--check` with the `--files-with-diff` flag [PR #3910](https://github.com/rust-lang/rustfmt/pull/3910)
+  - Produce valid JSON when using the JSON emitter [PR #3953](https://github.com/rust-lang/rustfmt/pull/3953)
+  - Fix newlines in JSON output [PR #4262](https://github.com/rust-lang/rustfmt/pull/4262)
+  - Use `<stdin>` when emitting stdin as filename [PR #4298](https://github.com/rust-lang/rustfmt/pull/4298)
+- Always generate some output when formatting `@generated` files via stdin even when `format_generated_files=false`. Not producing output caused rust-analyzer to delete the file content [rust-lang/rust-analyzer](https://github.com/rust-lang/rust-analyzer/issues/11285) [#5172](https://github.com/rust-lang/rustfmt/issues/5172)
+- Properly block indent multi-line comments in empty struct definitions. Previously, only the first comment line would be block indented. All other comment lines would be aligned with the struct definition [#4854](https://github.com/rust-lang/rustfmt/issues/4854)
+- Prevent rustfmt from wrapping a comment at a byte position inside a non-ascii character when `wrap_comments=true`. This prevents rustfmt from panicking when breaking on the invalid position [#5023](https://github.com/rust-lang/rustfmt/issues/5023)
+- Prevent rustfmt from removing commented out trailing separators (e.g commas) when rewriting lists. For example, remove the comma from a comment like this `// ...,` would lead to a scenario where the entire list could not be rewritten because the content of the comment changed [#5042](https://github.com/rust-lang/rustfmt/issues/5042)
+- Fix panic when `import_granularity` was set to `Module`, `One`, or `Crate` and the import use declaration contained an alias `use crate a::b as b1` [#5131](https://github.com/rust-lang/rustfmt/issues/5131)
+- Add a newline between generic parameters and their doc comments to prevent the generic parameters from being merged into their doc comments [#5122](https://github.com/rust-lang/rustfmt/issues/5122)
+- Fixes indentation issue where string literals manually broken with line continuation characters (`\`) would be incorrectly indented in macro definitions when setting `format_strings=true`[#4036](https://github.com/rust-lang/rustfmt/issues/4036)
+- Properly wrap and format long markdown block quotes when `wrap_comments=true` [#5157](https://github.com/rust-lang/rustfmt/issues/5157)
+- Prevent rustfmt from wrapping markdown headers even when `wrap_comments=true`. Wrapping the markdown headers would prevent them from being properly rendered with rustdoc [#5238](https://github.com/rust-lang/rustfmt/issues/5238)
+- Prevent rustfmt from removing commas between struct fields when those fields were also separated by an empty line [#4791](https://github.com/rust-lang/rustfmt/issues/4791) [#4928](https://github.com/rust-lang/rustfmt/issues/4928)
+- Fix compiler error caused when formatting imports with `imports_granularity=Module` and a path containing `self`. Given the following import `use crate::lexer::{self, tokens::TokenData};`, rustfmt would transform the `self` import into `use crate::lexer::self;`. Now rustfmt produces `use crate::lexer::{self};` [#4681](https://github.com/rust-lang/rustfmt/issues/4681)
+- Prevent rustfmt from breaking long type links in doc comments on namespace qualifiers (`::`) when `wrap_comments=true`. Breaking these long type links over multiple lines prevented them from being properly rendered in rustdoc [#5260](https://github.com/rust-lang/rustfmt/issues/5260)
+- Correctly find the start of struct bodies after any generic `const` parameters. Naively searching for an opening `{` lead to issues since generic `const` parameters are also defined with `{}` (e.g. `struct Example<const N: usize = { 1048576 }> {}`) [#5273](https://github.com/rust-lang/rustfmt/issues/5273)
+- Prevent rustfmt from merging derives when using inner or outer `rustfmt::skip::attributes` attributes. For example, `#[rustfmt::skip::attributes(derive)]` [#5270](https://github.com/rust-lang/rustfmt/issues/5270)
+- Retain trailing `;` when rewriting macro calls in extern blocks. For example, `extern "C" { x!(-); }`[#5281](https://github.com/rust-lang/rustfmt/issues/5281)
+- Add a newline when formatting struct fields preceded by both doc comments and inline comments to prevent the field from being merged into the inline comment. This was not an issue when a struct was preceded by just a doc comment or just an inline comment [#5215](https://github.com/rust-lang/rustfmt/issues/5215)
+
+### Added
+
+- Added `One` as a new [group_imports](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#group_imports) option to create a single group for all imports [PR #4966](https://github.com/rust-lang/rustfmt/pull/4966)
+- Add [short_array_element_width_threshold](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#short_array_element_width_threshold) config option to give users more control over when `Mixed` list formatting is used [PR #5228](https://github.com/rust-lang/rustfmt/pull/5228)
 
-- Fixes issue where wrapped strings would be incorrectly indented in macro defs when `format_strings` was enabled [#4036](https://github.com/rust-lang/rustfmt/issues/4036)
+### Removed
+
+- Removed unstable, nightly-only config option `report_todo` [#5101](https://github.com/rust-lang/rustfmt/issues/5101)
+- Removed unstable, nightly-only config option `report_fixme` [#5102](https://github.com/rust-lang/rustfmt/issues/5102)
+- Removed unstable, nightly-only config option `license_template_path` [#5103](https://github.com/rust-lang/rustfmt/issues/5103)
+
+### Misc
+
+- Improved performance when formatting large and deeply nested expression trees, often found in generated code, which have many expressions that exceed `max_width` [#5128](https://github.com/rust-lang/rustfmt/issues/5128), [#4867](https://github.com/rust-lang/rustfmt/issues/4867), [#4476](https://github.com/rust-lang/rustfmt/issues/4476), [#5139](https://github.com/rust-lang/rustfmt/pull/5139)
+
+### Install/Download Options
+- **rustup (nightly)** - *pending*
+- **GitHub Release Binaries** - [Release v1.5.0](https://github.com/rust-lang/rustfmt/releases/tag/v1.5.0)
+- **Build from source** - [Tag v1.5.0](https://github.com/rust-lang/rustfmt/tree/v1.5.0), see instructions for how to [install rustfmt from source][install-from-source]
 
 ## [1.4.38] 2021-10-20
 
diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock
index b932e15ef74..639d35886dc 100644
--- a/src/tools/rustfmt/Cargo.lock
+++ b/src/tools/rustfmt/Cargo.lock
@@ -4,64 +4,57 @@ version = 3
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.6"
+version = "0.7.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "annotate-snippets"
-version = "0.8.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5"
+checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36"
 dependencies = [
+ "unicode-width",
  "yansi-term",
 ]
 
 [[package]]
-name = "ansi_term"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
-dependencies = [
- "winapi",
-]
-
-[[package]]
 name = "anyhow"
-version = "1.0.25"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14"
+checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
 
 [[package]]
 name = "atty"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
 dependencies = [
+ "hermit-abi",
  "libc",
  "winapi",
 ]
 
 [[package]]
 name = "autocfg"
-version = "1.0.1"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "bitflags"
-version = "1.2.1"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bstr"
-version = "0.2.8"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245"
+checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
 dependencies = [
  "memchr",
 ]
@@ -77,27 +70,27 @@ dependencies = [
 
 [[package]]
 name = "camino"
-version = "1.0.5"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"
+checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "cargo-platform"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0226944a63d1bf35a3b5f948dd7c59e263db83695c9e8bffc4037de02e30f1d7"
+checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "cargo_metadata"
-version = "0.14.0"
+version = "0.14.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a"
+checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
 dependencies = [
  "camino",
  "cargo-platform",
@@ -108,47 +101,55 @@ dependencies = [
 
 [[package]]
 name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
-name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "clap"
-version = "2.33.0"
+version = "3.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
+checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c"
 dependencies = [
- "ansi_term",
  "atty",
  "bitflags",
+ "clap_derive",
+ "indexmap",
+ "lazy_static",
+ "os_str_bytes",
  "strsim",
+ "termcolor",
  "textwrap",
- "unicode-width",
- "vec_map",
+]
+
+[[package]]
+name = "clap_derive"
+version = "3.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.3"
+version = "0.8.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
+checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
 dependencies = [
- "autocfg",
- "cfg-if 1.0.0",
+ "cfg-if",
  "lazy_static",
 ]
 
 [[package]]
 name = "derive-new"
-version = "0.5.8"
+version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9"
+checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -157,25 +158,45 @@ dependencies = [
 
 [[package]]
 name = "diff"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
+checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
 
 [[package]]
 name = "dirs"
-version = "2.0.2"
+version = "4.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
 dependencies = [
- "cfg-if 0.1.10",
  "dirs-sys",
 ]
 
 [[package]]
+name = "dirs-next"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
+dependencies = [
+ "cfg-if",
+ "dirs-sys-next",
+]
+
+[[package]]
 name = "dirs-sys"
-version = "0.3.6"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
+name = "dirs-sys-next"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
 dependencies = [
  "libc",
  "redox_users",
@@ -184,15 +205,15 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.5.3"
+version = "1.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
 
 [[package]]
 name = "env_logger"
-version = "0.8.1"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd"
+checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
 dependencies = [
  "atty",
  "humantime",
@@ -203,9 +224,9 @@ dependencies = [
 
 [[package]]
 name = "fnv"
-version = "1.0.6"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
 [[package]]
 name = "getopts"
@@ -218,20 +239,20 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.3"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "libc",
  "wasi",
 ]
 
 [[package]]
 name = "globset"
-version = "0.4.6"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
+checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd"
 dependencies = [
  "aho-corasick",
  "bstr",
@@ -241,12 +262,24 @@ dependencies = [
 ]
 
 [[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
 name = "heck"
-version = "0.3.1"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
+checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
 dependencies = [
- "unicode-segmentation",
+ "libc",
 ]
 
 [[package]]
@@ -257,9 +290,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "ignore"
-version = "0.4.17"
+version = "0.4.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c"
+checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d"
 dependencies = [
  "crossbeam-utils",
  "globset",
@@ -274,6 +307,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "indexmap"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
 name = "itertools"
 version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -284,9 +327,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "0.4.4"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
+checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
 
 [[package]]
 name = "lazy_static"
@@ -296,9 +339,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.77"
+version = "0.2.122"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
+checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259"
 
 [[package]]
 name = "libm"
@@ -308,34 +351,49 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
 
 [[package]]
 name = "log"
-version = "0.4.14"
+version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
 ]
 
 [[package]]
 name = "memchr"
-version = "2.2.1"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "once_cell"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
+
+[[package]]
+name = "os_str_bytes"
+version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
+checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
+dependencies = [
+ "memchr",
+]
 
 [[package]]
 name = "packed_simd_2"
-version = "0.3.4"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
+checksum = "defdcfef86dcc44ad208f71d9ff4ce28df6537a4e0d6b0e8e845cb8ca10059a6"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
  "libm",
 ]
 
 [[package]]
 name = "proc-macro-error"
-version = "0.4.11"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
 dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
@@ -346,71 +404,69 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error-attr"
-version = "0.4.11"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
- "syn-mid",
  "version_check",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.26"
+version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
+checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
 dependencies = [
  "unicode-xid",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.6"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
+checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.4"
+version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
+checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
 dependencies = [
  "bitflags",
 ]
 
 [[package]]
 name = "redox_users"
-version = "0.4.0"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
 dependencies = [
  "getrandom",
  "redox_syscall",
+ "thiserror",
 ]
 
 [[package]]
 name = "regex"
-version = "1.4.3"
+version = "1.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
 dependencies = [
  "aho-corasick",
  "memchr",
  "regex-syntax",
- "thread_local",
 ]
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.22"
+version = "0.6.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 
 [[package]]
 name = "rustc-workspace-hack"
@@ -429,12 +485,13 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.38"
+version = "1.5.0"
 dependencies = [
  "annotate-snippets",
  "anyhow",
  "bytecount",
  "cargo_metadata",
+ "clap",
  "derive-new",
  "diff",
  "dirs",
@@ -449,7 +506,6 @@ dependencies = [
  "rustfmt-config_proc_macro",
  "serde",
  "serde_json",
- "structopt",
  "term",
  "thiserror",
  "toml",
@@ -459,43 +515,49 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustversion"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
+
+[[package]]
 name = "ryu"
-version = "1.0.2"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
+checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
 
 [[package]]
 name = "same-file"
-version = "1.0.5"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
 dependencies = [
  "winapi-util",
 ]
 
 [[package]]
 name = "semver"
-version = "1.0.4"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
+checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.126"
+version = "1.0.136"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
+checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.126"
+version = "1.0.136"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
+checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -504,9 +566,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.59"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
+checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
 dependencies = [
  "itoa",
  "ryu",
@@ -515,39 +577,15 @@ dependencies = [
 
 [[package]]
 name = "strsim"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
-
-[[package]]
-name = "structopt"
-version = "0.3.11"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073"
-dependencies = [
- "clap",
- "lazy_static",
- "structopt-derive",
-]
-
-[[package]]
-name = "structopt-derive"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
-]
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "syn"
-version = "1.0.65"
+version = "1.0.91"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
+checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -555,58 +593,45 @@ dependencies = [
 ]
 
 [[package]]
-name = "syn-mid"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "term"
-version = "0.6.1"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
+checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
 dependencies = [
- "dirs",
+ "dirs-next",
+ "rustversion",
  "winapi",
 ]
 
 [[package]]
 name = "termcolor"
-version = "1.0.5"
+version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
 dependencies = [
- "wincolor",
+ "winapi-util",
 ]
 
 [[package]]
 name = "textwrap"
-version = "0.11.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
+checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
 
 [[package]]
 name = "thiserror"
-version = "1.0.6"
+version = "1.0.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc6b305ec0e323c7b6cfff6098a22516e0063d0bb7c3d88660a890217dca099a"
+checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.6"
+version = "1.0.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45ba8d810d9c48fc456b7ad54574e8bfb7c7918a57ad7a6e6a0985d7959e8597"
+checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -615,39 +640,39 @@ dependencies = [
 
 [[package]]
 name = "thread_local"
-version = "1.0.1"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
+checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
 dependencies = [
- "lazy_static",
+ "once_cell",
 ]
 
 [[package]]
 name = "toml"
-version = "0.5.3"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724"
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.3.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
+checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.6"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
 
 [[package]]
 name = "unicode-xid"
-version = "0.2.0"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
 
 [[package]]
 name = "unicode_categories"
@@ -656,22 +681,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
 
 [[package]]
-name = "vec_map"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
-
-[[package]]
 name = "version_check"
-version = "0.9.1"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "walkdir"
-version = "2.2.9"
+version = "2.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
 dependencies = [
  "same-file",
  "winapi",
@@ -686,9 +705,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
 
 [[package]]
 name = "winapi"
-version = "0.3.8"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
 dependencies = [
  "winapi-i686-pc-windows-gnu",
  "winapi-x86_64-pc-windows-gnu",
@@ -702,9 +721,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
 [[package]]
 name = "winapi-util"
-version = "0.1.2"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
 dependencies = [
  "winapi",
 ]
@@ -716,16 +735,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
-name = "wincolor"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9"
-dependencies = [
- "winapi",
- "winapi-util",
-]
-
-[[package]]
 name = "yansi-term"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index 764714638a9..f26e9824062 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 
 name = "rustfmt-nightly"
-version = "1.4.38"
+version = "1.5.0"
 description = "Tool to find and fix Rust formatting issues"
 repository = "https://github.com/rust-lang/rustfmt"
 readme = "README.md"
@@ -33,30 +33,31 @@ rustfmt-format-diff = []
 generic-simd = ["bytecount/generic-simd"]
 
 [dependencies]
-itertools = "0.10.1"
-toml = "0.5"
-serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"
-unicode-segmentation = "1.0.0"
-regex = "1.0"
-term = "0.6"
+annotate-snippets = { version = "0.9", features = ["color"] }
+anyhow = "1.0"
+bytecount = "0.6"
+cargo_metadata = "0.14"
+clap = { version = "3.1", features = ["derive"] }
+derive-new = "0.5"
 diff = "0.1"
-log = "0.4.14"
-env_logger = "0.8"
+dirs = "4.0"
+env_logger = "0.9"
 getopts = "0.2"
-derive-new = "0.5"
-cargo_metadata = "0.14"
-bytecount = "0.6"
-unicode-width = "0.1.5"
-unicode_categories = "0.1.1"
-dirs = "2.0.1"
-ignore = "0.4.17"
-annotate-snippets = { version = "0.8", features = ["color"] }
-structopt = "0.3"
-rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" }
-lazy_static = "1.0.0"
-anyhow = "1.0"
+ignore = "0.4"
+itertools = "0.10"
+lazy_static = "1.4"
+log = "0.4"
+regex = "1.5"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+term = "0.7"
 thiserror = "1.0"
+toml = "0.5"
+unicode-segmentation = "1.9"
+unicode-width = "0.1"
+unicode_categories = "0.1"
+
+rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" }
 
 # A noop dependency that changes in the Rust repository, it's a bit of a hack.
 # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md
index a47439b9ba9..8c84614352c 100644
--- a/src/tools/rustfmt/Configurations.md
+++ b/src/tools/rustfmt/Configurations.md
@@ -10,7 +10,7 @@ reorder_imports = false
 ```
 
 Each configuration option is either stable or unstable.
-Stable options can be used directly, while unstable options are opt-in.
+Stable options can always be used, while unstable options are only available on a nightly toolchain and must be opted into.
 To enable unstable options, set `unstable_features = true` in `rustfmt.toml` or pass `--unstable-features` to rustfmt.
 
 # Configuration Options
@@ -1065,7 +1065,7 @@ See also: [`tab_spaces`](#tab_spaces).
 Control the case of the letters in hexadecimal literal values
 
 - **Default value**: `Preserve`
-- **Possible values**: `Upper`, `Lower`
+- **Possible values**: `Preserve`, `Upper`, `Lower`
 - **Stable**: No (tracking issue: [#5081](https://github.com/rust-lang/rustfmt/issues/5081))
 
 ## `hide_parse_errors`
@@ -1473,26 +1473,6 @@ use core::slice;
 #[cfg(feature = "alloc")] use core::slice;
 ```
 
-## `license_template_path`
-
-Check whether beginnings of files match a license template.
-
-- **Default value**: `""`
-- **Possible values**: path to a license template file
-- **Stable**: No (tracking issue: [#3352](https://github.com/rust-lang/rustfmt/issues/3352))
-
-A license template is a plain text file which is matched literally against the
-beginning of each source file, except for `{}`-delimited blocks, which are
-matched as regular expressions. The following license template therefore
-matches strings like `// Copyright 2017 The Rust Project Developers.`, `//
-Copyright 2018 The Rust Project Developers.`, etc.:
-
-```
-// Copyright {\d+} The Rust Project Developers.
-```
-
-`\{`, `\}` and `\\` match literal braces / backslashes.
-
 ## `match_arm_blocks`
 
 Controls whether arm bodies are wrapped in cases where the first line of the body cannot fit on the same line as the `=>` operator.
@@ -1705,6 +1685,8 @@ How imports should be grouped into `use` statements. Imports will be merged or s
 - **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One`
 - **Stable**: No (tracking issue: [#4991](https://github.com/rust-lang/rustfmt/issues/4991))
 
+Note that rustfmt will not modify the granularity of imports containing comments if doing so could potentially lose or misplace said comments.
+
 #### `Preserve` (default):
 
 Do not change the granularity of any imports and preserve the original structure written by the developer.
@@ -2061,12 +2043,16 @@ use sit;
 
 ## `group_imports`
 
-Controls the strategy for how imports are grouped together.
+Controls the strategy for how consecutive imports are grouped together.
+
+Controls the strategy for grouping sets of consecutive imports. Imports may contain newlines between imports and still be grouped together as a single set, but other statements between imports will result in different grouping sets.
 
 - **Default value**: `Preserve`
 - **Possible values**: `Preserve`, `StdExternalCrate`, `One`
 - **Stable**: No (tracking issue: [#5083](https://github.com/rust-lang/rustfmt/issues/5083))
 
+Each set of imports (one or more `use` statements, optionally separated by newlines) will be formatted independently. Other statements such as `mod ...` or `extern crate ...` will cause imports to not be grouped together.
+
 #### `Preserve` (default):
 
 Preserve the source file's import groups.
@@ -2162,35 +2148,6 @@ mod sit;
 **Note** `mod` with `#[macro_export]` will not be reordered since that could change the semantics
 of the original source code.
 
-## `report_fixme`
-
-Report `FIXME` items in comments.
-
-- **Default value**: `"Never"`
-- **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"`
-- **Stable**: No (tracking issue: [#3394](https://github.com/rust-lang/rustfmt/issues/3394))
-
-Warns about any comments containing `FIXME` in them when set to `"Always"`. If
-it contains a `#X` (with `X` being a number) in parentheses following the
-`FIXME`, `"Unnumbered"` will ignore it.
-
-See also [`report_todo`](#report_todo).
-
-
-## `report_todo`
-
-Report `TODO` items in comments.
-
-- **Default value**: `"Never"`
-- **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"`
-- **Stable**: No (tracking issue: [#3393](https://github.com/rust-lang/rustfmt/issues/3393))
-
-Warns about any comments containing `TODO` in them when set to `"Always"`. If
-it contains a `#X` (with `X` being a number) in parentheses following the
-`TODO`, `"Unnumbered"` will ignore it.
-
-See also [`report_fixme`](#report_fixme).
-
 ## `required_version`
 
 Require a specific version of rustfmt. If you want to make sure that the
diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain
index 94b57d506c2..813e5e2c10f 100644
--- a/src/tools/rustfmt/rust-toolchain
+++ b/src/tools/rustfmt/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-03-27"
+channel = "nightly-2022-06-06"
 components = ["rustc-dev"]
diff --git a/src/tools/rustfmt/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs
index 8cb7b4585ec..55fd75f6de9 100644
--- a/src/tools/rustfmt/src/cargo-fmt/main.rs
+++ b/src/tools/rustfmt/src/cargo-fmt/main.rs
@@ -10,59 +10,63 @@ use std::ffi::OsStr;
 use std::fs;
 use std::hash::{Hash, Hasher};
 use std::io::{self, Write};
-use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::str;
 
-use structopt::StructOpt;
+use clap::{CommandFactory, Parser};
 
 #[path = "test/mod.rs"]
 #[cfg(test)]
 mod cargo_fmt_tests;
 
-#[derive(StructOpt, Debug)]
-#[structopt(
+#[derive(Parser)]
+#[clap(
     bin_name = "cargo fmt",
     about = "This utility formats all bin and lib files of \
              the current crate using rustfmt."
 )]
 pub struct Opts {
     /// No output printed to stdout
-    #[structopt(short = "q", long = "quiet")]
+    #[clap(short = 'q', long = "quiet")]
     quiet: bool,
 
     /// Use verbose output
-    #[structopt(short = "v", long = "verbose")]
+    #[clap(short = 'v', long = "verbose")]
     verbose: bool,
 
     /// Print rustfmt version and exit
-    #[structopt(long = "version")]
+    #[clap(long = "version")]
     version: bool,
 
     /// Specify package to format
-    #[structopt(short = "p", long = "package", value_name = "package")]
+    #[clap(
+        short = 'p',
+        long = "package",
+        value_name = "package",
+        multiple_values = true
+    )]
     packages: Vec<String>,
 
     /// Specify path to Cargo.toml
-    #[structopt(long = "manifest-path", value_name = "manifest-path")]
+    #[clap(long = "manifest-path", value_name = "manifest-path")]
     manifest_path: Option<String>,
 
     /// Specify message-format: short|json|human
-    #[structopt(long = "message-format", value_name = "message-format")]
+    #[clap(long = "message-format", value_name = "message-format")]
     message_format: Option<String>,
 
     /// Options passed to rustfmt
     // 'raw = true' to make `--` explicit.
-    #[structopt(name = "rustfmt_options", raw(true))]
+    #[clap(name = "rustfmt_options", raw(true))]
     rustfmt_options: Vec<String>,
 
     /// Format all packages, and also their local path-based dependencies
-    #[structopt(long = "all")]
+    #[clap(long = "all")]
     format_all: bool,
 
     /// Run rustfmt in check mode
-    #[structopt(long = "check")]
+    #[clap(long = "check")]
     check: bool,
 }
 
@@ -87,7 +91,7 @@ fn execute() -> i32 {
         }
     });
 
-    let opts = Opts::from_iter(args);
+    let opts = Opts::parse_from(args);
 
     let verbosity = match (opts.verbose, opts.quiet) {
         (false, false) => Verbosity::Normal,
@@ -204,7 +208,7 @@ fn convert_message_format_to_rustfmt_args(
 
 fn print_usage_to_stderr(reason: &str) {
     eprintln!("{}", reason);
-    let app = Opts::clap();
+    let app = Opts::command();
     app.after_help("")
         .write_help(&mut io::stderr())
         .expect("failed to write to stderr");
diff --git a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs
index 360503632c7..56e52fbabb6 100644
--- a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs
+++ b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs
@@ -6,7 +6,7 @@ mod targets;
 #[test]
 fn default_options() {
     let empty: Vec<String> = vec![];
-    let o = Opts::from_iter(&empty);
+    let o = Opts::parse_from(&empty);
     assert_eq!(false, o.quiet);
     assert_eq!(false, o.verbose);
     assert_eq!(false, o.version);
@@ -20,7 +20,7 @@ fn default_options() {
 
 #[test]
 fn good_options() {
-    let o = Opts::from_iter(&[
+    let o = Opts::parse_from(&[
         "test",
         "-q",
         "-p",
@@ -47,8 +47,8 @@ fn good_options() {
 #[test]
 fn unexpected_option() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "unexpected"])
+        Opts::command()
+            .try_get_matches_from(&["test", "unexpected"])
             .is_err()
     );
 }
@@ -56,8 +56,8 @@ fn unexpected_option() {
 #[test]
 fn unexpected_flag() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "--flag"])
+        Opts::command()
+            .try_get_matches_from(&["test", "--flag"])
             .is_err()
     );
 }
@@ -65,20 +65,20 @@ fn unexpected_flag() {
 #[test]
 fn mandatory_separator() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "--emit"])
+        Opts::command()
+            .try_get_matches_from(&["test", "--emit"])
             .is_err()
     );
     assert!(
-        !Opts::clap()
-            .get_matches_from_safe(&["test", "--", "--emit"])
+        !Opts::command()
+            .try_get_matches_from(&["test", "--", "--emit"])
             .is_err()
     );
 }
 
 #[test]
 fn multiple_packages_one_by_one() {
-    let o = Opts::from_iter(&[
+    let o = Opts::parse_from(&[
         "test",
         "-p",
         "package1",
@@ -92,7 +92,7 @@ fn multiple_packages_one_by_one() {
 
 #[test]
 fn multiple_packages_grouped() {
-    let o = Opts::from_iter(&[
+    let o = Opts::parse_from(&[
         "test",
         "--package",
         "package1",
@@ -106,14 +106,18 @@ fn multiple_packages_grouped() {
 
 #[test]
 fn empty_packages_1() {
-    assert!(Opts::clap().get_matches_from_safe(&["test", "-p"]).is_err());
+    assert!(
+        Opts::command()
+            .try_get_matches_from(&["test", "-p"])
+            .is_err()
+    );
 }
 
 #[test]
 fn empty_packages_2() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "-p", "--", "--check"])
+        Opts::command()
+            .try_get_matches_from(&["test", "-p", "--", "--check"])
             .is_err()
     );
 }
@@ -121,8 +125,8 @@ fn empty_packages_2() {
 #[test]
 fn empty_packages_3() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "-p", "--verbose"])
+        Opts::command()
+            .try_get_matches_from(&["test", "-p", "--verbose"])
             .is_err()
     );
 }
@@ -130,8 +134,8 @@ fn empty_packages_3() {
 #[test]
 fn empty_packages_4() {
     assert!(
-        Opts::clap()
-            .get_matches_from_safe(&["test", "-p", "--check"])
+        Opts::command()
+            .try_get_matches_from(&["test", "-p", "--check"])
             .is_err()
     );
 }
diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs
index f9d8a0fa70c..eb195b1f762 100644
--- a/src/tools/rustfmt/src/comment.rs
+++ b/src/tools/rustfmt/src/comment.rs
@@ -796,7 +796,7 @@ impl<'a> CommentRewrite<'a> {
         // 1) wrap_comments = true is configured
         // 2) The comment is not the start of a markdown header doc comment
         // 3) The comment width exceeds the shape's width
-        // 4) No URLS were found in the commnet
+        // 4) No URLS were found in the comment
         let should_wrap_comment = self.fmt.config.wrap_comments()
             && !is_markdown_header_doc_comment
             && unicode_str_width(line) > self.fmt.shape.width
diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs
index 7fc4486ddcd..e37ed798cb5 100644
--- a/src/tools/rustfmt/src/config/config_type.rs
+++ b/src/tools/rustfmt/src/config/config_type.rs
@@ -61,9 +61,6 @@ macro_rules! create_config {
         #[derive(Clone)]
         #[allow(unreachable_pub)]
         pub struct Config {
-            // if a license_template_path has been specified, successfully read, parsed and compiled
-            // into a regex, it will be stored here
-            pub license_template: Option<Regex>,
             // For each config item, we store a bool indicating whether it has
             // been accessed and the value, and a bool whether the option was
             // manually initialised, or taken from the default,
@@ -104,7 +101,6 @@ macro_rules! create_config {
                     | "struct_variant_width"
                     | "array_width"
                     | "chain_width" => self.0.set_heuristics(),
-                    "license_template_path" => self.0.set_license_template(),
                     "merge_imports" => self.0.set_merge_imports(),
                     &_ => (),
                 }
@@ -163,7 +159,6 @@ macro_rules! create_config {
                 }
             )+
                 self.set_heuristics();
-                self.set_license_template();
                 self.set_ignore(dir);
                 self.set_merge_imports();
                 self
@@ -247,7 +242,6 @@ macro_rules! create_config {
                     | "struct_variant_width"
                     | "array_width"
                     | "chain_width" => self.set_heuristics(),
-                    "license_template_path" => self.set_license_template(),
                     "merge_imports" => self.set_merge_imports(),
                     &_ => (),
                 }
@@ -386,21 +380,6 @@ macro_rules! create_config {
                 };
             }
 
-            fn set_license_template(&mut self) {
-                if self.was_set().license_template_path() {
-                    let lt_path = self.license_template_path();
-                    if lt_path.len() > 0 {
-                        match license::load_and_compile_template(&lt_path) {
-                            Ok(re) => self.license_template = Some(re),
-                            Err(msg) => eprintln!("Warning for license template file {:?}: {}",
-                                                lt_path, msg),
-                        }
-                    } else {
-                        self.license_template = None;
-                    }
-                }
-            }
-
             fn set_ignore(&mut self, dir: &Path) {
                 self.ignore.2.add_prefix(dir);
             }
@@ -437,7 +416,6 @@ macro_rules! create_config {
         impl Default for Config {
             fn default() -> Config {
                 Config {
-                    license_template: None,
                     $(
                         $i: (Cell::new(false), false, $def, $stb),
                     )+
diff --git a/src/tools/rustfmt/src/config/license.rs b/src/tools/rustfmt/src/config/license.rs
deleted file mode 100644
index c7feb502ea9..00000000000
--- a/src/tools/rustfmt/src/config/license.rs
+++ /dev/null
@@ -1,265 +0,0 @@
-use std::fmt;
-use std::fs::File;
-use std::io;
-use std::io::Read;
-
-use regex::Regex;
-
-#[derive(Debug)]
-pub(crate) enum LicenseError {
-    IO(io::Error),
-    Regex(regex::Error),
-    Parse(String),
-}
-
-impl fmt::Display for LicenseError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            LicenseError::IO(ref err) => err.fmt(f),
-            LicenseError::Regex(ref err) => err.fmt(f),
-            LicenseError::Parse(ref err) => write!(f, "parsing failed, {}", err),
-        }
-    }
-}
-
-impl From<io::Error> for LicenseError {
-    fn from(err: io::Error) -> LicenseError {
-        LicenseError::IO(err)
-    }
-}
-
-impl From<regex::Error> for LicenseError {
-    fn from(err: regex::Error) -> LicenseError {
-        LicenseError::Regex(err)
-    }
-}
-
-// the template is parsed using a state machine
-enum ParsingState {
-    Lit,
-    LitEsc,
-    // the u32 keeps track of brace nesting
-    Re(u32),
-    ReEsc(u32),
-    Abort(String),
-}
-
-use self::ParsingState::*;
-
-pub(crate) struct TemplateParser {
-    parsed: String,
-    buffer: String,
-    state: ParsingState,
-    linum: u32,
-    open_brace_line: u32,
-}
-
-impl TemplateParser {
-    fn new() -> Self {
-        Self {
-            parsed: "^".to_owned(),
-            buffer: String::new(),
-            state: Lit,
-            linum: 1,
-            // keeps track of last line on which a regex placeholder was started
-            open_brace_line: 0,
-        }
-    }
-
-    /// Converts a license template into a string which can be turned into a regex.
-    ///
-    /// The license template could use regex syntax directly, but that would require a lot of manual
-    /// escaping, which is inconvenient. It is therefore literal by default, with optional regex
-    /// subparts delimited by `{` and `}`. Additionally:
-    ///
-    /// - to insert literal `{`, `}` or `\`, escape it with `\`
-    /// - an empty regex placeholder (`{}`) is shorthand for `{.*?}`
-    ///
-    /// This function parses this input format and builds a properly escaped *string* representation
-    /// of the equivalent regular expression. It **does not** however guarantee that the returned
-    /// string is a syntactically valid regular expression.
-    ///
-    /// # Examples
-    ///
-    /// ```text
-    /// assert_eq!(
-    ///     TemplateParser::parse(
-    ///         r"
-    /// // Copyright {\d+} The \} Rust \\ Project \{ Developers. See the {([A-Z]+)}
-    /// // file at the top-level directory of this distribution and at
-    /// // {}.
-    /// //
-    /// // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-    /// // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-    /// // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-    /// // option. This file may not be copied, modified, or distributed
-    /// // except according to those terms.
-    /// "
-    ///     ).unwrap(),
-    ///     r"^
-    /// // Copyright \d+ The \} Rust \\ Project \{ Developers\. See the ([A-Z]+)
-    /// // file at the top\-level directory of this distribution and at
-    /// // .*?\.
-    /// //
-    /// // Licensed under the Apache License, Version 2\.0 <LICENSE\-APACHE or
-    /// // http://www\.apache\.org/licenses/LICENSE\-2\.0> or the MIT license
-    /// // <LICENSE\-MIT or http://opensource\.org/licenses/MIT>, at your
-    /// // option\. This file may not be copied, modified, or distributed
-    /// // except according to those terms\.
-    /// "
-    /// );
-    /// ```
-    pub(crate) fn parse(template: &str) -> Result<String, LicenseError> {
-        let mut parser = Self::new();
-        for chr in template.chars() {
-            if chr == '\n' {
-                parser.linum += 1;
-            }
-            parser.state = match parser.state {
-                Lit => parser.trans_from_lit(chr),
-                LitEsc => parser.trans_from_litesc(chr),
-                Re(brace_nesting) => parser.trans_from_re(chr, brace_nesting),
-                ReEsc(brace_nesting) => parser.trans_from_reesc(chr, brace_nesting),
-                Abort(msg) => return Err(LicenseError::Parse(msg)),
-            };
-        }
-        // check if we've ended parsing in a valid state
-        match parser.state {
-            Abort(msg) => return Err(LicenseError::Parse(msg)),
-            Re(_) | ReEsc(_) => {
-                return Err(LicenseError::Parse(format!(
-                    "escape or balance opening brace on l. {}",
-                    parser.open_brace_line
-                )));
-            }
-            LitEsc => {
-                return Err(LicenseError::Parse(format!(
-                    "incomplete escape sequence on l. {}",
-                    parser.linum
-                )));
-            }
-            _ => (),
-        }
-        parser.parsed.push_str(&regex::escape(&parser.buffer));
-
-        Ok(parser.parsed)
-    }
-
-    fn trans_from_lit(&mut self, chr: char) -> ParsingState {
-        match chr {
-            '{' => {
-                self.parsed.push_str(&regex::escape(&self.buffer));
-                self.buffer.clear();
-                self.open_brace_line = self.linum;
-                Re(1)
-            }
-            '}' => Abort(format!(
-                "escape or balance closing brace on l. {}",
-                self.linum
-            )),
-            '\\' => LitEsc,
-            _ => {
-                self.buffer.push(chr);
-                Lit
-            }
-        }
-    }
-
-    fn trans_from_litesc(&mut self, chr: char) -> ParsingState {
-        self.buffer.push(chr);
-        Lit
-    }
-
-    fn trans_from_re(&mut self, chr: char, brace_nesting: u32) -> ParsingState {
-        match chr {
-            '{' => {
-                self.buffer.push(chr);
-                Re(brace_nesting + 1)
-            }
-            '}' => {
-                match brace_nesting {
-                    1 => {
-                        // default regex for empty placeholder {}
-                        if self.buffer.is_empty() {
-                            self.parsed.push_str(".*?");
-                        } else {
-                            self.parsed.push_str(&self.buffer);
-                        }
-                        self.buffer.clear();
-                        Lit
-                    }
-                    _ => {
-                        self.buffer.push(chr);
-                        Re(brace_nesting - 1)
-                    }
-                }
-            }
-            '\\' => {
-                self.buffer.push(chr);
-                ReEsc(brace_nesting)
-            }
-            _ => {
-                self.buffer.push(chr);
-                Re(brace_nesting)
-            }
-        }
-    }
-
-    fn trans_from_reesc(&mut self, chr: char, brace_nesting: u32) -> ParsingState {
-        self.buffer.push(chr);
-        Re(brace_nesting)
-    }
-}
-
-pub(crate) fn load_and_compile_template(path: &str) -> Result<Regex, LicenseError> {
-    let mut lt_file = File::open(&path)?;
-    let mut lt_str = String::new();
-    lt_file.read_to_string(&mut lt_str)?;
-    let lt_parsed = TemplateParser::parse(&lt_str)?;
-    Ok(Regex::new(&lt_parsed)?)
-}
-
-#[cfg(test)]
-mod test {
-    use super::TemplateParser;
-
-    #[test]
-    fn test_parse_license_template() {
-        assert_eq!(
-            TemplateParser::parse("literal (.*)").unwrap(),
-            r"^literal \(\.\*\)"
-        );
-        assert_eq!(
-            TemplateParser::parse(r"escaping \}").unwrap(),
-            r"^escaping \}"
-        );
-        assert!(TemplateParser::parse("unbalanced } without escape").is_err());
-        assert_eq!(
-            TemplateParser::parse(r"{\d+} place{-?}holder{s?}").unwrap(),
-            r"^\d+ place-?holders?"
-        );
-        assert_eq!(TemplateParser::parse("default {}").unwrap(), "^default .*?");
-        assert_eq!(
-            TemplateParser::parse(r"unbalanced nested braces {\{{3}}").unwrap(),
-            r"^unbalanced nested braces \{{3}"
-        );
-        assert_eq!(
-            &TemplateParser::parse("parsing error }")
-                .unwrap_err()
-                .to_string(),
-            "parsing failed, escape or balance closing brace on l. 1"
-        );
-        assert_eq!(
-            &TemplateParser::parse("parsing error {\nsecond line")
-                .unwrap_err()
-                .to_string(),
-            "parsing failed, escape or balance opening brace on l. 1"
-        );
-        assert_eq!(
-            &TemplateParser::parse(r"parsing error \")
-                .unwrap_err()
-                .to_string(),
-            "parsing failed, incomplete escape sequence on l. 1"
-        );
-    }
-}
diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs
index 18e1854612b..a5169528187 100644
--- a/src/tools/rustfmt/src/config/mod.rs
+++ b/src/tools/rustfmt/src/config/mod.rs
@@ -5,7 +5,6 @@ use std::io::{Error, ErrorKind, Read};
 use std::path::{Path, PathBuf};
 use std::{env, fs};
 
-use regex::Regex;
 use thiserror::Error;
 
 use crate::config::config_type::ConfigType;
@@ -22,7 +21,6 @@ pub(crate) mod config_type;
 pub(crate) mod options;
 
 pub(crate) mod file_lines;
-pub(crate) mod license;
 pub(crate) mod lists;
 
 // This macro defines configuration options used in rustfmt. Each option
@@ -63,8 +61,6 @@ create_config! {
         "Maximum length of comments. No effect unless wrap_comments = true";
     normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible";
     normalize_doc_attributes: bool, false, false, "Normalize doc attributes as doc comments";
-    license_template_path: String, String::default(), false,
-        "Beginning of file must match license template";
     format_strings: bool, false, false, "Format string literals where necessary";
     format_macro_matchers: bool, false, false,
         "Format the metavariable matching patterns in macros";
@@ -164,10 +160,6 @@ create_config! {
     error_on_unformatted: bool, false, false,
         "Error if unable to get comments or string literals within max_width, \
          or they are left with trailing whitespaces";
-    report_todo: ReportTactic, ReportTactic::Never, false,
-        "Report all, none or unnumbered occurrences of TODO in source file comments";
-    report_fixme: ReportTactic, ReportTactic::Never, false,
-        "Report all, none or unnumbered occurrences of FIXME in source file comments";
     ignore: IgnoreList, IgnoreList::default(), false,
         "Skip formatting the specified files and directories";
 
@@ -418,8 +410,6 @@ mod test {
         create_config! {
             // Options that are used by the generated functions
             max_width: usize, 100, true, "Maximum width of each line";
-            license_template_path: String, String::default(), false,
-                "Beginning of file must match license template";
             required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false,
                 "Require a specific version of rustfmt.";
             ignore: IgnoreList, IgnoreList::default(), false,
@@ -525,31 +515,6 @@ mod test {
     }
 
     #[test]
-    fn test_empty_string_license_template_path() {
-        let toml = r#"license_template_path = """#;
-        let config = Config::from_toml(toml, Path::new("")).unwrap();
-        assert!(config.license_template.is_none());
-    }
-
-    #[nightly_only_test]
-    #[test]
-    fn test_valid_license_template_path() {
-        let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
-        let config = Config::from_toml(toml, Path::new("")).unwrap();
-        assert!(config.license_template.is_some());
-    }
-
-    #[nightly_only_test]
-    #[test]
-    fn test_override_existing_license_with_no_license() {
-        let toml = r#"license_template_path = "tests/license-template/lt.txt""#;
-        let mut config = Config::from_toml(toml, Path::new("")).unwrap();
-        assert!(config.license_template.is_some());
-        config.override_value("license_template_path", "");
-        assert!(config.license_template.is_none());
-    }
-
-    #[test]
     fn test_dump_default_config() {
         let default_config = format!(
             r#"max_width = 100
@@ -570,7 +535,6 @@ format_code_in_doc_comments = false
 comment_width = 80
 normalize_comments = false
 normalize_doc_attributes = false
-license_template_path = ""
 format_strings = false
 format_macro_matchers = false
 format_macro_bodies = true
@@ -625,8 +589,6 @@ skip_children = false
 hide_parse_errors = false
 error_on_line_overflow = false
 error_on_unformatted = false
-report_todo = "Never"
-report_fixme = "Never"
 ignore = []
 emit_mode = "Files"
 make_backup = false
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index e4cc93026f1..4ccf1ca70c9 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 use std::cmp::min;
+use std::collections::HashMap;
 
 use itertools::Itertools;
 use rustc_ast::token::{Delimiter, LitKind};
@@ -22,7 +23,7 @@ use crate::macros::{rewrite_macro, MacroPosition};
 use crate::matches::rewrite_match;
 use crate::overflow::{self, IntoOverflowableItem, OverflowableItem};
 use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{QueryId, Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
 use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
@@ -54,6 +55,54 @@ pub(crate) fn format_expr(
     context: &RewriteContext<'_>,
     shape: Shape,
 ) -> Option<String> {
+    // when max_width is tight, we should check all possible formattings, in order to find
+    // if we can fit expression in the limit. Doing it recursively takes exponential time
+    // relative to input size, and people hit it with rustfmt takes minutes in #4476 #4867 #5128
+    // By memoization of format_expr function, we format each pair of expression and shape
+    // only once, so worst case execution time becomes O(n*max_width^3).
+    if context.inside_macro() || context.is_macro_def {
+        // span ids are not unique in macros, so we don't memoize result of them.
+        return format_expr_inner(expr, expr_type, context, shape);
+    }
+    let clean;
+    let query_id = QueryId {
+        shape,
+        span: expr.span,
+    };
+    if let Some(map) = context.memoize.take() {
+        if let Some(r) = map.get(&query_id) {
+            let r = r.clone();
+            context.memoize.set(Some(map)); // restore map in the memoize cell for other users
+            return r;
+        }
+        context.memoize.set(Some(map));
+        clean = false;
+    } else {
+        context.memoize.set(Some(HashMap::default()));
+        clean = true; // We got None, so we are the top level called function. When
+        // this function finishes, no one is interested in what is in the map, because
+        // all of them are sub expressions of this top level expression, and this is
+        // done. So we should clean up memoize map to save some memory.
+    }
+
+    let r = format_expr_inner(expr, expr_type, context, shape);
+    if clean {
+        context.memoize.set(None);
+    } else {
+        if let Some(mut map) = context.memoize.take() {
+            map.insert(query_id, r.clone()); // insert the result in the memoize map
+            context.memoize.set(Some(map)); // so it won't be computed again
+        }
+    }
+    r
+}
+
+fn format_expr_inner(
+    expr: &ast::Expr,
+    expr_type: ExprType,
+    context: &RewriteContext<'_>,
+    shape: Shape,
+) -> Option<String> {
     skip_out_of_file_lines_range!(context, expr.span);
 
     if contains_skip(&*expr.attrs) {
diff --git a/src/tools/rustfmt/src/format-diff/main.rs b/src/tools/rustfmt/src/format-diff/main.rs
index 655aeda42bf..f6b739e1c2a 100644
--- a/src/tools/rustfmt/src/format-diff/main.rs
+++ b/src/tools/rustfmt/src/format-diff/main.rs
@@ -19,8 +19,7 @@ use std::process;
 
 use regex::Regex;
 
-use structopt::clap::AppSettings;
-use structopt::StructOpt;
+use clap::{CommandFactory, Parser};
 
 /// The default pattern of files to format.
 ///
@@ -37,16 +36,16 @@ enum FormatDiffError {
     IoError(#[from] io::Error),
 }
 
-#[derive(StructOpt, Debug)]
-#[structopt(
+#[derive(Parser, Debug)]
+#[clap(
     name = "rustfmt-format-diff",
-    setting = AppSettings::DisableVersion,
-    setting = AppSettings::NextLineHelp
+    disable_version_flag = true,
+    next_line_help = true
 )]
 pub struct Opts {
     /// Skip the smallest prefix containing NUMBER slashes
-    #[structopt(
-        short = "p",
+    #[clap(
+        short = 'p',
         long = "skip-prefix",
         value_name = "NUMBER",
         default_value = "0"
@@ -54,8 +53,8 @@ pub struct Opts {
     skip_prefix: u32,
 
     /// Custom pattern selecting file paths to reformat
-    #[structopt(
-        short = "f",
+    #[clap(
+        short = 'f',
         long = "filter",
         value_name = "PATTERN",
         default_value = DEFAULT_PATTERN
@@ -65,10 +64,12 @@ pub struct Opts {
 
 fn main() {
     env_logger::Builder::from_env("RUSTFMT_LOG").init();
-    let opts = Opts::from_args();
+    let opts = Opts::parse();
     if let Err(e) = run(opts) {
         println!("{}", e);
-        Opts::clap().print_help().expect("cannot write to stdout");
+        Opts::command()
+            .print_help()
+            .expect("cannot write to stdout");
         process::exit(1);
     }
 }
@@ -230,14 +231,14 @@ mod cmd_line_tests {
     #[test]
     fn default_options() {
         let empty: Vec<String> = vec![];
-        let o = Opts::from_iter(&empty);
+        let o = Opts::parse_from(&empty);
         assert_eq!(DEFAULT_PATTERN, o.filter);
         assert_eq!(0, o.skip_prefix);
     }
 
     #[test]
     fn good_options() {
-        let o = Opts::from_iter(&["test", "-p", "10", "-f", r".*\.hs"]);
+        let o = Opts::parse_from(&["test", "-p", "10", "-f", r".*\.hs"]);
         assert_eq!(r".*\.hs", o.filter);
         assert_eq!(10, o.skip_prefix);
     }
@@ -245,8 +246,8 @@ mod cmd_line_tests {
     #[test]
     fn unexpected_option() {
         assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "unexpected"])
+            Opts::command()
+                .try_get_matches_from(&["test", "unexpected"])
                 .is_err()
         );
     }
@@ -254,8 +255,8 @@ mod cmd_line_tests {
     #[test]
     fn unexpected_flag() {
         assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "--flag"])
+            Opts::command()
+                .try_get_matches_from(&["test", "--flag"])
                 .is_err()
         );
     }
@@ -263,8 +264,8 @@ mod cmd_line_tests {
     #[test]
     fn overridden_option() {
         assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "-p", "10", "-p", "20"])
+            Opts::command()
+                .try_get_matches_from(&["test", "-p", "10", "-p", "20"])
                 .is_err()
         );
     }
@@ -272,8 +273,8 @@ mod cmd_line_tests {
     #[test]
     fn negative_filter() {
         assert!(
-            Opts::clap()
-                .get_matches_from_safe(&["test", "-p", "-1"])
+            Opts::command()
+                .try_get_matches_from(&["test", "-p", "-1"])
                 .is_err()
         );
     }
diff --git a/src/tools/rustfmt/src/format_report_formatter.rs b/src/tools/rustfmt/src/format_report_formatter.rs
index 90406cdb95e..fd536d4df41 100644
--- a/src/tools/rustfmt/src/format_report_formatter.rs
+++ b/src/tools/rustfmt/src/format_report_formatter.rs
@@ -142,10 +142,9 @@ fn error_kind_to_snippet_annotation_type(error_kind: &ErrorKind) -> AnnotationTy
         | ErrorKind::ModuleResolutionError(_)
         | ErrorKind::ParseError
         | ErrorKind::LostComment
-        | ErrorKind::LicenseCheck
         | ErrorKind::BadAttr
         | ErrorKind::InvalidGlobPattern(_)
         | ErrorKind::VersionMismatch => AnnotationType::Error,
-        ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => AnnotationType::Warning,
+        ErrorKind::DeprecatedAttr => AnnotationType::Warning,
     }
 }
diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs
index ebadf3dd598..e644ea50eff 100644
--- a/src/tools/rustfmt/src/formatting.rs
+++ b/src/tools/rustfmt/src/formatting.rs
@@ -2,6 +2,7 @@
 
 use std::collections::HashMap;
 use std::io::{self, Write};
+use std::rc::Rc;
 use std::time::{Duration, Instant};
 
 use rustc_ast::ast;
@@ -11,7 +12,6 @@ use self::newline_style::apply_newline_style;
 use crate::comment::{CharClasses, FullCodeCharKind};
 use crate::config::{Config, FileName, Verbosity};
 use crate::formatting::generated::is_generated_file;
-use crate::issues::BadIssueSeeker;
 use crate::modules::Module;
 use crate::parse::parser::{DirectoryOwnership, Parser, ParserError};
 use crate::parse::session::ParseSess;
@@ -39,12 +39,10 @@ impl<'b, T: Write + 'b> Session<'b, T> {
         rustc_span::create_session_if_not_set_then(self.config.edition().into(), |_| {
             if self.config.disable_all_formatting() {
                 // When the input is from stdin, echo back the input.
-                if let Input::Text(ref buf) = input {
-                    if let Err(e) = io::stdout().write_all(buf.as_bytes()) {
-                        return Err(From::from(e));
-                    }
-                }
-                return Ok(FormatReport::new());
+                return match input {
+                    Input::Text(ref buf) => echo_back_stdin(buf),
+                    _ => Ok(FormatReport::new()),
+                };
             }
 
             let config = &self.config.clone();
@@ -93,6 +91,13 @@ fn should_skip_module<T: FormatHandler>(
     false
 }
 
+fn echo_back_stdin(input: &str) -> Result<FormatReport, ErrorKind> {
+    if let Err(e) = io::stdout().write_all(input.as_bytes()) {
+        return Err(From::from(e));
+    }
+    Ok(FormatReport::new())
+}
+
 // Format an entire crate (or subset of the module tree).
 fn format_project<T: FormatHandler>(
     input: Input,
@@ -135,7 +140,8 @@ fn format_project<T: FormatHandler>(
     .visit_crate(&krate)?
     .into_iter()
     .filter(|(path, module)| {
-        !should_skip_module(config, &context, input_is_stdin, &main_file, path, module)
+        input_is_stdin
+            || !should_skip_module(config, &context, input_is_stdin, &main_file, path, module)
     })
     .collect::<Vec<_>>();
 
@@ -145,6 +151,14 @@ fn format_project<T: FormatHandler>(
     context.parse_session.set_silent_emitter();
 
     for (path, module) in files {
+        if input_is_stdin && contains_skip(module.attrs()) {
+            return echo_back_stdin(
+                context
+                    .parse_session
+                    .snippet_provider(module.span)
+                    .entire_snippet(),
+            );
+        }
         should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path));
         context.format_file(path, &module, is_macro_def)?;
     }
@@ -189,6 +203,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
             self.config,
             &snippet_provider,
             self.report.clone(),
+            Rc::default(),
         );
         visitor.skip_context.update_with_attrs(&self.krate.attrs);
         visitor.is_macro_def = is_macro_def;
@@ -329,10 +344,8 @@ impl FormattingError {
             ErrorKind::LineOverflow(found, max) => (max, found - max),
             ErrorKind::TrailingWhitespace
             | ErrorKind::DeprecatedAttr
-            | ErrorKind::BadIssue(_)
             | ErrorKind::BadAttr
-            | ErrorKind::LostComment
-            | ErrorKind::LicenseCheck => {
+            | ErrorKind::LostComment => {
                 let trailing_ws_start = self
                     .line_buffer
                     .rfind(|c: char| !c.is_whitespace())
@@ -364,7 +377,7 @@ pub(crate) struct ReportedErrors {
     // Code contains macro call that was unable to format.
     pub(crate) has_macro_format_failure: bool,
 
-    // Failed a check, such as the license check or other opt-in checking.
+    // Failed an opt-in checking.
     pub(crate) has_check_errors: bool,
 
     /// Formatted code differs from existing code (--check only).
@@ -460,7 +473,6 @@ fn format_lines(
     report: &FormatReport,
 ) {
     let mut formatter = FormatLines::new(name, skipped_range, config);
-    formatter.check_license(text);
     formatter.iterate(text);
 
     if formatter.newline_count > 1 {
@@ -480,11 +492,9 @@ struct FormatLines<'a> {
     cur_line: usize,
     newline_count: usize,
     errors: Vec<FormattingError>,
-    issue_seeker: BadIssueSeeker,
     line_buffer: String,
     current_line_contains_string_literal: bool,
     format_line: bool,
-    allow_issue_seek: bool,
     config: &'a Config,
 }
 
@@ -494,7 +504,6 @@ impl<'a> FormatLines<'a> {
         skipped_range: &'a [(usize, usize)],
         config: &'a Config,
     ) -> FormatLines<'a> {
-        let issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme());
         FormatLines {
             name,
             skipped_range,
@@ -503,8 +512,6 @@ impl<'a> FormatLines<'a> {
             cur_line: 1,
             newline_count: 0,
             errors: vec![],
-            allow_issue_seek: !issue_seeker.is_disabled(),
-            issue_seeker,
             line_buffer: String::with_capacity(config.max_width() * 2),
             current_line_contains_string_literal: false,
             format_line: config.file_lines().contains_line(name, 1),
@@ -512,20 +519,6 @@ impl<'a> FormatLines<'a> {
         }
     }
 
-    fn check_license(&mut self, text: &mut String) {
-        if let Some(ref license_template) = self.config.license_template {
-            if !license_template.is_match(text) {
-                self.errors.push(FormattingError {
-                    line: self.cur_line,
-                    kind: ErrorKind::LicenseCheck,
-                    is_comment: false,
-                    is_string: false,
-                    line_buffer: String::new(),
-                });
-            }
-        }
-    }
-
     // Iterate over the chars in the file map.
     fn iterate(&mut self, text: &mut String) {
         for (kind, c) in CharClasses::new(text.chars()) {
@@ -533,13 +526,6 @@ impl<'a> FormatLines<'a> {
                 continue;
             }
 
-            if self.allow_issue_seek && self.format_line {
-                // Add warnings for bad todos/ fixmes
-                if let Some(issue) = self.issue_seeker.inspect(c) {
-                    self.push_err(ErrorKind::BadIssue(issue), false, false);
-                }
-            }
-
             if c == '\n' {
                 self.new_line(kind);
             } else {
diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs
index 02319809486..559ed3917db 100644
--- a/src/tools/rustfmt/src/imports.rs
+++ b/src/tools/rustfmt/src/imports.rs
@@ -2,6 +2,10 @@ use std::borrow::Cow;
 use std::cmp::Ordering;
 use std::fmt;
 
+use core::hash::{Hash, Hasher};
+
+use itertools::Itertools;
+
 use rustc_ast::ast::{self, UseTreeKind};
 use rustc_span::{
     symbol::{self, sym},
@@ -10,6 +14,7 @@ use rustc_span::{
 
 use crate::comment::combine_strs_with_missing_comments;
 use crate::config::lists::*;
+use crate::config::ImportGranularity;
 use crate::config::{Edition, IndentStyle};
 use crate::lists::{
     definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
@@ -86,7 +91,7 @@ impl<'a> FmtVisitor<'a> {
 // sorting.
 
 // FIXME we do a lot of allocation to make our own representation.
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, Hash, PartialEq)]
 pub(crate) enum UseSegment {
     Ident(String, Option<String>),
     Slf(Option<String>),
@@ -180,17 +185,36 @@ impl UseSegment {
             }
         })
     }
+
+    fn contains_comment(&self) -> bool {
+        if let UseSegment::List(list) = self {
+            list.iter().any(|subtree| subtree.contains_comment())
+        } else {
+            false
+        }
+    }
 }
 
-pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -> Vec<UseTree> {
+pub(crate) fn normalize_use_trees_with_granularity(
+    use_trees: Vec<UseTree>,
+    import_granularity: ImportGranularity,
+) -> Vec<UseTree> {
+    let merge_by = match import_granularity {
+        ImportGranularity::Item => return flatten_use_trees(use_trees, ImportGranularity::Item),
+        ImportGranularity::Preserve => return use_trees,
+        ImportGranularity::Crate => SharedPrefix::Crate,
+        ImportGranularity::Module => SharedPrefix::Module,
+        ImportGranularity::One => SharedPrefix::One,
+    };
+
     let mut result = Vec::with_capacity(use_trees.len());
     for use_tree in use_trees {
-        if use_tree.has_comment() || use_tree.attrs.is_some() {
+        if use_tree.contains_comment() || use_tree.attrs.is_some() {
             result.push(use_tree);
             continue;
         }
 
-        for mut flattened in use_tree.flatten() {
+        for mut flattened in use_tree.flatten(import_granularity) {
             if let Some(tree) = result
                 .iter_mut()
                 .find(|tree| tree.share_prefix(&flattened, merge_by))
@@ -208,11 +232,17 @@ pub(crate) fn merge_use_trees(use_trees: Vec<UseTree>, merge_by: SharedPrefix) -
     result
 }
 
-pub(crate) fn flatten_use_trees(use_trees: Vec<UseTree>) -> Vec<UseTree> {
+fn flatten_use_trees(
+    use_trees: Vec<UseTree>,
+    import_granularity: ImportGranularity,
+) -> Vec<UseTree> {
+    // Return non-sorted single occurance of the use-trees text string;
+    // order is by first occurance of the use-tree.
     use_trees
         .into_iter()
-        .flat_map(UseTree::flatten)
+        .flat_map(|tree| tree.flatten(import_granularity))
         .map(UseTree::nest_trailing_self)
+        .unique()
         .collect()
 }
 
@@ -541,6 +571,10 @@ impl UseTree {
         self.list_item.as_ref().map_or(false, ListItem::has_comment)
     }
 
+    fn contains_comment(&self) -> bool {
+        self.has_comment() || self.path.iter().any(|path| path.contains_comment())
+    }
+
     fn same_visibility(&self, other: &UseTree) -> bool {
         match (&self.visibility, &other.visibility) {
             (
@@ -567,6 +601,7 @@ impl UseTree {
         if self.path.is_empty()
             || other.path.is_empty()
             || self.attrs.is_some()
+            || self.contains_comment()
             || !self.same_visibility(other)
         {
             false
@@ -581,8 +616,8 @@ impl UseTree {
         }
     }
 
-    fn flatten(self) -> Vec<UseTree> {
-        if self.path.is_empty() {
+    fn flatten(self, import_granularity: ImportGranularity) -> Vec<UseTree> {
+        if self.path.is_empty() || self.contains_comment() {
             return vec![self];
         }
         match self.path.clone().last().unwrap() {
@@ -595,7 +630,7 @@ impl UseTree {
                 let prefix = &self.path[..self.path.len() - 1];
                 let mut result = vec![];
                 for nested_use_tree in list {
-                    for flattend in &mut nested_use_tree.clone().flatten() {
+                    for flattend in &mut nested_use_tree.clone().flatten(import_granularity) {
                         let mut new_path = prefix.to_vec();
                         new_path.append(&mut flattend.path);
                         result.push(UseTree {
@@ -603,7 +638,11 @@ impl UseTree {
                             span: self.span,
                             list_item: None,
                             visibility: self.visibility.clone(),
-                            attrs: None,
+                            // only retain attributes for `ImportGranularity::Item`
+                            attrs: match import_granularity {
+                                ImportGranularity::Item => self.attrs.clone(),
+                                _ => None,
+                            },
                         });
                     }
                 }
@@ -748,6 +787,12 @@ fn merge_use_trees_inner(trees: &mut Vec<UseTree>, use_tree: UseTree, merge_by:
     trees.sort();
 }
 
+impl Hash for UseTree {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.path.hash(state);
+    }
+}
+
 impl PartialOrd for UseSegment {
     fn partial_cmp(&self, other: &UseSegment) -> Option<Ordering> {
         Some(self.cmp(other))
@@ -951,7 +996,7 @@ impl Rewrite for UseTree {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub(crate) enum SharedPrefix {
+enum SharedPrefix {
     Crate,
     Module,
     One,
@@ -1106,7 +1151,10 @@ mod test {
     macro_rules! test_merge {
         ($by:ident, [$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) => {
             assert_eq!(
-                merge_use_trees(parse_use_trees!($($input,)*), SharedPrefix::$by),
+                normalize_use_trees_with_granularity(
+                    parse_use_trees!($($input,)*),
+                    ImportGranularity::$by,
+                ),
                 parse_use_trees!($($output,)*),
             );
         }
@@ -1215,12 +1263,18 @@ mod test {
     #[test]
     fn test_flatten_use_trees() {
         assert_eq!(
-            flatten_use_trees(parse_use_trees!["foo::{a::{b, c}, d::e}"]),
+            flatten_use_trees(
+                parse_use_trees!["foo::{a::{b, c}, d::e}"],
+                ImportGranularity::Item
+            ),
             parse_use_trees!["foo::a::b", "foo::a::c", "foo::d::e"]
         );
 
         assert_eq!(
-            flatten_use_trees(parse_use_trees!["foo::{self, a, b::{c, d}, e::*}"]),
+            flatten_use_trees(
+                parse_use_trees!["foo::{self, a, b::{c, d}, e::*}"],
+                ImportGranularity::Item
+            ),
             parse_use_trees![
                 "foo::{self}",
                 "foo::a",
@@ -1234,12 +1288,13 @@ mod test {
     #[test]
     fn test_use_tree_flatten() {
         assert_eq!(
-            parse_use_tree("a::b::{c, d, e, f}").flatten(),
+            parse_use_tree("a::b::{c, d, e, f}").flatten(ImportGranularity::Item),
             parse_use_trees!("a::b::c", "a::b::d", "a::b::e", "a::b::f",)
         );
 
         assert_eq!(
-            parse_use_tree("a::b::{c::{d, e, f}, g, h::{i, j, k}}").flatten(),
+            parse_use_tree("a::b::{c::{d, e, f}, g, h::{i, j, k}}")
+                .flatten(ImportGranularity::Item),
             parse_use_trees![
                 "a::b::c::d",
                 "a::b::c::e",
diff --git a/src/tools/rustfmt/src/issues.rs b/src/tools/rustfmt/src/issues.rs
deleted file mode 100644
index 33fb5522aea..00000000000
--- a/src/tools/rustfmt/src/issues.rs
+++ /dev/null
@@ -1,309 +0,0 @@
-// Objects for seeking through a char stream for occurrences of TODO and FIXME.
-// Depending on the loaded configuration, may also check that these have an
-// associated issue number.
-
-use std::fmt;
-
-use crate::config::ReportTactic;
-
-const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o'];
-const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e'];
-
-// Enabled implementation detail is here because it is
-// irrelevant outside the issues module
-fn is_enabled(report_tactic: ReportTactic) -> bool {
-    report_tactic != ReportTactic::Never
-}
-
-#[derive(Clone, Copy)]
-enum Seeking {
-    Issue { todo_idx: usize, fixme_idx: usize },
-    Number { issue: Issue, part: NumberPart },
-}
-
-#[derive(Clone, Copy)]
-enum NumberPart {
-    OpenParen,
-    Pound,
-    Number,
-    CloseParen,
-}
-
-#[derive(PartialEq, Eq, Debug, Clone, Copy)]
-pub struct Issue {
-    issue_type: IssueType,
-    // Indicates whether we're looking for issues with missing numbers, or
-    // all issues of this type.
-    missing_number: bool,
-}
-
-impl fmt::Display for Issue {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
-        let msg = match self.issue_type {
-            IssueType::Todo => "TODO",
-            IssueType::Fixme => "FIXME",
-        };
-        let details = if self.missing_number {
-            " without issue number"
-        } else {
-            ""
-        };
-
-        write!(fmt, "{}{}", msg, details)
-    }
-}
-
-#[derive(PartialEq, Eq, Debug, Clone, Copy)]
-enum IssueType {
-    Todo,
-    Fixme,
-}
-
-enum IssueClassification {
-    Good,
-    Bad(Issue),
-    None,
-}
-
-pub(crate) struct BadIssueSeeker {
-    state: Seeking,
-    report_todo: ReportTactic,
-    report_fixme: ReportTactic,
-}
-
-impl BadIssueSeeker {
-    pub(crate) fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker {
-        BadIssueSeeker {
-            state: Seeking::Issue {
-                todo_idx: 0,
-                fixme_idx: 0,
-            },
-            report_todo,
-            report_fixme,
-        }
-    }
-
-    pub(crate) fn is_disabled(&self) -> bool {
-        !is_enabled(self.report_todo) && !is_enabled(self.report_fixme)
-    }
-
-    // Check whether or not the current char is conclusive evidence for an
-    // unnumbered TO-DO or FIX-ME.
-    pub(crate) fn inspect(&mut self, c: char) -> Option<Issue> {
-        match self.state {
-            Seeking::Issue {
-                todo_idx,
-                fixme_idx,
-            } => {
-                self.state = self.inspect_issue(c, todo_idx, fixme_idx);
-            }
-            Seeking::Number { issue, part } => {
-                let result = self.inspect_number(c, issue, part);
-
-                if let IssueClassification::None = result {
-                    return None;
-                }
-
-                self.state = Seeking::Issue {
-                    todo_idx: 0,
-                    fixme_idx: 0,
-                };
-
-                if let IssueClassification::Bad(issue) = result {
-                    return Some(issue);
-                }
-            }
-        }
-
-        None
-    }
-
-    fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking {
-        if let Some(lower_case_c) = c.to_lowercase().next() {
-            if is_enabled(self.report_todo) && lower_case_c == TO_DO_CHARS[todo_idx] {
-                todo_idx += 1;
-                if todo_idx == TO_DO_CHARS.len() {
-                    return Seeking::Number {
-                        issue: Issue {
-                            issue_type: IssueType::Todo,
-                            missing_number: matches!(self.report_todo, ReportTactic::Unnumbered),
-                        },
-                        part: NumberPart::OpenParen,
-                    };
-                }
-                fixme_idx = 0;
-            } else if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] {
-                // Exploit the fact that the character sets of todo and fixme
-                // are disjoint by adding else.
-                fixme_idx += 1;
-                if fixme_idx == FIX_ME_CHARS.len() {
-                    return Seeking::Number {
-                        issue: Issue {
-                            issue_type: IssueType::Fixme,
-                            missing_number: matches!(self.report_fixme, ReportTactic::Unnumbered),
-                        },
-                        part: NumberPart::OpenParen,
-                    };
-                }
-                todo_idx = 0;
-            } else {
-                todo_idx = 0;
-                fixme_idx = 0;
-            }
-        }
-
-        Seeking::Issue {
-            todo_idx,
-            fixme_idx,
-        }
-    }
-
-    fn inspect_number(
-        &mut self,
-        c: char,
-        issue: Issue,
-        mut part: NumberPart,
-    ) -> IssueClassification {
-        if !issue.missing_number || c == '\n' {
-            return IssueClassification::Bad(issue);
-        } else if c == ')' {
-            return if let NumberPart::CloseParen = part {
-                IssueClassification::Good
-            } else {
-                IssueClassification::Bad(issue)
-            };
-        }
-
-        match part {
-            NumberPart::OpenParen => {
-                if c != '(' {
-                    return IssueClassification::Bad(issue);
-                } else {
-                    part = NumberPart::Pound;
-                }
-            }
-            NumberPart::Pound => {
-                if c == '#' {
-                    part = NumberPart::Number;
-                }
-            }
-            NumberPart::Number => {
-                if ('0'..='9').contains(&c) {
-                    part = NumberPart::CloseParen;
-                } else {
-                    return IssueClassification::Bad(issue);
-                }
-            }
-            NumberPart::CloseParen => {}
-        }
-
-        self.state = Seeking::Number { part, issue };
-
-        IssueClassification::None
-    }
-}
-
-#[test]
-fn find_unnumbered_issue() {
-    fn check_fail(text: &str, failing_pos: usize) {
-        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
-        assert_eq!(
-            Some(failing_pos),
-            text.find(|c| seeker.inspect(c).is_some())
-        );
-    }
-
-    fn check_pass(text: &str) {
-        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
-        assert_eq!(None, text.find(|c| seeker.inspect(c).is_some()));
-    }
-
-    check_fail("TODO\n", 4);
-    check_pass(" TO FIX DOME\n");
-    check_fail(" \n FIXME\n", 8);
-    check_fail("FIXME(\n", 6);
-    check_fail("FIXME(#\n", 7);
-    check_fail("FIXME(#1\n", 8);
-    check_fail("FIXME(#)1\n", 7);
-    check_pass("FIXME(#1222)\n");
-    check_fail("FIXME(#12\n22)\n", 9);
-    check_pass("FIXME(@maintainer, #1222, hello)\n");
-    check_fail("TODO(#22) FIXME\n", 15);
-}
-
-#[test]
-fn find_issue() {
-    fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool {
-        let mut seeker = BadIssueSeeker::new(report_todo, report_fixme);
-        text.chars().any(|c| seeker.inspect(c).is_some())
-    }
-
-    assert!(is_bad_issue(
-        "TODO(@maintainer, #1222, hello)\n",
-        ReportTactic::Always,
-        ReportTactic::Never,
-    ));
-
-    assert!(!is_bad_issue(
-        "TODO: no number\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
-
-    assert!(!is_bad_issue(
-        "Todo: mixed case\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
-
-    assert!(is_bad_issue(
-        "This is a FIXME(#1)\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
-
-    assert!(is_bad_issue(
-        "This is a FixMe(#1) mixed case\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
-
-    assert!(!is_bad_issue(
-        "bad FIXME\n",
-        ReportTactic::Always,
-        ReportTactic::Never,
-    ));
-}
-
-#[test]
-fn issue_type() {
-    let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never);
-    let expected = Some(Issue {
-        issue_type: IssueType::Todo,
-        missing_number: false,
-    });
-
-    assert_eq!(
-        expected,
-        "TODO(#100): more awesomeness"
-            .chars()
-            .map(|c| seeker.inspect(c))
-            .find(Option::is_some)
-            .unwrap()
-    );
-
-    let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered);
-    let expected = Some(Issue {
-        issue_type: IssueType::Fixme,
-        missing_number: true,
-    });
-
-    assert_eq!(
-        expected,
-        "Test. FIXME: bad, bad, not good"
-            .chars()
-            .map(|c| seeker.inspect(c))
-            .find(Option::is_some)
-            .unwrap()
-    );
-}
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 8816d7d2f1f..bab881f4b4e 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -1770,7 +1770,7 @@ pub(crate) fn rewrite_struct_field(
         .offset_left(overhead + spacing.len())
         .and_then(|ty_shape| field.ty.rewrite(context, ty_shape));
     if let Some(ref ty) = orig_ty {
-        if !ty.contains('\n') {
+        if !ty.contains('\n') && !contains_comment(context.snippet(missing_span)) {
             return Some(attr_prefix + &spacing + ty);
         }
     }
diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs
index fae8080c02e..1d1ef525f23 100644
--- a/src/tools/rustfmt/src/lib.rs
+++ b/src/tools/rustfmt/src/lib.rs
@@ -40,7 +40,6 @@ use thiserror::Error;
 use crate::comment::LineClasses;
 use crate::emitter::Emitter;
 use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile};
-use crate::issues::Issue;
 use crate::modules::ModuleResolutionError;
 use crate::parse::parser::DirectoryOwnership;
 use crate::shape::Indent;
@@ -70,7 +69,6 @@ mod format_report_formatter;
 pub(crate) mod formatting;
 mod ignore_path;
 mod imports;
-mod issues;
 mod items;
 mod lists;
 mod macros;
@@ -111,12 +109,6 @@ pub enum ErrorKind {
     /// Line ends in whitespace.
     #[error("left behind trailing whitespace")]
     TrailingWhitespace,
-    /// TODO or FIXME item without an issue number.
-    #[error("found {0}")]
-    BadIssue(Issue),
-    /// License check has failed.
-    #[error("license check failed")]
-    LicenseCheck,
     /// Used deprecated skip attribute.
     #[error("`rustfmt_skip` is deprecated; use `rustfmt::skip`")]
     DeprecatedAttr,
@@ -237,11 +229,7 @@ impl FormatReport {
                 ErrorKind::LostComment => {
                     errs.has_unformatted_code_errors = true;
                 }
-                ErrorKind::BadIssue(_)
-                | ErrorKind::LicenseCheck
-                | ErrorKind::DeprecatedAttr
-                | ErrorKind::BadAttr
-                | ErrorKind::VersionMismatch => {
+                ErrorKind::DeprecatedAttr | ErrorKind::BadAttr | ErrorKind::VersionMismatch => {
                     errs.has_check_errors = true;
                 }
                 _ => {}
diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs
index f115e7d0261..6bf8cd0c70b 100644
--- a/src/tools/rustfmt/src/overflow.rs
+++ b/src/tools/rustfmt/src/overflow.rs
@@ -32,7 +32,7 @@ use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_wid
 /// Organized as a list of `(&str, usize)` tuples, giving the name of the macro and the number of
 /// arguments before the format string (none for `format!("format", ...)`, one for `assert!(result,
 /// "format", ...)`, two for `assert_eq!(left, right, "format", ...)`).
-const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[
+const SPECIAL_CASE_MACROS: &[(&str, usize)] = &[
     // format! like macros
     // From the Rust Standard Library.
     ("eprint!", 0),
@@ -60,7 +60,7 @@ const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[
     ("debug_assert_ne!", 2),
 ];
 
-const SPECIAL_ATTR_WHITELIST: &[(&str, usize)] = &[
+const SPECIAL_CASE_ATTR: &[(&str, usize)] = &[
     // From the `failure` crate.
     ("fail", 0),
 ];
@@ -182,10 +182,10 @@ impl<'a> OverflowableItem<'a> {
         }
     }
 
-    fn whitelist(&self) -> &'static [(&'static str, usize)] {
+    fn special_cases(&self) -> &'static [(&'static str, usize)] {
         match self {
-            OverflowableItem::MacroArg(..) => SPECIAL_MACRO_WHITELIST,
-            OverflowableItem::NestedMetaItem(..) => SPECIAL_ATTR_WHITELIST,
+            OverflowableItem::MacroArg(..) => SPECIAL_CASE_MACROS,
+            OverflowableItem::NestedMetaItem(..) => SPECIAL_CASE_ATTR,
             _ => &[],
         }
     }
@@ -770,7 +770,7 @@ pub(crate) fn maybe_get_args_offset(
 ) -> Option<(bool, usize)> {
     if let Some(&(_, num_args_before)) = args
         .get(0)?
-        .whitelist()
+        .special_cases()
         .iter()
         .find(|&&(s, _)| s == callee_str)
     {
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index 4408e20747a..a0f71c2b8ba 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -170,7 +170,7 @@ impl ParseSess {
     /// * `relative` - If Some(symbol), the symbol name is a directory relative to the dir_path.
     ///   If relative is Some, resolve the submodle at {dir_path}/{symbol}/{id}.rs
     ///   or {dir_path}/{symbol}/{id}/mod.rs. if None, resolve the module at {dir_path}/{id}.rs.
-    /// *  `dir_path` - Module resolution will occur relative to this direcotry.
+    /// *  `dir_path` - Module resolution will occur relative to this directory.
     pub(crate) fn default_submod_path(
         &self,
         id: symbol::Ident,
diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs
index 13bfc92507d..8ae297de25b 100644
--- a/src/tools/rustfmt/src/reorder.rs
+++ b/src/tools/rustfmt/src/reorder.rs
@@ -11,8 +11,8 @@ use std::cmp::{Ord, Ordering};
 use rustc_ast::ast;
 use rustc_span::{symbol::sym, Span};
 
-use crate::config::{Config, GroupImportsTactic, ImportGranularity};
-use crate::imports::{flatten_use_trees, merge_use_trees, SharedPrefix, UseSegment, UseTree};
+use crate::config::{Config, GroupImportsTactic};
+use crate::imports::{normalize_use_trees_with_granularity, UseSegment, UseTree};
 use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod};
 use crate::lists::{itemize_list, write_list, ListFormatting, ListItem};
 use crate::rewrite::RewriteContext;
@@ -107,15 +107,10 @@ fn rewrite_reorderable_or_regroupable_items(
             for (item, list_item) in normalized_items.iter_mut().zip(list_items) {
                 item.list_item = Some(list_item.clone());
             }
-            normalized_items = match context.config.imports_granularity() {
-                ImportGranularity::Crate => merge_use_trees(normalized_items, SharedPrefix::Crate),
-                ImportGranularity::Module => {
-                    merge_use_trees(normalized_items, SharedPrefix::Module)
-                }
-                ImportGranularity::Item => flatten_use_trees(normalized_items),
-                ImportGranularity::One => merge_use_trees(normalized_items, SharedPrefix::One),
-                ImportGranularity::Preserve => normalized_items,
-            };
+            normalized_items = normalize_use_trees_with_granularity(
+                normalized_items,
+                context.config.imports_granularity(),
+            );
 
             let mut regrouped_items = match context.config.group_imports() {
                 GroupImportsTactic::Preserve | GroupImportsTactic::One => {
diff --git a/src/tools/rustfmt/src/rewrite.rs b/src/tools/rustfmt/src/rewrite.rs
index 4a3bd129d16..f97df70cc6a 100644
--- a/src/tools/rustfmt/src/rewrite.rs
+++ b/src/tools/rustfmt/src/rewrite.rs
@@ -12,6 +12,7 @@ use crate::shape::Shape;
 use crate::skip::SkipContext;
 use crate::visitor::SnippetProvider;
 use crate::FormatReport;
+use rustc_data_structures::stable_map::FxHashMap;
 
 pub(crate) trait Rewrite {
     /// Rewrite self into shape.
@@ -24,10 +25,22 @@ impl<T: Rewrite> Rewrite for ptr::P<T> {
     }
 }
 
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub(crate) struct QueryId {
+    pub(crate) shape: Shape,
+    pub(crate) span: Span,
+}
+
+// We use Option<HashMap> instead of HashMap, because in case of `None`
+// the function clean the memoize map, but it doesn't clean when
+// there is `Some(empty)`, so they are different.
+pub(crate) type Memoize = Rc<Cell<Option<FxHashMap<QueryId, Option<String>>>>>;
+
 #[derive(Clone)]
 pub(crate) struct RewriteContext<'a> {
     pub(crate) parse_sess: &'a ParseSess,
     pub(crate) config: &'a Config,
+    pub(crate) memoize: Memoize,
     pub(crate) inside_macro: Rc<Cell<bool>>,
     // Force block indent style even if we are using visual indent style.
     pub(crate) use_block: Cell<bool>,
diff --git a/src/tools/rustfmt/src/shape.rs b/src/tools/rustfmt/src/shape.rs
index 4376fd12b52..b3f785a9470 100644
--- a/src/tools/rustfmt/src/shape.rs
+++ b/src/tools/rustfmt/src/shape.rs
@@ -4,7 +4,7 @@ use std::ops::{Add, Sub};
 
 use crate::Config;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub(crate) struct Indent {
     // Width of the block indent, in characters. Must be a multiple of
     // Config::tab_spaces.
@@ -139,7 +139,7 @@ impl Sub<usize> for Indent {
 // 8096 is close enough to infinite for rustfmt.
 const INFINITE_SHAPE_WIDTH: usize = 8096;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub(crate) struct Shape {
     pub(crate) width: usize,
     // The current indentation of code.
diff --git a/src/tools/rustfmt/src/string.rs b/src/tools/rustfmt/src/string.rs
index b65aa5b33b2..78b72a50cb2 100644
--- a/src/tools/rustfmt/src/string.rs
+++ b/src/tools/rustfmt/src/string.rs
@@ -315,20 +315,21 @@ fn break_string(max_width: usize, trim_end: bool, line_end: &str, input: &[&str]
         // Found a whitespace and what is on its left side is big enough.
         Some(index) if index >= MIN_STRING => break_at(index),
         // No whitespace found, try looking for a punctuation instead
-        _ => match input[0..max_width_index_in_input]
-            .iter()
-            .rposition(|grapheme| is_punctuation(grapheme))
+        _ => match (0..max_width_index_in_input)
+            .rev()
+            .skip_while(|pos| !is_valid_linebreak(input, *pos))
+            .next()
         {
             // Found a punctuation and what is on its left side is big enough.
             Some(index) if index >= MIN_STRING => break_at(index),
             // Either no boundary character was found to the left of `input[max_chars]`, or the line
             // got too small. We try searching for a boundary character to the right.
-            _ => match input[max_width_index_in_input..]
-                .iter()
-                .position(|grapheme| is_whitespace(grapheme) || is_punctuation(grapheme))
+            _ => match (max_width_index_in_input..input.len())
+                .skip_while(|pos| !is_valid_linebreak(input, *pos))
+                .next()
             {
                 // A boundary was found after the line limit
-                Some(index) => break_at(max_width_index_in_input + index),
+                Some(index) => break_at(index),
                 // No boundary to the right, the input cannot be broken
                 None => SnippetState::EndOfInput(input.concat()),
             },
@@ -336,6 +337,23 @@ fn break_string(max_width: usize, trim_end: bool, line_end: &str, input: &[&str]
     }
 }
 
+fn is_valid_linebreak(input: &[&str], pos: usize) -> bool {
+    let is_whitespace = is_whitespace(input[pos]);
+    if is_whitespace {
+        return true;
+    }
+    let is_punctuation = is_punctuation(input[pos]);
+    if is_punctuation && !is_part_of_type(input, pos) {
+        return true;
+    }
+    false
+}
+
+fn is_part_of_type(input: &[&str], pos: usize) -> bool {
+    input.get(pos..=pos + 1) == Some(&[":", ":"])
+        || input.get(pos.saturating_sub(1)..=pos) == Some(&[":", ":"])
+}
+
 fn is_new_line(grapheme: &str) -> bool {
     let bytes = grapheme.as_bytes();
     bytes.starts_with(b"\n") || bytes.starts_with(b"\r\n")
@@ -370,6 +388,19 @@ mod test {
     }
 
     #[test]
+    fn line_break_at_valid_points_test() {
+        let string = "[TheName](Dont::break::my::type::That::would::be::very::nice) break here";
+        let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
+        assert_eq!(
+            break_string(20, false, "", &graphemes[..]),
+            SnippetState::LineEnd(
+                "[TheName](Dont::break::my::type::That::would::be::very::nice) ".to_string(),
+                62
+            )
+        );
+    }
+
+    #[test]
     fn should_break_on_whitespace() {
         let string = "Placerat felis. Mauris porta ante sagittis purus.";
         let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::<Vec<&str>>();
diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs
index ab966d4a360..6b5bc2b30dd 100644
--- a/src/tools/rustfmt/src/test/mod.rs
+++ b/src/tools/rustfmt/src/test/mod.rs
@@ -9,7 +9,7 @@ use std::process::{Command, Stdio};
 use std::str::Chars;
 use std::thread;
 
-use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic};
+use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle};
 use crate::formatting::{ReportedErrors, SourceFile};
 use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter};
 use crate::source_file;
@@ -24,7 +24,7 @@ mod parser;
 const DIFF_CONTEXT_SIZE: usize = 3;
 
 // A list of files on which we want to skip testing.
-const SKIP_FILE_WHITE_LIST: &[&str] = &[
+const FILE_SKIP_LIST: &[&str] = &[
     // We want to make sure that the `skip_children` is correctly working,
     // so we do not want to test this file directly.
     "configs/skip_children/foo/mod.rs",
@@ -90,7 +90,7 @@ where
 }
 
 fn is_file_skip(path: &Path) -> bool {
-    SKIP_FILE_WHITE_LIST
+    FILE_SKIP_LIST
         .iter()
         .any(|file_path| is_subpath(path, file_path))
 }
@@ -579,6 +579,30 @@ fn stdin_generated_files_issue_5172() {
 }
 
 #[test]
+fn stdin_handles_mod_inner_ignore_attr() {
+    // see https://github.com/rust-lang/rustfmt/issues/5368
+    init_log();
+    let input = String::from("#![rustfmt::skip]\n\nfn    main() {  }");
+    let mut child = Command::new(rustfmt().to_str().unwrap())
+        .stdin(Stdio::piped())
+        .stdout(Stdio::piped())
+        .spawn()
+        .expect("failed to execute child");
+
+    {
+        let stdin = child.stdin.as_mut().expect("failed to get stdin");
+        stdin
+            .write_all(input.as_bytes())
+            .expect("failed to write stdin");
+    }
+
+    let output = child.wait_with_output().expect("failed to wait on child");
+    assert!(output.status.success());
+    assert!(output.stderr.is_empty());
+    assert_eq!(input, String::from_utf8(output.stdout).unwrap());
+}
+
+#[test]
 fn format_lines_errors_are_reported() {
     init_log();
     let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap();
@@ -688,9 +712,6 @@ fn read_config(filename: &Path) -> Config {
         }
     }
 
-    // Don't generate warnings for to-do items.
-    config.set().report_todo(ReportTactic::Never);
-
     config
 }
 
@@ -957,12 +978,6 @@ fn rustfmt() -> PathBuf {
     // Chop off `deps`.
     me.pop();
 
-    // If we run `cargo test --release`, we might only have a release build.
-    if cfg!(release) {
-        // `../release/`
-        me.pop();
-        me.push("release");
-    }
     me.push("rustfmt");
     assert!(
         me.is_file() || me.with_extension("exe").is_file(),
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 9a0e0752c12..3ff56d52f92 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -17,7 +17,7 @@ use crate::items::{
 use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
 use crate::modules::Module;
 use crate::parse::session::ParseSess;
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{Memoize, Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
 use crate::skip::{is_skip_attr, SkipContext};
 use crate::source_map::{LineRangeUtils, SpanUtils};
@@ -71,6 +71,7 @@ impl SnippetProvider {
 
 pub(crate) struct FmtVisitor<'a> {
     parent_context: Option<&'a RewriteContext<'a>>,
+    pub(crate) memoize: Memoize,
     pub(crate) parse_sess: &'a ParseSess,
     pub(crate) buffer: String,
     pub(crate) last_pos: BytePos,
@@ -758,6 +759,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             ctx.config,
             ctx.snippet_provider,
             ctx.report.clone(),
+            ctx.memoize.clone(),
         );
         visitor.skip_context.update(ctx.skip_context.clone());
         visitor.set_parent_context(ctx);
@@ -769,10 +771,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         config: &'a Config,
         snippet_provider: &'a SnippetProvider,
         report: FormatReport,
+        memoize: Memoize,
     ) -> FmtVisitor<'a> {
         FmtVisitor {
             parent_context: None,
             parse_sess: parse_session,
+            memoize,
             buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2),
             last_pos: BytePos(0),
             block_indent: Indent::empty(),
@@ -995,6 +999,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         RewriteContext {
             parse_sess: self.parse_sess,
             config: self.config,
+            memoize: self.memoize.clone(),
             inside_macro: Rc::new(Cell::new(false)),
             use_block: Cell::new(false),
             is_if_else_block: Cell::new(false),
diff --git a/src/tools/rustfmt/tests/config/issue-3802.toml b/src/tools/rustfmt/tests/config/issue-3802.toml
deleted file mode 100644
index 74ee8b010dd..00000000000
--- a/src/tools/rustfmt/tests/config/issue-3802.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-unstable_features = true
-license_template_path = ""
diff --git a/src/tools/rustfmt/tests/config/small_tabs.toml b/src/tools/rustfmt/tests/config/small_tabs.toml
index 35c8fd86467..c3cfd34317a 100644
--- a/src/tools/rustfmt/tests/config/small_tabs.toml
+++ b/src/tools/rustfmt/tests/config/small_tabs.toml
@@ -6,7 +6,5 @@ brace_style = "SameLineWhere"
 fn_args_layout = "Tall"
 trailing_comma = "Vertical"
 indent_style = "Block"
-report_todo = "Always"
-report_fixme = "Never"
 reorder_imports = false
 format_strings = true
diff --git a/src/tools/rustfmt/tests/license-template/lt.txt b/src/tools/rustfmt/tests/license-template/lt.txt
deleted file mode 100644
index ea4390371a0..00000000000
--- a/src/tools/rustfmt/tests/license-template/lt.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-// rustfmt-license_template_path: tests/license-template/lt.txt
-// Copyright {\d+} The rustfmt developers.
diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs
index 450051d2fec..4c6d52726f3 100644
--- a/src/tools/rustfmt/tests/rustfmt/main.rs
+++ b/src/tools/rustfmt/tests/rustfmt/main.rs
@@ -143,7 +143,7 @@ fn mod_resolution_error_relative_module_not_found() {
     let args = ["tests/mod-resolver/module-not-found/relative_module/lib.rs"];
     let (_stdout, stderr) = rustfmt(&args);
     // The file `./a.rs` and directory `./a` both exist.
-    // Module resolution fails becuase we're unable to find `./a/b.rs`
+    // Module resolution fails because we're unable to find `./a/b.rs`
     #[cfg(not(windows))]
     assert!(stderr.contains("a/b.rs does not exist"));
     #[cfg(windows)]
diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs b/src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs
new file mode 100644
index 00000000000..f239a0efa08
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs
@@ -0,0 +1,27 @@
+// rustfmt-group_imports: StdExternalCrate
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+
+
+
+
+use juniper::{FieldError, FieldResult};
+
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+extern crate uuid;
+
+
+
+
+
+use std::sync::Arc;
+
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/source/imports-impl-only-use.rs b/src/tools/rustfmt/tests/source/imports/imports-impl-only-use.rs
index d290d8d9185..d290d8d9185 100644
--- a/src/tools/rustfmt/tests/source/imports-impl-only-use.rs
+++ b/src/tools/rustfmt/tests/source/imports/imports-impl-only-use.rs
diff --git a/src/tools/rustfmt/tests/source/imports-reorder-lines-and-items.rs b/src/tools/rustfmt/tests/source/imports/imports-reorder-lines-and-items.rs
index b6380f31c61..b6380f31c61 100644
--- a/src/tools/rustfmt/tests/source/imports-reorder-lines-and-items.rs
+++ b/src/tools/rustfmt/tests/source/imports/imports-reorder-lines-and-items.rs
diff --git a/src/tools/rustfmt/tests/source/imports-reorder-lines.rs b/src/tools/rustfmt/tests/source/imports/imports-reorder-lines.rs
index 2b018544eae..2b018544eae 100644
--- a/src/tools/rustfmt/tests/source/imports-reorder-lines.rs
+++ b/src/tools/rustfmt/tests/source/imports/imports-reorder-lines.rs
diff --git a/src/tools/rustfmt/tests/source/imports-reorder.rs b/src/tools/rustfmt/tests/source/imports/imports-reorder.rs
index cbe9d6ca78a..cbe9d6ca78a 100644
--- a/src/tools/rustfmt/tests/source/imports-reorder.rs
+++ b/src/tools/rustfmt/tests/source/imports/imports-reorder.rs
diff --git a/src/tools/rustfmt/tests/source/imports.rs b/src/tools/rustfmt/tests/source/imports/imports.rs
index 4dfc6ed94e3..4dfc6ed94e3 100644
--- a/src/tools/rustfmt/tests/source/imports.rs
+++ b/src/tools/rustfmt/tests/source/imports/imports.rs
diff --git a/src/tools/rustfmt/tests/source/imports_block_indent.rs b/src/tools/rustfmt/tests/source/imports/imports_block_indent.rs
index 016deefe58c..016deefe58c 100644
--- a/src/tools/rustfmt/tests/source/imports_block_indent.rs
+++ b/src/tools/rustfmt/tests/source/imports/imports_block_indent.rs
diff --git a/src/tools/rustfmt/tests/source/imports_granularity_crate.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_crate.rs
index d16681b01b5..f6f7761e82e 100644
--- a/src/tools/rustfmt/tests/source/imports_granularity_crate.rs
+++ b/src/tools/rustfmt/tests/source/imports/imports_granularity_crate.rs
@@ -35,3 +35,31 @@ use j::{a::{self}};
 
 use {k::{a, b}, l::{a, b}};
 use {k::{c, d}, l::{c, d}};
+
+use b::{f::g, h::{i, j} /* After b::h group */};
+use b::e;
+use b::{/* Before b::l group */ l::{self, m, n::o, p::*}, q};
+use b::d;
+use b::r; // After b::r
+use b::q::{self /* After b::q::self */};
+use b::u::{
+    a,
+    b,
+};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::t::{/* Before b::t::self */ self};
+use b::c;
diff --git a/src/tools/rustfmt/tests/source/imports/imports_granularity_default-with-dups.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_default-with-dups.rs
new file mode 100644
index 00000000000..cbb21a9f1b3
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/imports/imports_granularity_default-with-dups.rs
@@ -0,0 +1,6 @@
+use crate::lexer;
+use crate::lexer::tokens::TokenData;
+use crate::lexer::{tokens::TokenData};
+use crate::lexer::self;
+use crate::lexer::{self};
+use crate::lexer::{self, tokens::TokenData};
diff --git a/src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs
new file mode 100644
index 00000000000..e23705a884f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs
@@ -0,0 +1,13 @@
+// rustfmt-imports_granularity: Item
+// rustfmt-reorder_imports: false
+// rustfmt-group_imports: StdExternalCrate
+
+use crate::lexer;
+use crate::lexer;
+use crate::lexer::tokens::TokenData;
+use crate::lexer::{tokens::TokenData};
+use crate::lexer::self;
+use crate::lexer;
+use crate::lexer;
+use crate::lexer::{self};
+use crate::lexer::{self, tokens::TokenData};
diff --git a/src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups.rs
new file mode 100644
index 00000000000..3e9589c299f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups.rs
@@ -0,0 +1,11 @@
+// rustfmt-imports_granularity: Item
+
+use crate::lexer;
+use crate::lexer;
+use crate::lexer::tokens::TokenData;
+use crate::lexer::{tokens::TokenData};
+use crate::lexer::self;
+use crate::lexer;
+use crate::lexer;
+use crate::lexer::{self};
+use crate::lexer::{self, tokens::TokenData};
diff --git a/src/tools/rustfmt/tests/source/imports/imports_granularity_item.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_item.rs
new file mode 100644
index 00000000000..b82c0d33caf
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/imports/imports_granularity_item.rs
@@ -0,0 +1,34 @@
+// rustfmt-imports_granularity: Item
+
+use a::{b, c, d};
+use a::{f::g, h::{i, j}};
+use a::{l::{self, m, n::o, p::*}};
+use a::q::{self};
+
+use b::{f::g, h::{i, j} /* After b::h group */};
+use b::e;
+use b::{/* Before b::l group */ l::{self, m, n::o, p::*}, q};
+use b::d;
+use b::r; // After b::r
+use b::q::{self /* After b::q::self */};
+use b::u::{
+    a,
+    b,
+};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::t::{/* Before b::t::self */ self};
+use b::c;
diff --git a/src/tools/rustfmt/tests/source/imports/imports_granularity_module.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_module.rs
new file mode 100644
index 00000000000..c7f68cea6d4
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/imports/imports_granularity_module.rs
@@ -0,0 +1,47 @@
+// rustfmt-imports_granularity: Module
+
+use a::{b::c, d::e};
+use a::{f, g::{h, i}};
+use a::{j::{self, k::{self, l}, m}, n::{o::p, q}};
+pub use a::{r::s, t};
+use b::{c::d, self};
+
+#[cfg(test)]
+use foo::{a::b, c::d};
+use foo::e;
+
+use bar::{
+    // comment
+    a::b,
+    // more comment
+    c::d,
+    e::f,
+};
+
+use b::{f::g, h::{i, j} /* After b::h group */};
+use b::e;
+use b::{/* Before b::l group */ l::{self, m, n::o, p::*}, q};
+use b::d;
+use b::r; // After b::r
+use b::q::{self /* After b::q::self */};
+use b::u::{
+    a,
+    b,
+};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::t::{/* Before b::t::self */ self};
+use b::c;
diff --git a/src/tools/rustfmt/tests/source/imports_granularity_item.rs b/src/tools/rustfmt/tests/source/imports_granularity_item.rs
deleted file mode 100644
index d0e94df66ae..00000000000
--- a/src/tools/rustfmt/tests/source/imports_granularity_item.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// rustfmt-imports_granularity: Item
-
-use a::{b, c, d};
-use a::{f::g, h::{i, j}};
-use a::{l::{self, m, n::o, p::*}};
-use a::q::{self};
diff --git a/src/tools/rustfmt/tests/source/imports_granularity_module.rs b/src/tools/rustfmt/tests/source/imports_granularity_module.rs
deleted file mode 100644
index 2d7bb299aaa..00000000000
--- a/src/tools/rustfmt/tests/source/imports_granularity_module.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// rustfmt-imports_granularity: Module
-
-use a::{b::c, d::e};
-use a::{f, g::{h, i}};
-use a::{j::{self, k::{self, l}, m}, n::{o::p, q}};
-pub use a::{r::s, t};
-use b::{c::d, self};
-
-#[cfg(test)]
-use foo::{a::b, c::d};
-use foo::e;
-
-use bar::{
-    // comment
-    a::b,
-    // more comment
-    c::d,
-    e::f,
-};
diff --git a/src/tools/rustfmt/tests/source/imports_granularity_one.rs b/src/tools/rustfmt/tests/source/imports_granularity_one.rs
index c21707df395..4d5a4795641 100644
--- a/src/tools/rustfmt/tests/source/imports_granularity_one.rs
+++ b/src/tools/rustfmt/tests/source/imports_granularity_one.rs
@@ -58,3 +58,31 @@ use a::{
 };
 use b as x;
 use a::ad::ada;
+
+use b::{f::g, h::{i, j} /* After b::h group */};
+use b::e;
+use b::{/* Before b::l group */ l::{self, m, n::o, p::*}, q};
+use b::d;
+use b::r; // After b::r
+use b::q::{self /* After b::q::self */};
+use b::u::{
+    a,
+    b,
+};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::t::{/* Before b::t::self */ self};
+use b::c;
diff --git a/src/tools/rustfmt/tests/source/issue-5030.rs b/src/tools/rustfmt/tests/source/issue-5030.rs
new file mode 100644
index 00000000000..08ffaac7d1d
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5030.rs
@@ -0,0 +1,22 @@
+// rustfmt-imports_granularity: Item
+// rustfmt-group_imports: One
+
+// Confirm that attributes are duplicated to all items in the use statement
+#[cfg(feature = "foo")]
+use std::collections::{
+    HashMap,
+    HashSet,
+};
+
+// Separate the imports below from the ones above
+const A: usize = 0;
+
+// Copying attrs works with import grouping as well
+#[cfg(feature = "foo")]
+use std::collections::{
+    HashMap,
+    HashSet,
+};
+
+#[cfg(feature = "spam")]
+use qux::{bar, baz};
diff --git a/src/tools/rustfmt/tests/source/issue-5260.rs b/src/tools/rustfmt/tests/source/issue-5260.rs
new file mode 100644
index 00000000000..c0606817290
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-5260.rs
@@ -0,0 +1,14 @@
+// rustfmt-wrap_comments: true
+
+/// [MyType](VeryLongPathToMyType::NoLineBreak::Here::Okay::ThatWouldBeNice::Thanks)
+fn documented_with_longtype() {
+    // # We're using a long type link, rustfmt should not break line
+    // on the type when `wrap_comments = true`
+}
+
+/// VeryLongPathToMyType::JustMyType::But::VeryVery::Long::NoLineBreak::Here::Okay::ThatWouldBeNice::Thanks
+fn documented_with_verylongtype() {
+    // # We're using a long type link, rustfmt should not break line
+    // on the type when `wrap_comments = true`
+}
+
diff --git a/src/tools/rustfmt/tests/source/license-templates/empty_license_path.rs b/src/tools/rustfmt/tests/source/license-templates/empty_license_path.rs
deleted file mode 100644
index d3a91e4231d..00000000000
--- a/src/tools/rustfmt/tests/source/license-templates/empty_license_path.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// rustfmt-config: issue-3802.toml
-
-fn main() {
-println!("Hello world!");
-}
diff --git a/src/tools/rustfmt/tests/source/license-templates/license.rs b/src/tools/rustfmt/tests/source/license-templates/license.rs
deleted file mode 100644
index 6816011c60d..00000000000
--- a/src/tools/rustfmt/tests/source/license-templates/license.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// rustfmt-license_template_path: tests/license-template/lt.txt
-// Copyright 2019 The rustfmt developers.
-
-fn main() {
-println!("Hello world!");
-}
diff --git a/src/tools/rustfmt/tests/source/performance/issue-4476.rs b/src/tools/rustfmt/tests/source/performance/issue-4476.rs
new file mode 100644
index 00000000000..8da3f19b62d
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/performance/issue-4476.rs
@@ -0,0 +1,638 @@
+use super::SemverParser;
+
+#[allow(dead_code, non_camel_case_types)]
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub enum Rule {
+  EOI,
+  range_set,
+  logical_or,
+  range,
+  empty,
+  hyphen,
+  simple,
+  primitive,
+  primitive_op,
+  partial,
+  xr,
+  xr_op,
+  nr,
+  tilde,
+  caret,
+  qualifier,
+  parts,
+  part,
+  space,
+}
+#[allow(clippy::all)]
+impl ::pest::Parser<Rule> for SemverParser {
+  fn parse<'i>(
+    rule: Rule,
+    input: &'i str,
+  ) -> ::std::result::Result<::pest::iterators::Pairs<'i, Rule>, ::pest::error::Error<Rule>> {
+    mod rules {
+      pub mod hidden {
+        use super::super::Rule;
+        #[inline]
+        #[allow(dead_code, non_snake_case, unused_variables)]
+        pub fn skip(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          Ok(state)
+        }
+      }
+      pub mod visible {
+        use super::super::Rule;
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn range_set(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::range_set, |state| {
+            state.sequence(|state| {
+              self::SOI(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::range(state))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      state
+                        .sequence(|state| {
+                          self::logical_or(state)
+                            .and_then(|state| super::hidden::skip(state))
+                            .and_then(|state| self::range(state))
+                        })
+                        .and_then(|state| {
+                          state.repeat(|state| {
+                            state.sequence(|state| {
+                              super::hidden::skip(state).and_then(|state| {
+                                state.sequence(|state| {
+                                  self::logical_or(state)
+                                    .and_then(|state| super::hidden::skip(state))
+                                    .and_then(|state| self::range(state))
+                                })
+                              })
+                            })
+                          })
+                        })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::EOI(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn logical_or(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::logical_or, |state| {
+            state.sequence(|state| {
+              state
+                .sequence(|state| {
+                  state.optional(|state| {
+                    self::space(state).and_then(|state| {
+                      state.repeat(|state| {
+                        state.sequence(|state| {
+                          super::hidden::skip(state).and_then(|state| self::space(state))
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| state.match_string("||"))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn range(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::range, |state| {
+            self::hyphen(state)
+              .or_else(|state| {
+                state.sequence(|state| {
+                  self::simple(state)
+                    .and_then(|state| super::hidden::skip(state))
+                    .and_then(|state| {
+                      state.sequence(|state| {
+                        state.optional(|state| {
+                          state
+                            .sequence(|state| {
+                              state
+                                .optional(|state| state.match_string(","))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                  state.sequence(|state| {
+                                    self::space(state)
+                                      .and_then(|state| super::hidden::skip(state))
+                                      .and_then(|state| {
+                                        state.sequence(|state| {
+                                          state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                              state.repeat(|state| {
+                                                state.sequence(|state| {
+                                                  super::hidden::skip(state)
+                                                    .and_then(|state| self::space(state))
+                                                })
+                                              })
+                                            })
+                                          })
+                                        })
+                                      })
+                                  })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::simple(state))
+                            })
+                            .and_then(|state| {
+                              state.repeat(|state| {
+                                state.sequence(|state| {
+                                  super::hidden::skip(state).and_then(|state| {
+                                    state.sequence(|state| {
+                                      state
+                                        .optional(|state| state.match_string(","))
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| {
+                                          state.sequence(|state| {
+                                            self::space(state)
+                                              .and_then(|state| super::hidden::skip(state))
+                                              .and_then(|state| {
+                                                state.sequence(|state| {
+                                                  state.optional(|state| {
+                                                    self::space(state).and_then(|state| {
+                                                      state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                          super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                        })
+                                                      })
+                                                    })
+                                                  })
+                                                })
+                                              })
+                                          })
+                                        })
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| self::simple(state))
+                                    })
+                                  })
+                                })
+                              })
+                            })
+                        })
+                      })
+                    })
+                })
+              })
+              .or_else(|state| self::empty(state))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn empty(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::empty, |state| state.match_string(""))
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn hyphen(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::hyphen, |state| {
+            state.sequence(|state| {
+              self::partial(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    self::space(state)
+                      .and_then(|state| super::hidden::skip(state))
+                      .and_then(|state| {
+                        state.sequence(|state| {
+                          state.optional(|state| {
+                            self::space(state).and_then(|state| {
+                              state.repeat(|state| {
+                                state.sequence(|state| {
+                                  super::hidden::skip(state).and_then(|state| self::space(state))
+                                })
+                              })
+                            })
+                          })
+                        })
+                      })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| state.match_string("-"))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    self::space(state)
+                      .and_then(|state| super::hidden::skip(state))
+                      .and_then(|state| {
+                        state.sequence(|state| {
+                          state.optional(|state| {
+                            self::space(state).and_then(|state| {
+                              state.repeat(|state| {
+                                state.sequence(|state| {
+                                  super::hidden::skip(state).and_then(|state| self::space(state))
+                                })
+                              })
+                            })
+                          })
+                        })
+                      })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::partial(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn simple(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::simple, |state| {
+            self::primitive(state)
+              .or_else(|state| self::partial(state))
+              .or_else(|state| self::tilde(state))
+              .or_else(|state| self::caret(state))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn primitive(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::primitive, |state| {
+            state.sequence(|state| {
+              self::primitive_op(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::partial(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn primitive_op(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::primitive_op, |state| {
+            state
+              .match_string("<=")
+              .or_else(|state| state.match_string(">="))
+              .or_else(|state| state.match_string(">"))
+              .or_else(|state| state.match_string("<"))
+              .or_else(|state| state.match_string("="))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn partial(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::partial, |state| {
+            state.sequence(|state| {
+              self::xr(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.optional(|state| {
+                    state.sequence(|state| {
+                      state
+                        .match_string(".")
+                        .and_then(|state| super::hidden::skip(state))
+                        .and_then(|state| self::xr(state))
+                        .and_then(|state| super::hidden::skip(state))
+                        .and_then(|state| {
+                          state.optional(|state| {
+                            state.sequence(|state| {
+                              state
+                                .match_string(".")
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::xr(state))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| state.optional(|state| self::qualifier(state)))
+                            })
+                          })
+                        })
+                    })
+                  })
+                })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn xr(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::xr, |state| {
+            self::xr_op(state).or_else(|state| self::nr(state))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn xr_op(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::xr_op, |state| {
+            state
+              .match_string("x")
+              .or_else(|state| state.match_string("X"))
+              .or_else(|state| state.match_string("*"))
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn nr(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::nr, |state| {
+            state.match_string("0").or_else(|state| {
+              state.sequence(|state| {
+                state
+                  .match_range('1'..'9')
+                  .and_then(|state| super::hidden::skip(state))
+                  .and_then(|state| {
+                    state.sequence(|state| {
+                      state.optional(|state| {
+                        state.match_range('0'..'9').and_then(|state| {
+                          state.repeat(|state| {
+                            state.sequence(|state| {
+                              super::hidden::skip(state)
+                                .and_then(|state| state.match_range('0'..'9'))
+                            })
+                          })
+                        })
+                      })
+                    })
+                  })
+              })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn tilde(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::tilde, |state| {
+            state.sequence(|state| {
+              state
+                .match_string("~>")
+                .or_else(|state| state.match_string("~"))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::partial(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn caret(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::caret, |state| {
+            state.sequence(|state| {
+              state
+                .match_string("^")
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      self::space(state).and_then(|state| {
+                        state.repeat(|state| {
+                          state.sequence(|state| {
+                            super::hidden::skip(state).and_then(|state| self::space(state))
+                          })
+                        })
+                      })
+                    })
+                  })
+                })
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::partial(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn qualifier(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::qualifier, |state| {
+            state.sequence(|state| {
+              state
+                .match_string("-")
+                .or_else(|state| state.match_string("+"))
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| self::parts(state))
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn parts(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::parts, |state| {
+            state.sequence(|state| {
+              self::part(state)
+                .and_then(|state| super::hidden::skip(state))
+                .and_then(|state| {
+                  state.sequence(|state| {
+                    state.optional(|state| {
+                      state
+                        .sequence(|state| {
+                          state
+                            .match_string(".")
+                            .and_then(|state| super::hidden::skip(state))
+                            .and_then(|state| self::part(state))
+                        })
+                        .and_then(|state| {
+                          state.repeat(|state| {
+                            state.sequence(|state| {
+                              super::hidden::skip(state).and_then(|state| {
+                                state.sequence(|state| {
+                                  state
+                                    .match_string(".")
+                                    .and_then(|state| super::hidden::skip(state))
+                                    .and_then(|state| self::part(state))
+                                })
+                              })
+                            })
+                          })
+                        })
+                    })
+                  })
+                })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn part(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::part, |state| {
+            self::nr(state).or_else(|state| {
+              state.sequence(|state| {
+                state
+                  .match_string("-")
+                  .or_else(|state| state.match_range('0'..'9'))
+                  .or_else(|state| state.match_range('A'..'Z'))
+                  .or_else(|state| state.match_range('a'..'z'))
+                  .and_then(|state| super::hidden::skip(state))
+                  .and_then(|state| {
+                    state.sequence(|state| {
+                      state.optional(|state| {
+                        state
+                          .match_string("-")
+                          .or_else(|state| state.match_range('0'..'9'))
+                          .or_else(|state| state.match_range('A'..'Z'))
+                          .or_else(|state| state.match_range('a'..'z'))
+                          .and_then(|state| {
+                            state.repeat(|state| {
+                              state.sequence(|state| {
+                                super::hidden::skip(state).and_then(|state| {
+                                  state
+                                    .match_string("-")
+                                    .or_else(|state| state.match_range('0'..'9'))
+                                    .or_else(|state| state.match_range('A'..'Z'))
+                                    .or_else(|state| state.match_range('a'..'z'))
+                                })
+                              })
+                            })
+                          })
+                      })
+                    })
+                  })
+              })
+            })
+          })
+        }
+        #[inline]
+        #[allow(non_snake_case, unused_variables)]
+        pub fn space(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state
+            .match_string(" ")
+            .or_else(|state| state.match_string("\t"))
+        }
+        #[inline]
+        #[allow(dead_code, non_snake_case, unused_variables)]
+        pub fn EOI(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.rule(Rule::EOI, |state| state.end_of_input())
+        }
+        #[inline]
+        #[allow(dead_code, non_snake_case, unused_variables)]
+        pub fn SOI(
+          state: Box<::pest::ParserState<Rule>>,
+        ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+          state.start_of_input()
+        }
+      }
+      pub use self::visible::*;
+    }
+    ::pest::state(input, |state| match rule {
+      Rule::range_set => rules::range_set(state),
+      Rule::logical_or => rules::logical_or(state),
+      Rule::range => rules::range(state),
+      Rule::empty => rules::empty(state),
+      Rule::hyphen => rules::hyphen(state),
+      Rule::simple => rules::simple(state),
+      Rule::primitive => rules::primitive(state),
+      Rule::primitive_op => rules::primitive_op(state),
+      Rule::partial => rules::partial(state),
+      Rule::xr => rules::xr(state),
+      Rule::xr_op => rules::xr_op(state),
+      Rule::nr => rules::nr(state),
+      Rule::tilde => rules::tilde(state),
+      Rule::caret => rules::caret(state),
+      Rule::qualifier => rules::qualifier(state),
+      Rule::parts => rules::parts(state),
+      Rule::part => rules::part(state),
+      Rule::space => rules::space(state),
+      Rule::EOI => rules::EOI(state),
+    })
+  }
+}
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/source/performance/issue-5128.rs b/src/tools/rustfmt/tests/source/performance/issue-5128.rs
new file mode 100644
index 00000000000..3adce49601c
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/performance/issue-5128.rs
@@ -0,0 +1,5127 @@
+
+fn takes_a_long_time_to_rustfmt() {
+    let inner_cte = vec![Node {
+        node: Some(node::Node::CommonTableExpr(Box::new(CommonTableExpr {
+            ctename: String::from("ranked_by_age_within_key"),
+            aliascolnames: vec![],
+            ctematerialized: CteMaterialize::Default as i32,
+            ctequery: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+                    target_list: vec![
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from(""),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::AStar(AStar{}))
+                                        }],
+                                        location: 80
+                                    }))
+                                })),
+                                location: 80
+                            })))
+                        },
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("rank_in_key"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::FuncCall(Box::new(FuncCall {
+                                        funcname: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("row_number")
+                                            }))
+                                        }],
+                                        args: vec![],
+                                        agg_order: vec![],
+                                        agg_filter: None,
+                                        agg_within_group: false,
+                                        agg_star: false,
+                                        agg_distinct: false,
+                                        func_variadic: false,
+                                        over: Some(Box::new(WindowDef {
+                                            name: String::from(""),
+                                            refname: String::from(""),
+                                            partition_clause: vec![
+                                                Node {
+                                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                                        fields: vec![Node {
+                                                            node: Some(node::Node::String(String2 {
+                                                                str: String::from("synthetic_key")
+                                                            }))
+                                                        }], location: 123
+                                                    }))
+                                                }], order_clause: vec![Node {
+                                                    node: Some(node::Node::SortBy(Box::new(SortBy {
+                                                        node: Some(Box::new(Node {
+                                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                                fields: vec![Node {
+                                                                    node: Some(node::Node::String(String2 {
+                                                                        str: String::from("logical_timestamp")
+                                                                    }))
+                                                                }], location: 156
+                                                            }))
+                                                        })),
+                                                        sortby_dir: SortByDir::SortbyDesc as i32,
+                                                        sortby_nulls: SortByNulls::SortbyNullsDefault as i32,
+                                                        use_op: vec![],
+                                                        location: -1
+                                                    })))
+                                                }], frame_options: 1058, start_offset: None, end_offset: None, location: 109
+                                            })),
+                                            location: 91
+                                        })))
+                                    })),
+                                    location: 91
+                                })))
+                            }],
+                            from_clause: vec![Node {
+                                node: Some(node::Node::RangeVar(RangeVar {
+                                    catalogname: String::from(""), schemaname: String::from("_supertables"), relname: String::from("9999-9999-9999"), inh: true, relpersistence: String::from("p"), alias: None, location: 206
+                                }))
+                            }],
+                            where_clause: Some(Box::new(Node {
+                                node: Some(node::Node::AExpr(Box::new(AExpr {
+                                    kind: AExprKind::AexprOp as i32,
+                                    name: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("<=")
+                                        }))
+                                    }],
+                                    lexpr: Some(Box::new(Node {
+                                        node: Some(node::Node::ColumnRef(ColumnRef {
+                                            fields: vec![Node {
+                                                node: Some(node::Node::String(String2 {
+                                                    str: String::from("logical_timestamp")
+                                                }))
+                                            }],
+                                            location: 250
+                                        }))
+                                    })),
+                                    rexpr: Some(Box::new(Node {
+                                        node: Some(node::Node::AConst(Box::new(AConst {
+                                            val: Some(Box::new(Node {
+                                                node: Some(node::Node::Integer(Integer {
+                                                    ival: 9000
+                                                }))
+                                            })),
+                                            location: 271
+                                        })))
+                                    })),
+                                    location: 268
+                                })))
+                            })),
+                            group_clause: vec![],
+                            having_clause: None,
+                            window_clause: vec![],
+                            values_lists: vec![],
+                            sort_clause: vec![],
+                            limit_offset: None,
+                            limit_count: None,
+                            limit_option: LimitOption::Default as i32,
+                            locking_clause: vec![],
+                            with_clause: None,
+                            op: SetOperation::SetopNone as i32,
+                            all: false,
+                            larg: None,
+                            rarg: None
+                        }))),
+            })),
+            location: 29,
+            cterecursive: false,
+            cterefcount: 0,
+            ctecolnames: vec![],
+            ctecoltypes: vec![],
+            ctecoltypmods: vec![],
+            ctecolcollations: vec![],
+        }))),
+    }];
+    let outer_cte = vec![Node {
+        node: Some(node::Node::CommonTableExpr(Box::new(CommonTableExpr {
+            ctename: String::from("table_name"),
+            aliascolnames: vec![],
+            ctematerialized: CteMaterialize::Default as i32,
+            ctequery: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+                    target_list: vec![
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("column1"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("c1"),
+                                            })),
+                                        }],
+                                        location: 301,
+                                    })),
+                                })),
+                                location: 301,
+                            }))),
+                        },
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("column2"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("c2"),
+                                            })),
+                                        }],
+                                        location: 324,
+                                    })),
+                                })),
+                                location: 324,
+                            }))),
+                        },
+                    ],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from(""),
+                            relname: String::from("ranked_by_age_within_key"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 347,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::BoolExpr(Box::new(BoolExpr {
+                            xpr: None,
+                            boolop: BoolExprType::AndExpr as i32,
+                            args: vec![
+                                Node {
+                                    node: Some(node::Node::AExpr(Box::new(AExpr {
+                                        kind: AExprKind::AexprOp as i32,
+                                        name: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("="),
+                                            })),
+                                        }],
+                                        lexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                fields: vec![Node {
+                                                    node: Some(node::Node::String(
+                                                        String2 {
+                                                            str: String::from("rank_in_key"),
+                                                        },
+                                                    )),
+                                                }],
+                                                location: 382,
+                                            })),
+                                        })),
+                                        rexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::AConst(Box::new(AConst {
+                                                val: Some(Box::new(Node {
+                                                    node: Some(node::Node::Integer(
+                                                        Integer { ival: 1 },
+                                                    )),
+                                                })),
+                                                location: 396,
+                                            }))),
+                                        })),
+                                        location: 394,
+                                    }))),
+                                },
+                                Node {
+                                    node: Some(node::Node::AExpr(Box::new(AExpr {
+                                        kind: AExprKind::AexprOp as i32,
+                                        name: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("="),
+                                            })),
+                                        }],
+                                        lexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                fields: vec![Node {
+                                                    node: Some(node::Node::String(
+                                                        String2 {
+                                                            str: String::from("is_deleted"),
+                                                        },
+                                                    )),
+                                                }],
+                                                location: 402,
+                                            })),
+                                        })),
+                                        rexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::TypeCast(Box::new(
+                                                TypeCast {
+                                                    arg: Some(Box::new(Node {
+                                                        node: Some(node::Node::AConst(
+                                                            Box::new(AConst {
+                                                                val: Some(Box::new(Node {
+                                                                    node: Some(
+                                                                        node::Node::String(
+                                                                            String2 {
+                                                                                str:
+                                                                                    String::from(
+                                                                                        "f",
+                                                                                    ),
+                                                                            },
+                                                                        ),
+                                                                    ),
+                                                                })),
+                                                                location: 415,
+                                                            }),
+                                                        )),
+                                                    })),
+                                                    type_name: Some(TypeName {
+                                                        names: vec![
+                                                            Node {
+                                                                node: Some(node::Node::String(
+                                                                    String2 {
+                                                                        str: String::from(
+                                                                            "pg_catalog",
+                                                                        ),
+                                                                    },
+                                                                )),
+                                                            },
+                                                            Node {
+                                                                node: Some(node::Node::String(
+                                                                    String2 {
+                                                                        str: String::from(
+                                                                            "bool",
+                                                                        ),
+                                                                    },
+                                                                )),
+                                                            },
+                                                        ],
+                                                        type_oid: 0,
+                                                        setof: false,
+                                                        pct_type: false,
+                                                        typmods: vec![],
+                                                        typemod: -1,
+                                                        array_bounds: vec![],
+                                                        location: -1,
+                                                    }),
+                                                    location: -1,
+                                                },
+                                            ))),
+                                        })),
+                                        location: 413,
+                                    }))),
+                                },
+                            ],
+                            location: 398,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: Some(WithClause {
+                        ctes: inner_cte,
+                        recursive: false,
+                        location: 24,
+                    }),
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            location: 5,
+            cterecursive: false,
+            cterefcount: 0,
+            ctecolnames: vec![],
+            ctecoltypes: vec![],
+            ctecoltypmods: vec![],
+            ctecolcollations: vec![],
+        }))),
+    }];
+    let expected_result = ParseResult {
+        version: 130003,
+        stmts: vec![RawStmt {
+            stmt: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+
+                    target_list: vec![Node {
+                        node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                            name: String::from(""),
+                            indirection: vec![],
+                            val: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("column1"),
+                                        })),
+                                    }],
+                                    location: 430,
+                                })),
+                            })),
+                            location: 430,
+                        }))),
+                    }],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from(""),
+                            relname: String::from("table_name"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 443,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::AExpr(Box::new(AExpr {
+                            kind: AExprKind::AexprOp as i32,
+                            name: vec![Node {
+                                node: Some(node::Node::String(String2 {
+                                    str: String::from(">"),
+                                })),
+                            }],
+                            lexpr: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("column2"),
+                                        })),
+                                    }],
+                                    location: 460,
+                                })),
+                            })),
+                            rexpr: Some(Box::new(Node {
+                                node: Some(node::Node::AConst(Box::new(AConst {
+                                    val: Some(Box::new(Node {
+                                        node: Some(node::Node::Integer(Integer {
+                                            ival: 9000,
+                                        })),
+                                    })),
+                                    location: 470,
+                                }))),
+                            })),
+                            location: 468,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: Some(WithClause {
+                        ctes: outer_cte,
+                        recursive: false,
+                        location: 0,
+                    }),
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            stmt_location: 0,
+            stmt_len: 0,
+        }],
+    };
+
+}
+#[derive(Clone, PartialEq)]
+pub struct ParseResult {
+
+    pub version: i32,
+
+    pub stmts: Vec<RawStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScanResult {
+
+    pub version: i32,
+
+    pub tokens: Vec<ScanToken>,
+}
+#[derive(Clone, PartialEq)]
+pub struct Node {
+    pub node: ::core::option::Option<node::Node>,
+}
+/// Nested message and enum types in `Node`.
+pub mod node {
+    #[derive(Clone, PartialEq)]
+    pub enum Node {
+
+        Alias(super::Alias),
+
+        RangeVar(super::RangeVar),
+
+        TableFunc(Box<super::TableFunc>),
+
+        Expr(super::Expr),
+
+        Var(Box<super::Var>),
+
+        Param(Box<super::Param>),
+
+        Aggref(Box<super::Aggref>),
+
+        GroupingFunc(Box<super::GroupingFunc>),
+
+        WindowFunc(Box<super::WindowFunc>),
+
+        SubscriptingRef(Box<super::SubscriptingRef>),
+
+        FuncExpr(Box<super::FuncExpr>),
+
+        NamedArgExpr(Box<super::NamedArgExpr>),
+
+        OpExpr(Box<super::OpExpr>),
+
+        DistinctExpr(Box<super::DistinctExpr>),
+
+        NullIfExpr(Box<super::NullIfExpr>),
+
+        ScalarArrayOpExpr(Box<super::ScalarArrayOpExpr>),
+
+        BoolExpr(Box<super::BoolExpr>),
+
+        SubLink(Box<super::SubLink>),
+
+        SubPlan(Box<super::SubPlan>),
+
+        AlternativeSubPlan(Box<super::AlternativeSubPlan>),
+
+        FieldSelect(Box<super::FieldSelect>),
+
+        FieldStore(Box<super::FieldStore>),
+
+        RelabelType(Box<super::RelabelType>),
+
+        CoerceViaIo(Box<super::CoerceViaIo>),
+
+        ArrayCoerceExpr(Box<super::ArrayCoerceExpr>),
+
+        ConvertRowtypeExpr(Box<super::ConvertRowtypeExpr>),
+
+        CollateExpr(Box<super::CollateExpr>),
+
+        CaseExpr(Box<super::CaseExpr>),
+
+        CaseWhen(Box<super::CaseWhen>),
+
+        CaseTestExpr(Box<super::CaseTestExpr>),
+
+        ArrayExpr(Box<super::ArrayExpr>),
+
+        RowExpr(Box<super::RowExpr>),
+
+        RowCompareExpr(Box<super::RowCompareExpr>),
+
+        CoalesceExpr(Box<super::CoalesceExpr>),
+
+        MinMaxExpr(Box<super::MinMaxExpr>),
+
+        SqlvalueFunction(Box<super::SqlValueFunction>),
+
+        XmlExpr(Box<super::XmlExpr>),
+
+        NullTest(Box<super::NullTest>),
+
+        BooleanTest(Box<super::BooleanTest>),
+
+        CoerceToDomain(Box<super::CoerceToDomain>),
+
+        CoerceToDomainValue(Box<super::CoerceToDomainValue>),
+
+        SetToDefault(Box<super::SetToDefault>),
+
+        CurrentOfExpr(Box<super::CurrentOfExpr>),
+
+        NextValueExpr(Box<super::NextValueExpr>),
+
+        InferenceElem(Box<super::InferenceElem>),
+
+        TargetEntry(Box<super::TargetEntry>),
+
+        RangeTblRef(super::RangeTblRef),
+
+        JoinExpr(Box<super::JoinExpr>),
+
+        FromExpr(Box<super::FromExpr>),
+
+        OnConflictExpr(Box<super::OnConflictExpr>),
+
+        IntoClause(Box<super::IntoClause>),
+
+        RawStmt(Box<super::RawStmt>),
+
+        Query(Box<super::Query>),
+
+        InsertStmt(Box<super::InsertStmt>),
+
+        DeleteStmt(Box<super::DeleteStmt>),
+
+        UpdateStmt(Box<super::UpdateStmt>),
+
+        SelectStmt(Box<super::SelectStmt>),
+
+        AlterTableStmt(super::AlterTableStmt),
+
+        AlterTableCmd(Box<super::AlterTableCmd>),
+
+        AlterDomainStmt(Box<super::AlterDomainStmt>),
+
+        SetOperationStmt(Box<super::SetOperationStmt>),
+
+        GrantStmt(super::GrantStmt),
+
+        GrantRoleStmt(super::GrantRoleStmt),
+
+        AlterDefaultPrivilegesStmt(super::AlterDefaultPrivilegesStmt),
+
+        ClosePortalStmt(super::ClosePortalStmt),
+
+        ClusterStmt(super::ClusterStmt),
+
+        CopyStmt(Box<super::CopyStmt>),
+
+        CreateStmt(super::CreateStmt),
+
+        DefineStmt(super::DefineStmt),
+
+        DropStmt(super::DropStmt),
+
+        TruncateStmt(super::TruncateStmt),
+
+        CommentStmt(Box<super::CommentStmt>),
+
+        FetchStmt(super::FetchStmt),
+
+        IndexStmt(Box<super::IndexStmt>),
+
+        CreateFunctionStmt(super::CreateFunctionStmt),
+
+        AlterFunctionStmt(super::AlterFunctionStmt),
+
+        DoStmt(super::DoStmt),
+
+        RenameStmt(Box<super::RenameStmt>),
+
+        RuleStmt(Box<super::RuleStmt>),
+
+        NotifyStmt(super::NotifyStmt),
+
+        ListenStmt(super::ListenStmt),
+
+        UnlistenStmt(super::UnlistenStmt),
+
+        TransactionStmt(super::TransactionStmt),
+
+        ViewStmt(Box<super::ViewStmt>),
+
+        LoadStmt(super::LoadStmt),
+
+        CreateDomainStmt(Box<super::CreateDomainStmt>),
+
+        CreatedbStmt(super::CreatedbStmt),
+
+        DropdbStmt(super::DropdbStmt),
+
+        VacuumStmt(super::VacuumStmt),
+
+        ExplainStmt(Box<super::ExplainStmt>),
+
+        CreateTableAsStmt(Box<super::CreateTableAsStmt>),
+
+        CreateSeqStmt(super::CreateSeqStmt),
+
+        AlterSeqStmt(super::AlterSeqStmt),
+
+        VariableSetStmt(super::VariableSetStmt),
+
+        VariableShowStmt(super::VariableShowStmt),
+
+        DiscardStmt(super::DiscardStmt),
+
+        CreateTrigStmt(Box<super::CreateTrigStmt>),
+
+        CreatePlangStmt(super::CreatePLangStmt),
+
+        CreateRoleStmt(super::CreateRoleStmt),
+
+        AlterRoleStmt(super::AlterRoleStmt),
+
+        DropRoleStmt(super::DropRoleStmt),
+
+        LockStmt(super::LockStmt),
+
+        ConstraintsSetStmt(super::ConstraintsSetStmt),
+
+        ReindexStmt(super::ReindexStmt),
+
+        CheckPointStmt(super::CheckPointStmt),
+
+        CreateSchemaStmt(super::CreateSchemaStmt),
+
+        AlterDatabaseStmt(super::AlterDatabaseStmt),
+
+        AlterDatabaseSetStmt(super::AlterDatabaseSetStmt),
+
+        AlterRoleSetStmt(super::AlterRoleSetStmt),
+
+        CreateConversionStmt(super::CreateConversionStmt),
+
+        CreateCastStmt(super::CreateCastStmt),
+
+        CreateOpClassStmt(super::CreateOpClassStmt),
+
+        CreateOpFamilyStmt(super::CreateOpFamilyStmt),
+
+        AlterOpFamilyStmt(super::AlterOpFamilyStmt),
+
+        PrepareStmt(Box<super::PrepareStmt>),
+
+        ExecuteStmt(super::ExecuteStmt),
+
+        DeallocateStmt(super::DeallocateStmt),
+
+        DeclareCursorStmt(Box<super::DeclareCursorStmt>),
+
+        CreateTableSpaceStmt(super::CreateTableSpaceStmt),
+
+        DropTableSpaceStmt(super::DropTableSpaceStmt),
+
+        AlterObjectDependsStmt(Box<super::AlterObjectDependsStmt>),
+
+        AlterObjectSchemaStmt(Box<super::AlterObjectSchemaStmt>),
+
+        AlterOwnerStmt(Box<super::AlterOwnerStmt>),
+
+        AlterOperatorStmt(super::AlterOperatorStmt),
+
+        AlterTypeStmt(super::AlterTypeStmt),
+
+        DropOwnedStmt(super::DropOwnedStmt),
+
+        ReassignOwnedStmt(super::ReassignOwnedStmt),
+
+        CompositeTypeStmt(super::CompositeTypeStmt),
+
+        CreateEnumStmt(super::CreateEnumStmt),
+
+        CreateRangeStmt(super::CreateRangeStmt),
+
+        AlterEnumStmt(super::AlterEnumStmt),
+
+        AlterTsdictionaryStmt(super::AlterTsDictionaryStmt),
+
+        AlterTsconfigurationStmt(super::AlterTsConfigurationStmt),
+
+        CreateFdwStmt(super::CreateFdwStmt),
+
+        AlterFdwStmt(super::AlterFdwStmt),
+
+        CreateForeignServerStmt(super::CreateForeignServerStmt),
+
+        AlterForeignServerStmt(super::AlterForeignServerStmt),
+
+        CreateUserMappingStmt(super::CreateUserMappingStmt),
+
+        AlterUserMappingStmt(super::AlterUserMappingStmt),
+
+        DropUserMappingStmt(super::DropUserMappingStmt),
+
+        AlterTableSpaceOptionsStmt(super::AlterTableSpaceOptionsStmt),
+
+        AlterTableMoveAllStmt(super::AlterTableMoveAllStmt),
+
+        SecLabelStmt(Box<super::SecLabelStmt>),
+
+        CreateForeignTableStmt(super::CreateForeignTableStmt),
+
+        ImportForeignSchemaStmt(super::ImportForeignSchemaStmt),
+
+        CreateExtensionStmt(super::CreateExtensionStmt),
+
+        AlterExtensionStmt(super::AlterExtensionStmt),
+
+        AlterExtensionContentsStmt(Box<super::AlterExtensionContentsStmt>),
+
+        CreateEventTrigStmt(super::CreateEventTrigStmt),
+
+        AlterEventTrigStmt(super::AlterEventTrigStmt),
+
+        RefreshMatViewStmt(super::RefreshMatViewStmt),
+
+        ReplicaIdentityStmt(super::ReplicaIdentityStmt),
+
+        AlterSystemStmt(super::AlterSystemStmt),
+
+        CreatePolicyStmt(Box<super::CreatePolicyStmt>),
+
+        AlterPolicyStmt(Box<super::AlterPolicyStmt>),
+
+        CreateTransformStmt(super::CreateTransformStmt),
+
+        CreateAmStmt(super::CreateAmStmt),
+
+        CreatePublicationStmt(super::CreatePublicationStmt),
+
+        AlterPublicationStmt(super::AlterPublicationStmt),
+
+        CreateSubscriptionStmt(super::CreateSubscriptionStmt),
+
+        AlterSubscriptionStmt(super::AlterSubscriptionStmt),
+
+        DropSubscriptionStmt(super::DropSubscriptionStmt),
+
+        CreateStatsStmt(super::CreateStatsStmt),
+
+        AlterCollationStmt(super::AlterCollationStmt),
+
+        CallStmt(Box<super::CallStmt>),
+
+        AlterStatsStmt(super::AlterStatsStmt),
+
+        AExpr(Box<super::AExpr>),
+
+        ColumnRef(super::ColumnRef),
+
+        ParamRef(super::ParamRef),
+
+        AConst(Box<super::AConst>),
+
+        FuncCall(Box<super::FuncCall>),
+
+        AStar(super::AStar),
+
+        AIndices(Box<super::AIndices>),
+
+        AIndirection(Box<super::AIndirection>),
+
+        AArrayExpr(super::AArrayExpr),
+
+        ResTarget(Box<super::ResTarget>),
+
+        MultiAssignRef(Box<super::MultiAssignRef>),
+
+        TypeCast(Box<super::TypeCast>),
+
+        CollateClause(Box<super::CollateClause>),
+
+        SortBy(Box<super::SortBy>),
+
+        WindowDef(Box<super::WindowDef>),
+
+        RangeSubselect(Box<super::RangeSubselect>),
+
+        RangeFunction(super::RangeFunction),
+
+        RangeTableSample(Box<super::RangeTableSample>),
+
+        RangeTableFunc(Box<super::RangeTableFunc>),
+
+        RangeTableFuncCol(Box<super::RangeTableFuncCol>),
+
+        TypeName(super::TypeName),
+
+        ColumnDef(Box<super::ColumnDef>),
+
+        IndexElem(Box<super::IndexElem>),
+
+        Constraint(Box<super::Constraint>),
+
+        DefElem(Box<super::DefElem>),
+
+        RangeTblEntry(Box<super::RangeTblEntry>),
+
+        RangeTblFunction(Box<super::RangeTblFunction>),
+
+        TableSampleClause(Box<super::TableSampleClause>),
+
+        WithCheckOption(Box<super::WithCheckOption>),
+
+        SortGroupClause(super::SortGroupClause),
+
+        GroupingSet(super::GroupingSet),
+
+        WindowClause(Box<super::WindowClause>),
+
+        ObjectWithArgs(super::ObjectWithArgs),
+
+        AccessPriv(super::AccessPriv),
+
+        CreateOpClassItem(super::CreateOpClassItem),
+
+        TableLikeClause(super::TableLikeClause),
+
+        FunctionParameter(Box<super::FunctionParameter>),
+
+        LockingClause(super::LockingClause),
+
+        RowMarkClause(super::RowMarkClause),
+
+        XmlSerialize(Box<super::XmlSerialize>),
+
+        WithClause(super::WithClause),
+
+        InferClause(Box<super::InferClause>),
+
+        OnConflictClause(Box<super::OnConflictClause>),
+
+        CommonTableExpr(Box<super::CommonTableExpr>),
+
+        RoleSpec(super::RoleSpec),
+
+        TriggerTransition(super::TriggerTransition),
+
+        PartitionElem(Box<super::PartitionElem>),
+
+        PartitionSpec(super::PartitionSpec),
+
+        PartitionBoundSpec(super::PartitionBoundSpec),
+
+        PartitionRangeDatum(Box<super::PartitionRangeDatum>),
+
+        PartitionCmd(super::PartitionCmd),
+
+        VacuumRelation(super::VacuumRelation),
+
+        InlineCodeBlock(super::InlineCodeBlock),
+
+        CallContext(super::CallContext),
+
+        Integer(super::Integer),
+
+        Float(super::Float),
+
+        String(super::String2),
+
+        BitString(super::BitString),
+
+        Null(super::Null),
+
+        List(super::List),
+
+        IntList(super::IntList),
+
+        OidList(super::OidList),
+    }
+}
+#[derive(Clone, PartialEq)]
+pub struct Integer {
+    /// machine integer
+
+    pub ival: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Float {
+    /// string
+
+    pub str: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct String2 {
+    /// string
+
+    pub str: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct BitString {
+    /// string
+
+    pub str: String,
+}
+/// intentionally empty
+#[derive(Clone, PartialEq)]
+pub struct Null {}
+#[derive(Clone, PartialEq)]
+pub struct List {
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct OidList {
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct IntList {
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct Alias {
+
+    pub aliasname: String,
+
+    pub colnames: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeVar {
+
+    pub catalogname: String,
+
+    pub schemaname: String,
+
+    pub relname: String,
+
+    pub inh: bool,
+
+    pub relpersistence: String,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableFunc {
+
+    pub ns_uris: Vec<Node>,
+
+    pub ns_names: Vec<Node>,
+
+    pub docexpr: ::core::option::Option<Box<Node>>,
+
+    pub rowexpr: ::core::option::Option<Box<Node>>,
+
+    pub colnames: Vec<Node>,
+
+    pub coltypes: Vec<Node>,
+
+    pub coltypmods: Vec<Node>,
+
+    pub colcollations: Vec<Node>,
+
+    pub colexprs: Vec<Node>,
+
+    pub coldefexprs: Vec<Node>,
+
+    pub notnulls: Vec<u64>,
+
+    pub ordinalitycol: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Expr {}
+#[derive(Clone, PartialEq)]
+pub struct Var {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub varno: u32,
+
+    pub varattno: i32,
+
+    pub vartype: u32,
+
+    pub vartypmod: i32,
+
+    pub varcollid: u32,
+
+    pub varlevelsup: u32,
+
+    pub varnosyn: u32,
+
+    pub varattnosyn: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Param {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub paramkind: i32,
+
+    pub paramid: i32,
+
+    pub paramtype: u32,
+
+    pub paramtypmod: i32,
+
+    pub paramcollid: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Aggref {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub aggfnoid: u32,
+
+    pub aggtype: u32,
+
+    pub aggcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub aggtranstype: u32,
+
+    pub aggargtypes: Vec<Node>,
+
+    pub aggdirectargs: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub aggorder: Vec<Node>,
+
+    pub aggdistinct: Vec<Node>,
+
+    pub aggfilter: ::core::option::Option<Box<Node>>,
+
+    pub aggstar: bool,
+
+    pub aggvariadic: bool,
+
+    pub aggkind: String,
+
+    pub agglevelsup: u32,
+
+    pub aggsplit: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct GroupingFunc {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub refs: Vec<Node>,
+
+    pub cols: Vec<Node>,
+
+    pub agglevelsup: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowFunc {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub winfnoid: u32,
+
+    pub wintype: u32,
+
+    pub wincollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub aggfilter: ::core::option::Option<Box<Node>>,
+
+    pub winref: u32,
+
+    pub winstar: bool,
+
+    pub winagg: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubscriptingRef {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub refcontainertype: u32,
+
+    pub refelemtype: u32,
+
+    pub reftypmod: i32,
+
+    pub refcollid: u32,
+
+    pub refupperindexpr: Vec<Node>,
+
+    pub reflowerindexpr: Vec<Node>,
+
+    pub refexpr: ::core::option::Option<Box<Node>>,
+
+    pub refassgnexpr: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct FuncExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub funcid: u32,
+
+    pub funcresulttype: u32,
+
+    pub funcretset: bool,
+
+    pub funcvariadic: bool,
+
+    pub funcformat: i32,
+
+    pub funccollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NamedArgExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub name: String,
+
+    pub argnumber: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct OpExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DistinctExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NullIfExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScalarArrayOpExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub use_or: bool,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct BoolExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub boolop: i32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubLink {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub sub_link_type: i32,
+
+    pub sub_link_id: i32,
+
+    pub testexpr: ::core::option::Option<Box<Node>>,
+
+    pub oper_name: Vec<Node>,
+
+    pub subselect: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubPlan {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub sub_link_type: i32,
+
+    pub testexpr: ::core::option::Option<Box<Node>>,
+
+    pub param_ids: Vec<Node>,
+
+    pub plan_id: i32,
+
+    pub plan_name: String,
+
+    pub first_col_type: u32,
+
+    pub first_col_typmod: i32,
+
+    pub first_col_collation: u32,
+
+    pub use_hash_table: bool,
+
+    pub unknown_eq_false: bool,
+
+    pub parallel_safe: bool,
+
+    pub set_param: Vec<Node>,
+
+    pub par_param: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub startup_cost: f64,
+
+    pub per_call_cost: f64,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlternativeSubPlan {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub subplans: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct FieldSelect {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub fieldnum: i32,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FieldStore {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub newvals: Vec<Node>,
+
+    pub fieldnums: Vec<Node>,
+
+    pub resulttype: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RelabelType {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub relabelformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceViaIo {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resultcollid: u32,
+
+    pub coerceformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ArrayCoerceExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub elemexpr: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub coerceformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ConvertRowtypeExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub convertformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CollateExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub coll_oid: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub casetype: u32,
+
+    pub casecollid: u32,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub defresult: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseWhen {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub result: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseTestExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ArrayExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub array_typeid: u32,
+
+    pub array_collid: u32,
+
+    pub element_typeid: u32,
+
+    pub elements: Vec<Node>,
+
+    pub multidims: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub row_typeid: u32,
+
+    pub row_format: i32,
+
+    pub colnames: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowCompareExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub rctype: i32,
+
+    pub opnos: Vec<Node>,
+
+    pub opfamilies: Vec<Node>,
+
+    pub inputcollids: Vec<Node>,
+
+    pub largs: Vec<Node>,
+
+    pub rargs: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoalesceExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub coalescetype: u32,
+
+    pub coalescecollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct MinMaxExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub minmaxtype: u32,
+
+    pub minmaxcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub op: i32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SqlValueFunction {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub op: i32,
+
+    pub r#type: u32,
+
+    pub typmod: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct XmlExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub op: i32,
+
+    pub name: String,
+
+    pub named_args: Vec<Node>,
+
+    pub arg_names: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub xmloption: i32,
+
+    pub r#type: u32,
+
+    pub typmod: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NullTest {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub nulltesttype: i32,
+
+    pub argisrow: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct BooleanTest {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub booltesttype: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceToDomain {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub coercionformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceToDomainValue {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SetToDefault {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CurrentOfExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub cvarno: u32,
+
+    pub cursor_name: String,
+
+    pub cursor_param: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NextValueExpr {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub seqid: u32,
+
+    pub type_id: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InferenceElem {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub infercollid: u32,
+
+    pub inferopclass: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TargetEntry {
+
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub resno: i32,
+
+    pub resname: String,
+
+    pub ressortgroupref: u32,
+
+    pub resorigtbl: u32,
+
+    pub resorigcol: i32,
+
+    pub resjunk: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblRef {
+
+    pub rtindex: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct JoinExpr {
+
+    pub jointype: i32,
+
+    pub is_natural: bool,
+
+    pub larg: ::core::option::Option<Box<Node>>,
+
+    pub rarg: ::core::option::Option<Box<Node>>,
+
+    pub using_clause: Vec<Node>,
+
+    pub quals: ::core::option::Option<Box<Node>>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub rtindex: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FromExpr {
+
+    pub fromlist: Vec<Node>,
+
+    pub quals: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct OnConflictExpr {
+
+    pub action: i32,
+
+    pub arbiter_elems: Vec<Node>,
+
+    pub arbiter_where: ::core::option::Option<Box<Node>>,
+
+    pub constraint: u32,
+
+    pub on_conflict_set: Vec<Node>,
+
+    pub on_conflict_where: ::core::option::Option<Box<Node>>,
+
+    pub excl_rel_index: i32,
+
+    pub excl_rel_tlist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct IntoClause {
+
+    pub rel: ::core::option::Option<RangeVar>,
+
+    pub col_names: Vec<Node>,
+
+    pub access_method: String,
+
+    pub options: Vec<Node>,
+
+    pub on_commit: i32,
+
+    pub table_space_name: String,
+
+    pub view_query: ::core::option::Option<Box<Node>>,
+
+    pub skip_data: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RawStmt {
+
+    pub stmt: ::core::option::Option<Box<Node>>,
+
+    pub stmt_location: i32,
+
+    pub stmt_len: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Query {
+
+    pub command_type: i32,
+
+    pub query_source: i32,
+
+    pub can_set_tag: bool,
+
+    pub utility_stmt: ::core::option::Option<Box<Node>>,
+
+    pub result_relation: i32,
+
+    pub has_aggs: bool,
+
+    pub has_window_funcs: bool,
+
+    pub has_target_srfs: bool,
+
+    pub has_sub_links: bool,
+
+    pub has_distinct_on: bool,
+
+    pub has_recursive: bool,
+
+    pub has_modifying_cte: bool,
+
+    pub has_for_update: bool,
+
+    pub has_row_security: bool,
+
+    pub cte_list: Vec<Node>,
+
+    pub rtable: Vec<Node>,
+
+    pub jointree: ::core::option::Option<Box<FromExpr>>,
+
+    pub target_list: Vec<Node>,
+
+    pub r#override: i32,
+
+    pub on_conflict: ::core::option::Option<Box<OnConflictExpr>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub group_clause: Vec<Node>,
+
+    pub grouping_sets: Vec<Node>,
+
+    pub having_qual: ::core::option::Option<Box<Node>>,
+
+    pub window_clause: Vec<Node>,
+
+    pub distinct_clause: Vec<Node>,
+
+    pub sort_clause: Vec<Node>,
+
+    pub limit_offset: ::core::option::Option<Box<Node>>,
+
+    pub limit_count: ::core::option::Option<Box<Node>>,
+
+    pub limit_option: i32,
+
+    pub row_marks: Vec<Node>,
+
+    pub set_operations: ::core::option::Option<Box<Node>>,
+
+    pub constraint_deps: Vec<Node>,
+
+    pub with_check_options: Vec<Node>,
+
+    pub stmt_location: i32,
+
+    pub stmt_len: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InsertStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub cols: Vec<Node>,
+
+    pub select_stmt: ::core::option::Option<Box<Node>>,
+
+    pub on_conflict_clause: ::core::option::Option<Box<OnConflictClause>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+
+    pub r#override: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeleteStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub using_clause: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+}
+#[derive(Clone, PartialEq)]
+pub struct UpdateStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub target_list: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub from_clause: Vec<Node>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+}
+#[derive(Clone, PartialEq)]
+pub struct SelectStmt {
+
+    pub distinct_clause: Vec<Node>,
+
+    pub into_clause: ::core::option::Option<Box<IntoClause>>,
+
+    pub target_list: Vec<Node>,
+
+    pub from_clause: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub group_clause: Vec<Node>,
+
+    pub having_clause: ::core::option::Option<Box<Node>>,
+
+    pub window_clause: Vec<Node>,
+
+    pub values_lists: Vec<Node>,
+
+    pub sort_clause: Vec<Node>,
+
+    pub limit_offset: ::core::option::Option<Box<Node>>,
+
+    pub limit_count: ::core::option::Option<Box<Node>>,
+
+    pub limit_option: i32,
+
+    pub locking_clause: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+
+    pub op: i32,
+
+    pub all: bool,
+
+    pub larg: ::core::option::Option<Box<SelectStmt>>,
+
+    pub rarg: ::core::option::Option<Box<SelectStmt>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub cmds: Vec<Node>,
+
+    pub relkind: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableCmd {
+
+    pub subtype: i32,
+
+    pub name: String,
+
+    pub num: i32,
+
+    pub newowner: ::core::option::Option<RoleSpec>,
+
+    pub def: ::core::option::Option<Box<Node>>,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDomainStmt {
+
+    pub subtype: String,
+
+    pub type_name: Vec<Node>,
+
+    pub name: String,
+
+    pub def: ::core::option::Option<Box<Node>>,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SetOperationStmt {
+
+    pub op: i32,
+
+    pub all: bool,
+
+    pub larg: ::core::option::Option<Box<Node>>,
+
+    pub rarg: ::core::option::Option<Box<Node>>,
+
+    pub col_types: Vec<Node>,
+
+    pub col_typmods: Vec<Node>,
+
+    pub col_collations: Vec<Node>,
+
+    pub group_clauses: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct GrantStmt {
+
+    pub is_grant: bool,
+
+    pub targtype: i32,
+
+    pub objtype: i32,
+
+    pub objects: Vec<Node>,
+
+    pub privileges: Vec<Node>,
+
+    pub grantees: Vec<Node>,
+
+    pub grant_option: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct GrantRoleStmt {
+
+    pub granted_roles: Vec<Node>,
+
+    pub grantee_roles: Vec<Node>,
+
+    pub is_grant: bool,
+
+    pub admin_opt: bool,
+
+    pub grantor: ::core::option::Option<RoleSpec>,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDefaultPrivilegesStmt {
+
+    pub options: Vec<Node>,
+
+    pub action: ::core::option::Option<GrantStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ClosePortalStmt {
+
+    pub portalname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct ClusterStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub indexname: String,
+
+    pub options: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CopyStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub attlist: Vec<Node>,
+
+    pub is_from: bool,
+
+    pub is_program: bool,
+
+    pub filename: String,
+
+    pub options: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub table_elts: Vec<Node>,
+
+    pub inh_relations: Vec<Node>,
+
+    pub partbound: ::core::option::Option<PartitionBoundSpec>,
+
+    pub partspec: ::core::option::Option<PartitionSpec>,
+
+    pub of_typename: ::core::option::Option<TypeName>,
+
+    pub constraints: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub oncommit: i32,
+
+    pub tablespacename: String,
+
+    pub access_method: String,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DefineStmt {
+
+    pub kind: i32,
+
+    pub oldstyle: bool,
+
+    pub defnames: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub definition: Vec<Node>,
+
+    pub if_not_exists: bool,
+
+    pub replace: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropStmt {
+
+    pub objects: Vec<Node>,
+
+    pub remove_type: i32,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+
+    pub concurrent: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct TruncateStmt {
+
+    pub relations: Vec<Node>,
+
+    pub restart_seqs: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CommentStmt {
+
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub comment: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct FetchStmt {
+
+    pub direction: i32,
+
+    pub how_many: i64,
+
+    pub portalname: String,
+
+    pub ismove: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct IndexStmt {
+
+    pub idxname: String,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub access_method: String,
+
+    pub table_space: String,
+
+    pub index_params: Vec<Node>,
+
+    pub index_including_params: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub exclude_op_names: Vec<Node>,
+
+    pub idxcomment: String,
+
+    pub index_oid: u32,
+
+    pub old_node: u32,
+
+    pub old_create_subid: u32,
+
+    pub old_first_relfilenode_subid: u32,
+
+    pub unique: bool,
+
+    pub primary: bool,
+
+    pub isconstraint: bool,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub transformed: bool,
+
+    pub concurrent: bool,
+
+    pub if_not_exists: bool,
+
+    pub reset_default_tblspc: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateFunctionStmt {
+
+    pub is_procedure: bool,
+
+    pub replace: bool,
+
+    pub funcname: Vec<Node>,
+
+    pub parameters: Vec<Node>,
+
+    pub return_type: ::core::option::Option<TypeName>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterFunctionStmt {
+
+    pub objtype: i32,
+
+    pub func: ::core::option::Option<ObjectWithArgs>,
+
+    pub actions: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DoStmt {
+
+    pub args: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RenameStmt {
+
+    pub rename_type: i32,
+
+    pub relation_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub subname: String,
+
+    pub newname: String,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RuleStmt {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub rulename: String,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub event: i32,
+
+    pub instead: bool,
+
+    pub actions: Vec<Node>,
+
+    pub replace: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct NotifyStmt {
+
+    pub conditionname: String,
+
+    pub payload: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct ListenStmt {
+
+    pub conditionname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct UnlistenStmt {
+
+    pub conditionname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct TransactionStmt {
+
+    pub kind: i32,
+
+    pub options: Vec<Node>,
+
+    pub savepoint_name: String,
+
+    pub gid: String,
+
+    pub chain: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ViewStmt {
+
+    pub view: ::core::option::Option<RangeVar>,
+
+    pub aliases: Vec<Node>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub replace: bool,
+
+    pub options: Vec<Node>,
+
+    pub with_check_option: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct LoadStmt {
+
+    pub filename: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateDomainStmt {
+
+    pub domainname: Vec<Node>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub coll_clause: ::core::option::Option<Box<CollateClause>>,
+
+    pub constraints: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatedbStmt {
+
+    pub dbname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropdbStmt {
+
+    pub dbname: String,
+
+    pub missing_ok: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct VacuumStmt {
+
+    pub options: Vec<Node>,
+
+    pub rels: Vec<Node>,
+
+    pub is_vacuumcmd: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ExplainStmt {
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTableAsStmt {
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub into: ::core::option::Option<Box<IntoClause>>,
+
+    pub relkind: i32,
+
+    pub is_select_into: bool,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateSeqStmt {
+
+    pub sequence: ::core::option::Option<RangeVar>,
+
+    pub options: Vec<Node>,
+
+    pub owner_id: u32,
+
+    pub for_identity: bool,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSeqStmt {
+
+    pub sequence: ::core::option::Option<RangeVar>,
+
+    pub options: Vec<Node>,
+
+    pub for_identity: bool,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct VariableSetStmt {
+
+    pub kind: i32,
+
+    pub name: String,
+
+    pub args: Vec<Node>,
+
+    pub is_local: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct VariableShowStmt {
+
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct DiscardStmt {
+
+    pub target: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTrigStmt {
+
+    pub trigname: String,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub funcname: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub row: bool,
+
+    pub timing: i32,
+
+    pub events: i32,
+
+    pub columns: Vec<Node>,
+
+    pub when_clause: ::core::option::Option<Box<Node>>,
+
+    pub isconstraint: bool,
+
+    pub transition_rels: Vec<Node>,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub constrrel: ::core::option::Option<RangeVar>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePLangStmt {
+
+    pub replace: bool,
+
+    pub plname: String,
+
+    pub plhandler: Vec<Node>,
+
+    pub plinline: Vec<Node>,
+
+    pub plvalidator: Vec<Node>,
+
+    pub pltrusted: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateRoleStmt {
+
+    pub stmt_type: i32,
+
+    pub role: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterRoleStmt {
+
+    pub role: ::core::option::Option<RoleSpec>,
+
+    pub options: Vec<Node>,
+
+    pub action: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropRoleStmt {
+
+    pub roles: Vec<Node>,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct LockStmt {
+
+    pub relations: Vec<Node>,
+
+    pub mode: i32,
+
+    pub nowait: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ConstraintsSetStmt {
+
+    pub constraints: Vec<Node>,
+
+    pub deferred: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReindexStmt {
+
+    pub kind: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub name: String,
+
+    pub options: i32,
+
+    pub concurrent: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CheckPointStmt {}
+#[derive(Clone, PartialEq)]
+pub struct CreateSchemaStmt {
+
+    pub schemaname: String,
+
+    pub authrole: ::core::option::Option<RoleSpec>,
+
+    pub schema_elts: Vec<Node>,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDatabaseStmt {
+
+    pub dbname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDatabaseSetStmt {
+
+    pub dbname: String,
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterRoleSetStmt {
+
+    pub role: ::core::option::Option<RoleSpec>,
+
+    pub database: String,
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateConversionStmt {
+
+    pub conversion_name: Vec<Node>,
+
+    pub for_encoding_name: String,
+
+    pub to_encoding_name: String,
+
+    pub func_name: Vec<Node>,
+
+    pub def: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateCastStmt {
+
+    pub sourcetype: ::core::option::Option<TypeName>,
+
+    pub targettype: ::core::option::Option<TypeName>,
+
+    pub func: ::core::option::Option<ObjectWithArgs>,
+
+    pub context: i32,
+
+    pub inout: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpClassStmt {
+
+    pub opclassname: Vec<Node>,
+
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+
+    pub datatype: ::core::option::Option<TypeName>,
+
+    pub items: Vec<Node>,
+
+    pub is_default: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpFamilyStmt {
+
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOpFamilyStmt {
+
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+
+    pub is_drop: bool,
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct PrepareStmt {
+
+    pub name: String,
+
+    pub argtypes: Vec<Node>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ExecuteStmt {
+
+    pub name: String,
+
+    pub params: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeallocateStmt {
+
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeclareCursorStmt {
+
+    pub portalname: String,
+
+    pub options: i32,
+
+    pub query: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTableSpaceStmt {
+
+    pub tablespacename: String,
+
+    pub owner: ::core::option::Option<RoleSpec>,
+
+    pub location: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropTableSpaceStmt {
+
+    pub tablespacename: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterObjectDependsStmt {
+
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub extname: ::core::option::Option<Box<Node>>,
+
+    pub remove: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterObjectSchemaStmt {
+
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub newschema: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOwnerStmt {
+
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub newowner: ::core::option::Option<RoleSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOperatorStmt {
+
+    pub opername: ::core::option::Option<ObjectWithArgs>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTypeStmt {
+
+    pub type_name: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropOwnedStmt {
+
+    pub roles: Vec<Node>,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReassignOwnedStmt {
+
+    pub roles: Vec<Node>,
+
+    pub newrole: ::core::option::Option<RoleSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CompositeTypeStmt {
+
+    pub typevar: ::core::option::Option<RangeVar>,
+
+    pub coldeflist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateEnumStmt {
+
+    pub type_name: Vec<Node>,
+
+    pub vals: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateRangeStmt {
+
+    pub type_name: Vec<Node>,
+
+    pub params: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterEnumStmt {
+
+    pub type_name: Vec<Node>,
+
+    pub old_val: String,
+
+    pub new_val: String,
+
+    pub new_val_neighbor: String,
+
+    pub new_val_is_after: bool,
+
+    pub skip_if_new_val_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTsDictionaryStmt {
+
+    pub dictname: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTsConfigurationStmt {
+
+    pub kind: i32,
+
+    pub cfgname: Vec<Node>,
+
+    pub tokentype: Vec<Node>,
+
+    pub dicts: Vec<Node>,
+
+    pub r#override: bool,
+
+    pub replace: bool,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateFdwStmt {
+
+    pub fdwname: String,
+
+    pub func_options: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterFdwStmt {
+
+    pub fdwname: String,
+
+    pub func_options: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateForeignServerStmt {
+
+    pub servername: String,
+
+    pub servertype: String,
+
+    pub version: String,
+
+    pub fdwname: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterForeignServerStmt {
+
+    pub servername: String,
+
+    pub version: String,
+
+    pub options: Vec<Node>,
+
+    pub has_version: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateUserMappingStmt {
+
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterUserMappingStmt {
+
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropUserMappingStmt {
+
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableSpaceOptionsStmt {
+
+    pub tablespacename: String,
+
+    pub options: Vec<Node>,
+
+    pub is_reset: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableMoveAllStmt {
+
+    pub orig_tablespacename: String,
+
+    pub objtype: i32,
+
+    pub roles: Vec<Node>,
+
+    pub new_tablespacename: String,
+
+    pub nowait: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SecLabelStmt {
+
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub provider: String,
+
+    pub label: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateForeignTableStmt {
+
+    pub base_stmt: ::core::option::Option<CreateStmt>,
+
+    pub servername: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ImportForeignSchemaStmt {
+
+    pub server_name: String,
+
+    pub remote_schema: String,
+
+    pub local_schema: String,
+
+    pub list_type: i32,
+
+    pub table_list: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateExtensionStmt {
+
+    pub extname: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterExtensionStmt {
+
+    pub extname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterExtensionContentsStmt {
+
+    pub extname: String,
+
+    pub action: i32,
+
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateEventTrigStmt {
+
+    pub trigname: String,
+
+    pub eventname: String,
+
+    pub whenclause: Vec<Node>,
+
+    pub funcname: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterEventTrigStmt {
+
+    pub trigname: String,
+
+    pub tgenabled: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct RefreshMatViewStmt {
+
+    pub concurrent: bool,
+
+    pub skip_data: bool,
+
+    pub relation: ::core::option::Option<RangeVar>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReplicaIdentityStmt {
+
+    pub identity_type: String,
+
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSystemStmt {
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePolicyStmt {
+
+    pub policy_name: String,
+
+    pub table: ::core::option::Option<RangeVar>,
+
+    pub cmd_name: String,
+
+    pub permissive: bool,
+
+    pub roles: Vec<Node>,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub with_check: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterPolicyStmt {
+
+    pub policy_name: String,
+
+    pub table: ::core::option::Option<RangeVar>,
+
+    pub roles: Vec<Node>,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub with_check: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTransformStmt {
+
+    pub replace: bool,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub lang: String,
+
+    pub fromsql: ::core::option::Option<ObjectWithArgs>,
+
+    pub tosql: ::core::option::Option<ObjectWithArgs>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateAmStmt {
+
+    pub amname: String,
+
+    pub handler_name: Vec<Node>,
+
+    pub amtype: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePublicationStmt {
+
+    pub pubname: String,
+
+    pub options: Vec<Node>,
+
+    pub tables: Vec<Node>,
+
+    pub for_all_tables: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterPublicationStmt {
+
+    pub pubname: String,
+
+    pub options: Vec<Node>,
+
+    pub tables: Vec<Node>,
+
+    pub for_all_tables: bool,
+
+    pub table_action: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateSubscriptionStmt {
+
+    pub subname: String,
+
+    pub conninfo: String,
+
+    pub publication: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSubscriptionStmt {
+
+    pub kind: i32,
+
+    pub subname: String,
+
+    pub conninfo: String,
+
+    pub publication: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropSubscriptionStmt {
+
+    pub subname: String,
+
+    pub missing_ok: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateStatsStmt {
+
+    pub defnames: Vec<Node>,
+
+    pub stat_types: Vec<Node>,
+
+    pub exprs: Vec<Node>,
+
+    pub relations: Vec<Node>,
+
+    pub stxcomment: String,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterCollationStmt {
+
+    pub collname: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CallStmt {
+
+    pub funccall: ::core::option::Option<Box<FuncCall>>,
+
+    pub funcexpr: ::core::option::Option<Box<FuncExpr>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterStatsStmt {
+
+    pub defnames: Vec<Node>,
+
+    pub stxstattarget: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AExpr {
+
+    pub kind: i32,
+
+    pub name: Vec<Node>,
+
+    pub lexpr: ::core::option::Option<Box<Node>>,
+
+    pub rexpr: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ColumnRef {
+
+    pub fields: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ParamRef {
+
+    pub number: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AConst {
+
+    pub val: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FuncCall {
+
+    pub funcname: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub agg_order: Vec<Node>,
+
+    pub agg_filter: ::core::option::Option<Box<Node>>,
+
+    pub agg_within_group: bool,
+
+    pub agg_star: bool,
+
+    pub agg_distinct: bool,
+
+    pub func_variadic: bool,
+
+    pub over: ::core::option::Option<Box<WindowDef>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AStar {}
+#[derive(Clone, PartialEq)]
+pub struct AIndices {
+
+    pub is_slice: bool,
+
+    pub lidx: ::core::option::Option<Box<Node>>,
+
+    pub uidx: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AIndirection {
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub indirection: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AArrayExpr {
+
+    pub elements: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ResTarget {
+
+    pub name: String,
+
+    pub indirection: Vec<Node>,
+
+    pub val: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct MultiAssignRef {
+
+    pub source: ::core::option::Option<Box<Node>>,
+
+    pub colno: i32,
+
+    pub ncolumns: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TypeCast {
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CollateClause {
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub collname: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SortBy {
+
+    pub node: ::core::option::Option<Box<Node>>,
+
+    pub sortby_dir: i32,
+
+    pub sortby_nulls: i32,
+
+    pub use_op: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowDef {
+
+    pub name: String,
+
+    pub refname: String,
+
+    pub partition_clause: Vec<Node>,
+
+    pub order_clause: Vec<Node>,
+
+    pub frame_options: i32,
+
+    pub start_offset: ::core::option::Option<Box<Node>>,
+
+    pub end_offset: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeSubselect {
+
+    pub lateral: bool,
+
+    pub subquery: ::core::option::Option<Box<Node>>,
+
+    pub alias: ::core::option::Option<Alias>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeFunction {
+
+    pub lateral: bool,
+
+    pub ordinality: bool,
+
+    pub is_rowsfrom: bool,
+
+    pub functions: Vec<Node>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub coldeflist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableSample {
+
+    pub relation: ::core::option::Option<Box<Node>>,
+
+    pub method: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub repeatable: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableFunc {
+
+    pub lateral: bool,
+
+    pub docexpr: ::core::option::Option<Box<Node>>,
+
+    pub rowexpr: ::core::option::Option<Box<Node>>,
+
+    pub namespaces: Vec<Node>,
+
+    pub columns: Vec<Node>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableFuncCol {
+
+    pub colname: String,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub for_ordinality: bool,
+
+    pub is_not_null: bool,
+
+    pub colexpr: ::core::option::Option<Box<Node>>,
+
+    pub coldefexpr: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TypeName {
+
+    pub names: Vec<Node>,
+
+    pub type_oid: u32,
+
+    pub setof: bool,
+
+    pub pct_type: bool,
+
+    pub typmods: Vec<Node>,
+
+    pub typemod: i32,
+
+    pub array_bounds: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ColumnDef {
+
+    pub colname: String,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub inhcount: i32,
+
+    pub is_local: bool,
+
+    pub is_not_null: bool,
+
+    pub is_from_type: bool,
+
+    pub storage: String,
+
+    pub raw_default: ::core::option::Option<Box<Node>>,
+
+    pub cooked_default: ::core::option::Option<Box<Node>>,
+
+    pub identity: String,
+
+    pub identity_sequence: ::core::option::Option<RangeVar>,
+
+    pub generated: String,
+
+    pub coll_clause: ::core::option::Option<Box<CollateClause>>,
+
+    pub coll_oid: u32,
+
+    pub constraints: Vec<Node>,
+
+    pub fdwoptions: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct IndexElem {
+
+    pub name: String,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub indexcolname: String,
+
+    pub collation: Vec<Node>,
+
+    pub opclass: Vec<Node>,
+
+    pub opclassopts: Vec<Node>,
+
+    pub ordering: i32,
+
+    pub nulls_ordering: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Constraint {
+
+    pub contype: i32,
+
+    pub conname: String,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub location: i32,
+
+    pub is_no_inherit: bool,
+
+    pub raw_expr: ::core::option::Option<Box<Node>>,
+
+    pub cooked_expr: String,
+
+    pub generated_when: String,
+
+    pub keys: Vec<Node>,
+
+    pub including: Vec<Node>,
+
+    pub exclusions: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub indexname: String,
+
+    pub indexspace: String,
+
+    pub reset_default_tblspc: bool,
+
+    pub access_method: String,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub pktable: ::core::option::Option<RangeVar>,
+
+    pub fk_attrs: Vec<Node>,
+
+    pub pk_attrs: Vec<Node>,
+
+    pub fk_matchtype: String,
+
+    pub fk_upd_action: String,
+
+    pub fk_del_action: String,
+
+    pub old_conpfeqop: Vec<Node>,
+
+    pub old_pktable_oid: u32,
+
+    pub skip_validation: bool,
+
+    pub initially_valid: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DefElem {
+
+    pub defnamespace: String,
+
+    pub defname: String,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub defaction: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblEntry {
+
+    pub rtekind: i32,
+
+    pub relid: u32,
+
+    pub relkind: String,
+
+    pub rellockmode: i32,
+
+    pub tablesample: ::core::option::Option<Box<TableSampleClause>>,
+
+    pub subquery: ::core::option::Option<Box<Query>>,
+
+    pub security_barrier: bool,
+
+    pub jointype: i32,
+
+    pub joinmergedcols: i32,
+
+    pub joinaliasvars: Vec<Node>,
+
+    pub joinleftcols: Vec<Node>,
+
+    pub joinrightcols: Vec<Node>,
+
+    pub functions: Vec<Node>,
+
+    pub funcordinality: bool,
+
+    pub tablefunc: ::core::option::Option<Box<TableFunc>>,
+
+    pub values_lists: Vec<Node>,
+
+    pub ctename: String,
+
+    pub ctelevelsup: u32,
+
+    pub self_reference: bool,
+
+    pub coltypes: Vec<Node>,
+
+    pub coltypmods: Vec<Node>,
+
+    pub colcollations: Vec<Node>,
+
+    pub enrname: String,
+
+    pub enrtuples: f64,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub eref: ::core::option::Option<Alias>,
+
+    pub lateral: bool,
+
+    pub inh: bool,
+
+    pub in_from_cl: bool,
+
+    pub required_perms: u32,
+
+    pub check_as_user: u32,
+
+    pub selected_cols: Vec<u64>,
+
+    pub inserted_cols: Vec<u64>,
+
+    pub updated_cols: Vec<u64>,
+
+    pub extra_updated_cols: Vec<u64>,
+
+    pub security_quals: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblFunction {
+
+    pub funcexpr: ::core::option::Option<Box<Node>>,
+
+    pub funccolcount: i32,
+
+    pub funccolnames: Vec<Node>,
+
+    pub funccoltypes: Vec<Node>,
+
+    pub funccoltypmods: Vec<Node>,
+
+    pub funccolcollations: Vec<Node>,
+
+    pub funcparams: Vec<u64>,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableSampleClause {
+
+    pub tsmhandler: u32,
+
+    pub args: Vec<Node>,
+
+    pub repeatable: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct WithCheckOption {
+
+    pub kind: i32,
+
+    pub relname: String,
+
+    pub polname: String,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub cascaded: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SortGroupClause {
+
+    pub tle_sort_group_ref: u32,
+
+    pub eqop: u32,
+
+    pub sortop: u32,
+
+    pub nulls_first: bool,
+
+    pub hashable: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct GroupingSet {
+
+    pub kind: i32,
+
+    pub content: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowClause {
+
+    pub name: String,
+
+    pub refname: String,
+
+    pub partition_clause: Vec<Node>,
+
+    pub order_clause: Vec<Node>,
+
+    pub frame_options: i32,
+
+    pub start_offset: ::core::option::Option<Box<Node>>,
+
+    pub end_offset: ::core::option::Option<Box<Node>>,
+
+    pub start_in_range_func: u32,
+
+    pub end_in_range_func: u32,
+
+    pub in_range_coll: u32,
+
+    pub in_range_asc: bool,
+
+    pub in_range_nulls_first: bool,
+
+    pub winref: u32,
+
+    pub copied_order: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ObjectWithArgs {
+
+    pub objname: Vec<Node>,
+
+    pub objargs: Vec<Node>,
+
+    pub args_unspecified: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AccessPriv {
+
+    pub priv_name: String,
+
+    pub cols: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpClassItem {
+
+    pub itemtype: i32,
+
+    pub name: ::core::option::Option<ObjectWithArgs>,
+
+    pub number: i32,
+
+    pub order_family: Vec<Node>,
+
+    pub class_args: Vec<Node>,
+
+    pub storedtype: ::core::option::Option<TypeName>,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableLikeClause {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub options: u32,
+
+    pub relation_oid: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FunctionParameter {
+
+    pub name: String,
+
+    pub arg_type: ::core::option::Option<TypeName>,
+
+    pub mode: i32,
+
+    pub defexpr: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct LockingClause {
+
+    pub locked_rels: Vec<Node>,
+
+    pub strength: i32,
+
+    pub wait_policy: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowMarkClause {
+
+    pub rti: u32,
+
+    pub strength: i32,
+
+    pub wait_policy: i32,
+
+    pub pushed_down: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct XmlSerialize {
+
+    pub xmloption: i32,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WithClause {
+
+    pub ctes: Vec<Node>,
+
+    pub recursive: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InferClause {
+
+    pub index_elems: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub conname: String,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct OnConflictClause {
+
+    pub action: i32,
+
+    pub infer: ::core::option::Option<Box<InferClause>>,
+
+    pub target_list: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CommonTableExpr {
+
+    pub ctename: String,
+
+    pub aliascolnames: Vec<Node>,
+
+    pub ctematerialized: i32,
+
+    pub ctequery: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+
+    pub cterecursive: bool,
+
+    pub cterefcount: i32,
+
+    pub ctecolnames: Vec<Node>,
+
+    pub ctecoltypes: Vec<Node>,
+
+    pub ctecoltypmods: Vec<Node>,
+
+    pub ctecolcollations: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RoleSpec {
+
+    pub roletype: i32,
+
+    pub rolename: String,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TriggerTransition {
+
+    pub name: String,
+
+    pub is_new: bool,
+
+    pub is_table: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionElem {
+
+    pub name: String,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub collation: Vec<Node>,
+
+    pub opclass: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionSpec {
+
+    pub strategy: String,
+
+    pub part_params: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionBoundSpec {
+
+    pub strategy: String,
+
+    pub is_default: bool,
+
+    pub modulus: i32,
+
+    pub remainder: i32,
+
+    pub listdatums: Vec<Node>,
+
+    pub lowerdatums: Vec<Node>,
+
+    pub upperdatums: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionRangeDatum {
+
+    pub kind: i32,
+
+    pub value: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionCmd {
+
+    pub name: ::core::option::Option<RangeVar>,
+
+    pub bound: ::core::option::Option<PartitionBoundSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct VacuumRelation {
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub oid: u32,
+
+    pub va_cols: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct InlineCodeBlock {
+
+    pub source_text: String,
+
+    pub lang_oid: u32,
+
+    pub lang_is_trusted: bool,
+
+    pub atomic: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CallContext {
+
+    pub atomic: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScanToken {
+
+    pub start: i32,
+
+    pub end: i32,
+
+    pub token: i32,
+
+    pub keyword_kind: i32,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OverridingKind {
+    Undefined = 0,
+    OverridingNotSet = 1,
+    OverridingUserValue = 2,
+    OverridingSystemValue = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum QuerySource {
+    Undefined = 0,
+    QsrcOriginal = 1,
+    QsrcParser = 2,
+    QsrcInsteadRule = 3,
+    QsrcQualInsteadRule = 4,
+    QsrcNonInsteadRule = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SortByDir {
+    Undefined = 0,
+    SortbyDefault = 1,
+    SortbyAsc = 2,
+    SortbyDesc = 3,
+    SortbyUsing = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SortByNulls {
+    Undefined = 0,
+    SortbyNullsDefault = 1,
+    SortbyNullsFirst = 2,
+    SortbyNullsLast = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AExprKind {
+    Undefined = 0,
+    AexprOp = 1,
+    AexprOpAny = 2,
+    AexprOpAll = 3,
+    AexprDistinct = 4,
+    AexprNotDistinct = 5,
+    AexprNullif = 6,
+    AexprOf = 7,
+    AexprIn = 8,
+    AexprLike = 9,
+    AexprIlike = 10,
+    AexprSimilar = 11,
+    AexprBetween = 12,
+    AexprNotBetween = 13,
+    AexprBetweenSym = 14,
+    AexprNotBetweenSym = 15,
+    AexprParen = 16,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RoleSpecType {
+    Undefined = 0,
+    RolespecCstring = 1,
+    RolespecCurrentUser = 2,
+    RolespecSessionUser = 3,
+    RolespecPublic = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum TableLikeOption {
+    Undefined = 0,
+    CreateTableLikeComments = 1,
+    CreateTableLikeConstraints = 2,
+    CreateTableLikeDefaults = 3,
+    CreateTableLikeGenerated = 4,
+    CreateTableLikeIdentity = 5,
+    CreateTableLikeIndexes = 6,
+    CreateTableLikeStatistics = 7,
+    CreateTableLikeStorage = 8,
+    CreateTableLikeAll = 9,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DefElemAction {
+    Undefined = 0,
+    DefelemUnspec = 1,
+    DefelemSet = 2,
+    DefelemAdd = 3,
+    DefelemDrop = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum PartitionRangeDatumKind {
+    Undefined = 0,
+    PartitionRangeDatumMinvalue = 1,
+    PartitionRangeDatumValue = 2,
+    PartitionRangeDatumMaxvalue = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RteKind {
+    RtekindUndefined = 0,
+    RteRelation = 1,
+    RteSubquery = 2,
+    RteJoin = 3,
+    RteFunction = 4,
+    RteTablefunc = 5,
+    RteValues = 6,
+    RteCte = 7,
+    RteNamedtuplestore = 8,
+    RteResult = 9,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum WcoKind {
+    WcokindUndefined = 0,
+    WcoViewCheck = 1,
+    WcoRlsInsertCheck = 2,
+    WcoRlsUpdateCheck = 3,
+    WcoRlsConflictCheck = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum GroupingSetKind {
+    Undefined = 0,
+    GroupingSetEmpty = 1,
+    GroupingSetSimple = 2,
+    GroupingSetRollup = 3,
+    GroupingSetCube = 4,
+    GroupingSetSets = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CteMaterialize {
+    CtematerializeUndefined = 0,
+    Default = 1,
+    Always = 2,
+    Never = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOperation {
+    Undefined = 0,
+    SetopNone = 1,
+    SetopUnion = 2,
+    SetopIntersect = 3,
+    SetopExcept = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ObjectType {
+    Undefined = 0,
+    ObjectAccessMethod = 1,
+    ObjectAggregate = 2,
+    ObjectAmop = 3,
+    ObjectAmproc = 4,
+    ObjectAttribute = 5,
+    ObjectCast = 6,
+    ObjectColumn = 7,
+    ObjectCollation = 8,
+    ObjectConversion = 9,
+    ObjectDatabase = 10,
+    ObjectDefault = 11,
+    ObjectDefacl = 12,
+    ObjectDomain = 13,
+    ObjectDomconstraint = 14,
+    ObjectEventTrigger = 15,
+    ObjectExtension = 16,
+    ObjectFdw = 17,
+    ObjectForeignServer = 18,
+    ObjectForeignTable = 19,
+    ObjectFunction = 20,
+    ObjectIndex = 21,
+    ObjectLanguage = 22,
+    ObjectLargeobject = 23,
+    ObjectMatview = 24,
+    ObjectOpclass = 25,
+    ObjectOperator = 26,
+    ObjectOpfamily = 27,
+    ObjectPolicy = 28,
+    ObjectProcedure = 29,
+    ObjectPublication = 30,
+    ObjectPublicationRel = 31,
+    ObjectRole = 32,
+    ObjectRoutine = 33,
+    ObjectRule = 34,
+    ObjectSchema = 35,
+    ObjectSequence = 36,
+    ObjectSubscription = 37,
+    ObjectStatisticExt = 38,
+    ObjectTabconstraint = 39,
+    ObjectTable = 40,
+    ObjectTablespace = 41,
+    ObjectTransform = 42,
+    ObjectTrigger = 43,
+    ObjectTsconfiguration = 44,
+    ObjectTsdictionary = 45,
+    ObjectTsparser = 46,
+    ObjectTstemplate = 47,
+    ObjectType = 48,
+    ObjectUserMapping = 49,
+    ObjectView = 50,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DropBehavior {
+    Undefined = 0,
+    DropRestrict = 1,
+    DropCascade = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterTableType {
+    Undefined = 0,
+    AtAddColumn = 1,
+    AtAddColumnRecurse = 2,
+    AtAddColumnToView = 3,
+    AtColumnDefault = 4,
+    AtCookedColumnDefault = 5,
+    AtDropNotNull = 6,
+    AtSetNotNull = 7,
+    AtDropExpression = 8,
+    AtCheckNotNull = 9,
+    AtSetStatistics = 10,
+    AtSetOptions = 11,
+    AtResetOptions = 12,
+    AtSetStorage = 13,
+    AtDropColumn = 14,
+    AtDropColumnRecurse = 15,
+    AtAddIndex = 16,
+    AtReAddIndex = 17,
+    AtAddConstraint = 18,
+    AtAddConstraintRecurse = 19,
+    AtReAddConstraint = 20,
+    AtReAddDomainConstraint = 21,
+    AtAlterConstraint = 22,
+    AtValidateConstraint = 23,
+    AtValidateConstraintRecurse = 24,
+    AtAddIndexConstraint = 25,
+    AtDropConstraint = 26,
+    AtDropConstraintRecurse = 27,
+    AtReAddComment = 28,
+    AtAlterColumnType = 29,
+    AtAlterColumnGenericOptions = 30,
+    AtChangeOwner = 31,
+    AtClusterOn = 32,
+    AtDropCluster = 33,
+    AtSetLogged = 34,
+    AtSetUnLogged = 35,
+    AtDropOids = 36,
+    AtSetTableSpace = 37,
+    AtSetRelOptions = 38,
+    AtResetRelOptions = 39,
+    AtReplaceRelOptions = 40,
+    AtEnableTrig = 41,
+    AtEnableAlwaysTrig = 42,
+    AtEnableReplicaTrig = 43,
+    AtDisableTrig = 44,
+    AtEnableTrigAll = 45,
+    AtDisableTrigAll = 46,
+    AtEnableTrigUser = 47,
+    AtDisableTrigUser = 48,
+    AtEnableRule = 49,
+    AtEnableAlwaysRule = 50,
+    AtEnableReplicaRule = 51,
+    AtDisableRule = 52,
+    AtAddInherit = 53,
+    AtDropInherit = 54,
+    AtAddOf = 55,
+    AtDropOf = 56,
+    AtReplicaIdentity = 57,
+    AtEnableRowSecurity = 58,
+    AtDisableRowSecurity = 59,
+    AtForceRowSecurity = 60,
+    AtNoForceRowSecurity = 61,
+    AtGenericOptions = 62,
+    AtAttachPartition = 63,
+    AtDetachPartition = 64,
+    AtAddIdentity = 65,
+    AtSetIdentity = 66,
+    AtDropIdentity = 67,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum GrantTargetType {
+    Undefined = 0,
+    AclTargetObject = 1,
+    AclTargetAllInSchema = 2,
+    AclTargetDefaults = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum VariableSetKind {
+    Undefined = 0,
+    VarSetValue = 1,
+    VarSetDefault = 2,
+    VarSetCurrent = 3,
+    VarSetMulti = 4,
+    VarReset = 5,
+    VarResetAll = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ConstrType {
+    Undefined = 0,
+    ConstrNull = 1,
+    ConstrNotnull = 2,
+    ConstrDefault = 3,
+    ConstrIdentity = 4,
+    ConstrGenerated = 5,
+    ConstrCheck = 6,
+    ConstrPrimary = 7,
+    ConstrUnique = 8,
+    ConstrExclusion = 9,
+    ConstrForeign = 10,
+    ConstrAttrDeferrable = 11,
+    ConstrAttrNotDeferrable = 12,
+    ConstrAttrDeferred = 13,
+    ConstrAttrImmediate = 14,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ImportForeignSchemaType {
+    Undefined = 0,
+    FdwImportSchemaAll = 1,
+    FdwImportSchemaLimitTo = 2,
+    FdwImportSchemaExcept = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RoleStmtType {
+    Undefined = 0,
+    RolestmtRole = 1,
+    RolestmtUser = 2,
+    RolestmtGroup = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum FetchDirection {
+    Undefined = 0,
+    FetchForward = 1,
+    FetchBackward = 2,
+    FetchAbsolute = 3,
+    FetchRelative = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum FunctionParameterMode {
+    Undefined = 0,
+    FuncParamIn = 1,
+    FuncParamOut = 2,
+    FuncParamInout = 3,
+    FuncParamVariadic = 4,
+    FuncParamTable = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum TransactionStmtKind {
+    Undefined = 0,
+    TransStmtBegin = 1,
+    TransStmtStart = 2,
+    TransStmtCommit = 3,
+    TransStmtRollback = 4,
+    TransStmtSavepoint = 5,
+    TransStmtRelease = 6,
+    TransStmtRollbackTo = 7,
+    TransStmtPrepare = 8,
+    TransStmtCommitPrepared = 9,
+    TransStmtRollbackPrepared = 10,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ViewCheckOption {
+    Undefined = 0,
+    NoCheckOption = 1,
+    LocalCheckOption = 2,
+    CascadedCheckOption = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ClusterOption {
+    Undefined = 0,
+    CluoptRecheck = 1,
+    CluoptVerbose = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DiscardMode {
+    Undefined = 0,
+    DiscardAll = 1,
+    DiscardPlans = 2,
+    DiscardSequences = 3,
+    DiscardTemp = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ReindexObjectType {
+    Undefined = 0,
+    ReindexObjectIndex = 1,
+    ReindexObjectTable = 2,
+    ReindexObjectSchema = 3,
+    ReindexObjectSystem = 4,
+    ReindexObjectDatabase = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterTsConfigType {
+    AlterTsconfigTypeUndefined = 0,
+    AlterTsconfigAddMapping = 1,
+    AlterTsconfigAlterMappingForToken = 2,
+    AlterTsconfigReplaceDict = 3,
+    AlterTsconfigReplaceDictForToken = 4,
+    AlterTsconfigDropMapping = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterSubscriptionType {
+    Undefined = 0,
+    AlterSubscriptionOptions = 1,
+    AlterSubscriptionConnection = 2,
+    AlterSubscriptionPublication = 3,
+    AlterSubscriptionRefresh = 4,
+    AlterSubscriptionEnabled = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OnCommitAction {
+    Undefined = 0,
+    OncommitNoop = 1,
+    OncommitPreserveRows = 2,
+    OncommitDeleteRows = 3,
+    OncommitDrop = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ParamKind {
+    Undefined = 0,
+    ParamExtern = 1,
+    ParamExec = 2,
+    ParamSublink = 3,
+    ParamMultiexpr = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CoercionContext {
+    Undefined = 0,
+    CoercionImplicit = 1,
+    CoercionAssignment = 2,
+    CoercionExplicit = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CoercionForm {
+    Undefined = 0,
+    CoerceExplicitCall = 1,
+    CoerceExplicitCast = 2,
+    CoerceImplicitCast = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum BoolExprType {
+    Undefined = 0,
+    AndExpr = 1,
+    OrExpr = 2,
+    NotExpr = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SubLinkType {
+    Undefined = 0,
+    ExistsSublink = 1,
+    AllSublink = 2,
+    AnySublink = 3,
+    RowcompareSublink = 4,
+    ExprSublink = 5,
+    MultiexprSublink = 6,
+    ArraySublink = 7,
+    CteSublink = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RowCompareType {
+    Undefined = 0,
+    RowcompareLt = 1,
+    RowcompareLe = 2,
+    RowcompareEq = 3,
+    RowcompareGe = 4,
+    RowcompareGt = 5,
+    RowcompareNe = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum MinMaxOp {
+    Undefined = 0,
+    IsGreatest = 1,
+    IsLeast = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SqlValueFunctionOp {
+    SqlvalueFunctionOpUndefined = 0,
+    SvfopCurrentDate = 1,
+    SvfopCurrentTime = 2,
+    SvfopCurrentTimeN = 3,
+    SvfopCurrentTimestamp = 4,
+    SvfopCurrentTimestampN = 5,
+    SvfopLocaltime = 6,
+    SvfopLocaltimeN = 7,
+    SvfopLocaltimestamp = 8,
+    SvfopLocaltimestampN = 9,
+    SvfopCurrentRole = 10,
+    SvfopCurrentUser = 11,
+    SvfopUser = 12,
+    SvfopSessionUser = 13,
+    SvfopCurrentCatalog = 14,
+    SvfopCurrentSchema = 15,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum XmlExprOp {
+    Undefined = 0,
+    IsXmlconcat = 1,
+    IsXmlelement = 2,
+    IsXmlforest = 3,
+    IsXmlparse = 4,
+    IsXmlpi = 5,
+    IsXmlroot = 6,
+    IsXmlserialize = 7,
+    IsDocument = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum XmlOptionType {
+    Undefined = 0,
+    XmloptionDocument = 1,
+    XmloptionContent = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum NullTestType {
+    Undefined = 0,
+    IsNull = 1,
+    IsNotNull = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum BoolTestType {
+    Undefined = 0,
+    IsTrue = 1,
+    IsNotTrue = 2,
+    IsFalse = 3,
+    IsNotFalse = 4,
+    IsUnknown = 5,
+    IsNotUnknown = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CmdType {
+    Undefined = 0,
+    CmdUnknown = 1,
+    CmdSelect = 2,
+    CmdUpdate = 3,
+    CmdInsert = 4,
+    CmdDelete = 5,
+    CmdUtility = 6,
+    CmdNothing = 7,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum JoinType {
+    Undefined = 0,
+    JoinInner = 1,
+    JoinLeft = 2,
+    JoinFull = 3,
+    JoinRight = 4,
+    JoinSemi = 5,
+    JoinAnti = 6,
+    JoinUniqueOuter = 7,
+    JoinUniqueInner = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AggStrategy {
+    Undefined = 0,
+    AggPlain = 1,
+    AggSorted = 2,
+    AggHashed = 3,
+    AggMixed = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AggSplit {
+    Undefined = 0,
+    AggsplitSimple = 1,
+    AggsplitInitialSerial = 2,
+    AggsplitFinalDeserial = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOpCmd {
+    Undefined = 0,
+    SetopcmdIntersect = 1,
+    SetopcmdIntersectAll = 2,
+    SetopcmdExcept = 3,
+    SetopcmdExceptAll = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOpStrategy {
+    Undefined = 0,
+    SetopSorted = 1,
+    SetopHashed = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OnConflictAction {
+    Undefined = 0,
+    OnconflictNone = 1,
+    OnconflictNothing = 2,
+    OnconflictUpdate = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LimitOption {
+    Undefined = 0,
+    Default = 1,
+    Count = 2,
+    WithTies = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockClauseStrength {
+    Undefined = 0,
+    LcsNone = 1,
+    LcsForkeyshare = 2,
+    LcsForshare = 3,
+    LcsFornokeyupdate = 4,
+    LcsForupdate = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockWaitPolicy {
+    Undefined = 0,
+    LockWaitBlock = 1,
+    LockWaitSkip = 2,
+    LockWaitError = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockTupleMode {
+    Undefined = 0,
+    LockTupleKeyShare = 1,
+    LockTupleShare = 2,
+    LockTupleNoKeyExclusive = 3,
+    LockTupleExclusive = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum KeywordKind {
+    NoKeyword = 0,
+    UnreservedKeyword = 1,
+    ColNameKeyword = 2,
+    TypeFuncNameKeyword = 3,
+    ReservedKeyword = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum Token {
+    Nul = 0,
+    /// Single-character tokens that are returned 1:1 (identical with "self" list in scan.l)
+    /// Either supporting syntax, or single-character operators (some can be both)
+    /// Also see <https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-SPECIAL-CHARS>
+    ///
+    /// "%"
+    Ascii37 = 37,
+    /// "("
+    Ascii40 = 40,
+    /// ")"
+    Ascii41 = 41,
+    /// "*"
+    Ascii42 = 42,
+    /// "+"
+    Ascii43 = 43,
+    /// ","
+    Ascii44 = 44,
+    /// "-"
+    Ascii45 = 45,
+    /// "."
+    Ascii46 = 46,
+    /// "/"
+    Ascii47 = 47,
+    /// ":"
+    Ascii58 = 58,
+    /// ";"
+    Ascii59 = 59,
+    /// "<"
+    Ascii60 = 60,
+    /// "="
+    Ascii61 = 61,
+    /// ">"
+    Ascii62 = 62,
+    /// "?"
+    Ascii63 = 63,
+    /// "["
+    Ascii91 = 91,
+    /// "\"
+    Ascii92 = 92,
+    /// "]"
+    Ascii93 = 93,
+    /// "^"
+    Ascii94 = 94,
+    /// Named tokens in scan.l
+    Ident = 258,
+    Uident = 259,
+    Fconst = 260,
+    Sconst = 261,
+    Usconst = 262,
+    Bconst = 263,
+    Xconst = 264,
+    Op = 265,
+    Iconst = 266,
+    Param = 267,
+    Typecast = 268,
+    DotDot = 269,
+    ColonEquals = 270,
+    EqualsGreater = 271,
+    LessEquals = 272,
+    GreaterEquals = 273,
+    NotEquals = 274,
+    SqlComment = 275,
+    CComment = 276,
+    AbortP = 277,
+    AbsoluteP = 278,
+    Access = 279,
+    Action = 280,
+    AddP = 281,
+    Admin = 282,
+    After = 283,
+    Aggregate = 284,
+    All = 285,
+    Also = 286,
+    Alter = 287,
+    Always = 288,
+    Analyse = 289,
+    Analyze = 290,
+    And = 291,
+    Any = 292,
+    Array = 293,
+    As = 294,
+    Asc = 295,
+    Assertion = 296,
+    Assignment = 297,
+    Asymmetric = 298,
+    At = 299,
+    Attach = 300,
+    Attribute = 301,
+    Authorization = 302,
+    Backward = 303,
+    Before = 304,
+    BeginP = 305,
+    Between = 306,
+    Bigint = 307,
+    Binary = 308,
+    Bit = 309,
+    BooleanP = 310,
+    Both = 311,
+    By = 312,
+    Cache = 313,
+    Call = 314,
+    Called = 315,
+    Cascade = 316,
+    Cascaded = 317,
+    Case = 318,
+    Cast = 319,
+    CatalogP = 320,
+    Chain = 321,
+    CharP = 322,
+    Character = 323,
+    Characteristics = 324,
+    Check = 325,
+    Checkpoint = 326,
+    Class = 327,
+    Close = 328,
+    Cluster = 329,
+    Coalesce = 330,
+    Collate = 331,
+    Collation = 332,
+    Column = 333,
+    Columns = 334,
+    Comment = 335,
+    Comments = 336,
+    Commit = 337,
+    Committed = 338,
+    Concurrently = 339,
+    Configuration = 340,
+    Conflict = 341,
+    Connection = 342,
+    Constraint = 343,
+    Constraints = 344,
+    ContentP = 345,
+    ContinueP = 346,
+    ConversionP = 347,
+    Copy = 348,
+    Cost = 349,
+    Create = 350,
+    Cross = 351,
+    Csv = 352,
+    Cube = 353,
+    CurrentP = 354,
+    CurrentCatalog = 355,
+    CurrentDate = 356,
+    CurrentRole = 357,
+    CurrentSchema = 358,
+    CurrentTime = 359,
+    CurrentTimestamp = 360,
+    CurrentUser = 361,
+    Cursor = 362,
+    Cycle = 363,
+    DataP = 364,
+    Database = 365,
+    DayP = 366,
+    Deallocate = 367,
+    Dec = 368,
+    DecimalP = 369,
+    Declare = 370,
+    Default = 371,
+    Defaults = 372,
+    Deferrable = 373,
+    Deferred = 374,
+    Definer = 375,
+    DeleteP = 376,
+    Delimiter = 377,
+    Delimiters = 378,
+    Depends = 379,
+    Desc = 380,
+    Detach = 381,
+    Dictionary = 382,
+    DisableP = 383,
+    Discard = 384,
+    Distinct = 385,
+    Do = 386,
+    DocumentP = 387,
+    DomainP = 388,
+    DoubleP = 389,
+    Drop = 390,
+    Each = 391,
+    Else = 392,
+    EnableP = 393,
+    Encoding = 394,
+    Encrypted = 395,
+    EndP = 396,
+    EnumP = 397,
+    Escape = 398,
+    Event = 399,
+    Except = 400,
+    Exclude = 401,
+    Excluding = 402,
+    Exclusive = 403,
+    Execute = 404,
+    Exists = 405,
+    Explain = 406,
+    Expression = 407,
+    Extension = 408,
+    External = 409,
+    Extract = 410,
+    FalseP = 411,
+    Family = 412,
+    Fetch = 413,
+    Filter = 414,
+    FirstP = 415,
+    FloatP = 416,
+    Following = 417,
+    For = 418,
+    Force = 419,
+    Foreign = 420,
+    Forward = 421,
+    Freeze = 422,
+    From = 423,
+    Full = 424,
+    Function = 425,
+    Functions = 426,
+    Generated = 427,
+    Global = 428,
+    Grant = 429,
+    Granted = 430,
+    Greatest = 431,
+    GroupP = 432,
+    Grouping = 433,
+    Groups = 434,
+    Handler = 435,
+    Having = 436,
+    HeaderP = 437,
+    Hold = 438,
+    HourP = 439,
+    IdentityP = 440,
+    IfP = 441,
+    Ilike = 442,
+    Immediate = 443,
+    Immutable = 444,
+    ImplicitP = 445,
+    ImportP = 446,
+    InP = 447,
+    Include = 448,
+    Including = 449,
+    Increment = 450,
+    Index = 451,
+    Indexes = 452,
+    Inherit = 453,
+    Inherits = 454,
+    Initially = 455,
+    InlineP = 456,
+    InnerP = 457,
+    Inout = 458,
+    InputP = 459,
+    Insensitive = 460,
+    Insert = 461,
+    Instead = 462,
+    IntP = 463,
+    Integer = 464,
+    Intersect = 465,
+    Interval = 466,
+    Into = 467,
+    Invoker = 468,
+    Is = 469,
+    Isnull = 470,
+    Isolation = 471,
+    Join = 472,
+    Key = 473,
+    Label = 474,
+    Language = 475,
+    LargeP = 476,
+    LastP = 477,
+    LateralP = 478,
+    Leading = 479,
+    Leakproof = 480,
+    Least = 481,
+    Left = 482,
+    Level = 483,
+    Like = 484,
+    Limit = 485,
+    Listen = 486,
+    Load = 487,
+    Local = 488,
+    Localtime = 489,
+    Localtimestamp = 490,
+    Location = 491,
+    LockP = 492,
+    Locked = 493,
+    Logged = 494,
+    Mapping = 495,
+    Match = 496,
+    Materialized = 497,
+    Maxvalue = 498,
+    Method = 499,
+    MinuteP = 500,
+    Minvalue = 501,
+    Mode = 502,
+    MonthP = 503,
+    Move = 504,
+    NameP = 505,
+    Names = 506,
+    National = 507,
+    Natural = 508,
+    Nchar = 509,
+    New = 510,
+    Next = 511,
+    Nfc = 512,
+    Nfd = 513,
+    Nfkc = 514,
+    Nfkd = 515,
+    No = 516,
+    None = 517,
+    Normalize = 518,
+    Normalized = 519,
+    Not = 520,
+    Nothing = 521,
+    Notify = 522,
+    Notnull = 523,
+    Nowait = 524,
+    NullP = 525,
+    Nullif = 526,
+    NullsP = 527,
+    Numeric = 528,
+    ObjectP = 529,
+    Of = 530,
+    Off = 531,
+    Offset = 532,
+    Oids = 533,
+    Old = 534,
+    On = 535,
+    Only = 536,
+    Operator = 537,
+    Option = 538,
+    Options = 539,
+    Or = 540,
+    Order = 541,
+    Ordinality = 542,
+    Others = 543,
+    OutP = 544,
+    OuterP = 545,
+    Over = 546,
+    Overlaps = 547,
+    Overlay = 548,
+    Overriding = 549,
+    Owned = 550,
+    Owner = 551,
+    Parallel = 552,
+    Parser = 553,
+    Partial = 554,
+    Partition = 555,
+    Passing = 556,
+    Password = 557,
+    Placing = 558,
+    Plans = 559,
+    Policy = 560,
+    Position = 561,
+    Preceding = 562,
+    Precision = 563,
+    Preserve = 564,
+    Prepare = 565,
+    Prepared = 566,
+    Primary = 567,
+    Prior = 568,
+    Privileges = 569,
+    Procedural = 570,
+    Procedure = 571,
+    Procedures = 572,
+    Program = 573,
+    Publication = 574,
+    Quote = 575,
+    Range = 576,
+    Read = 577,
+    Real = 578,
+    Reassign = 579,
+    Recheck = 580,
+    Recursive = 581,
+    Ref = 582,
+    References = 583,
+    Referencing = 584,
+    Refresh = 585,
+    Reindex = 586,
+    RelativeP = 587,
+    Release = 588,
+    Rename = 589,
+    Repeatable = 590,
+    Replace = 591,
+    Replica = 592,
+    Reset = 593,
+    Restart = 594,
+    Restrict = 595,
+    Returning = 596,
+    Returns = 597,
+    Revoke = 598,
+    Right = 599,
+    Role = 600,
+    Rollback = 601,
+    Rollup = 602,
+    Routine = 603,
+    Routines = 604,
+    Row = 605,
+    Rows = 606,
+    Rule = 607,
+    Savepoint = 608,
+    Schema = 609,
+    Schemas = 610,
+    Scroll = 611,
+    Search = 612,
+    SecondP = 613,
+    Security = 614,
+    Select = 615,
+    Sequence = 616,
+    Sequences = 617,
+    Serializable = 618,
+    Server = 619,
+    Session = 620,
+    SessionUser = 621,
+    Set = 622,
+    Sets = 623,
+    Setof = 624,
+    Share = 625,
+    Show = 626,
+    Similar = 627,
+    Simple = 628,
+    Skip = 629,
+    Smallint = 630,
+    Snapshot = 631,
+    Some = 632,
+    SqlP = 633,
+    Stable = 634,
+    StandaloneP = 635,
+    Start = 636,
+    Statement = 637,
+    Statistics = 638,
+    Stdin = 639,
+    Stdout = 640,
+    Storage = 641,
+    Stored = 642,
+    StrictP = 643,
+    StripP = 644,
+    Subscription = 645,
+    Substring = 646,
+    Support = 647,
+    Symmetric = 648,
+    Sysid = 649,
+    SystemP = 650,
+    Table = 651,
+    Tables = 652,
+    Tablesample = 653,
+    Tablespace = 654,
+    Temp = 655,
+    Template = 656,
+    Temporary = 657,
+    TextP = 658,
+    Then = 659,
+    Ties = 660,
+    Time = 661,
+    Timestamp = 662,
+    To = 663,
+    Trailing = 664,
+    Transaction = 665,
+    Transform = 666,
+    Treat = 667,
+    Trigger = 668,
+    Trim = 669,
+    TrueP = 670,
+    Truncate = 671,
+    Trusted = 672,
+    TypeP = 673,
+    TypesP = 674,
+    Uescape = 675,
+    Unbounded = 676,
+    Uncommitted = 677,
+    Unencrypted = 678,
+    Union = 679,
+    Unique = 680,
+    Unknown = 681,
+    Unlisten = 682,
+    Unlogged = 683,
+    Until = 684,
+    Update = 685,
+    User = 686,
+    Using = 687,
+    Vacuum = 688,
+    Valid = 689,
+    Validate = 690,
+    Validator = 691,
+    ValueP = 692,
+    Values = 693,
+    Varchar = 694,
+    Variadic = 695,
+    Varying = 696,
+    Verbose = 697,
+    VersionP = 698,
+    View = 699,
+    Views = 700,
+    Volatile = 701,
+    When = 702,
+    Where = 703,
+    WhitespaceP = 704,
+    Window = 705,
+    With = 706,
+    Within = 707,
+    Without = 708,
+    Work = 709,
+    Wrapper = 710,
+    Write = 711,
+    XmlP = 712,
+    Xmlattributes = 713,
+    Xmlconcat = 714,
+    Xmlelement = 715,
+    Xmlexists = 716,
+    Xmlforest = 717,
+    Xmlnamespaces = 718,
+    Xmlparse = 719,
+    Xmlpi = 720,
+    Xmlroot = 721,
+    Xmlserialize = 722,
+    Xmltable = 723,
+    YearP = 724,
+    YesP = 725,
+    Zone = 726,
+    NotLa = 727,
+    NullsLa = 728,
+    WithLa = 729,
+    Postfixop = 730,
+    Uminus = 731,
+}
diff --git a/src/tools/rustfmt/tests/source/struct_field_doc_comment.rs b/src/tools/rustfmt/tests/source/struct_field_doc_comment.rs
new file mode 100644
index 00000000000..191a6210045
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/struct_field_doc_comment.rs
@@ -0,0 +1,72 @@
+// #5215
+struct MyTuple(
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */ u32,
+    /// Doc Comments
+    // TODO note
+    u64,
+);
+
+struct MyTuple(
+    #[cfg(unix)] // some comment
+    u64,
+    #[cfg(not(unix))] /*block comment */
+    u32,
+);
+
+struct MyTuple(
+    #[cfg(unix)]
+    // some comment
+    u64,
+    #[cfg(not(unix))]
+    /*block comment */
+    u32,
+);
+
+struct MyTuple(
+    #[cfg(unix)] // some comment
+    pub u64,
+    #[cfg(not(unix))] /*block comment */
+    pub(crate) u32,
+);
+
+struct MyTuple(
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    pub u32,
+    /// Doc Comments
+    // TODO note
+    pub(crate) u64,
+);
+
+struct MyStruct {
+    #[cfg(unix)] // some comment
+    a: u64,
+    #[cfg(not(unix))] /*block comment */
+    b: u32,
+}
+
+struct MyStruct {
+    #[cfg(unix)] // some comment
+    pub a: u64,
+    #[cfg(not(unix))] /*block comment */
+    pub(crate) b: u32,
+}
+
+struct MyStruct {
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    a: u32,
+    /// Doc Comments
+    // TODO note
+    b: u64,
+}
+
+struct MyStruct {
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    pub a: u32,
+    /// Doc Comments
+    // TODO note
+    pub(crate) b: u64,
+}
diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs b/src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs
new file mode 100644
index 00000000000..ecc8ede02cc
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs
@@ -0,0 +1,18 @@
+// rustfmt-group_imports: StdExternalCrate
+use alloc::alloc::Layout;
+
+use chrono::Utc;
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+
+use super::update::convert_publish_payload;
+
+extern crate uuid;
+
+use core::f32;
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/target/import-fencepost-length.rs b/src/tools/rustfmt/tests/target/imports/import-fencepost-length.rs
index fd09d50d72d..fd09d50d72d 100644
--- a/src/tools/rustfmt/tests/target/import-fencepost-length.rs
+++ b/src/tools/rustfmt/tests/target/imports/import-fencepost-length.rs
diff --git a/src/tools/rustfmt/tests/target/imports-impl-only-use.rs b/src/tools/rustfmt/tests/target/imports/imports-impl-only-use.rs
index d290d8d9185..d290d8d9185 100644
--- a/src/tools/rustfmt/tests/target/imports-impl-only-use.rs
+++ b/src/tools/rustfmt/tests/target/imports/imports-impl-only-use.rs
diff --git a/src/tools/rustfmt/tests/target/imports-reorder-lines-and-items.rs b/src/tools/rustfmt/tests/target/imports/imports-reorder-lines-and-items.rs
index 98a5afe4348..98a5afe4348 100644
--- a/src/tools/rustfmt/tests/target/imports-reorder-lines-and-items.rs
+++ b/src/tools/rustfmt/tests/target/imports/imports-reorder-lines-and-items.rs
diff --git a/src/tools/rustfmt/tests/target/imports-reorder-lines.rs b/src/tools/rustfmt/tests/target/imports/imports-reorder-lines.rs
index 5b85503b55d..5b85503b55d 100644
--- a/src/tools/rustfmt/tests/target/imports-reorder-lines.rs
+++ b/src/tools/rustfmt/tests/target/imports/imports-reorder-lines.rs
diff --git a/src/tools/rustfmt/tests/target/imports-reorder.rs b/src/tools/rustfmt/tests/target/imports/imports-reorder.rs
index 84e97c0224f..84e97c0224f 100644
--- a/src/tools/rustfmt/tests/target/imports-reorder.rs
+++ b/src/tools/rustfmt/tests/target/imports/imports-reorder.rs
diff --git a/src/tools/rustfmt/tests/target/imports.rs b/src/tools/rustfmt/tests/target/imports/imports.rs
index 87584d89f66..87584d89f66 100644
--- a/src/tools/rustfmt/tests/target/imports.rs
+++ b/src/tools/rustfmt/tests/target/imports/imports.rs
diff --git a/src/tools/rustfmt/tests/target/imports_2021_edition.rs b/src/tools/rustfmt/tests/target/imports/imports_2021_edition.rs
index 34dcc866a0b..34dcc866a0b 100644
--- a/src/tools/rustfmt/tests/target/imports_2021_edition.rs
+++ b/src/tools/rustfmt/tests/target/imports/imports_2021_edition.rs
diff --git a/src/tools/rustfmt/tests/target/imports_block_indent.rs b/src/tools/rustfmt/tests/target/imports/imports_block_indent.rs
index 8c90f7ce29c..8c90f7ce29c 100644
--- a/src/tools/rustfmt/tests/target/imports_block_indent.rs
+++ b/src/tools/rustfmt/tests/target/imports/imports_block_indent.rs
diff --git a/src/tools/rustfmt/tests/target/imports_granularity_crate.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_crate.rs
index d75906d30f1..36e01558ff0 100644
--- a/src/tools/rustfmt/tests/target/imports_granularity_crate.rs
+++ b/src/tools/rustfmt/tests/target/imports/imports_granularity_crate.rs
@@ -26,3 +26,34 @@ use j::a::{self};
 
 use k::{a, b, c, d};
 use l::{a, b, c, d};
+
+use b::q::{self /* After b::q::self */};
+use b::r; // After b::r
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::t::{/* Before b::t::self */ self};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::{
+    c, d, e,
+    u::{a, b},
+};
+use b::{
+    f::g,
+    h::{i, j}, /* After b::h group */
+};
+use b::{
+    /* Before b::l group */ l::{self, m, n::o, p::*},
+    q,
+};
diff --git a/src/tools/rustfmt/tests/target/imports/imports_granularity_default-with-dups.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_default-with-dups.rs
new file mode 100644
index 00000000000..5da6d588e6d
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/imports/imports_granularity_default-with-dups.rs
@@ -0,0 +1,6 @@
+use crate::lexer;
+use crate::lexer;
+use crate::lexer::tokens::TokenData;
+use crate::lexer::tokens::TokenData;
+use crate::lexer::{self};
+use crate::lexer::{self, tokens::TokenData};
diff --git a/src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs
new file mode 100644
index 00000000000..ed4df544d6f
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs
@@ -0,0 +1,7 @@
+// rustfmt-imports_granularity: Item
+// rustfmt-reorder_imports: false
+// rustfmt-group_imports: StdExternalCrate
+
+use crate::lexer;
+use crate::lexer::tokens::TokenData;
+use crate::lexer::{self};
diff --git a/src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups.rs
new file mode 100644
index 00000000000..00df37f9332
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups.rs
@@ -0,0 +1,5 @@
+// rustfmt-imports_granularity: Item
+
+use crate::lexer;
+use crate::lexer::tokens::TokenData;
+use crate::lexer::{self};
diff --git a/src/tools/rustfmt/tests/target/imports/imports_granularity_item.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_item.rs
new file mode 100644
index 00000000000..d2f5496fdac
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/imports/imports_granularity_item.rs
@@ -0,0 +1,45 @@
+// rustfmt-imports_granularity: Item
+
+use a::b;
+use a::c;
+use a::d;
+use a::f::g;
+use a::h::i;
+use a::h::j;
+use a::l::m;
+use a::l::n::o;
+use a::l::p::*;
+use a::l::{self};
+use a::q::{self};
+
+use b::c;
+use b::d;
+use b::e;
+use b::q::{self /* After b::q::self */};
+use b::r; // After b::r
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::t::{/* Before b::t::self */ self};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::u::a;
+use b::u::b;
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::{
+    f::g,
+    h::{i, j}, /* After b::h group */
+};
+use b::{
+    /* Before b::l group */ l::{self, m, n::o, p::*},
+    q,
+};
diff --git a/src/tools/rustfmt/tests/target/imports/imports_granularity_module.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_module.rs
new file mode 100644
index 00000000000..14f341016ff
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/imports/imports_granularity_module.rs
@@ -0,0 +1,55 @@
+// rustfmt-imports_granularity: Module
+
+use a::b::c;
+use a::d::e;
+use a::f;
+use a::g::{h, i};
+use a::j::k::{self, l};
+use a::j::{self, m};
+use a::n::o::p;
+use a::n::q;
+pub use a::r::s;
+pub use a::t;
+use b::c::d;
+use b::{self};
+
+use foo::e;
+#[cfg(test)]
+use foo::{a::b, c::d};
+
+use bar::{
+    // comment
+    a::b,
+    // more comment
+    c::d,
+    e::f,
+};
+
+use b::q::{self /* After b::q::self */};
+use b::r; // After b::r
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::t::{/* Before b::t::self */ self};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::u::{a, b};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::{c, d, e};
+use b::{
+    f::g,
+    h::{i, j}, /* After b::h group */
+};
+use b::{
+    /* Before b::l group */ l::{self, m, n::o, p::*},
+    q,
+};
diff --git a/src/tools/rustfmt/tests/target/imports_granularity_item.rs b/src/tools/rustfmt/tests/target/imports_granularity_item.rs
deleted file mode 100644
index eace785e670..00000000000
--- a/src/tools/rustfmt/tests/target/imports_granularity_item.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// rustfmt-imports_granularity: Item
-
-use a::b;
-use a::c;
-use a::d;
-use a::f::g;
-use a::h::i;
-use a::h::j;
-use a::l::m;
-use a::l::n::o;
-use a::l::p::*;
-use a::l::{self};
-use a::q::{self};
diff --git a/src/tools/rustfmt/tests/target/imports_granularity_module.rs b/src/tools/rustfmt/tests/target/imports_granularity_module.rs
deleted file mode 100644
index e4e1a299e58..00000000000
--- a/src/tools/rustfmt/tests/target/imports_granularity_module.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// rustfmt-imports_granularity: Module
-
-use a::b::c;
-use a::d::e;
-use a::f;
-use a::g::{h, i};
-use a::j::k::{self, l};
-use a::j::{self, m};
-use a::n::o::p;
-use a::n::q;
-pub use a::r::s;
-pub use a::t;
-use b::c::d;
-use b::{self};
-
-use foo::e;
-#[cfg(test)]
-use foo::{a::b, c::d};
-
-use bar::a::b;
-use bar::c::d;
-use bar::e::f;
diff --git a/src/tools/rustfmt/tests/target/imports_granularity_one.rs b/src/tools/rustfmt/tests/target/imports_granularity_one.rs
index 78ec5e7325c..da4c6678db1 100644
--- a/src/tools/rustfmt/tests/target/imports_granularity_one.rs
+++ b/src/tools/rustfmt/tests/target/imports_granularity_one.rs
@@ -68,12 +68,42 @@ use {
     c::{self, ca},
 };
 
-use {
-    a::{
-        aa::{aaa, aab},
-        ab,
-        ac::aca,
-        ad::ada,
-    },
-    b as x,
+use a::{
+    // some comment
+    aa::{aaa, aab},
+    ab,
+    // another comment
+    ac::aca,
+};
+use {a::ad::ada, b as x};
+
+use b::q::{self /* After b::q::self */};
+use b::r; // After b::r
+use b::s::{
+    a,
+    b, // After b::s::b
+};
+use b::t::{/* Before b::t::self */ self};
+use b::t::{
+    // Before b::t::a
+    a,
+    b,
+};
+use b::v::{
+    // Before b::v::a
+    a,
+    // Before b::v::b
+    b,
+};
+use b::{
+    c, d, e,
+    u::{a, b},
+};
+use b::{
+    f::g,
+    h::{i, j}, /* After b::h group */
+};
+use b::{
+    /* Before b::l group */ l::{self, m, n::o, p::*},
+    q,
 };
diff --git a/src/tools/rustfmt/tests/target/issue-5030.rs b/src/tools/rustfmt/tests/target/issue-5030.rs
new file mode 100644
index 00000000000..8ac3888bdbe
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5030.rs
@@ -0,0 +1,21 @@
+// rustfmt-imports_granularity: Item
+// rustfmt-group_imports: One
+
+// Confirm that attributes are duplicated to all items in the use statement
+#[cfg(feature = "foo")]
+use std::collections::HashMap;
+#[cfg(feature = "foo")]
+use std::collections::HashSet;
+
+// Separate the imports below from the ones above
+const A: usize = 0;
+
+// Copying attrs works with import grouping as well
+#[cfg(feature = "spam")]
+use qux::bar;
+#[cfg(feature = "spam")]
+use qux::baz;
+#[cfg(feature = "foo")]
+use std::collections::HashMap;
+#[cfg(feature = "foo")]
+use std::collections::HashSet;
diff --git a/src/tools/rustfmt/tests/target/issue-5260.rs b/src/tools/rustfmt/tests/target/issue-5260.rs
new file mode 100644
index 00000000000..171f6fa51b7
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5260.rs
@@ -0,0 +1,13 @@
+// rustfmt-wrap_comments: true
+
+/// [MyType](VeryLongPathToMyType::NoLineBreak::Here::Okay::ThatWouldBeNice::Thanks)
+fn documented_with_longtype() {
+    // # We're using a long type link, rustfmt should not break line
+    // on the type when `wrap_comments = true`
+}
+
+/// VeryLongPathToMyType::JustMyType::But::VeryVery::Long::NoLineBreak::Here::Okay::ThatWouldBeNice::Thanks
+fn documented_with_verylongtype() {
+    // # We're using a long type link, rustfmt should not break line
+    // on the type when `wrap_comments = true`
+}
diff --git a/src/tools/rustfmt/tests/target/issue_3937.rs b/src/tools/rustfmt/tests/target/issue_3937.rs
new file mode 100644
index 00000000000..80673108500
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_3937.rs
@@ -0,0 +1,13 @@
+// rustfmt-format_code_in_doc_comments:true
+
+struct Foo {
+    // a: i32,
+    //
+    // b: i32,
+}
+
+struct Foo {
+    a: i32,
+    //
+    // b: i32,
+}
diff --git a/src/tools/rustfmt/tests/target/issue_4573.rs b/src/tools/rustfmt/tests/target/issue_4573.rs
new file mode 100644
index 00000000000..82cfe4f5359
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_4573.rs
@@ -0,0 +1,245 @@
+// rustmft-version:Two
+// rustmft-use_small_heuristics:Max
+// rustmft-merge_derives:false
+// These are the same rustfmt configuration options that are used
+// in the comiler as of ce39461ca75a and 8eb7c58dbb7b
+// These are commits in https://github.com/rust-lang/rust
+
+#![no_std] // inner attribute comment
+// inner attribute comment
+#![no_implicit_prelude]
+// post inner attribute comment
+
+#[cfg(not(miri))] // inline comment
+#[no_link]
+extern crate foo;
+
+// before attributes
+#[no_link]
+// between attributes
+#[cfg(not(miri))] // inline comment
+extern crate foo as bar;
+
+#[cfg(not(miri))] // inline comment
+// between attribute and use
+use foo;
+
+#[cfg(not(miri))] // inline comment
+use foo;
+
+/* pre attributre */
+#[cfg(not(miri))]
+use foo::bar;
+
+#[cfg(not(miri))] // inline comment
+use foo::bar as FooBar;
+
+#[cfg(not(miri))] // inline comment
+#[allow(unused)]
+#[deprecated(
+    since = "5.2",  // inline inner comment
+    note = "FOO was rarely used. Users should instead use BAR"
+)]
+#[allow(unused)]
+static FOO: i32 = 42;
+
+#[used]
+#[export_name = "FOO"]
+#[cfg(not(miri))] // inline comment
+#[deprecated(
+    since = "5.2",
+    note = "FOO was rarely used. Users should instead use BAR"
+)]
+static FOO: i32 = 42;
+
+#[cfg(not(miri))] // inline comment
+#[export_name = "FOO"]
+static BAR: &'static str = "bar";
+
+#[cfg(not(miri))] // inline comment
+const BAR: i32 = 42;
+
+#[cfg(not(miri))] // inline comment
+#[no_mangle]
+#[link_section = ".example_section"]
+fn foo(bar: usize) {
+    #[cfg(not(miri))] // inline comment
+    println!("hello world!");
+}
+
+#[cfg(not(miri))] // inline comment
+mod foo {}
+
+#[cfg(not(miri))] // inline comment
+extern "C" {
+    fn my_c_function(x: i32) -> bool;
+}
+
+#[cfg(not(miri))] // inline comment
+#[link(name = "CoreFoundation", kind = "framework")]
+extern "C" {
+
+    #[link_name = "actual_symbol_name"] // inline comment
+    // between attribute and function
+    fn my_c_function(x: i32) -> bool;
+}
+
+#[cfg(not(miri))] // inline comment
+pub extern "C" fn callable_from_c(x: i32) -> bool {
+    x % 3 == 0
+}
+
+#[cfg(not(miri))] // inline comment
+/* between attribute block comment */
+#[no_mangle]
+/* between attribute and type */
+type Foo = Bar<u8>;
+
+#[no_mangle]
+#[cfg(not(miri))] // inline comment
+#[non_exhaustive] // inline comment
+enum Foo {
+    Bar,
+    Baz,
+}
+
+#[no_mangle]
+#[cfg(not(miri))] /* inline comment */
+struct Foo<A> {
+    x: A,
+}
+
+#[cfg(not(miri))] // inline comment
+union Foo<A, B> {
+    x: A,
+    y: B,
+}
+
+#[cfg(not(miri))] // inline comment
+trait Foo {}
+
+#[cfg(not(miri))] // inline comment
+trait Foo = Bar + Quux;
+
+#[cfg(not(miri))] // inline comment
+impl Foo {}
+
+#[cfg(not(miri))] // inline comment
+macro_rules! bar {
+    (3) => {};
+}
+
+mod nested {
+    #[cfg(not(miri))] // inline comment
+    // between attribute and use
+    use foo;
+
+    #[cfg(not(miri))] // inline comment
+    use foo;
+
+    #[cfg(not(miri))] // inline comment
+    use foo::bar;
+
+    #[cfg(not(miri))] // inline comment
+    use foo::bar as FooBar;
+
+    #[cfg(not(miri))] // inline comment
+    static FOO: i32 = 42;
+
+    #[cfg(not(miri))] // inline comment
+    static FOO: i32 = 42;
+
+    #[cfg(not(miri))] // inline comment
+    static FOO: &'static str = "bar";
+
+    #[cfg(not(miri))] // inline comment
+    const FOO: i32 = 42;
+
+    #[cfg(not(miri))] // inline comment
+    fn foo(bar: usize) {
+        #[cfg(not(miri))] // inline comment
+        println!("hello world!");
+    }
+
+    #[cfg(not(miri))] // inline comment
+    mod foo {}
+
+    #[cfg(not(miri))] // inline comment
+    mod foo {}
+
+    #[cfg(not(miri))] // inline comment
+    extern "C" {
+        fn my_c_function(x: i32) -> bool;
+    }
+
+    #[cfg(not(miri))] // inline comment
+    #[link(name = "CoreFoundation", kind = "framework")]
+    extern "C" {
+
+        #[link_name = "actual_symbol_name"] // inline comment
+        // between attribute and function
+        fn my_c_function(x: i32) -> bool;
+    }
+
+    #[cfg(not(miri))] // inline comment
+    pub extern "C" fn callable_from_c(x: i32) -> bool {
+        x % 3 == 0
+    }
+
+    #[cfg(not(miri))] // inline comment
+    type Foo = Bar<u8>;
+
+    #[cfg(not(miri))] // inline comment
+    #[non_exhaustive] // inline comment
+    enum Foo {
+        // comment
+        #[attribute_1]
+        #[attribute_2] // comment
+        // comment!
+        Bar,
+        /* comment */
+        #[attribute_1]
+        #[attribute_2] /* comment */
+        #[attribute_3]
+        #[attribute_4]
+        /* comment! */
+        Baz,
+    }
+
+    #[cfg(not(miri))] // inline comment
+    struct Foo<A> {
+        x: A,
+    }
+
+    #[cfg(not(miri))] // inline comment
+    union Foo<A, B> {
+        #[attribute_1]
+        #[attribute_2] /* comment */
+        #[attribute_3]
+        #[attribute_4] // comment
+        x: A,
+        y: B,
+    }
+
+    #[cfg(not(miri))] // inline comment
+    #[allow(missing_docs)]
+    trait Foo {
+        #[must_use] /* comment
+                     * that wrappes to
+                     * the next line */
+        fn bar() {}
+    }
+
+    #[allow(missing_docs)]
+    #[cfg(not(miri))] // inline comment
+    trait Foo = Bar + Quux;
+
+    #[allow(missing_docs)]
+    #[cfg(not(miri))] // inline comment
+    impl Foo {}
+
+    #[cfg(not(miri))] // inline comment
+    macro_rules! bar {
+        (3) => {};
+    }
+}
diff --git a/src/tools/rustfmt/tests/target/license-templates/empty_license_path.rs b/src/tools/rustfmt/tests/target/license-templates/empty_license_path.rs
deleted file mode 100644
index 950f103ed39..00000000000
--- a/src/tools/rustfmt/tests/target/license-templates/empty_license_path.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// rustfmt-config: issue-3802.toml
-
-fn main() {
-    println!("Hello world!");
-}
diff --git a/src/tools/rustfmt/tests/target/license-templates/license.rs b/src/tools/rustfmt/tests/target/license-templates/license.rs
deleted file mode 100644
index 7169c7b2576..00000000000
--- a/src/tools/rustfmt/tests/target/license-templates/license.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// rustfmt-license_template_path: tests/license-template/lt.txt
-// Copyright 2019 The rustfmt developers.
-
-fn main() {
-    println!("Hello world!");
-}
diff --git a/src/tools/rustfmt/tests/target/performance/issue-4476.rs b/src/tools/rustfmt/tests/target/performance/issue-4476.rs
new file mode 100644
index 00000000000..30567f2644b
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/performance/issue-4476.rs
@@ -0,0 +1,705 @@
+use super::SemverParser;
+
+#[allow(dead_code, non_camel_case_types)]
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub enum Rule {
+    EOI,
+    range_set,
+    logical_or,
+    range,
+    empty,
+    hyphen,
+    simple,
+    primitive,
+    primitive_op,
+    partial,
+    xr,
+    xr_op,
+    nr,
+    tilde,
+    caret,
+    qualifier,
+    parts,
+    part,
+    space,
+}
+#[allow(clippy::all)]
+impl ::pest::Parser<Rule> for SemverParser {
+    fn parse<'i>(
+        rule: Rule,
+        input: &'i str,
+    ) -> ::std::result::Result<::pest::iterators::Pairs<'i, Rule>, ::pest::error::Error<Rule>> {
+        mod rules {
+            pub mod hidden {
+                use super::super::Rule;
+                #[inline]
+                #[allow(dead_code, non_snake_case, unused_variables)]
+                pub fn skip(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    Ok(state)
+                }
+            }
+            pub mod visible {
+                use super::super::Rule;
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn range_set(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::range_set, |state| {
+                        state.sequence(|state| {
+                            self::SOI(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::range(state))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            state
+                                                .sequence(|state| {
+                                                    self::logical_or(state)
+                                                        .and_then(|state| {
+                                                            super::hidden::skip(state)
+                                                        })
+                                                        .and_then(|state| self::range(state))
+                                                })
+                                                .and_then(|state| {
+                                                    state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                            super::hidden::skip(state).and_then(
+                                                                |state| {
+                                                                    state.sequence(|state| {
+                                                                        self::logical_or(state)
+                                                                            .and_then(|state| {
+                                                                                super::hidden::skip(
+                                                                                    state,
+                                                                                )
+                                                                            })
+                                                                            .and_then(|state| {
+                                                                                self::range(state)
+                                                                            })
+                                                                    })
+                                                                },
+                                                            )
+                                                        })
+                                                    })
+                                                })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::EOI(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn logical_or(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::logical_or, |state| {
+                        state.sequence(|state| {
+                            state
+                                .sequence(|state| {
+                                    state.optional(|state| {
+                                        self::space(state).and_then(|state| {
+                                            state.repeat(|state| {
+                                                state.sequence(|state| {
+                                                    super::hidden::skip(state)
+                                                        .and_then(|state| self::space(state))
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| state.match_string("||"))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn range(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::range, |state| {
+                        self::hyphen(state)
+                            .or_else(|state| {
+                                state.sequence(|state| {
+                                    self::simple(state)
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| {
+                                            state.sequence(|state| {
+                                                state.optional(|state| {
+                                                    state
+                                                        .sequence(|state| {
+                                                            state
+                                                                .optional(|state| {
+                                                                    state.match_string(",")
+                                                                })
+                                                                .and_then(|state| {
+                                                                    super::hidden::skip(state)
+                                                                })
+                                                                .and_then(|state| {
+                                                                    state.sequence(|state| {
+                                                                        self::space(state)
+                                      .and_then(|state| super::hidden::skip(state))
+                                      .and_then(|state| {
+                                        state.sequence(|state| {
+                                          state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                              state.repeat(|state| {
+                                                state.sequence(|state| {
+                                                  super::hidden::skip(state)
+                                                    .and_then(|state| self::space(state))
+                                                })
+                                              })
+                                            })
+                                          })
+                                        })
+                                      })
+                                                                    })
+                                                                })
+                                                                .and_then(|state| {
+                                                                    super::hidden::skip(state)
+                                                                })
+                                                                .and_then(|state| {
+                                                                    self::simple(state)
+                                                                })
+                                                        })
+                                                        .and_then(|state| {
+                                                            state.repeat(|state| {
+                                                                state.sequence(|state| {
+                                                                    super::hidden::skip(state)
+                                                                        .and_then(|state| {
+                                                                            state.sequence(
+                                                                                |state| {
+                                                                                    state
+                                        .optional(|state| state.match_string(","))
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| {
+                                          state.sequence(|state| {
+                                            self::space(state)
+                                              .and_then(|state| super::hidden::skip(state))
+                                              .and_then(|state| {
+                                                state.sequence(|state| {
+                                                  state.optional(|state| {
+                                                    self::space(state).and_then(|state| {
+                                                      state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                          super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                        })
+                                                      })
+                                                    })
+                                                  })
+                                                })
+                                              })
+                                          })
+                                        })
+                                        .and_then(|state| super::hidden::skip(state))
+                                        .and_then(|state| self::simple(state))
+                                                                                },
+                                                                            )
+                                                                        })
+                                                                })
+                                                            })
+                                                        })
+                                                })
+                                            })
+                                        })
+                                })
+                            })
+                            .or_else(|state| self::empty(state))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn empty(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::empty, |state| state.match_string(""))
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn hyphen(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::hyphen, |state| {
+                        state.sequence(|state| {
+                            self::partial(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        self::space(state)
+                                            .and_then(|state| super::hidden::skip(state))
+                                            .and_then(|state| {
+                                                state.sequence(|state| {
+                                                    state.optional(|state| {
+                                                        self::space(state).and_then(|state| {
+                                                            state.repeat(|state| {
+                                                                state.sequence(|state| {
+                                                                    super::hidden::skip(state)
+                                                                        .and_then(|state| {
+                                                                            self::space(state)
+                                                                        })
+                                                                })
+                                                            })
+                                                        })
+                                                    })
+                                                })
+                                            })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| state.match_string("-"))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        self::space(state)
+                                            .and_then(|state| super::hidden::skip(state))
+                                            .and_then(|state| {
+                                                state.sequence(|state| {
+                                                    state.optional(|state| {
+                                                        self::space(state).and_then(|state| {
+                                                            state.repeat(|state| {
+                                                                state.sequence(|state| {
+                                                                    super::hidden::skip(state)
+                                                                        .and_then(|state| {
+                                                                            self::space(state)
+                                                                        })
+                                                                })
+                                                            })
+                                                        })
+                                                    })
+                                                })
+                                            })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::partial(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn simple(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::simple, |state| {
+                        self::primitive(state)
+                            .or_else(|state| self::partial(state))
+                            .or_else(|state| self::tilde(state))
+                            .or_else(|state| self::caret(state))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn primitive(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::primitive, |state| {
+                        state.sequence(|state| {
+                            self::primitive_op(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::partial(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn primitive_op(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::primitive_op, |state| {
+                        state
+                            .match_string("<=")
+                            .or_else(|state| state.match_string(">="))
+                            .or_else(|state| state.match_string(">"))
+                            .or_else(|state| state.match_string("<"))
+                            .or_else(|state| state.match_string("="))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn partial(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::partial, |state| {
+                        state.sequence(|state| {
+                            self::xr(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.optional(|state| {
+                                        state.sequence(|state| {
+                                            state
+                                                .match_string(".")
+                                                .and_then(|state| super::hidden::skip(state))
+                                                .and_then(|state| self::xr(state))
+                                                .and_then(|state| super::hidden::skip(state))
+                                                .and_then(|state| {
+                                                    state.optional(|state| {
+                                                        state.sequence(|state| {
+                                                            state
+                                                                .match_string(".")
+                                                                .and_then(|state| {
+                                                                    super::hidden::skip(state)
+                                                                })
+                                                                .and_then(|state| self::xr(state))
+                                                                .and_then(|state| {
+                                                                    super::hidden::skip(state)
+                                                                })
+                                                                .and_then(|state| {
+                                                                    state.optional(|state| {
+                                                                        self::qualifier(state)
+                                                                    })
+                                                                })
+                                                        })
+                                                    })
+                                                })
+                                        })
+                                    })
+                                })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn xr(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::xr, |state| {
+                        self::xr_op(state).or_else(|state| self::nr(state))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn xr_op(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::xr_op, |state| {
+                        state
+                            .match_string("x")
+                            .or_else(|state| state.match_string("X"))
+                            .or_else(|state| state.match_string("*"))
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn nr(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::nr, |state| {
+                        state.match_string("0").or_else(|state| {
+                            state.sequence(|state| {
+                                state
+                                    .match_range('1'..'9')
+                                    .and_then(|state| super::hidden::skip(state))
+                                    .and_then(|state| {
+                                        state.sequence(|state| {
+                                            state.optional(|state| {
+                                                state.match_range('0'..'9').and_then(|state| {
+                                                    state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                            super::hidden::skip(state).and_then(
+                                                                |state| state.match_range('0'..'9'),
+                                                            )
+                                                        })
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                            })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn tilde(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::tilde, |state| {
+                        state.sequence(|state| {
+                            state
+                                .match_string("~>")
+                                .or_else(|state| state.match_string("~"))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::partial(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn caret(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::caret, |state| {
+                        state.sequence(|state| {
+                            state
+                                .match_string("^")
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            self::space(state).and_then(|state| {
+                                                state.repeat(|state| {
+                                                    state.sequence(|state| {
+                                                        super::hidden::skip(state)
+                                                            .and_then(|state| self::space(state))
+                                                    })
+                                                })
+                                            })
+                                        })
+                                    })
+                                })
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::partial(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn qualifier(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::qualifier, |state| {
+                        state.sequence(|state| {
+                            state
+                                .match_string("-")
+                                .or_else(|state| state.match_string("+"))
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| self::parts(state))
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn parts(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::parts, |state| {
+                        state.sequence(|state| {
+                            self::part(state)
+                                .and_then(|state| super::hidden::skip(state))
+                                .and_then(|state| {
+                                    state.sequence(|state| {
+                                        state.optional(|state| {
+                                            state
+                                                .sequence(|state| {
+                                                    state
+                                                        .match_string(".")
+                                                        .and_then(|state| {
+                                                            super::hidden::skip(state)
+                                                        })
+                                                        .and_then(|state| self::part(state))
+                                                })
+                                                .and_then(|state| {
+                                                    state.repeat(|state| {
+                                                        state.sequence(|state| {
+                                                            super::hidden::skip(state).and_then(
+                                                                |state| {
+                                                                    state.sequence(|state| {
+                                                                        state
+                                                                            .match_string(".")
+                                                                            .and_then(|state| {
+                                                                                super::hidden::skip(
+                                                                                    state,
+                                                                                )
+                                                                            })
+                                                                            .and_then(|state| {
+                                                                                self::part(state)
+                                                                            })
+                                                                    })
+                                                                },
+                                                            )
+                                                        })
+                                                    })
+                                                })
+                                        })
+                                    })
+                                })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn part(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::part, |state| {
+                        self::nr(state).or_else(|state| {
+                            state.sequence(|state| {
+                                state
+                                    .match_string("-")
+                                    .or_else(|state| state.match_range('0'..'9'))
+                                    .or_else(|state| state.match_range('A'..'Z'))
+                                    .or_else(|state| state.match_range('a'..'z'))
+                                    .and_then(|state| super::hidden::skip(state))
+                                    .and_then(|state| {
+                                        state.sequence(|state| {
+                                            state.optional(|state| {
+                                                state
+                                                    .match_string("-")
+                                                    .or_else(|state| state.match_range('0'..'9'))
+                                                    .or_else(|state| state.match_range('A'..'Z'))
+                                                    .or_else(|state| state.match_range('a'..'z'))
+                                                    .and_then(|state| {
+                                                        state.repeat(|state| {
+                                                            state.sequence(|state| {
+                                                                super::hidden::skip(state).and_then(
+                                                                    |state| {
+                                                                        state
+                                                                            .match_string("-")
+                                                                            .or_else(|state| {
+                                                                                state.match_range(
+                                                                                    '0'..'9',
+                                                                                )
+                                                                            })
+                                                                            .or_else(|state| {
+                                                                                state.match_range(
+                                                                                    'A'..'Z',
+                                                                                )
+                                                                            })
+                                                                            .or_else(|state| {
+                                                                                state.match_range(
+                                                                                    'a'..'z',
+                                                                                )
+                                                                            })
+                                                                    },
+                                                                )
+                                                            })
+                                                        })
+                                                    })
+                                            })
+                                        })
+                                    })
+                            })
+                        })
+                    })
+                }
+                #[inline]
+                #[allow(non_snake_case, unused_variables)]
+                pub fn space(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state
+                        .match_string(" ")
+                        .or_else(|state| state.match_string("\t"))
+                }
+                #[inline]
+                #[allow(dead_code, non_snake_case, unused_variables)]
+                pub fn EOI(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.rule(Rule::EOI, |state| state.end_of_input())
+                }
+                #[inline]
+                #[allow(dead_code, non_snake_case, unused_variables)]
+                pub fn SOI(
+                    state: Box<::pest::ParserState<Rule>>,
+                ) -> ::pest::ParseResult<Box<::pest::ParserState<Rule>>> {
+                    state.start_of_input()
+                }
+            }
+            pub use self::visible::*;
+        }
+        ::pest::state(input, |state| match rule {
+            Rule::range_set => rules::range_set(state),
+            Rule::logical_or => rules::logical_or(state),
+            Rule::range => rules::range(state),
+            Rule::empty => rules::empty(state),
+            Rule::hyphen => rules::hyphen(state),
+            Rule::simple => rules::simple(state),
+            Rule::primitive => rules::primitive(state),
+            Rule::primitive_op => rules::primitive_op(state),
+            Rule::partial => rules::partial(state),
+            Rule::xr => rules::xr(state),
+            Rule::xr_op => rules::xr_op(state),
+            Rule::nr => rules::nr(state),
+            Rule::tilde => rules::tilde(state),
+            Rule::caret => rules::caret(state),
+            Rule::qualifier => rules::qualifier(state),
+            Rule::parts => rules::parts(state),
+            Rule::part => rules::part(state),
+            Rule::space => rules::space(state),
+            Rule::EOI => rules::EOI(state),
+        })
+    }
+}
diff --git a/src/tools/rustfmt/tests/target/performance/issue-4867.rs b/src/tools/rustfmt/tests/target/performance/issue-4867.rs
new file mode 100644
index 00000000000..336dae1b64a
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/performance/issue-4867.rs
@@ -0,0 +1,13 @@
+mod modA {
+    mod modB {
+        mod modC {
+            mod modD {
+                mod modE {
+                    fn func() {
+                        state . rule (Rule :: myrule , | state | { state . sequence (| state | { state . sequence (| state | { state . match_string ("abc") . and_then (| state | { super :: hidden :: skip (state) }) . and_then (| state | { state . match_string ("def") }) }) . and_then (| state | { super :: hidden :: skip (state) }) . and_then (| state | { state . sequence (| state | { state . optional (| state | { state . sequence (| state | { state . match_string ("abc") . and_then (| state | { super :: hidden :: skip (state) }) . and_then (| state | { state . match_string ("def") }) }) . and_then (| state | { state . repeat (| state | { state . sequence (| state | { super :: hidden :: skip (state) . and_then (| state | { state . sequence (| state | { state . match_string ("abc") . and_then (| state | { super :: hidden :: skip (state) }) . and_then (| state | { state . match_string ("def") }) }) }) }) }) }) }) }) }) }) });
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/rustfmt/tests/target/performance/issue-5128.rs b/src/tools/rustfmt/tests/target/performance/issue-5128.rs
new file mode 100644
index 00000000000..ba9ebfc6243
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/performance/issue-5128.rs
@@ -0,0 +1,4898 @@
+fn takes_a_long_time_to_rustfmt() {
+    let inner_cte = vec![Node {
+        node: Some(node::Node::CommonTableExpr(Box::new(CommonTableExpr {
+            ctename: String::from("ranked_by_age_within_key"),
+            aliascolnames: vec![],
+            ctematerialized: CteMaterialize::Default as i32,
+            ctequery: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+                    target_list: vec![
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from(""),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::AStar(AStar {})),
+                                        }],
+                                        location: 80,
+                                    })),
+                                })),
+                                location: 80,
+                            }))),
+                        },
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("rank_in_key"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::FuncCall(Box::new(FuncCall {
+                                        funcname: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("row_number"),
+                                            })),
+                                        }],
+                                        args: vec![],
+                                        agg_order: vec![],
+                                        agg_filter: None,
+                                        agg_within_group: false,
+                                        agg_star: false,
+                                        agg_distinct: false,
+                                        func_variadic: false,
+                                        over: Some(Box::new(WindowDef {
+                                            name: String::from(""),
+                                            refname: String::from(""),
+                                            partition_clause: vec![Node {
+                                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                                    fields: vec![Node {
+                                                        node: Some(node::Node::String(String2 {
+                                                            str: String::from("synthetic_key"),
+                                                        })),
+                                                    }],
+                                                    location: 123,
+                                                })),
+                                            }],
+                                            order_clause: vec![Node {
+                                                node: Some(node::Node::SortBy(Box::new(SortBy {
+                                                    node: Some(Box::new(Node {
+                                                        node: Some(node::Node::ColumnRef(
+                                                            ColumnRef {
+                                                                fields: vec![Node {
+                                                                    node: Some(node::Node::String(
+                                                                        String2 {
+                                                                            str: String::from(
+                                                                                "logical_timestamp",
+                                                                            ),
+                                                                        },
+                                                                    )),
+                                                                }],
+                                                                location: 156,
+                                                            },
+                                                        )),
+                                                    })),
+                                                    sortby_dir: SortByDir::SortbyDesc as i32,
+                                                    sortby_nulls: SortByNulls::SortbyNullsDefault
+                                                        as i32,
+                                                    use_op: vec![],
+                                                    location: -1,
+                                                }))),
+                                            }],
+                                            frame_options: 1058,
+                                            start_offset: None,
+                                            end_offset: None,
+                                            location: 109,
+                                        })),
+                                        location: 91,
+                                    }))),
+                                })),
+                                location: 91,
+                            }))),
+                        },
+                    ],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from("_supertables"),
+                            relname: String::from("9999-9999-9999"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 206,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::AExpr(Box::new(AExpr {
+                            kind: AExprKind::AexprOp as i32,
+                            name: vec![Node {
+                                node: Some(node::Node::String(String2 {
+                                    str: String::from("<="),
+                                })),
+                            }],
+                            lexpr: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("logical_timestamp"),
+                                        })),
+                                    }],
+                                    location: 250,
+                                })),
+                            })),
+                            rexpr: Some(Box::new(Node {
+                                node: Some(node::Node::AConst(Box::new(AConst {
+                                    val: Some(Box::new(Node {
+                                        node: Some(node::Node::Integer(Integer { ival: 9000 })),
+                                    })),
+                                    location: 271,
+                                }))),
+                            })),
+                            location: 268,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: None,
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            location: 29,
+            cterecursive: false,
+            cterefcount: 0,
+            ctecolnames: vec![],
+            ctecoltypes: vec![],
+            ctecoltypmods: vec![],
+            ctecolcollations: vec![],
+        }))),
+    }];
+    let outer_cte = vec![Node {
+        node: Some(node::Node::CommonTableExpr(Box::new(CommonTableExpr {
+            ctename: String::from("table_name"),
+            aliascolnames: vec![],
+            ctematerialized: CteMaterialize::Default as i32,
+            ctequery: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+                    target_list: vec![
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("column1"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("c1"),
+                                            })),
+                                        }],
+                                        location: 301,
+                                    })),
+                                })),
+                                location: 301,
+                            }))),
+                        },
+                        Node {
+                            node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                                name: String::from("column2"),
+                                indirection: vec![],
+                                val: Some(Box::new(Node {
+                                    node: Some(node::Node::ColumnRef(ColumnRef {
+                                        fields: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("c2"),
+                                            })),
+                                        }],
+                                        location: 324,
+                                    })),
+                                })),
+                                location: 324,
+                            }))),
+                        },
+                    ],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from(""),
+                            relname: String::from("ranked_by_age_within_key"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 347,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::BoolExpr(Box::new(BoolExpr {
+                            xpr: None,
+                            boolop: BoolExprType::AndExpr as i32,
+                            args: vec![
+                                Node {
+                                    node: Some(node::Node::AExpr(Box::new(AExpr {
+                                        kind: AExprKind::AexprOp as i32,
+                                        name: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("="),
+                                            })),
+                                        }],
+                                        lexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                fields: vec![Node {
+                                                    node: Some(node::Node::String(String2 {
+                                                        str: String::from("rank_in_key"),
+                                                    })),
+                                                }],
+                                                location: 382,
+                                            })),
+                                        })),
+                                        rexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::AConst(Box::new(AConst {
+                                                val: Some(Box::new(Node {
+                                                    node: Some(node::Node::Integer(Integer {
+                                                        ival: 1,
+                                                    })),
+                                                })),
+                                                location: 396,
+                                            }))),
+                                        })),
+                                        location: 394,
+                                    }))),
+                                },
+                                Node {
+                                    node: Some(node::Node::AExpr(Box::new(AExpr {
+                                        kind: AExprKind::AexprOp as i32,
+                                        name: vec![Node {
+                                            node: Some(node::Node::String(String2 {
+                                                str: String::from("="),
+                                            })),
+                                        }],
+                                        lexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::ColumnRef(ColumnRef {
+                                                fields: vec![Node {
+                                                    node: Some(node::Node::String(String2 {
+                                                        str: String::from("is_deleted"),
+                                                    })),
+                                                }],
+                                                location: 402,
+                                            })),
+                                        })),
+                                        rexpr: Some(Box::new(Node {
+                                            node: Some(node::Node::TypeCast(Box::new(TypeCast {
+                                                arg: Some(Box::new(Node {
+                                                    node: Some(node::Node::AConst(Box::new(
+                                                        AConst {
+                                                            val: Some(Box::new(Node {
+                                                                node: Some(node::Node::String(
+                                                                    String2 {
+                                                                        str: String::from("f"),
+                                                                    },
+                                                                )),
+                                                            })),
+                                                            location: 415,
+                                                        },
+                                                    ))),
+                                                })),
+                                                type_name: Some(TypeName {
+                                                    names: vec![
+                                                        Node {
+                                                            node: Some(node::Node::String(
+                                                                String2 {
+                                                                    str: String::from("pg_catalog"),
+                                                                },
+                                                            )),
+                                                        },
+                                                        Node {
+                                                            node: Some(node::Node::String(
+                                                                String2 {
+                                                                    str: String::from("bool"),
+                                                                },
+                                                            )),
+                                                        },
+                                                    ],
+                                                    type_oid: 0,
+                                                    setof: false,
+                                                    pct_type: false,
+                                                    typmods: vec![],
+                                                    typemod: -1,
+                                                    array_bounds: vec![],
+                                                    location: -1,
+                                                }),
+                                                location: -1,
+                                            }))),
+                                        })),
+                                        location: 413,
+                                    }))),
+                                },
+                            ],
+                            location: 398,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: Some(WithClause {
+                        ctes: inner_cte,
+                        recursive: false,
+                        location: 24,
+                    }),
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            location: 5,
+            cterecursive: false,
+            cterefcount: 0,
+            ctecolnames: vec![],
+            ctecoltypes: vec![],
+            ctecoltypmods: vec![],
+            ctecolcollations: vec![],
+        }))),
+    }];
+    let expected_result = ParseResult {
+        version: 130003,
+        stmts: vec![RawStmt {
+            stmt: Some(Box::new(Node {
+                node: Some(node::Node::SelectStmt(Box::new(SelectStmt {
+                    distinct_clause: vec![],
+                    into_clause: None,
+
+                    target_list: vec![Node {
+                        node: Some(node::Node::ResTarget(Box::new(ResTarget {
+                            name: String::from(""),
+                            indirection: vec![],
+                            val: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("column1"),
+                                        })),
+                                    }],
+                                    location: 430,
+                                })),
+                            })),
+                            location: 430,
+                        }))),
+                    }],
+                    from_clause: vec![Node {
+                        node: Some(node::Node::RangeVar(RangeVar {
+                            catalogname: String::from(""),
+                            schemaname: String::from(""),
+                            relname: String::from("table_name"),
+                            inh: true,
+                            relpersistence: String::from("p"),
+                            alias: None,
+                            location: 443,
+                        })),
+                    }],
+                    where_clause: Some(Box::new(Node {
+                        node: Some(node::Node::AExpr(Box::new(AExpr {
+                            kind: AExprKind::AexprOp as i32,
+                            name: vec![Node {
+                                node: Some(node::Node::String(String2 {
+                                    str: String::from(">"),
+                                })),
+                            }],
+                            lexpr: Some(Box::new(Node {
+                                node: Some(node::Node::ColumnRef(ColumnRef {
+                                    fields: vec![Node {
+                                        node: Some(node::Node::String(String2 {
+                                            str: String::from("column2"),
+                                        })),
+                                    }],
+                                    location: 460,
+                                })),
+                            })),
+                            rexpr: Some(Box::new(Node {
+                                node: Some(node::Node::AConst(Box::new(AConst {
+                                    val: Some(Box::new(Node {
+                                        node: Some(node::Node::Integer(Integer { ival: 9000 })),
+                                    })),
+                                    location: 470,
+                                }))),
+                            })),
+                            location: 468,
+                        }))),
+                    })),
+                    group_clause: vec![],
+                    having_clause: None,
+                    window_clause: vec![],
+                    values_lists: vec![],
+                    sort_clause: vec![],
+                    limit_offset: None,
+                    limit_count: None,
+                    limit_option: LimitOption::Default as i32,
+                    locking_clause: vec![],
+                    with_clause: Some(WithClause {
+                        ctes: outer_cte,
+                        recursive: false,
+                        location: 0,
+                    }),
+                    op: SetOperation::SetopNone as i32,
+                    all: false,
+                    larg: None,
+                    rarg: None,
+                }))),
+            })),
+            stmt_location: 0,
+            stmt_len: 0,
+        }],
+    };
+}
+#[derive(Clone, PartialEq)]
+pub struct ParseResult {
+    pub version: i32,
+
+    pub stmts: Vec<RawStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScanResult {
+    pub version: i32,
+
+    pub tokens: Vec<ScanToken>,
+}
+#[derive(Clone, PartialEq)]
+pub struct Node {
+    pub node: ::core::option::Option<node::Node>,
+}
+/// Nested message and enum types in `Node`.
+pub mod node {
+    #[derive(Clone, PartialEq)]
+    pub enum Node {
+        Alias(super::Alias),
+
+        RangeVar(super::RangeVar),
+
+        TableFunc(Box<super::TableFunc>),
+
+        Expr(super::Expr),
+
+        Var(Box<super::Var>),
+
+        Param(Box<super::Param>),
+
+        Aggref(Box<super::Aggref>),
+
+        GroupingFunc(Box<super::GroupingFunc>),
+
+        WindowFunc(Box<super::WindowFunc>),
+
+        SubscriptingRef(Box<super::SubscriptingRef>),
+
+        FuncExpr(Box<super::FuncExpr>),
+
+        NamedArgExpr(Box<super::NamedArgExpr>),
+
+        OpExpr(Box<super::OpExpr>),
+
+        DistinctExpr(Box<super::DistinctExpr>),
+
+        NullIfExpr(Box<super::NullIfExpr>),
+
+        ScalarArrayOpExpr(Box<super::ScalarArrayOpExpr>),
+
+        BoolExpr(Box<super::BoolExpr>),
+
+        SubLink(Box<super::SubLink>),
+
+        SubPlan(Box<super::SubPlan>),
+
+        AlternativeSubPlan(Box<super::AlternativeSubPlan>),
+
+        FieldSelect(Box<super::FieldSelect>),
+
+        FieldStore(Box<super::FieldStore>),
+
+        RelabelType(Box<super::RelabelType>),
+
+        CoerceViaIo(Box<super::CoerceViaIo>),
+
+        ArrayCoerceExpr(Box<super::ArrayCoerceExpr>),
+
+        ConvertRowtypeExpr(Box<super::ConvertRowtypeExpr>),
+
+        CollateExpr(Box<super::CollateExpr>),
+
+        CaseExpr(Box<super::CaseExpr>),
+
+        CaseWhen(Box<super::CaseWhen>),
+
+        CaseTestExpr(Box<super::CaseTestExpr>),
+
+        ArrayExpr(Box<super::ArrayExpr>),
+
+        RowExpr(Box<super::RowExpr>),
+
+        RowCompareExpr(Box<super::RowCompareExpr>),
+
+        CoalesceExpr(Box<super::CoalesceExpr>),
+
+        MinMaxExpr(Box<super::MinMaxExpr>),
+
+        SqlvalueFunction(Box<super::SqlValueFunction>),
+
+        XmlExpr(Box<super::XmlExpr>),
+
+        NullTest(Box<super::NullTest>),
+
+        BooleanTest(Box<super::BooleanTest>),
+
+        CoerceToDomain(Box<super::CoerceToDomain>),
+
+        CoerceToDomainValue(Box<super::CoerceToDomainValue>),
+
+        SetToDefault(Box<super::SetToDefault>),
+
+        CurrentOfExpr(Box<super::CurrentOfExpr>),
+
+        NextValueExpr(Box<super::NextValueExpr>),
+
+        InferenceElem(Box<super::InferenceElem>),
+
+        TargetEntry(Box<super::TargetEntry>),
+
+        RangeTblRef(super::RangeTblRef),
+
+        JoinExpr(Box<super::JoinExpr>),
+
+        FromExpr(Box<super::FromExpr>),
+
+        OnConflictExpr(Box<super::OnConflictExpr>),
+
+        IntoClause(Box<super::IntoClause>),
+
+        RawStmt(Box<super::RawStmt>),
+
+        Query(Box<super::Query>),
+
+        InsertStmt(Box<super::InsertStmt>),
+
+        DeleteStmt(Box<super::DeleteStmt>),
+
+        UpdateStmt(Box<super::UpdateStmt>),
+
+        SelectStmt(Box<super::SelectStmt>),
+
+        AlterTableStmt(super::AlterTableStmt),
+
+        AlterTableCmd(Box<super::AlterTableCmd>),
+
+        AlterDomainStmt(Box<super::AlterDomainStmt>),
+
+        SetOperationStmt(Box<super::SetOperationStmt>),
+
+        GrantStmt(super::GrantStmt),
+
+        GrantRoleStmt(super::GrantRoleStmt),
+
+        AlterDefaultPrivilegesStmt(super::AlterDefaultPrivilegesStmt),
+
+        ClosePortalStmt(super::ClosePortalStmt),
+
+        ClusterStmt(super::ClusterStmt),
+
+        CopyStmt(Box<super::CopyStmt>),
+
+        CreateStmt(super::CreateStmt),
+
+        DefineStmt(super::DefineStmt),
+
+        DropStmt(super::DropStmt),
+
+        TruncateStmt(super::TruncateStmt),
+
+        CommentStmt(Box<super::CommentStmt>),
+
+        FetchStmt(super::FetchStmt),
+
+        IndexStmt(Box<super::IndexStmt>),
+
+        CreateFunctionStmt(super::CreateFunctionStmt),
+
+        AlterFunctionStmt(super::AlterFunctionStmt),
+
+        DoStmt(super::DoStmt),
+
+        RenameStmt(Box<super::RenameStmt>),
+
+        RuleStmt(Box<super::RuleStmt>),
+
+        NotifyStmt(super::NotifyStmt),
+
+        ListenStmt(super::ListenStmt),
+
+        UnlistenStmt(super::UnlistenStmt),
+
+        TransactionStmt(super::TransactionStmt),
+
+        ViewStmt(Box<super::ViewStmt>),
+
+        LoadStmt(super::LoadStmt),
+
+        CreateDomainStmt(Box<super::CreateDomainStmt>),
+
+        CreatedbStmt(super::CreatedbStmt),
+
+        DropdbStmt(super::DropdbStmt),
+
+        VacuumStmt(super::VacuumStmt),
+
+        ExplainStmt(Box<super::ExplainStmt>),
+
+        CreateTableAsStmt(Box<super::CreateTableAsStmt>),
+
+        CreateSeqStmt(super::CreateSeqStmt),
+
+        AlterSeqStmt(super::AlterSeqStmt),
+
+        VariableSetStmt(super::VariableSetStmt),
+
+        VariableShowStmt(super::VariableShowStmt),
+
+        DiscardStmt(super::DiscardStmt),
+
+        CreateTrigStmt(Box<super::CreateTrigStmt>),
+
+        CreatePlangStmt(super::CreatePLangStmt),
+
+        CreateRoleStmt(super::CreateRoleStmt),
+
+        AlterRoleStmt(super::AlterRoleStmt),
+
+        DropRoleStmt(super::DropRoleStmt),
+
+        LockStmt(super::LockStmt),
+
+        ConstraintsSetStmt(super::ConstraintsSetStmt),
+
+        ReindexStmt(super::ReindexStmt),
+
+        CheckPointStmt(super::CheckPointStmt),
+
+        CreateSchemaStmt(super::CreateSchemaStmt),
+
+        AlterDatabaseStmt(super::AlterDatabaseStmt),
+
+        AlterDatabaseSetStmt(super::AlterDatabaseSetStmt),
+
+        AlterRoleSetStmt(super::AlterRoleSetStmt),
+
+        CreateConversionStmt(super::CreateConversionStmt),
+
+        CreateCastStmt(super::CreateCastStmt),
+
+        CreateOpClassStmt(super::CreateOpClassStmt),
+
+        CreateOpFamilyStmt(super::CreateOpFamilyStmt),
+
+        AlterOpFamilyStmt(super::AlterOpFamilyStmt),
+
+        PrepareStmt(Box<super::PrepareStmt>),
+
+        ExecuteStmt(super::ExecuteStmt),
+
+        DeallocateStmt(super::DeallocateStmt),
+
+        DeclareCursorStmt(Box<super::DeclareCursorStmt>),
+
+        CreateTableSpaceStmt(super::CreateTableSpaceStmt),
+
+        DropTableSpaceStmt(super::DropTableSpaceStmt),
+
+        AlterObjectDependsStmt(Box<super::AlterObjectDependsStmt>),
+
+        AlterObjectSchemaStmt(Box<super::AlterObjectSchemaStmt>),
+
+        AlterOwnerStmt(Box<super::AlterOwnerStmt>),
+
+        AlterOperatorStmt(super::AlterOperatorStmt),
+
+        AlterTypeStmt(super::AlterTypeStmt),
+
+        DropOwnedStmt(super::DropOwnedStmt),
+
+        ReassignOwnedStmt(super::ReassignOwnedStmt),
+
+        CompositeTypeStmt(super::CompositeTypeStmt),
+
+        CreateEnumStmt(super::CreateEnumStmt),
+
+        CreateRangeStmt(super::CreateRangeStmt),
+
+        AlterEnumStmt(super::AlterEnumStmt),
+
+        AlterTsdictionaryStmt(super::AlterTsDictionaryStmt),
+
+        AlterTsconfigurationStmt(super::AlterTsConfigurationStmt),
+
+        CreateFdwStmt(super::CreateFdwStmt),
+
+        AlterFdwStmt(super::AlterFdwStmt),
+
+        CreateForeignServerStmt(super::CreateForeignServerStmt),
+
+        AlterForeignServerStmt(super::AlterForeignServerStmt),
+
+        CreateUserMappingStmt(super::CreateUserMappingStmt),
+
+        AlterUserMappingStmt(super::AlterUserMappingStmt),
+
+        DropUserMappingStmt(super::DropUserMappingStmt),
+
+        AlterTableSpaceOptionsStmt(super::AlterTableSpaceOptionsStmt),
+
+        AlterTableMoveAllStmt(super::AlterTableMoveAllStmt),
+
+        SecLabelStmt(Box<super::SecLabelStmt>),
+
+        CreateForeignTableStmt(super::CreateForeignTableStmt),
+
+        ImportForeignSchemaStmt(super::ImportForeignSchemaStmt),
+
+        CreateExtensionStmt(super::CreateExtensionStmt),
+
+        AlterExtensionStmt(super::AlterExtensionStmt),
+
+        AlterExtensionContentsStmt(Box<super::AlterExtensionContentsStmt>),
+
+        CreateEventTrigStmt(super::CreateEventTrigStmt),
+
+        AlterEventTrigStmt(super::AlterEventTrigStmt),
+
+        RefreshMatViewStmt(super::RefreshMatViewStmt),
+
+        ReplicaIdentityStmt(super::ReplicaIdentityStmt),
+
+        AlterSystemStmt(super::AlterSystemStmt),
+
+        CreatePolicyStmt(Box<super::CreatePolicyStmt>),
+
+        AlterPolicyStmt(Box<super::AlterPolicyStmt>),
+
+        CreateTransformStmt(super::CreateTransformStmt),
+
+        CreateAmStmt(super::CreateAmStmt),
+
+        CreatePublicationStmt(super::CreatePublicationStmt),
+
+        AlterPublicationStmt(super::AlterPublicationStmt),
+
+        CreateSubscriptionStmt(super::CreateSubscriptionStmt),
+
+        AlterSubscriptionStmt(super::AlterSubscriptionStmt),
+
+        DropSubscriptionStmt(super::DropSubscriptionStmt),
+
+        CreateStatsStmt(super::CreateStatsStmt),
+
+        AlterCollationStmt(super::AlterCollationStmt),
+
+        CallStmt(Box<super::CallStmt>),
+
+        AlterStatsStmt(super::AlterStatsStmt),
+
+        AExpr(Box<super::AExpr>),
+
+        ColumnRef(super::ColumnRef),
+
+        ParamRef(super::ParamRef),
+
+        AConst(Box<super::AConst>),
+
+        FuncCall(Box<super::FuncCall>),
+
+        AStar(super::AStar),
+
+        AIndices(Box<super::AIndices>),
+
+        AIndirection(Box<super::AIndirection>),
+
+        AArrayExpr(super::AArrayExpr),
+
+        ResTarget(Box<super::ResTarget>),
+
+        MultiAssignRef(Box<super::MultiAssignRef>),
+
+        TypeCast(Box<super::TypeCast>),
+
+        CollateClause(Box<super::CollateClause>),
+
+        SortBy(Box<super::SortBy>),
+
+        WindowDef(Box<super::WindowDef>),
+
+        RangeSubselect(Box<super::RangeSubselect>),
+
+        RangeFunction(super::RangeFunction),
+
+        RangeTableSample(Box<super::RangeTableSample>),
+
+        RangeTableFunc(Box<super::RangeTableFunc>),
+
+        RangeTableFuncCol(Box<super::RangeTableFuncCol>),
+
+        TypeName(super::TypeName),
+
+        ColumnDef(Box<super::ColumnDef>),
+
+        IndexElem(Box<super::IndexElem>),
+
+        Constraint(Box<super::Constraint>),
+
+        DefElem(Box<super::DefElem>),
+
+        RangeTblEntry(Box<super::RangeTblEntry>),
+
+        RangeTblFunction(Box<super::RangeTblFunction>),
+
+        TableSampleClause(Box<super::TableSampleClause>),
+
+        WithCheckOption(Box<super::WithCheckOption>),
+
+        SortGroupClause(super::SortGroupClause),
+
+        GroupingSet(super::GroupingSet),
+
+        WindowClause(Box<super::WindowClause>),
+
+        ObjectWithArgs(super::ObjectWithArgs),
+
+        AccessPriv(super::AccessPriv),
+
+        CreateOpClassItem(super::CreateOpClassItem),
+
+        TableLikeClause(super::TableLikeClause),
+
+        FunctionParameter(Box<super::FunctionParameter>),
+
+        LockingClause(super::LockingClause),
+
+        RowMarkClause(super::RowMarkClause),
+
+        XmlSerialize(Box<super::XmlSerialize>),
+
+        WithClause(super::WithClause),
+
+        InferClause(Box<super::InferClause>),
+
+        OnConflictClause(Box<super::OnConflictClause>),
+
+        CommonTableExpr(Box<super::CommonTableExpr>),
+
+        RoleSpec(super::RoleSpec),
+
+        TriggerTransition(super::TriggerTransition),
+
+        PartitionElem(Box<super::PartitionElem>),
+
+        PartitionSpec(super::PartitionSpec),
+
+        PartitionBoundSpec(super::PartitionBoundSpec),
+
+        PartitionRangeDatum(Box<super::PartitionRangeDatum>),
+
+        PartitionCmd(super::PartitionCmd),
+
+        VacuumRelation(super::VacuumRelation),
+
+        InlineCodeBlock(super::InlineCodeBlock),
+
+        CallContext(super::CallContext),
+
+        Integer(super::Integer),
+
+        Float(super::Float),
+
+        String(super::String2),
+
+        BitString(super::BitString),
+
+        Null(super::Null),
+
+        List(super::List),
+
+        IntList(super::IntList),
+
+        OidList(super::OidList),
+    }
+}
+#[derive(Clone, PartialEq)]
+pub struct Integer {
+    /// machine integer
+    pub ival: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Float {
+    /// string
+    pub str: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct String2 {
+    /// string
+    pub str: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct BitString {
+    /// string
+    pub str: String,
+}
+/// intentionally empty
+#[derive(Clone, PartialEq)]
+pub struct Null {}
+#[derive(Clone, PartialEq)]
+pub struct List {
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct OidList {
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct IntList {
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct Alias {
+    pub aliasname: String,
+
+    pub colnames: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeVar {
+    pub catalogname: String,
+
+    pub schemaname: String,
+
+    pub relname: String,
+
+    pub inh: bool,
+
+    pub relpersistence: String,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableFunc {
+    pub ns_uris: Vec<Node>,
+
+    pub ns_names: Vec<Node>,
+
+    pub docexpr: ::core::option::Option<Box<Node>>,
+
+    pub rowexpr: ::core::option::Option<Box<Node>>,
+
+    pub colnames: Vec<Node>,
+
+    pub coltypes: Vec<Node>,
+
+    pub coltypmods: Vec<Node>,
+
+    pub colcollations: Vec<Node>,
+
+    pub colexprs: Vec<Node>,
+
+    pub coldefexprs: Vec<Node>,
+
+    pub notnulls: Vec<u64>,
+
+    pub ordinalitycol: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Expr {}
+#[derive(Clone, PartialEq)]
+pub struct Var {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub varno: u32,
+
+    pub varattno: i32,
+
+    pub vartype: u32,
+
+    pub vartypmod: i32,
+
+    pub varcollid: u32,
+
+    pub varlevelsup: u32,
+
+    pub varnosyn: u32,
+
+    pub varattnosyn: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Param {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub paramkind: i32,
+
+    pub paramid: i32,
+
+    pub paramtype: u32,
+
+    pub paramtypmod: i32,
+
+    pub paramcollid: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Aggref {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub aggfnoid: u32,
+
+    pub aggtype: u32,
+
+    pub aggcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub aggtranstype: u32,
+
+    pub aggargtypes: Vec<Node>,
+
+    pub aggdirectargs: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub aggorder: Vec<Node>,
+
+    pub aggdistinct: Vec<Node>,
+
+    pub aggfilter: ::core::option::Option<Box<Node>>,
+
+    pub aggstar: bool,
+
+    pub aggvariadic: bool,
+
+    pub aggkind: String,
+
+    pub agglevelsup: u32,
+
+    pub aggsplit: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct GroupingFunc {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub refs: Vec<Node>,
+
+    pub cols: Vec<Node>,
+
+    pub agglevelsup: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowFunc {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub winfnoid: u32,
+
+    pub wintype: u32,
+
+    pub wincollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub aggfilter: ::core::option::Option<Box<Node>>,
+
+    pub winref: u32,
+
+    pub winstar: bool,
+
+    pub winagg: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubscriptingRef {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub refcontainertype: u32,
+
+    pub refelemtype: u32,
+
+    pub reftypmod: i32,
+
+    pub refcollid: u32,
+
+    pub refupperindexpr: Vec<Node>,
+
+    pub reflowerindexpr: Vec<Node>,
+
+    pub refexpr: ::core::option::Option<Box<Node>>,
+
+    pub refassgnexpr: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct FuncExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub funcid: u32,
+
+    pub funcresulttype: u32,
+
+    pub funcretset: bool,
+
+    pub funcvariadic: bool,
+
+    pub funcformat: i32,
+
+    pub funccollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NamedArgExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub name: String,
+
+    pub argnumber: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct OpExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DistinctExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NullIfExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub opresulttype: u32,
+
+    pub opretset: bool,
+
+    pub opcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScalarArrayOpExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub opno: u32,
+
+    pub opfuncid: u32,
+
+    pub use_or: bool,
+
+    pub inputcollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct BoolExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub boolop: i32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubLink {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub sub_link_type: i32,
+
+    pub sub_link_id: i32,
+
+    pub testexpr: ::core::option::Option<Box<Node>>,
+
+    pub oper_name: Vec<Node>,
+
+    pub subselect: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SubPlan {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub sub_link_type: i32,
+
+    pub testexpr: ::core::option::Option<Box<Node>>,
+
+    pub param_ids: Vec<Node>,
+
+    pub plan_id: i32,
+
+    pub plan_name: String,
+
+    pub first_col_type: u32,
+
+    pub first_col_typmod: i32,
+
+    pub first_col_collation: u32,
+
+    pub use_hash_table: bool,
+
+    pub unknown_eq_false: bool,
+
+    pub parallel_safe: bool,
+
+    pub set_param: Vec<Node>,
+
+    pub par_param: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub startup_cost: f64,
+
+    pub per_call_cost: f64,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlternativeSubPlan {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub subplans: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct FieldSelect {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub fieldnum: i32,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FieldStore {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub newvals: Vec<Node>,
+
+    pub fieldnums: Vec<Node>,
+
+    pub resulttype: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RelabelType {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub relabelformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceViaIo {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resultcollid: u32,
+
+    pub coerceformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ArrayCoerceExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub elemexpr: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub coerceformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ConvertRowtypeExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub convertformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CollateExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub coll_oid: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub casetype: u32,
+
+    pub casecollid: u32,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub defresult: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseWhen {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub result: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CaseTestExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ArrayExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub array_typeid: u32,
+
+    pub array_collid: u32,
+
+    pub element_typeid: u32,
+
+    pub elements: Vec<Node>,
+
+    pub multidims: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub args: Vec<Node>,
+
+    pub row_typeid: u32,
+
+    pub row_format: i32,
+
+    pub colnames: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowCompareExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub rctype: i32,
+
+    pub opnos: Vec<Node>,
+
+    pub opfamilies: Vec<Node>,
+
+    pub inputcollids: Vec<Node>,
+
+    pub largs: Vec<Node>,
+
+    pub rargs: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoalesceExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub coalescetype: u32,
+
+    pub coalescecollid: u32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct MinMaxExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub minmaxtype: u32,
+
+    pub minmaxcollid: u32,
+
+    pub inputcollid: u32,
+
+    pub op: i32,
+
+    pub args: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SqlValueFunction {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub op: i32,
+
+    pub r#type: u32,
+
+    pub typmod: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct XmlExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub op: i32,
+
+    pub name: String,
+
+    pub named_args: Vec<Node>,
+
+    pub arg_names: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub xmloption: i32,
+
+    pub r#type: u32,
+
+    pub typmod: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NullTest {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub nulltesttype: i32,
+
+    pub argisrow: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct BooleanTest {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub booltesttype: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceToDomain {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub resulttype: u32,
+
+    pub resulttypmod: i32,
+
+    pub resultcollid: u32,
+
+    pub coercionformat: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CoerceToDomainValue {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SetToDefault {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub type_id: u32,
+
+    pub type_mod: i32,
+
+    pub collation: u32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CurrentOfExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub cvarno: u32,
+
+    pub cursor_name: String,
+
+    pub cursor_param: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct NextValueExpr {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub seqid: u32,
+
+    pub type_id: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InferenceElem {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub infercollid: u32,
+
+    pub inferopclass: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TargetEntry {
+    pub xpr: ::core::option::Option<Box<Node>>,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub resno: i32,
+
+    pub resname: String,
+
+    pub ressortgroupref: u32,
+
+    pub resorigtbl: u32,
+
+    pub resorigcol: i32,
+
+    pub resjunk: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblRef {
+    pub rtindex: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct JoinExpr {
+    pub jointype: i32,
+
+    pub is_natural: bool,
+
+    pub larg: ::core::option::Option<Box<Node>>,
+
+    pub rarg: ::core::option::Option<Box<Node>>,
+
+    pub using_clause: Vec<Node>,
+
+    pub quals: ::core::option::Option<Box<Node>>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub rtindex: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FromExpr {
+    pub fromlist: Vec<Node>,
+
+    pub quals: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct OnConflictExpr {
+    pub action: i32,
+
+    pub arbiter_elems: Vec<Node>,
+
+    pub arbiter_where: ::core::option::Option<Box<Node>>,
+
+    pub constraint: u32,
+
+    pub on_conflict_set: Vec<Node>,
+
+    pub on_conflict_where: ::core::option::Option<Box<Node>>,
+
+    pub excl_rel_index: i32,
+
+    pub excl_rel_tlist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct IntoClause {
+    pub rel: ::core::option::Option<RangeVar>,
+
+    pub col_names: Vec<Node>,
+
+    pub access_method: String,
+
+    pub options: Vec<Node>,
+
+    pub on_commit: i32,
+
+    pub table_space_name: String,
+
+    pub view_query: ::core::option::Option<Box<Node>>,
+
+    pub skip_data: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RawStmt {
+    pub stmt: ::core::option::Option<Box<Node>>,
+
+    pub stmt_location: i32,
+
+    pub stmt_len: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Query {
+    pub command_type: i32,
+
+    pub query_source: i32,
+
+    pub can_set_tag: bool,
+
+    pub utility_stmt: ::core::option::Option<Box<Node>>,
+
+    pub result_relation: i32,
+
+    pub has_aggs: bool,
+
+    pub has_window_funcs: bool,
+
+    pub has_target_srfs: bool,
+
+    pub has_sub_links: bool,
+
+    pub has_distinct_on: bool,
+
+    pub has_recursive: bool,
+
+    pub has_modifying_cte: bool,
+
+    pub has_for_update: bool,
+
+    pub has_row_security: bool,
+
+    pub cte_list: Vec<Node>,
+
+    pub rtable: Vec<Node>,
+
+    pub jointree: ::core::option::Option<Box<FromExpr>>,
+
+    pub target_list: Vec<Node>,
+
+    pub r#override: i32,
+
+    pub on_conflict: ::core::option::Option<Box<OnConflictExpr>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub group_clause: Vec<Node>,
+
+    pub grouping_sets: Vec<Node>,
+
+    pub having_qual: ::core::option::Option<Box<Node>>,
+
+    pub window_clause: Vec<Node>,
+
+    pub distinct_clause: Vec<Node>,
+
+    pub sort_clause: Vec<Node>,
+
+    pub limit_offset: ::core::option::Option<Box<Node>>,
+
+    pub limit_count: ::core::option::Option<Box<Node>>,
+
+    pub limit_option: i32,
+
+    pub row_marks: Vec<Node>,
+
+    pub set_operations: ::core::option::Option<Box<Node>>,
+
+    pub constraint_deps: Vec<Node>,
+
+    pub with_check_options: Vec<Node>,
+
+    pub stmt_location: i32,
+
+    pub stmt_len: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InsertStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub cols: Vec<Node>,
+
+    pub select_stmt: ::core::option::Option<Box<Node>>,
+
+    pub on_conflict_clause: ::core::option::Option<Box<OnConflictClause>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+
+    pub r#override: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeleteStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub using_clause: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+}
+#[derive(Clone, PartialEq)]
+pub struct UpdateStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub target_list: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub from_clause: Vec<Node>,
+
+    pub returning_list: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+}
+#[derive(Clone, PartialEq)]
+pub struct SelectStmt {
+    pub distinct_clause: Vec<Node>,
+
+    pub into_clause: ::core::option::Option<Box<IntoClause>>,
+
+    pub target_list: Vec<Node>,
+
+    pub from_clause: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub group_clause: Vec<Node>,
+
+    pub having_clause: ::core::option::Option<Box<Node>>,
+
+    pub window_clause: Vec<Node>,
+
+    pub values_lists: Vec<Node>,
+
+    pub sort_clause: Vec<Node>,
+
+    pub limit_offset: ::core::option::Option<Box<Node>>,
+
+    pub limit_count: ::core::option::Option<Box<Node>>,
+
+    pub limit_option: i32,
+
+    pub locking_clause: Vec<Node>,
+
+    pub with_clause: ::core::option::Option<WithClause>,
+
+    pub op: i32,
+
+    pub all: bool,
+
+    pub larg: ::core::option::Option<Box<SelectStmt>>,
+
+    pub rarg: ::core::option::Option<Box<SelectStmt>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub cmds: Vec<Node>,
+
+    pub relkind: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableCmd {
+    pub subtype: i32,
+
+    pub name: String,
+
+    pub num: i32,
+
+    pub newowner: ::core::option::Option<RoleSpec>,
+
+    pub def: ::core::option::Option<Box<Node>>,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDomainStmt {
+    pub subtype: String,
+
+    pub type_name: Vec<Node>,
+
+    pub name: String,
+
+    pub def: ::core::option::Option<Box<Node>>,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SetOperationStmt {
+    pub op: i32,
+
+    pub all: bool,
+
+    pub larg: ::core::option::Option<Box<Node>>,
+
+    pub rarg: ::core::option::Option<Box<Node>>,
+
+    pub col_types: Vec<Node>,
+
+    pub col_typmods: Vec<Node>,
+
+    pub col_collations: Vec<Node>,
+
+    pub group_clauses: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct GrantStmt {
+    pub is_grant: bool,
+
+    pub targtype: i32,
+
+    pub objtype: i32,
+
+    pub objects: Vec<Node>,
+
+    pub privileges: Vec<Node>,
+
+    pub grantees: Vec<Node>,
+
+    pub grant_option: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct GrantRoleStmt {
+    pub granted_roles: Vec<Node>,
+
+    pub grantee_roles: Vec<Node>,
+
+    pub is_grant: bool,
+
+    pub admin_opt: bool,
+
+    pub grantor: ::core::option::Option<RoleSpec>,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDefaultPrivilegesStmt {
+    pub options: Vec<Node>,
+
+    pub action: ::core::option::Option<GrantStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ClosePortalStmt {
+    pub portalname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct ClusterStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub indexname: String,
+
+    pub options: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CopyStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub attlist: Vec<Node>,
+
+    pub is_from: bool,
+
+    pub is_program: bool,
+
+    pub filename: String,
+
+    pub options: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub table_elts: Vec<Node>,
+
+    pub inh_relations: Vec<Node>,
+
+    pub partbound: ::core::option::Option<PartitionBoundSpec>,
+
+    pub partspec: ::core::option::Option<PartitionSpec>,
+
+    pub of_typename: ::core::option::Option<TypeName>,
+
+    pub constraints: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub oncommit: i32,
+
+    pub tablespacename: String,
+
+    pub access_method: String,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DefineStmt {
+    pub kind: i32,
+
+    pub oldstyle: bool,
+
+    pub defnames: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub definition: Vec<Node>,
+
+    pub if_not_exists: bool,
+
+    pub replace: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropStmt {
+    pub objects: Vec<Node>,
+
+    pub remove_type: i32,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+
+    pub concurrent: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct TruncateStmt {
+    pub relations: Vec<Node>,
+
+    pub restart_seqs: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CommentStmt {
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub comment: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct FetchStmt {
+    pub direction: i32,
+
+    pub how_many: i64,
+
+    pub portalname: String,
+
+    pub ismove: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct IndexStmt {
+    pub idxname: String,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub access_method: String,
+
+    pub table_space: String,
+
+    pub index_params: Vec<Node>,
+
+    pub index_including_params: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub exclude_op_names: Vec<Node>,
+
+    pub idxcomment: String,
+
+    pub index_oid: u32,
+
+    pub old_node: u32,
+
+    pub old_create_subid: u32,
+
+    pub old_first_relfilenode_subid: u32,
+
+    pub unique: bool,
+
+    pub primary: bool,
+
+    pub isconstraint: bool,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub transformed: bool,
+
+    pub concurrent: bool,
+
+    pub if_not_exists: bool,
+
+    pub reset_default_tblspc: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateFunctionStmt {
+    pub is_procedure: bool,
+
+    pub replace: bool,
+
+    pub funcname: Vec<Node>,
+
+    pub parameters: Vec<Node>,
+
+    pub return_type: ::core::option::Option<TypeName>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterFunctionStmt {
+    pub objtype: i32,
+
+    pub func: ::core::option::Option<ObjectWithArgs>,
+
+    pub actions: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DoStmt {
+    pub args: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RenameStmt {
+    pub rename_type: i32,
+
+    pub relation_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub subname: String,
+
+    pub newname: String,
+
+    pub behavior: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct RuleStmt {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub rulename: String,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub event: i32,
+
+    pub instead: bool,
+
+    pub actions: Vec<Node>,
+
+    pub replace: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct NotifyStmt {
+    pub conditionname: String,
+
+    pub payload: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct ListenStmt {
+    pub conditionname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct UnlistenStmt {
+    pub conditionname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct TransactionStmt {
+    pub kind: i32,
+
+    pub options: Vec<Node>,
+
+    pub savepoint_name: String,
+
+    pub gid: String,
+
+    pub chain: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ViewStmt {
+    pub view: ::core::option::Option<RangeVar>,
+
+    pub aliases: Vec<Node>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub replace: bool,
+
+    pub options: Vec<Node>,
+
+    pub with_check_option: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct LoadStmt {
+    pub filename: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateDomainStmt {
+    pub domainname: Vec<Node>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub coll_clause: ::core::option::Option<Box<CollateClause>>,
+
+    pub constraints: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatedbStmt {
+    pub dbname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropdbStmt {
+    pub dbname: String,
+
+    pub missing_ok: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct VacuumStmt {
+    pub options: Vec<Node>,
+
+    pub rels: Vec<Node>,
+
+    pub is_vacuumcmd: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ExplainStmt {
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTableAsStmt {
+    pub query: ::core::option::Option<Box<Node>>,
+
+    pub into: ::core::option::Option<Box<IntoClause>>,
+
+    pub relkind: i32,
+
+    pub is_select_into: bool,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateSeqStmt {
+    pub sequence: ::core::option::Option<RangeVar>,
+
+    pub options: Vec<Node>,
+
+    pub owner_id: u32,
+
+    pub for_identity: bool,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSeqStmt {
+    pub sequence: ::core::option::Option<RangeVar>,
+
+    pub options: Vec<Node>,
+
+    pub for_identity: bool,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct VariableSetStmt {
+    pub kind: i32,
+
+    pub name: String,
+
+    pub args: Vec<Node>,
+
+    pub is_local: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct VariableShowStmt {
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct DiscardStmt {
+    pub target: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTrigStmt {
+    pub trigname: String,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub funcname: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub row: bool,
+
+    pub timing: i32,
+
+    pub events: i32,
+
+    pub columns: Vec<Node>,
+
+    pub when_clause: ::core::option::Option<Box<Node>>,
+
+    pub isconstraint: bool,
+
+    pub transition_rels: Vec<Node>,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub constrrel: ::core::option::Option<RangeVar>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePLangStmt {
+    pub replace: bool,
+
+    pub plname: String,
+
+    pub plhandler: Vec<Node>,
+
+    pub plinline: Vec<Node>,
+
+    pub plvalidator: Vec<Node>,
+
+    pub pltrusted: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateRoleStmt {
+    pub stmt_type: i32,
+
+    pub role: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterRoleStmt {
+    pub role: ::core::option::Option<RoleSpec>,
+
+    pub options: Vec<Node>,
+
+    pub action: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropRoleStmt {
+    pub roles: Vec<Node>,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct LockStmt {
+    pub relations: Vec<Node>,
+
+    pub mode: i32,
+
+    pub nowait: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ConstraintsSetStmt {
+    pub constraints: Vec<Node>,
+
+    pub deferred: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReindexStmt {
+    pub kind: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub name: String,
+
+    pub options: i32,
+
+    pub concurrent: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CheckPointStmt {}
+#[derive(Clone, PartialEq)]
+pub struct CreateSchemaStmt {
+    pub schemaname: String,
+
+    pub authrole: ::core::option::Option<RoleSpec>,
+
+    pub schema_elts: Vec<Node>,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDatabaseStmt {
+    pub dbname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterDatabaseSetStmt {
+    pub dbname: String,
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterRoleSetStmt {
+    pub role: ::core::option::Option<RoleSpec>,
+
+    pub database: String,
+
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateConversionStmt {
+    pub conversion_name: Vec<Node>,
+
+    pub for_encoding_name: String,
+
+    pub to_encoding_name: String,
+
+    pub func_name: Vec<Node>,
+
+    pub def: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateCastStmt {
+    pub sourcetype: ::core::option::Option<TypeName>,
+
+    pub targettype: ::core::option::Option<TypeName>,
+
+    pub func: ::core::option::Option<ObjectWithArgs>,
+
+    pub context: i32,
+
+    pub inout: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpClassStmt {
+    pub opclassname: Vec<Node>,
+
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+
+    pub datatype: ::core::option::Option<TypeName>,
+
+    pub items: Vec<Node>,
+
+    pub is_default: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpFamilyStmt {
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOpFamilyStmt {
+    pub opfamilyname: Vec<Node>,
+
+    pub amname: String,
+
+    pub is_drop: bool,
+
+    pub items: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct PrepareStmt {
+    pub name: String,
+
+    pub argtypes: Vec<Node>,
+
+    pub query: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ExecuteStmt {
+    pub name: String,
+
+    pub params: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeallocateStmt {
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct DeclareCursorStmt {
+    pub portalname: String,
+
+    pub options: i32,
+
+    pub query: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTableSpaceStmt {
+    pub tablespacename: String,
+
+    pub owner: ::core::option::Option<RoleSpec>,
+
+    pub location: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropTableSpaceStmt {
+    pub tablespacename: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterObjectDependsStmt {
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub extname: ::core::option::Option<Box<Node>>,
+
+    pub remove: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterObjectSchemaStmt {
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub newschema: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOwnerStmt {
+    pub object_type: i32,
+
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub newowner: ::core::option::Option<RoleSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterOperatorStmt {
+    pub opername: ::core::option::Option<ObjectWithArgs>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTypeStmt {
+    pub type_name: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropOwnedStmt {
+    pub roles: Vec<Node>,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReassignOwnedStmt {
+    pub roles: Vec<Node>,
+
+    pub newrole: ::core::option::Option<RoleSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CompositeTypeStmt {
+    pub typevar: ::core::option::Option<RangeVar>,
+
+    pub coldeflist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateEnumStmt {
+    pub type_name: Vec<Node>,
+
+    pub vals: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateRangeStmt {
+    pub type_name: Vec<Node>,
+
+    pub params: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterEnumStmt {
+    pub type_name: Vec<Node>,
+
+    pub old_val: String,
+
+    pub new_val: String,
+
+    pub new_val_neighbor: String,
+
+    pub new_val_is_after: bool,
+
+    pub skip_if_new_val_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTsDictionaryStmt {
+    pub dictname: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTsConfigurationStmt {
+    pub kind: i32,
+
+    pub cfgname: Vec<Node>,
+
+    pub tokentype: Vec<Node>,
+
+    pub dicts: Vec<Node>,
+
+    pub r#override: bool,
+
+    pub replace: bool,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateFdwStmt {
+    pub fdwname: String,
+
+    pub func_options: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterFdwStmt {
+    pub fdwname: String,
+
+    pub func_options: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateForeignServerStmt {
+    pub servername: String,
+
+    pub servertype: String,
+
+    pub version: String,
+
+    pub fdwname: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterForeignServerStmt {
+    pub servername: String,
+
+    pub version: String,
+
+    pub options: Vec<Node>,
+
+    pub has_version: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateUserMappingStmt {
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterUserMappingStmt {
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropUserMappingStmt {
+    pub user: ::core::option::Option<RoleSpec>,
+
+    pub servername: String,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableSpaceOptionsStmt {
+    pub tablespacename: String,
+
+    pub options: Vec<Node>,
+
+    pub is_reset: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterTableMoveAllStmt {
+    pub orig_tablespacename: String,
+
+    pub objtype: i32,
+
+    pub roles: Vec<Node>,
+
+    pub new_tablespacename: String,
+
+    pub nowait: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SecLabelStmt {
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+
+    pub provider: String,
+
+    pub label: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateForeignTableStmt {
+    pub base_stmt: ::core::option::Option<CreateStmt>,
+
+    pub servername: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ImportForeignSchemaStmt {
+    pub server_name: String,
+
+    pub remote_schema: String,
+
+    pub local_schema: String,
+
+    pub list_type: i32,
+
+    pub table_list: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateExtensionStmt {
+    pub extname: String,
+
+    pub if_not_exists: bool,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterExtensionStmt {
+    pub extname: String,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterExtensionContentsStmt {
+    pub extname: String,
+
+    pub action: i32,
+
+    pub objtype: i32,
+
+    pub object: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateEventTrigStmt {
+    pub trigname: String,
+
+    pub eventname: String,
+
+    pub whenclause: Vec<Node>,
+
+    pub funcname: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterEventTrigStmt {
+    pub trigname: String,
+
+    pub tgenabled: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct RefreshMatViewStmt {
+    pub concurrent: bool,
+
+    pub skip_data: bool,
+
+    pub relation: ::core::option::Option<RangeVar>,
+}
+#[derive(Clone, PartialEq)]
+pub struct ReplicaIdentityStmt {
+    pub identity_type: String,
+
+    pub name: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSystemStmt {
+    pub setstmt: ::core::option::Option<VariableSetStmt>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePolicyStmt {
+    pub policy_name: String,
+
+    pub table: ::core::option::Option<RangeVar>,
+
+    pub cmd_name: String,
+
+    pub permissive: bool,
+
+    pub roles: Vec<Node>,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub with_check: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterPolicyStmt {
+    pub policy_name: String,
+
+    pub table: ::core::option::Option<RangeVar>,
+
+    pub roles: Vec<Node>,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub with_check: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateTransformStmt {
+    pub replace: bool,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub lang: String,
+
+    pub fromsql: ::core::option::Option<ObjectWithArgs>,
+
+    pub tosql: ::core::option::Option<ObjectWithArgs>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateAmStmt {
+    pub amname: String,
+
+    pub handler_name: Vec<Node>,
+
+    pub amtype: String,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreatePublicationStmt {
+    pub pubname: String,
+
+    pub options: Vec<Node>,
+
+    pub tables: Vec<Node>,
+
+    pub for_all_tables: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterPublicationStmt {
+    pub pubname: String,
+
+    pub options: Vec<Node>,
+
+    pub tables: Vec<Node>,
+
+    pub for_all_tables: bool,
+
+    pub table_action: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateSubscriptionStmt {
+    pub subname: String,
+
+    pub conninfo: String,
+
+    pub publication: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterSubscriptionStmt {
+    pub kind: i32,
+
+    pub subname: String,
+
+    pub conninfo: String,
+
+    pub publication: Vec<Node>,
+
+    pub options: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct DropSubscriptionStmt {
+    pub subname: String,
+
+    pub missing_ok: bool,
+
+    pub behavior: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateStatsStmt {
+    pub defnames: Vec<Node>,
+
+    pub stat_types: Vec<Node>,
+
+    pub exprs: Vec<Node>,
+
+    pub relations: Vec<Node>,
+
+    pub stxcomment: String,
+
+    pub if_not_exists: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterCollationStmt {
+    pub collname: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CallStmt {
+    pub funccall: ::core::option::Option<Box<FuncCall>>,
+
+    pub funcexpr: ::core::option::Option<Box<FuncExpr>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AlterStatsStmt {
+    pub defnames: Vec<Node>,
+
+    pub stxstattarget: i32,
+
+    pub missing_ok: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AExpr {
+    pub kind: i32,
+
+    pub name: Vec<Node>,
+
+    pub lexpr: ::core::option::Option<Box<Node>>,
+
+    pub rexpr: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ColumnRef {
+    pub fields: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ParamRef {
+    pub number: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AConst {
+    pub val: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FuncCall {
+    pub funcname: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub agg_order: Vec<Node>,
+
+    pub agg_filter: ::core::option::Option<Box<Node>>,
+
+    pub agg_within_group: bool,
+
+    pub agg_star: bool,
+
+    pub agg_distinct: bool,
+
+    pub func_variadic: bool,
+
+    pub over: ::core::option::Option<Box<WindowDef>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct AStar {}
+#[derive(Clone, PartialEq)]
+pub struct AIndices {
+    pub is_slice: bool,
+
+    pub lidx: ::core::option::Option<Box<Node>>,
+
+    pub uidx: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AIndirection {
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub indirection: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct AArrayExpr {
+    pub elements: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ResTarget {
+    pub name: String,
+
+    pub indirection: Vec<Node>,
+
+    pub val: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct MultiAssignRef {
+    pub source: ::core::option::Option<Box<Node>>,
+
+    pub colno: i32,
+
+    pub ncolumns: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TypeCast {
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CollateClause {
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub collname: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct SortBy {
+    pub node: ::core::option::Option<Box<Node>>,
+
+    pub sortby_dir: i32,
+
+    pub sortby_nulls: i32,
+
+    pub use_op: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowDef {
+    pub name: String,
+
+    pub refname: String,
+
+    pub partition_clause: Vec<Node>,
+
+    pub order_clause: Vec<Node>,
+
+    pub frame_options: i32,
+
+    pub start_offset: ::core::option::Option<Box<Node>>,
+
+    pub end_offset: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeSubselect {
+    pub lateral: bool,
+
+    pub subquery: ::core::option::Option<Box<Node>>,
+
+    pub alias: ::core::option::Option<Alias>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeFunction {
+    pub lateral: bool,
+
+    pub ordinality: bool,
+
+    pub is_rowsfrom: bool,
+
+    pub functions: Vec<Node>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub coldeflist: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableSample {
+    pub relation: ::core::option::Option<Box<Node>>,
+
+    pub method: Vec<Node>,
+
+    pub args: Vec<Node>,
+
+    pub repeatable: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableFunc {
+    pub lateral: bool,
+
+    pub docexpr: ::core::option::Option<Box<Node>>,
+
+    pub rowexpr: ::core::option::Option<Box<Node>>,
+
+    pub namespaces: Vec<Node>,
+
+    pub columns: Vec<Node>,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTableFuncCol {
+    pub colname: String,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub for_ordinality: bool,
+
+    pub is_not_null: bool,
+
+    pub colexpr: ::core::option::Option<Box<Node>>,
+
+    pub coldefexpr: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TypeName {
+    pub names: Vec<Node>,
+
+    pub type_oid: u32,
+
+    pub setof: bool,
+
+    pub pct_type: bool,
+
+    pub typmods: Vec<Node>,
+
+    pub typemod: i32,
+
+    pub array_bounds: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct ColumnDef {
+    pub colname: String,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub inhcount: i32,
+
+    pub is_local: bool,
+
+    pub is_not_null: bool,
+
+    pub is_from_type: bool,
+
+    pub storage: String,
+
+    pub raw_default: ::core::option::Option<Box<Node>>,
+
+    pub cooked_default: ::core::option::Option<Box<Node>>,
+
+    pub identity: String,
+
+    pub identity_sequence: ::core::option::Option<RangeVar>,
+
+    pub generated: String,
+
+    pub coll_clause: ::core::option::Option<Box<CollateClause>>,
+
+    pub coll_oid: u32,
+
+    pub constraints: Vec<Node>,
+
+    pub fdwoptions: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct IndexElem {
+    pub name: String,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub indexcolname: String,
+
+    pub collation: Vec<Node>,
+
+    pub opclass: Vec<Node>,
+
+    pub opclassopts: Vec<Node>,
+
+    pub ordering: i32,
+
+    pub nulls_ordering: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct Constraint {
+    pub contype: i32,
+
+    pub conname: String,
+
+    pub deferrable: bool,
+
+    pub initdeferred: bool,
+
+    pub location: i32,
+
+    pub is_no_inherit: bool,
+
+    pub raw_expr: ::core::option::Option<Box<Node>>,
+
+    pub cooked_expr: String,
+
+    pub generated_when: String,
+
+    pub keys: Vec<Node>,
+
+    pub including: Vec<Node>,
+
+    pub exclusions: Vec<Node>,
+
+    pub options: Vec<Node>,
+
+    pub indexname: String,
+
+    pub indexspace: String,
+
+    pub reset_default_tblspc: bool,
+
+    pub access_method: String,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub pktable: ::core::option::Option<RangeVar>,
+
+    pub fk_attrs: Vec<Node>,
+
+    pub pk_attrs: Vec<Node>,
+
+    pub fk_matchtype: String,
+
+    pub fk_upd_action: String,
+
+    pub fk_del_action: String,
+
+    pub old_conpfeqop: Vec<Node>,
+
+    pub old_pktable_oid: u32,
+
+    pub skip_validation: bool,
+
+    pub initially_valid: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct DefElem {
+    pub defnamespace: String,
+
+    pub defname: String,
+
+    pub arg: ::core::option::Option<Box<Node>>,
+
+    pub defaction: i32,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblEntry {
+    pub rtekind: i32,
+
+    pub relid: u32,
+
+    pub relkind: String,
+
+    pub rellockmode: i32,
+
+    pub tablesample: ::core::option::Option<Box<TableSampleClause>>,
+
+    pub subquery: ::core::option::Option<Box<Query>>,
+
+    pub security_barrier: bool,
+
+    pub jointype: i32,
+
+    pub joinmergedcols: i32,
+
+    pub joinaliasvars: Vec<Node>,
+
+    pub joinleftcols: Vec<Node>,
+
+    pub joinrightcols: Vec<Node>,
+
+    pub functions: Vec<Node>,
+
+    pub funcordinality: bool,
+
+    pub tablefunc: ::core::option::Option<Box<TableFunc>>,
+
+    pub values_lists: Vec<Node>,
+
+    pub ctename: String,
+
+    pub ctelevelsup: u32,
+
+    pub self_reference: bool,
+
+    pub coltypes: Vec<Node>,
+
+    pub coltypmods: Vec<Node>,
+
+    pub colcollations: Vec<Node>,
+
+    pub enrname: String,
+
+    pub enrtuples: f64,
+
+    pub alias: ::core::option::Option<Alias>,
+
+    pub eref: ::core::option::Option<Alias>,
+
+    pub lateral: bool,
+
+    pub inh: bool,
+
+    pub in_from_cl: bool,
+
+    pub required_perms: u32,
+
+    pub check_as_user: u32,
+
+    pub selected_cols: Vec<u64>,
+
+    pub inserted_cols: Vec<u64>,
+
+    pub updated_cols: Vec<u64>,
+
+    pub extra_updated_cols: Vec<u64>,
+
+    pub security_quals: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RangeTblFunction {
+    pub funcexpr: ::core::option::Option<Box<Node>>,
+
+    pub funccolcount: i32,
+
+    pub funccolnames: Vec<Node>,
+
+    pub funccoltypes: Vec<Node>,
+
+    pub funccoltypmods: Vec<Node>,
+
+    pub funccolcollations: Vec<Node>,
+
+    pub funcparams: Vec<u64>,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableSampleClause {
+    pub tsmhandler: u32,
+
+    pub args: Vec<Node>,
+
+    pub repeatable: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct WithCheckOption {
+    pub kind: i32,
+
+    pub relname: String,
+
+    pub polname: String,
+
+    pub qual: ::core::option::Option<Box<Node>>,
+
+    pub cascaded: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct SortGroupClause {
+    pub tle_sort_group_ref: u32,
+
+    pub eqop: u32,
+
+    pub sortop: u32,
+
+    pub nulls_first: bool,
+
+    pub hashable: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct GroupingSet {
+    pub kind: i32,
+
+    pub content: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WindowClause {
+    pub name: String,
+
+    pub refname: String,
+
+    pub partition_clause: Vec<Node>,
+
+    pub order_clause: Vec<Node>,
+
+    pub frame_options: i32,
+
+    pub start_offset: ::core::option::Option<Box<Node>>,
+
+    pub end_offset: ::core::option::Option<Box<Node>>,
+
+    pub start_in_range_func: u32,
+
+    pub end_in_range_func: u32,
+
+    pub in_range_coll: u32,
+
+    pub in_range_asc: bool,
+
+    pub in_range_nulls_first: bool,
+
+    pub winref: u32,
+
+    pub copied_order: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ObjectWithArgs {
+    pub objname: Vec<Node>,
+
+    pub objargs: Vec<Node>,
+
+    pub args_unspecified: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct AccessPriv {
+    pub priv_name: String,
+
+    pub cols: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct CreateOpClassItem {
+    pub itemtype: i32,
+
+    pub name: ::core::option::Option<ObjectWithArgs>,
+
+    pub number: i32,
+
+    pub order_family: Vec<Node>,
+
+    pub class_args: Vec<Node>,
+
+    pub storedtype: ::core::option::Option<TypeName>,
+}
+#[derive(Clone, PartialEq)]
+pub struct TableLikeClause {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub options: u32,
+
+    pub relation_oid: u32,
+}
+#[derive(Clone, PartialEq)]
+pub struct FunctionParameter {
+    pub name: String,
+
+    pub arg_type: ::core::option::Option<TypeName>,
+
+    pub mode: i32,
+
+    pub defexpr: ::core::option::Option<Box<Node>>,
+}
+#[derive(Clone, PartialEq)]
+pub struct LockingClause {
+    pub locked_rels: Vec<Node>,
+
+    pub strength: i32,
+
+    pub wait_policy: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct RowMarkClause {
+    pub rti: u32,
+
+    pub strength: i32,
+
+    pub wait_policy: i32,
+
+    pub pushed_down: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct XmlSerialize {
+    pub xmloption: i32,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub type_name: ::core::option::Option<TypeName>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct WithClause {
+    pub ctes: Vec<Node>,
+
+    pub recursive: bool,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct InferClause {
+    pub index_elems: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub conname: String,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct OnConflictClause {
+    pub action: i32,
+
+    pub infer: ::core::option::Option<Box<InferClause>>,
+
+    pub target_list: Vec<Node>,
+
+    pub where_clause: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct CommonTableExpr {
+    pub ctename: String,
+
+    pub aliascolnames: Vec<Node>,
+
+    pub ctematerialized: i32,
+
+    pub ctequery: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+
+    pub cterecursive: bool,
+
+    pub cterefcount: i32,
+
+    pub ctecolnames: Vec<Node>,
+
+    pub ctecoltypes: Vec<Node>,
+
+    pub ctecoltypmods: Vec<Node>,
+
+    pub ctecolcollations: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct RoleSpec {
+    pub roletype: i32,
+
+    pub rolename: String,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct TriggerTransition {
+    pub name: String,
+
+    pub is_new: bool,
+
+    pub is_table: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionElem {
+    pub name: String,
+
+    pub expr: ::core::option::Option<Box<Node>>,
+
+    pub collation: Vec<Node>,
+
+    pub opclass: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionSpec {
+    pub strategy: String,
+
+    pub part_params: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionBoundSpec {
+    pub strategy: String,
+
+    pub is_default: bool,
+
+    pub modulus: i32,
+
+    pub remainder: i32,
+
+    pub listdatums: Vec<Node>,
+
+    pub lowerdatums: Vec<Node>,
+
+    pub upperdatums: Vec<Node>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionRangeDatum {
+    pub kind: i32,
+
+    pub value: ::core::option::Option<Box<Node>>,
+
+    pub location: i32,
+}
+#[derive(Clone, PartialEq)]
+pub struct PartitionCmd {
+    pub name: ::core::option::Option<RangeVar>,
+
+    pub bound: ::core::option::Option<PartitionBoundSpec>,
+}
+#[derive(Clone, PartialEq)]
+pub struct VacuumRelation {
+    pub relation: ::core::option::Option<RangeVar>,
+
+    pub oid: u32,
+
+    pub va_cols: Vec<Node>,
+}
+#[derive(Clone, PartialEq)]
+pub struct InlineCodeBlock {
+    pub source_text: String,
+
+    pub lang_oid: u32,
+
+    pub lang_is_trusted: bool,
+
+    pub atomic: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct CallContext {
+    pub atomic: bool,
+}
+#[derive(Clone, PartialEq)]
+pub struct ScanToken {
+    pub start: i32,
+
+    pub end: i32,
+
+    pub token: i32,
+
+    pub keyword_kind: i32,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OverridingKind {
+    Undefined = 0,
+    OverridingNotSet = 1,
+    OverridingUserValue = 2,
+    OverridingSystemValue = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum QuerySource {
+    Undefined = 0,
+    QsrcOriginal = 1,
+    QsrcParser = 2,
+    QsrcInsteadRule = 3,
+    QsrcQualInsteadRule = 4,
+    QsrcNonInsteadRule = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SortByDir {
+    Undefined = 0,
+    SortbyDefault = 1,
+    SortbyAsc = 2,
+    SortbyDesc = 3,
+    SortbyUsing = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SortByNulls {
+    Undefined = 0,
+    SortbyNullsDefault = 1,
+    SortbyNullsFirst = 2,
+    SortbyNullsLast = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AExprKind {
+    Undefined = 0,
+    AexprOp = 1,
+    AexprOpAny = 2,
+    AexprOpAll = 3,
+    AexprDistinct = 4,
+    AexprNotDistinct = 5,
+    AexprNullif = 6,
+    AexprOf = 7,
+    AexprIn = 8,
+    AexprLike = 9,
+    AexprIlike = 10,
+    AexprSimilar = 11,
+    AexprBetween = 12,
+    AexprNotBetween = 13,
+    AexprBetweenSym = 14,
+    AexprNotBetweenSym = 15,
+    AexprParen = 16,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RoleSpecType {
+    Undefined = 0,
+    RolespecCstring = 1,
+    RolespecCurrentUser = 2,
+    RolespecSessionUser = 3,
+    RolespecPublic = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum TableLikeOption {
+    Undefined = 0,
+    CreateTableLikeComments = 1,
+    CreateTableLikeConstraints = 2,
+    CreateTableLikeDefaults = 3,
+    CreateTableLikeGenerated = 4,
+    CreateTableLikeIdentity = 5,
+    CreateTableLikeIndexes = 6,
+    CreateTableLikeStatistics = 7,
+    CreateTableLikeStorage = 8,
+    CreateTableLikeAll = 9,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DefElemAction {
+    Undefined = 0,
+    DefelemUnspec = 1,
+    DefelemSet = 2,
+    DefelemAdd = 3,
+    DefelemDrop = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum PartitionRangeDatumKind {
+    Undefined = 0,
+    PartitionRangeDatumMinvalue = 1,
+    PartitionRangeDatumValue = 2,
+    PartitionRangeDatumMaxvalue = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RteKind {
+    RtekindUndefined = 0,
+    RteRelation = 1,
+    RteSubquery = 2,
+    RteJoin = 3,
+    RteFunction = 4,
+    RteTablefunc = 5,
+    RteValues = 6,
+    RteCte = 7,
+    RteNamedtuplestore = 8,
+    RteResult = 9,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum WcoKind {
+    WcokindUndefined = 0,
+    WcoViewCheck = 1,
+    WcoRlsInsertCheck = 2,
+    WcoRlsUpdateCheck = 3,
+    WcoRlsConflictCheck = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum GroupingSetKind {
+    Undefined = 0,
+    GroupingSetEmpty = 1,
+    GroupingSetSimple = 2,
+    GroupingSetRollup = 3,
+    GroupingSetCube = 4,
+    GroupingSetSets = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CteMaterialize {
+    CtematerializeUndefined = 0,
+    Default = 1,
+    Always = 2,
+    Never = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOperation {
+    Undefined = 0,
+    SetopNone = 1,
+    SetopUnion = 2,
+    SetopIntersect = 3,
+    SetopExcept = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ObjectType {
+    Undefined = 0,
+    ObjectAccessMethod = 1,
+    ObjectAggregate = 2,
+    ObjectAmop = 3,
+    ObjectAmproc = 4,
+    ObjectAttribute = 5,
+    ObjectCast = 6,
+    ObjectColumn = 7,
+    ObjectCollation = 8,
+    ObjectConversion = 9,
+    ObjectDatabase = 10,
+    ObjectDefault = 11,
+    ObjectDefacl = 12,
+    ObjectDomain = 13,
+    ObjectDomconstraint = 14,
+    ObjectEventTrigger = 15,
+    ObjectExtension = 16,
+    ObjectFdw = 17,
+    ObjectForeignServer = 18,
+    ObjectForeignTable = 19,
+    ObjectFunction = 20,
+    ObjectIndex = 21,
+    ObjectLanguage = 22,
+    ObjectLargeobject = 23,
+    ObjectMatview = 24,
+    ObjectOpclass = 25,
+    ObjectOperator = 26,
+    ObjectOpfamily = 27,
+    ObjectPolicy = 28,
+    ObjectProcedure = 29,
+    ObjectPublication = 30,
+    ObjectPublicationRel = 31,
+    ObjectRole = 32,
+    ObjectRoutine = 33,
+    ObjectRule = 34,
+    ObjectSchema = 35,
+    ObjectSequence = 36,
+    ObjectSubscription = 37,
+    ObjectStatisticExt = 38,
+    ObjectTabconstraint = 39,
+    ObjectTable = 40,
+    ObjectTablespace = 41,
+    ObjectTransform = 42,
+    ObjectTrigger = 43,
+    ObjectTsconfiguration = 44,
+    ObjectTsdictionary = 45,
+    ObjectTsparser = 46,
+    ObjectTstemplate = 47,
+    ObjectType = 48,
+    ObjectUserMapping = 49,
+    ObjectView = 50,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DropBehavior {
+    Undefined = 0,
+    DropRestrict = 1,
+    DropCascade = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterTableType {
+    Undefined = 0,
+    AtAddColumn = 1,
+    AtAddColumnRecurse = 2,
+    AtAddColumnToView = 3,
+    AtColumnDefault = 4,
+    AtCookedColumnDefault = 5,
+    AtDropNotNull = 6,
+    AtSetNotNull = 7,
+    AtDropExpression = 8,
+    AtCheckNotNull = 9,
+    AtSetStatistics = 10,
+    AtSetOptions = 11,
+    AtResetOptions = 12,
+    AtSetStorage = 13,
+    AtDropColumn = 14,
+    AtDropColumnRecurse = 15,
+    AtAddIndex = 16,
+    AtReAddIndex = 17,
+    AtAddConstraint = 18,
+    AtAddConstraintRecurse = 19,
+    AtReAddConstraint = 20,
+    AtReAddDomainConstraint = 21,
+    AtAlterConstraint = 22,
+    AtValidateConstraint = 23,
+    AtValidateConstraintRecurse = 24,
+    AtAddIndexConstraint = 25,
+    AtDropConstraint = 26,
+    AtDropConstraintRecurse = 27,
+    AtReAddComment = 28,
+    AtAlterColumnType = 29,
+    AtAlterColumnGenericOptions = 30,
+    AtChangeOwner = 31,
+    AtClusterOn = 32,
+    AtDropCluster = 33,
+    AtSetLogged = 34,
+    AtSetUnLogged = 35,
+    AtDropOids = 36,
+    AtSetTableSpace = 37,
+    AtSetRelOptions = 38,
+    AtResetRelOptions = 39,
+    AtReplaceRelOptions = 40,
+    AtEnableTrig = 41,
+    AtEnableAlwaysTrig = 42,
+    AtEnableReplicaTrig = 43,
+    AtDisableTrig = 44,
+    AtEnableTrigAll = 45,
+    AtDisableTrigAll = 46,
+    AtEnableTrigUser = 47,
+    AtDisableTrigUser = 48,
+    AtEnableRule = 49,
+    AtEnableAlwaysRule = 50,
+    AtEnableReplicaRule = 51,
+    AtDisableRule = 52,
+    AtAddInherit = 53,
+    AtDropInherit = 54,
+    AtAddOf = 55,
+    AtDropOf = 56,
+    AtReplicaIdentity = 57,
+    AtEnableRowSecurity = 58,
+    AtDisableRowSecurity = 59,
+    AtForceRowSecurity = 60,
+    AtNoForceRowSecurity = 61,
+    AtGenericOptions = 62,
+    AtAttachPartition = 63,
+    AtDetachPartition = 64,
+    AtAddIdentity = 65,
+    AtSetIdentity = 66,
+    AtDropIdentity = 67,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum GrantTargetType {
+    Undefined = 0,
+    AclTargetObject = 1,
+    AclTargetAllInSchema = 2,
+    AclTargetDefaults = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum VariableSetKind {
+    Undefined = 0,
+    VarSetValue = 1,
+    VarSetDefault = 2,
+    VarSetCurrent = 3,
+    VarSetMulti = 4,
+    VarReset = 5,
+    VarResetAll = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ConstrType {
+    Undefined = 0,
+    ConstrNull = 1,
+    ConstrNotnull = 2,
+    ConstrDefault = 3,
+    ConstrIdentity = 4,
+    ConstrGenerated = 5,
+    ConstrCheck = 6,
+    ConstrPrimary = 7,
+    ConstrUnique = 8,
+    ConstrExclusion = 9,
+    ConstrForeign = 10,
+    ConstrAttrDeferrable = 11,
+    ConstrAttrNotDeferrable = 12,
+    ConstrAttrDeferred = 13,
+    ConstrAttrImmediate = 14,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ImportForeignSchemaType {
+    Undefined = 0,
+    FdwImportSchemaAll = 1,
+    FdwImportSchemaLimitTo = 2,
+    FdwImportSchemaExcept = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RoleStmtType {
+    Undefined = 0,
+    RolestmtRole = 1,
+    RolestmtUser = 2,
+    RolestmtGroup = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum FetchDirection {
+    Undefined = 0,
+    FetchForward = 1,
+    FetchBackward = 2,
+    FetchAbsolute = 3,
+    FetchRelative = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum FunctionParameterMode {
+    Undefined = 0,
+    FuncParamIn = 1,
+    FuncParamOut = 2,
+    FuncParamInout = 3,
+    FuncParamVariadic = 4,
+    FuncParamTable = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum TransactionStmtKind {
+    Undefined = 0,
+    TransStmtBegin = 1,
+    TransStmtStart = 2,
+    TransStmtCommit = 3,
+    TransStmtRollback = 4,
+    TransStmtSavepoint = 5,
+    TransStmtRelease = 6,
+    TransStmtRollbackTo = 7,
+    TransStmtPrepare = 8,
+    TransStmtCommitPrepared = 9,
+    TransStmtRollbackPrepared = 10,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ViewCheckOption {
+    Undefined = 0,
+    NoCheckOption = 1,
+    LocalCheckOption = 2,
+    CascadedCheckOption = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ClusterOption {
+    Undefined = 0,
+    CluoptRecheck = 1,
+    CluoptVerbose = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum DiscardMode {
+    Undefined = 0,
+    DiscardAll = 1,
+    DiscardPlans = 2,
+    DiscardSequences = 3,
+    DiscardTemp = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ReindexObjectType {
+    Undefined = 0,
+    ReindexObjectIndex = 1,
+    ReindexObjectTable = 2,
+    ReindexObjectSchema = 3,
+    ReindexObjectSystem = 4,
+    ReindexObjectDatabase = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterTsConfigType {
+    AlterTsconfigTypeUndefined = 0,
+    AlterTsconfigAddMapping = 1,
+    AlterTsconfigAlterMappingForToken = 2,
+    AlterTsconfigReplaceDict = 3,
+    AlterTsconfigReplaceDictForToken = 4,
+    AlterTsconfigDropMapping = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AlterSubscriptionType {
+    Undefined = 0,
+    AlterSubscriptionOptions = 1,
+    AlterSubscriptionConnection = 2,
+    AlterSubscriptionPublication = 3,
+    AlterSubscriptionRefresh = 4,
+    AlterSubscriptionEnabled = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OnCommitAction {
+    Undefined = 0,
+    OncommitNoop = 1,
+    OncommitPreserveRows = 2,
+    OncommitDeleteRows = 3,
+    OncommitDrop = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum ParamKind {
+    Undefined = 0,
+    ParamExtern = 1,
+    ParamExec = 2,
+    ParamSublink = 3,
+    ParamMultiexpr = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CoercionContext {
+    Undefined = 0,
+    CoercionImplicit = 1,
+    CoercionAssignment = 2,
+    CoercionExplicit = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CoercionForm {
+    Undefined = 0,
+    CoerceExplicitCall = 1,
+    CoerceExplicitCast = 2,
+    CoerceImplicitCast = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum BoolExprType {
+    Undefined = 0,
+    AndExpr = 1,
+    OrExpr = 2,
+    NotExpr = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SubLinkType {
+    Undefined = 0,
+    ExistsSublink = 1,
+    AllSublink = 2,
+    AnySublink = 3,
+    RowcompareSublink = 4,
+    ExprSublink = 5,
+    MultiexprSublink = 6,
+    ArraySublink = 7,
+    CteSublink = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum RowCompareType {
+    Undefined = 0,
+    RowcompareLt = 1,
+    RowcompareLe = 2,
+    RowcompareEq = 3,
+    RowcompareGe = 4,
+    RowcompareGt = 5,
+    RowcompareNe = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum MinMaxOp {
+    Undefined = 0,
+    IsGreatest = 1,
+    IsLeast = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SqlValueFunctionOp {
+    SqlvalueFunctionOpUndefined = 0,
+    SvfopCurrentDate = 1,
+    SvfopCurrentTime = 2,
+    SvfopCurrentTimeN = 3,
+    SvfopCurrentTimestamp = 4,
+    SvfopCurrentTimestampN = 5,
+    SvfopLocaltime = 6,
+    SvfopLocaltimeN = 7,
+    SvfopLocaltimestamp = 8,
+    SvfopLocaltimestampN = 9,
+    SvfopCurrentRole = 10,
+    SvfopCurrentUser = 11,
+    SvfopUser = 12,
+    SvfopSessionUser = 13,
+    SvfopCurrentCatalog = 14,
+    SvfopCurrentSchema = 15,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum XmlExprOp {
+    Undefined = 0,
+    IsXmlconcat = 1,
+    IsXmlelement = 2,
+    IsXmlforest = 3,
+    IsXmlparse = 4,
+    IsXmlpi = 5,
+    IsXmlroot = 6,
+    IsXmlserialize = 7,
+    IsDocument = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum XmlOptionType {
+    Undefined = 0,
+    XmloptionDocument = 1,
+    XmloptionContent = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum NullTestType {
+    Undefined = 0,
+    IsNull = 1,
+    IsNotNull = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum BoolTestType {
+    Undefined = 0,
+    IsTrue = 1,
+    IsNotTrue = 2,
+    IsFalse = 3,
+    IsNotFalse = 4,
+    IsUnknown = 5,
+    IsNotUnknown = 6,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum CmdType {
+    Undefined = 0,
+    CmdUnknown = 1,
+    CmdSelect = 2,
+    CmdUpdate = 3,
+    CmdInsert = 4,
+    CmdDelete = 5,
+    CmdUtility = 6,
+    CmdNothing = 7,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum JoinType {
+    Undefined = 0,
+    JoinInner = 1,
+    JoinLeft = 2,
+    JoinFull = 3,
+    JoinRight = 4,
+    JoinSemi = 5,
+    JoinAnti = 6,
+    JoinUniqueOuter = 7,
+    JoinUniqueInner = 8,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AggStrategy {
+    Undefined = 0,
+    AggPlain = 1,
+    AggSorted = 2,
+    AggHashed = 3,
+    AggMixed = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum AggSplit {
+    Undefined = 0,
+    AggsplitSimple = 1,
+    AggsplitInitialSerial = 2,
+    AggsplitFinalDeserial = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOpCmd {
+    Undefined = 0,
+    SetopcmdIntersect = 1,
+    SetopcmdIntersectAll = 2,
+    SetopcmdExcept = 3,
+    SetopcmdExceptAll = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum SetOpStrategy {
+    Undefined = 0,
+    SetopSorted = 1,
+    SetopHashed = 2,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum OnConflictAction {
+    Undefined = 0,
+    OnconflictNone = 1,
+    OnconflictNothing = 2,
+    OnconflictUpdate = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LimitOption {
+    Undefined = 0,
+    Default = 1,
+    Count = 2,
+    WithTies = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockClauseStrength {
+    Undefined = 0,
+    LcsNone = 1,
+    LcsForkeyshare = 2,
+    LcsForshare = 3,
+    LcsFornokeyupdate = 4,
+    LcsForupdate = 5,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockWaitPolicy {
+    Undefined = 0,
+    LockWaitBlock = 1,
+    LockWaitSkip = 2,
+    LockWaitError = 3,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum LockTupleMode {
+    Undefined = 0,
+    LockTupleKeyShare = 1,
+    LockTupleShare = 2,
+    LockTupleNoKeyExclusive = 3,
+    LockTupleExclusive = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum KeywordKind {
+    NoKeyword = 0,
+    UnreservedKeyword = 1,
+    ColNameKeyword = 2,
+    TypeFuncNameKeyword = 3,
+    ReservedKeyword = 4,
+}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[repr(i32)]
+pub enum Token {
+    Nul = 0,
+    /// Single-character tokens that are returned 1:1 (identical with "self" list in scan.l)
+    /// Either supporting syntax, or single-character operators (some can be both)
+    /// Also see <https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-SPECIAL-CHARS>
+    ///
+    /// "%"
+    Ascii37 = 37,
+    /// "("
+    Ascii40 = 40,
+    /// ")"
+    Ascii41 = 41,
+    /// "*"
+    Ascii42 = 42,
+    /// "+"
+    Ascii43 = 43,
+    /// ","
+    Ascii44 = 44,
+    /// "-"
+    Ascii45 = 45,
+    /// "."
+    Ascii46 = 46,
+    /// "/"
+    Ascii47 = 47,
+    /// ":"
+    Ascii58 = 58,
+    /// ";"
+    Ascii59 = 59,
+    /// "<"
+    Ascii60 = 60,
+    /// "="
+    Ascii61 = 61,
+    /// ">"
+    Ascii62 = 62,
+    /// "?"
+    Ascii63 = 63,
+    /// "["
+    Ascii91 = 91,
+    /// "\"
+    Ascii92 = 92,
+    /// "]"
+    Ascii93 = 93,
+    /// "^"
+    Ascii94 = 94,
+    /// Named tokens in scan.l
+    Ident = 258,
+    Uident = 259,
+    Fconst = 260,
+    Sconst = 261,
+    Usconst = 262,
+    Bconst = 263,
+    Xconst = 264,
+    Op = 265,
+    Iconst = 266,
+    Param = 267,
+    Typecast = 268,
+    DotDot = 269,
+    ColonEquals = 270,
+    EqualsGreater = 271,
+    LessEquals = 272,
+    GreaterEquals = 273,
+    NotEquals = 274,
+    SqlComment = 275,
+    CComment = 276,
+    AbortP = 277,
+    AbsoluteP = 278,
+    Access = 279,
+    Action = 280,
+    AddP = 281,
+    Admin = 282,
+    After = 283,
+    Aggregate = 284,
+    All = 285,
+    Also = 286,
+    Alter = 287,
+    Always = 288,
+    Analyse = 289,
+    Analyze = 290,
+    And = 291,
+    Any = 292,
+    Array = 293,
+    As = 294,
+    Asc = 295,
+    Assertion = 296,
+    Assignment = 297,
+    Asymmetric = 298,
+    At = 299,
+    Attach = 300,
+    Attribute = 301,
+    Authorization = 302,
+    Backward = 303,
+    Before = 304,
+    BeginP = 305,
+    Between = 306,
+    Bigint = 307,
+    Binary = 308,
+    Bit = 309,
+    BooleanP = 310,
+    Both = 311,
+    By = 312,
+    Cache = 313,
+    Call = 314,
+    Called = 315,
+    Cascade = 316,
+    Cascaded = 317,
+    Case = 318,
+    Cast = 319,
+    CatalogP = 320,
+    Chain = 321,
+    CharP = 322,
+    Character = 323,
+    Characteristics = 324,
+    Check = 325,
+    Checkpoint = 326,
+    Class = 327,
+    Close = 328,
+    Cluster = 329,
+    Coalesce = 330,
+    Collate = 331,
+    Collation = 332,
+    Column = 333,
+    Columns = 334,
+    Comment = 335,
+    Comments = 336,
+    Commit = 337,
+    Committed = 338,
+    Concurrently = 339,
+    Configuration = 340,
+    Conflict = 341,
+    Connection = 342,
+    Constraint = 343,
+    Constraints = 344,
+    ContentP = 345,
+    ContinueP = 346,
+    ConversionP = 347,
+    Copy = 348,
+    Cost = 349,
+    Create = 350,
+    Cross = 351,
+    Csv = 352,
+    Cube = 353,
+    CurrentP = 354,
+    CurrentCatalog = 355,
+    CurrentDate = 356,
+    CurrentRole = 357,
+    CurrentSchema = 358,
+    CurrentTime = 359,
+    CurrentTimestamp = 360,
+    CurrentUser = 361,
+    Cursor = 362,
+    Cycle = 363,
+    DataP = 364,
+    Database = 365,
+    DayP = 366,
+    Deallocate = 367,
+    Dec = 368,
+    DecimalP = 369,
+    Declare = 370,
+    Default = 371,
+    Defaults = 372,
+    Deferrable = 373,
+    Deferred = 374,
+    Definer = 375,
+    DeleteP = 376,
+    Delimiter = 377,
+    Delimiters = 378,
+    Depends = 379,
+    Desc = 380,
+    Detach = 381,
+    Dictionary = 382,
+    DisableP = 383,
+    Discard = 384,
+    Distinct = 385,
+    Do = 386,
+    DocumentP = 387,
+    DomainP = 388,
+    DoubleP = 389,
+    Drop = 390,
+    Each = 391,
+    Else = 392,
+    EnableP = 393,
+    Encoding = 394,
+    Encrypted = 395,
+    EndP = 396,
+    EnumP = 397,
+    Escape = 398,
+    Event = 399,
+    Except = 400,
+    Exclude = 401,
+    Excluding = 402,
+    Exclusive = 403,
+    Execute = 404,
+    Exists = 405,
+    Explain = 406,
+    Expression = 407,
+    Extension = 408,
+    External = 409,
+    Extract = 410,
+    FalseP = 411,
+    Family = 412,
+    Fetch = 413,
+    Filter = 414,
+    FirstP = 415,
+    FloatP = 416,
+    Following = 417,
+    For = 418,
+    Force = 419,
+    Foreign = 420,
+    Forward = 421,
+    Freeze = 422,
+    From = 423,
+    Full = 424,
+    Function = 425,
+    Functions = 426,
+    Generated = 427,
+    Global = 428,
+    Grant = 429,
+    Granted = 430,
+    Greatest = 431,
+    GroupP = 432,
+    Grouping = 433,
+    Groups = 434,
+    Handler = 435,
+    Having = 436,
+    HeaderP = 437,
+    Hold = 438,
+    HourP = 439,
+    IdentityP = 440,
+    IfP = 441,
+    Ilike = 442,
+    Immediate = 443,
+    Immutable = 444,
+    ImplicitP = 445,
+    ImportP = 446,
+    InP = 447,
+    Include = 448,
+    Including = 449,
+    Increment = 450,
+    Index = 451,
+    Indexes = 452,
+    Inherit = 453,
+    Inherits = 454,
+    Initially = 455,
+    InlineP = 456,
+    InnerP = 457,
+    Inout = 458,
+    InputP = 459,
+    Insensitive = 460,
+    Insert = 461,
+    Instead = 462,
+    IntP = 463,
+    Integer = 464,
+    Intersect = 465,
+    Interval = 466,
+    Into = 467,
+    Invoker = 468,
+    Is = 469,
+    Isnull = 470,
+    Isolation = 471,
+    Join = 472,
+    Key = 473,
+    Label = 474,
+    Language = 475,
+    LargeP = 476,
+    LastP = 477,
+    LateralP = 478,
+    Leading = 479,
+    Leakproof = 480,
+    Least = 481,
+    Left = 482,
+    Level = 483,
+    Like = 484,
+    Limit = 485,
+    Listen = 486,
+    Load = 487,
+    Local = 488,
+    Localtime = 489,
+    Localtimestamp = 490,
+    Location = 491,
+    LockP = 492,
+    Locked = 493,
+    Logged = 494,
+    Mapping = 495,
+    Match = 496,
+    Materialized = 497,
+    Maxvalue = 498,
+    Method = 499,
+    MinuteP = 500,
+    Minvalue = 501,
+    Mode = 502,
+    MonthP = 503,
+    Move = 504,
+    NameP = 505,
+    Names = 506,
+    National = 507,
+    Natural = 508,
+    Nchar = 509,
+    New = 510,
+    Next = 511,
+    Nfc = 512,
+    Nfd = 513,
+    Nfkc = 514,
+    Nfkd = 515,
+    No = 516,
+    None = 517,
+    Normalize = 518,
+    Normalized = 519,
+    Not = 520,
+    Nothing = 521,
+    Notify = 522,
+    Notnull = 523,
+    Nowait = 524,
+    NullP = 525,
+    Nullif = 526,
+    NullsP = 527,
+    Numeric = 528,
+    ObjectP = 529,
+    Of = 530,
+    Off = 531,
+    Offset = 532,
+    Oids = 533,
+    Old = 534,
+    On = 535,
+    Only = 536,
+    Operator = 537,
+    Option = 538,
+    Options = 539,
+    Or = 540,
+    Order = 541,
+    Ordinality = 542,
+    Others = 543,
+    OutP = 544,
+    OuterP = 545,
+    Over = 546,
+    Overlaps = 547,
+    Overlay = 548,
+    Overriding = 549,
+    Owned = 550,
+    Owner = 551,
+    Parallel = 552,
+    Parser = 553,
+    Partial = 554,
+    Partition = 555,
+    Passing = 556,
+    Password = 557,
+    Placing = 558,
+    Plans = 559,
+    Policy = 560,
+    Position = 561,
+    Preceding = 562,
+    Precision = 563,
+    Preserve = 564,
+    Prepare = 565,
+    Prepared = 566,
+    Primary = 567,
+    Prior = 568,
+    Privileges = 569,
+    Procedural = 570,
+    Procedure = 571,
+    Procedures = 572,
+    Program = 573,
+    Publication = 574,
+    Quote = 575,
+    Range = 576,
+    Read = 577,
+    Real = 578,
+    Reassign = 579,
+    Recheck = 580,
+    Recursive = 581,
+    Ref = 582,
+    References = 583,
+    Referencing = 584,
+    Refresh = 585,
+    Reindex = 586,
+    RelativeP = 587,
+    Release = 588,
+    Rename = 589,
+    Repeatable = 590,
+    Replace = 591,
+    Replica = 592,
+    Reset = 593,
+    Restart = 594,
+    Restrict = 595,
+    Returning = 596,
+    Returns = 597,
+    Revoke = 598,
+    Right = 599,
+    Role = 600,
+    Rollback = 601,
+    Rollup = 602,
+    Routine = 603,
+    Routines = 604,
+    Row = 605,
+    Rows = 606,
+    Rule = 607,
+    Savepoint = 608,
+    Schema = 609,
+    Schemas = 610,
+    Scroll = 611,
+    Search = 612,
+    SecondP = 613,
+    Security = 614,
+    Select = 615,
+    Sequence = 616,
+    Sequences = 617,
+    Serializable = 618,
+    Server = 619,
+    Session = 620,
+    SessionUser = 621,
+    Set = 622,
+    Sets = 623,
+    Setof = 624,
+    Share = 625,
+    Show = 626,
+    Similar = 627,
+    Simple = 628,
+    Skip = 629,
+    Smallint = 630,
+    Snapshot = 631,
+    Some = 632,
+    SqlP = 633,
+    Stable = 634,
+    StandaloneP = 635,
+    Start = 636,
+    Statement = 637,
+    Statistics = 638,
+    Stdin = 639,
+    Stdout = 640,
+    Storage = 641,
+    Stored = 642,
+    StrictP = 643,
+    StripP = 644,
+    Subscription = 645,
+    Substring = 646,
+    Support = 647,
+    Symmetric = 648,
+    Sysid = 649,
+    SystemP = 650,
+    Table = 651,
+    Tables = 652,
+    Tablesample = 653,
+    Tablespace = 654,
+    Temp = 655,
+    Template = 656,
+    Temporary = 657,
+    TextP = 658,
+    Then = 659,
+    Ties = 660,
+    Time = 661,
+    Timestamp = 662,
+    To = 663,
+    Trailing = 664,
+    Transaction = 665,
+    Transform = 666,
+    Treat = 667,
+    Trigger = 668,
+    Trim = 669,
+    TrueP = 670,
+    Truncate = 671,
+    Trusted = 672,
+    TypeP = 673,
+    TypesP = 674,
+    Uescape = 675,
+    Unbounded = 676,
+    Uncommitted = 677,
+    Unencrypted = 678,
+    Union = 679,
+    Unique = 680,
+    Unknown = 681,
+    Unlisten = 682,
+    Unlogged = 683,
+    Until = 684,
+    Update = 685,
+    User = 686,
+    Using = 687,
+    Vacuum = 688,
+    Valid = 689,
+    Validate = 690,
+    Validator = 691,
+    ValueP = 692,
+    Values = 693,
+    Varchar = 694,
+    Variadic = 695,
+    Varying = 696,
+    Verbose = 697,
+    VersionP = 698,
+    View = 699,
+    Views = 700,
+    Volatile = 701,
+    When = 702,
+    Where = 703,
+    WhitespaceP = 704,
+    Window = 705,
+    With = 706,
+    Within = 707,
+    Without = 708,
+    Work = 709,
+    Wrapper = 710,
+    Write = 711,
+    XmlP = 712,
+    Xmlattributes = 713,
+    Xmlconcat = 714,
+    Xmlelement = 715,
+    Xmlexists = 716,
+    Xmlforest = 717,
+    Xmlnamespaces = 718,
+    Xmlparse = 719,
+    Xmlpi = 720,
+    Xmlroot = 721,
+    Xmlserialize = 722,
+    Xmltable = 723,
+    YearP = 724,
+    YesP = 725,
+    Zone = 726,
+    NotLa = 727,
+    NullsLa = 728,
+    WithLa = 729,
+    Postfixop = 730,
+    Uminus = 731,
+}
diff --git a/src/tools/rustfmt/tests/target/struct_field_doc_comment.rs b/src/tools/rustfmt/tests/target/struct_field_doc_comment.rs
new file mode 100644
index 00000000000..ebb01a668f4
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/struct_field_doc_comment.rs
@@ -0,0 +1,69 @@
+// #5215
+struct MyTuple(
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    u32,
+    /// Doc Comments
+    // TODO note
+    u64,
+);
+
+struct MyTuple(
+    #[cfg(unix)] // some comment
+    u64,
+    #[cfg(not(unix))] /*block comment */ u32,
+);
+
+struct MyTuple(
+    #[cfg(unix)]
+    // some comment
+    u64,
+    #[cfg(not(unix))]
+    /*block comment */
+    u32,
+);
+
+struct MyTuple(
+    #[cfg(unix)] // some comment
+    pub  u64,
+    #[cfg(not(unix))] /*block comment */ pub(crate)  u32,
+);
+
+struct MyTuple(
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    pub  u32,
+    /// Doc Comments
+    // TODO note
+    pub(crate)  u64,
+);
+
+struct MyStruct {
+    #[cfg(unix)] // some comment
+    a: u64,
+    #[cfg(not(unix))] /*block comment */ b: u32,
+}
+
+struct MyStruct {
+    #[cfg(unix)] // some comment
+    pub a: u64,
+    #[cfg(not(unix))] /*block comment */ pub(crate) b: u32,
+}
+
+struct MyStruct {
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    a: u32,
+    /// Doc Comments
+    // TODO note
+    b: u64,
+}
+
+struct MyStruct {
+    /// Doc Comments
+    /* TODO note to add more to Doc Comments */
+    pub a: u32,
+    /// Doc Comments
+    // TODO note
+    pub(crate) b: u64,
+}
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 135a12b5571..f59121181d2 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -7,8 +7,8 @@ use std::path::Path;
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 969;
-const ISSUES_ENTRY_LIMIT: usize = 2211;
+const ROOT_ENTRY_LIMIT: usize = 968;
+const ISSUES_ENTRY_LIMIT: usize = 2179;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))