about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--Cargo.lock8
-rw-r--r--RELEASES.md91
-rw-r--r--compiler/rustc_abi/src/lib.rs10
-rw-r--r--compiler/rustc_apfloat/src/ieee.rs1
-rw-r--r--compiler/rustc_arena/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/ast.rs33
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs18
-rw-r--r--compiler/rustc_ast/src/ptr.rs1
-rw-r--r--compiler/rustc_ast/src/token.rs2
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs2
-rw-r--r--compiler/rustc_ast/src/util/literal.rs142
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs87
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs7
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs24
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs100
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs27
-rw-r--r--compiler/rustc_builtin_macros/src/alloc_error_handler.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/concat.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/concat_bytes.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/.cirrus.yml2
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/main.yml52
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml2
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml16
-rw-r--r--compiler/rustc_codegen_cranelift/.gitignore1
-rw-r--r--compiler/rustc_codegen_cranelift/.vscode/settings.json35
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock125
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml20
-rw-r--r--compiler/rustc_codegen_cranelift/Readme.md2
-rw-r--r--compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock57
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_backend.rs13
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs98
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/mod.rs91
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/path.rs70
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/prepare.rs154
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/rustc_info.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs553
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/utils.rs145
-rwxr-xr-xcompiler/rustc_codegen_cranelift/clean_all.sh2
-rw-r--r--compiler/rustc_codegen_cranelift/config.txt1
-rw-r--r--compiler/rustc_codegen_cranelift/docs/usage.md12
-rw-r--r--compiler/rustc_codegen_cranelift/example/issue-72793.rs24
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/rustfmt.toml2
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/filter_profile.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs36
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh22
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh14
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs36
-rw-r--r--compiler/rustc_codegen_cranelift/src/allocator.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/src/cast.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs11
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs82
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/discriminant.rs207
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/mod.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs176
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs222
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs197
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs96
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/num.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/optimize/peephole.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs15
-rwxr-xr-xcompiler/rustc_codegen_cranelift/test.sh2
-rwxr-xr-xcompiler/rustc_codegen_cranelift/y.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs70
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs688
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs51
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs164
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs135
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs16
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs59
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs13
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs64
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs9
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs8
-rw-r--r--compiler/rustc_const_eval/src/util/aggregate.rs1
-rw-r--r--compiler/rustc_const_eval/src/util/call_kind.rs18
-rw-r--r--compiler/rustc_const_eval/src/util/might_permit_raw_init.rs4
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs3
-rw-r--r--compiler/rustc_data_structures/src/base_n.rs2
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs1
-rw-r--r--compiler/rustc_data_structures/src/graph/scc/mod.rs1
-rw-r--r--compiler/rustc_data_structures/src/graph/vec_graph/mod.rs2
-rw-r--r--compiler/rustc_data_structures/src/owning_ref/mod.rs5
-rw-r--r--compiler/rustc_data_structures/src/owning_ref/tests.rs4
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs1
-rw-r--r--compiler/rustc_data_structures/src/sorted_map.rs9
-rw-r--r--compiler/rustc_data_structures/src/sorted_map/index_map.rs1
-rw-r--r--compiler/rustc_data_structures/src/sso/either_iter.rs2
-rw-r--r--compiler/rustc_data_structures/src/sso/map.rs1
-rw-r--r--compiler/rustc_data_structures/src/sso/set.rs1
-rw-r--r--compiler/rustc_data_structures/src/sync.rs2
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/drop.rs2
-rw-r--r--compiler/rustc_data_structures/src/vec_map.rs1
-rw-r--r--compiler/rustc_driver/src/lib.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0492.md1
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl2
-rw-r--r--compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl6
-rw-r--r--compiler/rustc_error_messages/locales/en-US/monomorphize.ftl3
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs8
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs2
-rw-r--r--compiler/rustc_errors/src/emitter.rs85
-rw-r--r--compiler/rustc_errors/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/base.rs3
-rw-r--r--compiler/rustc_expand/src/build.rs43
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs3
-rw-r--r--compiler/rustc_hir/src/hir.rs7
-rw-r--r--compiler/rustc_hir/src/pat_util.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs53
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs815
-rw-r--r--compiler/rustc_hir_analysis/src/collect/lifetimes.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs19
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs14
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs21
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs26
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs43
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs113
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs58
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs2
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs2
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs7
-rw-r--r--compiler/rustc_index/src/bit_set.rs2
-rw-r--r--compiler/rustc_index/src/vec.rs1
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/at.rs6
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs5
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs2
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs15
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs24
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs109
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs10
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs14
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs5
-rw-r--r--compiler/rustc_infer/src/infer/glb.rs5
-rw-r--r--compiler/rustc_infer/src/infer/lattice.rs12
-rw-r--r--compiler/rustc_infer/src/infer/lub.rs5
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs53
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs40
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs38
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs6
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs10
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs2
-rw-r--r--compiler/rustc_infer/src/infer/projection.rs4
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs15
-rw-r--r--compiler/rustc_infer/src/traits/project.rs4
-rw-r--r--compiler/rustc_infer/src/traits/util.rs3
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lexer/src/lib.rs1
-rw-r--r--compiler/rustc_lexer/src/unescape.rs3
-rw-r--r--compiler/rustc_lint/src/builtin.rs4
-rw-r--r--compiler/rustc_lint/src/context.rs2
-rw-r--r--compiler/rustc_lint/src/early.rs149
-rw-r--r--compiler/rustc_lint/src/late.rs89
-rw-r--r--compiler/rustc_lint/src/lib.rs6
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs6
-rw-r--r--compiler/rustc_lint/src/passes.rs10
-rw-r--r--compiler/rustc_lint/src/types.rs13
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs69
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp12
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic.rs2
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs47
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs16
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs20
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs1
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs1
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs8
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs9
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs2
-rw-r--r--compiler/rustc_middle/src/traits/query.rs6
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs1
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs765
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs21
-rw-r--r--compiler/rustc_middle/src/ty/error.rs92
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs68
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs6
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs30
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs17
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs7
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs40
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs42
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs9
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs113
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs45
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs6
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs117
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs2
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs689
-rw-r--r--compiler/rustc_middle/src/ty/util.rs32
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs2
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs1
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/custom/mod.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs114
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/stmt.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs34
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/drop_flag_effects.rs97
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs8
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/lattice.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs13
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs37
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs18
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs12
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs171
-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/normalize_array_len.rs3
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs6
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs12
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs1
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs14
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs6
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs78
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs1
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs1
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs1
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs50
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs75
-rw-r--r--compiler/rustc_parse/src/parser/item.rs13
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs22
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs4
-rw-r--r--compiler/rustc_privacy/src/lib.rs51
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs1
-rw-r--r--compiler/rustc_query_system/src/error.rs2
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs1
-rw-r--r--compiler/rustc_query_system/src/query/job.rs6
-rw-r--r--compiler/rustc_resolve/src/late.rs8
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs16
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_serialize/src/opaque.rs1
-rw-r--r--compiler/rustc_session/src/config.rs14
-rw-r--r--compiler/rustc_session/src/errors.rs35
-rw-r--r--compiler/rustc_session/src/filesearch.rs1
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_span/src/analyze_source_file.rs4
-rw-r--r--compiler/rustc_span/src/lib.rs9
-rw-r--r--compiler/rustc_span/src/source_map.rs22
-rw-r--r--compiler/rustc_span/src/symbol.rs6
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs9
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs12
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs5
-rw-r--r--compiler/rustc_target/src/lib.rs1
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs2
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs79
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs74
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs242
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs635
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs30
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs91
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/relationships.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs48
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs7
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs63
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs4
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs8
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs32
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs2
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/sty.rs119
-rw-r--r--library/core/src/borrow.rs2
-rw-r--r--library/core/src/intrinsics/mir.rs262
-rw-r--r--library/core/src/iter/traits/iterator.rs1
-rw-r--r--library/core/src/option.rs44
-rw-r--r--library/core/src/ptr/const_ptr.rs4
-rw-r--r--library/core/src/ptr/mut_ptr.rs4
-rw-r--r--library/core/src/result.rs7
-rw-r--r--library/core/src/sync/exclusive.rs4
-rw-r--r--library/proc_macro/src/lib.rs2
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/env.rs9
-rw-r--r--library/std/src/sys/unix/fs.rs7
-rw-r--r--library/std/src/sys/unix/kernel_copy.rs6
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs93
-rw-r--r--library/std/src/sys/unix/mod.rs12
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs7
-rw-r--r--library/std/src/sys/unix/stack_overflow.rs7
-rw-r--r--library/std/src/sys/unix/thread.rs7
-rw-r--r--library/std/src/sys/unix/thread_parker/pthread.rs4
-rw-r--r--library/std/src/sys/unix/time.rs3
-rw-r--r--src/bootstrap/cache.rs8
-rw-r--r--src/bootstrap/dist.rs56
-rw-r--r--src/bootstrap/tool.rs10
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py2
-rw-r--r--src/ci/github-actions/ci.yml1
-rw-r--r--src/doc/rustc/src/command-line-arguments.md3
-rw-r--r--src/doc/rustc/src/exploit-mitigations.md12
-rw-r--r--src/doc/rustc/src/linker-plugin-lto.md2
-rw-r--r--src/doc/rustc/src/platform-support/android.md2
-rw-r--r--src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md2
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md4
-rw-r--r--src/doc/rustc/src/targets/custom.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/branch-protection.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/control-flow-guard.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md6
-rw-r--r--src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md2
-rw-r--r--src/doc/unstable-book/src/language-features/auto-traits.md4
-rw-r--r--src/doc/unstable-book/src/language-features/unboxed-closures.md2
-rw-r--r--src/doc/unstable-book/src/library-features/default-free-fn.md2
-rw-r--r--src/doc/unstable-book/src/library-features/fn-traits.md2
-rw-r--r--src/librustdoc/clean/auto_trait.rs4
-rw-r--r--src/librustdoc/clean/blanket_impl.rs6
-rw-r--r--src/librustdoc/clean/cfg/tests.rs20
-rw-r--r--src/librustdoc/clean/inline.rs13
-rw-r--r--src/librustdoc/clean/mod.rs213
-rw-r--r--src/librustdoc/clean/types.rs18
-rw-r--r--src/librustdoc/clean/utils.rs33
-rw-r--r--src/librustdoc/formats/item_type.rs3
-rw-r--r--src/librustdoc/html/highlight.rs46
-rw-r--r--src/librustdoc/html/markdown.rs13
-rw-r--r--src/librustdoc/html/markdown/tests.rs45
-rw-r--r--src/librustdoc/html/render/context.rs2
-rw-r--r--src/librustdoc/html/render/mod.rs3
-rw-r--r--src/librustdoc/html/render/print_item.rs3
-rw-r--r--src/librustdoc/html/sources.rs2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css21
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css6
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css7
-rw-r--r--src/librustdoc/html/static/css/themes/light.css7
-rw-r--r--src/librustdoc/html/static/js/main.js1
-rw-r--r--src/librustdoc/markdown.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs3
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs6
-rw-r--r--src/test/codegen/avr/avr-func-addrspace.rs24
-rw-r--r--src/test/codegen/pgo-counter-bias.rs10
-rw-r--r--src/test/incremental/hashes/loop_expressions.rs4
-rw-r--r--src/test/incremental/hashes/while_let_loops.rs8
-rw-r--r--src/test/incremental/hashes/while_loops.rs8
-rw-r--r--src/test/mir-opt/building/custom/enums.rs120
-rw-r--r--src/test/mir-opt/building/custom/enums.set_discr.built.after.mir10
-rw-r--r--src/test/mir-opt/building/custom/enums.set_discr_repr.built.after.mir10
-rw-r--r--src/test/mir-opt/building/custom/enums.switch_bool.built.after.mir19
-rw-r--r--src/test/mir-opt/building/custom/enums.switch_option.built.after.mir21
-rw-r--r--src/test/mir-opt/building/custom/enums.switch_option_repr.built.after.mir21
-rw-r--r--src/test/mir-opt/building/custom/projections.rs85
-rw-r--r--src/test/mir-opt/building/custom/projections.set.built.after.mir10
-rw-r--r--src/test/mir-opt/building/custom/projections.simple_index.built.after.mir13
-rw-r--r--src/test/mir-opt/building/custom/projections.tuples.built.after.mir13
-rw-r--r--src/test/mir-opt/building/custom/projections.unions.built.after.mir10
-rw-r--r--src/test/mir-opt/building/custom/projections.unwrap.built.after.mir10
-rw-r--r--src/test/mir-opt/building/custom/projections.unwrap_deref.built.after.mir10
-rw-r--r--src/test/mir-opt/building/custom/references.raw_pointer.built.after.mir10
-rw-r--r--src/test/mir-opt/building/custom/references.rs14
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff7
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff7
-rw-r--r--src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff12
-rw-r--r--src/test/mir-opt/lower_array_len_e2e.rs2
-rw-r--r--src/test/rustdoc-gui/docblock-big-code-mobile.goml4
-rw-r--r--src/test/rustdoc-gui/docblock-code-block-line-number.goml2
-rw-r--r--src/test/rustdoc-gui/help-page.goml1
-rw-r--r--src/test/rustdoc-gui/impl-doc.goml9
-rw-r--r--src/test/rustdoc-gui/src/test_docs/lib.rs13
-rw-r--r--src/test/rustdoc-ui/unable-fulfill-trait.rs13
-rw-r--r--src/test/rustdoc-ui/unable-fulfill-trait.stderr26
-rw-r--r--src/test/rustdoc-ui/z-help.stdout1
-rw-r--r--src/test/rustdoc/toggle-trait-fn.rs7
-rw-r--r--src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs3
-rw-r--r--src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr28
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs6
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr51
-rw-r--r--src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr3
-rw-r--r--src/test/ui/anonymous-higher-ranked-lifetime.stderr52
-rw-r--r--src/test/ui/argument-suggestions/display-is-suggestable.rs8
-rw-r--r--src/test/ui/argument-suggestions/display-is-suggestable.stderr19
-rw-r--r--src/test/ui/array-slice-vec/infer_array_len.stderr4
-rw-r--r--src/test/ui/associated-item/issue-105449.rs59
-rw-r--r--src/test/ui/associated-type-bounds/const-projection-err.gce.stderr24
-rw-r--r--src/test/ui/associated-type-bounds/const-projection-err.rs18
-rw-r--r--src/test/ui/associated-type-bounds/const-projection-err.stock.stderr17
-rw-r--r--src/test/ui/associated-type-bounds/issue-99828.stderr3
-rw-r--r--src/test/ui/associated-types/associated-types-overridden-binding-2.rs2
-rw-r--r--src/test/ui/associated-types/associated-types-overridden-binding-2.stderr2
-rw-r--r--src/test/ui/associated-types/associated-types-unconstrained.stderr5
-rw-r--r--src/test/ui/associated-types/defaults-wf.stderr3
-rw-r--r--src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr3
-rw-r--r--src/test/ui/async-await/async-await-let-else.drop-tracking.stderr10
-rw-r--r--src/test/ui/async-await/async-await-let-else.no-drop-tracking.stderr10
-rw-r--r--src/test/ui/async-await/generator-desc.stderr3
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs7
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr11
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-extra.rs37
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-manual.rs29
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr11
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared.rs5
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err.rs2
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err.stderr18
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err2.rs4
-rw-r--r--src/test/ui/async-await/in-trait/issue-104678.rs31
-rw-r--r--src/test/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr10
-rw-r--r--src/test/ui/async-await/issue-72442.stderr3
-rw-r--r--src/test/ui/async-await/issues/issue-65159.stderr5
-rw-r--r--src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr10
-rw-r--r--src/test/ui/async-await/issues/issue-67893.stderr10
-rw-r--r--src/test/ui/async-await/pin-needed-to-poll-2.stderr3
-rw-r--r--src/test/ui/async-await/pin-needed-to-poll.stderr6
-rw-r--r--src/test/ui/async-await/track-caller/async-block.rs9
-rw-r--r--src/test/ui/async-await/track-caller/async-block.stderr12
-rw-r--r--src/test/ui/async-await/track-caller/async-closure-gate.rs10
-rw-r--r--src/test/ui/async-await/track-caller/async-closure-gate.stderr25
-rw-r--r--src/test/ui/async-await/track-caller/panic-track-caller.rs10
-rw-r--r--src/test/ui/binop/binop-consume-args.stderr30
-rw-r--r--src/test/ui/binop/binop-move-semantics.stderr6
-rw-r--r--src/test/ui/binop/issue-28837.stderr45
-rw-r--r--src/test/ui/binop/issue-3820.stderr5
-rw-r--r--src/test/ui/borrowck/access-mode-in-closures.stderr13
-rw-r--r--src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr45
-rw-r--r--src/test/ui/borrowck/borrowck-issue-2657-2.fixed12
-rw-r--r--src/test/ui/borrowck/borrowck-issue-2657-2.rs1
-rw-r--r--src/test/ui/borrowck/borrowck-issue-2657-2.stderr13
-rw-r--r--src/test/ui/borrowck/borrowck-move-error-with-note.fixed56
-rw-r--r--src/test/ui/borrowck/borrowck-move-error-with-note.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-error-with-note.stderr28
-rw-r--r--src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr11
-rw-r--r--src/test/ui/borrowck/borrowck-move-in-irrefut-pat.stderr41
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr11
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed24
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr21
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed24
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr21
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr6
-rw-r--r--src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr10
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs6
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr50
-rw-r--r--src/test/ui/borrowck/issue-104639-lifetime-order.rs10
-rw-r--r--src/test/ui/borrowck/issue-17718-static-move.stderr10
-rw-r--r--src/test/ui/borrowck/issue-20801.stderr44
-rw-r--r--src/test/ui/borrowck/issue-29166.rs (renamed from src/test/ui/issues/issue-29166.rs)0
-rw-r--r--src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr10
-rw-r--r--src/test/ui/borrowck/issue-51301.rs (renamed from src/test/ui/issues/issue-51301.rs)0
-rw-r--r--src/test/ui/borrowck/issue-51301.stderr (renamed from src/test/ui/issues/issue-51301.stderr)5
-rw-r--r--src/test/ui/borrowck/issue-51415.fixed12
-rw-r--r--src/test/ui/borrowck/issue-51415.rs1
-rw-r--r--src/test/ui/borrowck/issue-51415.stderr7
-rw-r--r--src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr11
-rw-r--r--src/test/ui/borrowck/issue-83760.stderr10
-rw-r--r--src/test/ui/borrowck/issue-87456-point-to-closure.stderr10
-rw-r--r--src/test/ui/borrowck/move-error-snippets.stderr9
-rw-r--r--src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr5
-rw-r--r--src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr5
-rw-r--r--src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr5
-rw-r--r--src/test/ui/box/into-boxed-slice-fail.stderr6
-rw-r--r--src/test/ui/by-move-pattern-binding.rs7
-rw-r--r--src/test/ui/by-move-pattern-binding.stderr47
-rw-r--r--src/test/ui/c-variadic/issue-86053-1.stderr6
-rw-r--r--src/test/ui/chalkify/bugs/async.stderr6
-rw-r--r--src/test/ui/check-static-values-constraints.stderr10
-rw-r--r--src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr4
-rw-r--r--src/test/ui/closures/closure-expected.stderr3
-rw-r--r--src/test/ui/closures/closure-move-sync.stderr6
-rw-r--r--src/test/ui/closures/closure-return-type-must-be-sized.stderr6
-rw-r--r--src/test/ui/closures/coerce-unsafe-to-closure.stderr3
-rw-r--r--src/test/ui/closures/issue-52437.stderr4
-rw-r--r--src/test/ui/closures/issue-78720.stderr6
-rw-r--r--src/test/ui/closures/issue-87461.stderr9
-rw-r--r--src/test/ui/closures/issue-90871.stderr6
-rw-r--r--src/test/ui/closures/multiple-fn-bounds.stderr6
-rw-r--r--src/test/ui/codemap_tests/tab_3.stderr5
-rw-r--r--src/test/ui/confuse-field-and-method/issue-33784.stderr4
-rw-r--r--src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr9
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr24
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-105608.rs15
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr14
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr24
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr18
-rw-r--r--src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr5
-rw-r--r--src/test/ui/const-generics/invalid-constant-in-args.stderr6
-rw-r--r--src/test/ui/const-generics/issue-105689.rs14
-rw-r--r--src/test/ui/const-generics/issues/issue-83249.stderr4
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.32bit.stderr120
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.64bit.stderr120
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.rs11
-rw-r--r--src/test/ui/const-ptr/out_of_bounds_read.stderr24
-rw-r--r--src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr67
-rw-r--r--src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr67
-rw-r--r--src/test/ui/consts/const-eval/ub-ref-ptr.rs9
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr100
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr100
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.rs1
-rw-r--r--src/test/ui/consts/const-float-bits-reject-conv.stderr36
-rw-r--r--src/test/ui/consts/const-fn-error.stderr3
-rw-r--r--src/test/ui/consts/const-for.stderr3
-rw-r--r--src/test/ui/consts/const_unsafe_unreachable_ub.stderr6
-rw-r--r--src/test/ui/consts/copy-intrinsic.rs2
-rw-r--r--src/test/ui/consts/extra-const-ub/detect-extra-ub.rs11
-rw-r--r--src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr30
-rw-r--r--src/test/ui/consts/issue-miri-1910.stderr9
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const.stderr9
-rw-r--r--src/test/ui/consts/miri_unleashed/drop.stderr6
-rw-r--r--src/test/ui/consts/missing_span_in_backtrace.rs2
-rw-r--r--src/test/ui/consts/offset_from_ub.stderr18
-rw-r--r--src/test/ui/consts/offset_ub.stderr72
-rw-r--r--src/test/ui/consts/ptr_comparisons.stderr6
-rw-r--r--src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr3
-rw-r--r--src/test/ui/derives/derives-span-Eq-enum.stderr3
-rw-r--r--src/test/ui/derives/derives-span-Eq-struct.stderr3
-rw-r--r--src/test/ui/derives/derives-span-Eq-tuple-struct.stderr3
-rw-r--r--src/test/ui/derives/deriving-meta-unknown-trait.stderr12
-rw-r--r--src/test/ui/deriving/issue-103157.stderr3
-rw-r--r--src/test/ui/destructuring-assignment/note-unsupported.stderr5
-rw-r--r--src/test/ui/diagnostic-width/long-E0308.rs17
-rw-r--r--src/test/ui/diagnostic-width/long-E0308.stderr8
-rw-r--r--src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed21
-rw-r--r--src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs3
-rw-r--r--src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr7
-rw-r--r--src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed19
-rw-r--r--src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs1
-rw-r--r--src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr7
-rw-r--r--src/test/ui/disambiguate-identical-names.stderr2
-rw-r--r--src/test/ui/drop/issue-21486.rs (renamed from src/test/ui/issues/issue-21486.rs)0
-rw-r--r--src/test/ui/dst/dst-rvalue.stderr6
-rw-r--r--src/test/ui/dyn-star/no-implicit-dyn-star.stderr2
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.stderr8
-rw-r--r--src/test/ui/error-codes/E0004-2.stderr13
-rw-r--r--src/test/ui/error-codes/E0005.stderr7
-rw-r--r--src/test/ui/error-codes/E0059.stderr3
-rw-r--r--src/test/ui/error-codes/E0282.stderr4
-rw-r--r--src/test/ui/error-codes/E0297.stderr7
-rw-r--r--src/test/ui/error-codes/E0401.stderr2
-rw-r--r--src/test/ui/error-codes/E0507.stderr2
-rw-r--r--src/test/ui/error-codes/E0508-fail.stderr6
-rw-r--r--src/test/ui/error-codes/E0508.stderr6
-rw-r--r--src/test/ui/error-codes/E0509.stderr6
-rw-r--r--src/test/ui/error-codes/E0790.stderr8
-rw-r--r--src/test/ui/error-festival.stderr5
-rw-r--r--src/test/ui/expr/malformed_closure/ruby_style_closure.stderr5
-rw-r--r--src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr7
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs14
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr38
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_locals.stderr4
-rw-r--r--src/test/ui/fmt/ifmt-bad-arg.stderr6
-rw-r--r--src/test/ui/fmt/ifmt-unimpl.stderr3
-rw-r--r--src/test/ui/functions-closures/fn-help-with-err.stderr4
-rw-r--r--src/test/ui/generator/issue-102645.stderr3
-rw-r--r--src/test/ui/generator/sized-yield.stderr3
-rw-r--r--src/test/ui/generic-associated-types/cross-crate-bounds.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-101020.stderr6
-rw-r--r--src/test/ui/generics/wrong-number-of-args.stderr64
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr2
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr2
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr6
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs16
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr22
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-30786.stderr8
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr2
-rw-r--r--src/test/ui/hygiene/issue-15221.rs (renamed from src/test/ui/issues/issue-15221.rs)0
-rw-r--r--src/test/ui/illegal-sized-bound/mutability-mismatch.rs34
-rw-r--r--src/test/ui/illegal-sized-bound/mutability-mismatch.stderr24
-rw-r--r--src/test/ui/illegal-sized-bound/regular.rs32
-rw-r--r--src/test/ui/illegal-sized-bound/regular.stderr20
-rw-r--r--src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr4
-rw-r--r--src/test/ui/impl-trait/impl-generic-mismatch.stderr6
-rw-r--r--src/test/ui/impl-trait/in-trait/wf-bounds.stderr3
-rw-r--r--src/test/ui/impl-trait/issues/issue-62742.stderr2
-rw-r--r--src/test/ui/impl-trait/issues/issue-86719.stderr4
-rw-r--r--src/test/ui/impl-trait/issues/issue-92305.stderr5
-rw-r--r--src/test/ui/impl-trait/no-method-suggested-traits.stderr32
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr4
-rw-r--r--src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr5
-rw-r--r--src/test/ui/imports/issue-26930.rs (renamed from src/test/ui/issues/issue-26930.rs)0
-rw-r--r--src/test/ui/inference/erase-type-params-in-label.stderr12
-rw-r--r--src/test/ui/inference/issue-71732.stderr3
-rw-r--r--src/test/ui/inference/issue-72690.stderr4
-rw-r--r--src/test/ui/inline-const/expr-unsafe-err.mir.stderr11
-rw-r--r--src/test/ui/inline-const/expr-unsafe-err.rs11
-rw-r--r--src/test/ui/inline-const/expr-unsafe-err.thir.stderr11
-rw-r--r--src/test/ui/inline-const/expr-unsafe.mir.stderr14
-rw-r--r--src/test/ui/inline-const/expr-unsafe.rs16
-rw-r--r--src/test/ui/inline-const/expr-unsafe.thir.stderr17
-rw-r--r--src/test/ui/inline-const/pat-unsafe-err.rs17
-rw-r--r--src/test/ui/inline-const/pat-unsafe.rs22
-rw-r--r--src/test/ui/interior-mutability/interior-mutability.stderr3
-rw-r--r--src/test/ui/intrinsics/const-eval-select-bad.stderr12
-rw-r--r--src/test/ui/issues/issue-105330.stderr8
-rw-r--r--src/test/ui/issues/issue-12567.stderr16
-rw-r--r--src/test/ui/issues/issue-14091-2.stderr5
-rw-r--r--src/test/ui/issues/issue-14092.stderr7
-rw-r--r--src/test/ui/issues/issue-16966.stderr5
-rw-r--r--src/test/ui/issues/issue-17546.stderr12
-rw-r--r--src/test/ui/issues/issue-17651.stderr3
-rw-r--r--src/test/ui/issues/issue-18107.stderr4
-rw-r--r--src/test/ui/issues/issue-18159.stderr4
-rw-r--r--src/test/ui/issues/issue-18423.stderr6
-rw-r--r--src/test/ui/issues/issue-20162.stderr9
-rw-r--r--src/test/ui/issues/issue-20433.stderr3
-rw-r--r--src/test/ui/issues/issue-2151.stderr4
-rw-r--r--src/test/ui/issues/issue-21974.stderr8
-rw-r--r--src/test/ui/issues/issue-23024.stderr5
-rw-r--r--src/test/ui/issues/issue-23966.stderr3
-rw-r--r--src/test/ui/issues/issue-24036.stderr4
-rw-r--r--src/test/ui/issues/issue-24424.stderr6
-rw-r--r--src/test/ui/issues/issue-27033.stderr6
-rw-r--r--src/test/ui/issues/issue-30123.stderr4
-rw-r--r--src/test/ui/issues/issue-3044.stderr3
-rw-r--r--src/test/ui/issues/issue-31173.rs3
-rw-r--r--src/test/ui/issues/issue-31173.stderr57
-rw-r--r--src/test/ui/issues/issue-32655.stderr12
-rw-r--r--src/test/ui/issues/issue-33941.rs6
-rw-r--r--src/test/ui/issues/issue-33941.stderr22
-rw-r--r--src/test/ui/issues/issue-34334.stderr19
-rw-r--r--src/test/ui/issues/issue-34721.stderr2
-rw-r--r--src/test/ui/issues/issue-38857.stderr3
-rw-r--r--src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr10
-rw-r--r--src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr6
-rw-r--r--src/test/ui/issues/issue-41880.stderr2
-rw-r--r--src/test/ui/issues/issue-42312.stderr4
-rw-r--r--src/test/ui/issues/issue-48364.stderr3
-rw-r--r--src/test/ui/issues/issue-51154.stderr3
-rw-r--r--src/test/ui/issues/issue-5353.rs18
-rw-r--r--src/test/ui/issues/issue-5883.stderr4
-rw-r--r--src/test/ui/issues/issue-61108.stderr5
-rw-r--r--src/test/ui/issues/issue-64559.stderr5
-rw-r--r--src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr33
-rw-r--r--src/test/ui/issues/issue-7607-1.stderr6
-rw-r--r--src/test/ui/issues/issue-83924.stderr5
-rw-r--r--src/test/ui/iterators/collect-into-array.rs1
-rw-r--r--src/test/ui/iterators/collect-into-array.stderr9
-rw-r--r--src/test/ui/iterators/collect-into-slice.rs1
-rw-r--r--src/test/ui/iterators/collect-into-slice.stderr12
-rw-r--r--src/test/ui/iterators/invalid-iterator-chain.rs53
-rw-r--r--src/test/ui/iterators/invalid-iterator-chain.stderr176
-rw-r--r--src/test/ui/iterators/vec-on-unimplemented.stderr6
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/branches.stderr9
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/branches3.stderr16
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr18
-rw-r--r--src/test/ui/let-else/let-else-deref-coercion.stderr2
-rw-r--r--src/test/ui/lifetimes/conflicting-bounds.rs11
-rw-r--r--src/test/ui/lifetimes/conflicting-bounds.stderr14
-rw-r--r--src/test/ui/lifetimes/issue-34979.stderr11
-rw-r--r--src/test/ui/limits/issue-55878.stderr6
-rw-r--r--src/test/ui/lint/invalid_value.stderr3
-rw-r--r--src/test/ui/lint/lint-const-item-mutation.stderr3
-rw-r--r--src/test/ui/loops/issue-82916.stderr5
-rw-r--r--src/test/ui/macros/format-args-temporaries-in-write.stderr10
-rw-r--r--src/test/ui/macros/issue-42954.fixed (renamed from src/test/ui/issues/issue-42954.fixed)0
-rw-r--r--src/test/ui/macros/issue-42954.rs (renamed from src/test/ui/issues/issue-42954.rs)0
-rw-r--r--src/test/ui/macros/issue-42954.stderr (renamed from src/test/ui/issues/issue-42954.stderr)0
-rw-r--r--src/test/ui/macros/issue-51848.rs (renamed from src/test/ui/issues/issue-51848.rs)0
-rw-r--r--src/test/ui/macros/issue-51848.stderr (renamed from src/test/ui/issues/issue-51848.stderr)0
-rw-r--r--src/test/ui/macros/macro-name-typo.stderr6
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-3.stderr6
-rw-r--r--src/test/ui/macros/unknown-builtin.stderr3
-rw-r--r--src/test/ui/malformed/malformed-derive-entry.stderr6
-rw-r--r--src/test/ui/match/match-unresolved-one-arm.stderr4
-rw-r--r--src/test/ui/methods/issues/issue-90315.stderr10
-rw-r--r--src/test/ui/methods/method-call-err-msg.stderr5
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-unresolved.stderr6
-rw-r--r--src/test/ui/methods/method-not-found-generic-arg-elision.stderr2
-rw-r--r--src/test/ui/mir/issue-29227.rs (renamed from src/test/ui/issues/issue-29227.rs)0
-rw-r--r--src/test/ui/mir/issue-46845.rs (renamed from src/test/ui/issues/issue-46845.rs)0
-rw-r--r--src/test/ui/mir/issue-77002.rs (renamed from src/test/ui/issues/issue-77002.rs)0
-rw-r--r--src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr5
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr12
-rw-r--r--src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr15
-rw-r--r--src/test/ui/mismatched_types/issue-35030.stderr3
-rw-r--r--src/test/ui/mismatched_types/issue-36053-2.stderr19
-rw-r--r--src/test/ui/mismatched_types/issue-47706-trait.stderr3
-rw-r--r--src/test/ui/mismatched_types/issue-47706.stderr3
-rw-r--r--src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr6
-rw-r--r--src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr9
-rw-r--r--src/test/ui/mismatched_types/similar_paths.stderr3
-rw-r--r--src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr2
-rw-r--r--src/test/ui/moves/issue-99470-move-out-of-some.stderr15
-rw-r--r--src/test/ui/moves/move-fn-self-receiver.stderr18
-rw-r--r--src/test/ui/moves/move-out-of-array-ref.stderr48
-rw-r--r--src/test/ui/moves/move-out-of-slice-1.stderr5
-rw-r--r--src/test/ui/moves/move-out-of-slice-2.rs1
-rw-r--r--src/test/ui/moves/move-out-of-slice-2.stderr28
-rw-r--r--src/test/ui/moves/moves-based-on-type-access-to-field.stderr5
-rw-r--r--src/test/ui/moves/moves-based-on-type-block-bad.stderr7
-rw-r--r--src/test/ui/moves/moves-based-on-type-exprs.stderr10
-rw-r--r--src/test/ui/never_type/fallback-closure-wrap.fallback.stderr2
-rw-r--r--src/test/ui/never_type/feature-gate-never_type_fallback.stderr2
-rw-r--r--src/test/ui/never_type/issue-52443.stderr3
-rw-r--r--src/test/ui/never_type/issue-96335.stderr3
-rw-r--r--src/test/ui/nll/cannot-move-block-spans.stderr84
-rw-r--r--src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr6
-rw-r--r--src/test/ui/nll/move-errors.stderr98
-rw-r--r--src/test/ui/no-capture-arc.stderr5
-rw-r--r--src/test/ui/no-reuse-move-arc.stderr5
-rw-r--r--src/test/ui/no-send-res-ports.stderr3
-rw-r--r--src/test/ui/not-clone-closure.stderr6
-rw-r--r--src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs34
-rw-r--r--src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr50
-rw-r--r--src/test/ui/on-unimplemented/sum.stderr32
-rw-r--r--src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr5
-rw-r--r--src/test/ui/overloaded/overloaded-calls-nontuple.stderr6
-rw-r--r--src/test/ui/parser/increment-autofix-2.fixed63
-rw-r--r--src/test/ui/parser/increment-autofix-2.rs (renamed from src/test/ui/parser/increment-notfixed.rs)8
-rw-r--r--src/test/ui/parser/increment-autofix-2.stderr (renamed from src/test/ui/parser/increment-notfixed.stderr)26
-rw-r--r--src/test/ui/parser/issue-104867-inc-dec-2.rs52
-rw-r--r--src/test/ui/parser/issue-104867-inc-dec-2.stderr107
-rw-r--r--src/test/ui/parser/issue-104867-inc-dec.rs45
-rw-r--r--src/test/ui/parser/issue-104867-inc-dec.stderr81
-rw-r--r--src/test/ui/parser/issue-39616.rs (renamed from src/test/ui/issues/issue-39616.rs)0
-rw-r--r--src/test/ui/parser/issue-39616.stderr (renamed from src/test/ui/issues/issue-39616.stderr)0
-rw-r--r--src/test/ui/parser/issue-49257.rs (renamed from src/test/ui/issues/issue-49257.rs)0
-rw-r--r--src/test/ui/parser/issue-49257.stderr (renamed from src/test/ui/issues/issue-49257.stderr)0
-rw-r--r--src/test/ui/parser/issues/issue-62894.stderr6
-rw-r--r--src/test/ui/parser/kw-in-trait-bounds.stderr24
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed12
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs12
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr17
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs4
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr14
-rw-r--r--src/test/ui/pattern/pat-tuple-bad-type.stderr4
-rw-r--r--src/test/ui/pattern/rest-pat-semantic-disallowed.stderr4
-rw-r--r--src/test/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr7
-rw-r--r--src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr7
-rw-r--r--src/test/ui/pattern/usefulness/issue-35609.stderr3
-rw-r--r--src/test/ui/pattern/usefulness/issue-3601.stderr6
-rw-r--r--src/test/ui/pattern/usefulness/match-arm-statics-2.stderr12
-rw-r--r--src/test/ui/pattern/usefulness/match-privately-empty.stderr7
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match.stderr7
-rw-r--r--src/test/ui/print_type_sizes/async.rs12
-rw-r--r--src/test/ui/print_type_sizes/async.stdout8
-rw-r--r--src/test/ui/print_type_sizes/generator.rs8
-rw-r--r--src/test/ui/print_type_sizes/generator_discr_placement.rs23
-rw-r--r--src/test/ui/print_type_sizes/generator_discr_placement.stdout11
-rw-r--r--src/test/ui/print_type_sizes/generics.rs24
-rw-r--r--src/test/ui/print_type_sizes/multiple_types.rs12
-rw-r--r--src/test/ui/print_type_sizes/niche-filling.rs10
-rw-r--r--src/test/ui/print_type_sizes/no_duplicates.rs8
-rw-r--r--src/test/ui/print_type_sizes/packed.rs20
-rw-r--r--src/test/ui/print_type_sizes/padding.rs8
-rw-r--r--src/test/ui/print_type_sizes/repr-align.rs12
-rw-r--r--src/test/ui/print_type_sizes/repr_int_c.rs8
-rw-r--r--src/test/ui/print_type_sizes/uninhabited.rs6
-rw-r--r--src/test/ui/print_type_sizes/variants.rs10
-rw-r--r--src/test/ui/print_type_sizes/zero-sized-fields.rs8
-rw-r--r--src/test/ui/privacy/associated-item-privacy-trait.rs4
-rw-r--r--src/test/ui/privacy/associated-item-privacy-trait.stderr4
-rw-r--r--src/test/ui/privacy/private-inferred-type-3.rs2
-rw-r--r--src/test/ui/privacy/private-inferred-type-3.stderr2
-rw-r--r--src/test/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr9
-rw-r--r--src/test/ui/proc-macro/parent-source-spans.stderr18
-rw-r--r--src/test/ui/proc-macro/resolve-error.stderr12
-rw-r--r--src/test/ui/proc-macro/signature.stderr3
-rw-r--r--src/test/ui/proc-macro/span-api-tests.rs1
-rw-r--r--src/test/ui/range/issue-54505-no-literals.stderr4
-rw-r--r--src/test/ui/range/issue-54505.stderr2
-rw-r--r--src/test/ui/range/issue-73553-misinterp-range-literal.stderr4
-rw-r--r--src/test/ui/range/range-1.stderr3
-rw-r--r--src/test/ui/reachable/auxiliary/issue-11225-1.rs (renamed from src/test/ui/issues/auxiliary/issue-11225-1.rs)0
-rw-r--r--src/test/ui/reachable/auxiliary/issue-11225-2.rs (renamed from src/test/ui/issues/auxiliary/issue-11225-2.rs)0
-rw-r--r--src/test/ui/reachable/auxiliary/issue-11225-3.rs (renamed from src/test/ui/issues/auxiliary/issue-11225-3.rs)0
-rw-r--r--src/test/ui/reachable/issue-11225-1.rs (renamed from src/test/ui/issues/issue-11225-1.rs)0
-rw-r--r--src/test/ui/reachable/issue-11225-2.rs (renamed from src/test/ui/issues/issue-11225-2.rs)0
-rw-r--r--src/test/ui/reachable/issue-11225-3.rs (renamed from src/test/ui/issues/issue-11225-3.rs)0
-rw-r--r--src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr7
-rw-r--r--src/test/ui/resolve/issue-104700-inner_scope.rs11
-rw-r--r--src/test/ui/resolve/issue-104700-inner_scope.stderr21
-rw-r--r--src/test/ui/resolve/issue-5035-2.stderr4
-rw-r--r--src/test/ui/resolve/issue-85348.stderr4
-rw-r--r--src/test/ui/resolve/levenshtein.stderr6
-rw-r--r--src/test/ui/resolve/resolve-primitive-fallback.stderr3
-rw-r--r--src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr3
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/for.stderr5
-rw-r--r--src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr5
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr38
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr6
-rw-r--r--src/test/ui/span/issue-39018.stderr5
-rw-r--r--src/test/ui/span/issue-71363.rs2
-rw-r--r--src/test/ui/span/method-and-field-eager-resolution.stderr8
-rw-r--r--src/test/ui/span/missing-unit-argument.stderr3
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr2
-rw-r--r--src/test/ui/stability-attribute/stability-in-private-module.stderr3
-rw-r--r--src/test/ui/std-uncopyable-atomics.stderr44
-rw-r--r--src/test/ui/stdlib-unit-tests/issue-21058.rs (renamed from src/test/ui/issues/issue-21058.rs)0
-rw-r--r--src/test/ui/str/str-idx.stderr6
-rw-r--r--src/test/ui/str/str-mut-idx.stderr6
-rw-r--r--src/test/ui/structs/struct-record-suggestion.stderr2
-rw-r--r--src/test/ui/suggestions/args-instead-of-tuple-errors.stderr12
-rw-r--r--src/test/ui/suggestions/args-instead-of-tuple.stderr15
-rw-r--r--src/test/ui/suggestions/as-ref-2.stderr5
-rw-r--r--src/test/ui/suggestions/attribute-typos.stderr6
-rw-r--r--src/test/ui/suggestions/borrow-for-loop-head.stderr5
-rw-r--r--src/test/ui/suggestions/bound-suggestions.stderr15
-rw-r--r--src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed16
-rw-r--r--src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs15
-rw-r--r--src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr43
-rw-r--r--src/test/ui/suggestions/derive-clone-for-eq.stderr3
-rw-r--r--src/test/ui/suggestions/derive-trait-for-method-call.stderr17
-rw-r--r--src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr6
-rw-r--r--src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs57
-rw-r--r--src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr253
-rw-r--r--src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs21
-rw-r--r--src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr187
-rw-r--r--src/test/ui/suggestions/dont-suggest-ref/simple.rs154
-rw-r--r--src/test/ui/suggestions/dont-suggest-ref/simple.stderr749
-rw-r--r--src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr12
-rw-r--r--src/test/ui/suggestions/for-i-in-vec.stderr10
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object.stderr6
-rw-r--r--src/test/ui/suggestions/import-trait-for-method-call.stderr6
-rw-r--r--src/test/ui/suggestions/issue-104287.stderr6
-rw-r--r--src/test/ui/suggestions/issue-104327.rs12
-rw-r--r--src/test/ui/suggestions/issue-104327.stderr17
-rw-r--r--src/test/ui/suggestions/issue-104328.rs12
-rw-r--r--src/test/ui/suggestions/issue-104328.stderr17
-rw-r--r--src/test/ui/suggestions/issue-105226.rs22
-rw-r--r--src/test/ui/suggestions/issue-105226.stderr31
-rw-r--r--src/test/ui/suggestions/issue-62843.stderr3
-rw-r--r--src/test/ui/suggestions/issue-71394-no-from-impl.stderr6
-rw-r--r--src/test/ui/suggestions/issue-89064.stderr5
-rw-r--r--src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr16
-rw-r--r--src/test/ui/suggestions/option-content-move-from-tuple-match.stderr5
-rw-r--r--src/test/ui/suggestions/option-content-move.stderr10
-rw-r--r--src/test/ui/suggestions/restrict-type-not-param.stderr5
-rw-r--r--src/test/ui/suggestions/sugg-else-for-closure.stderr3
-rw-r--r--src/test/ui/suggestions/suggest-change-mut.stderr9
-rw-r--r--src/test/ui/suggestions/suggest-tryinto-edition-change.stderr6
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr5
-rw-r--r--src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr4
-rw-r--r--src/test/ui/traits/alias/generic-default-in-dyn.stderr12
-rw-r--r--src/test/ui/traits/alias/object-fail.stderr3
-rw-r--r--src/test/ui/traits/assoc-type-in-superbad.rs2
-rw-r--r--src/test/ui/traits/assoc-type-in-superbad.stderr2
-rw-r--r--src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr30
-rw-r--r--src/test/ui/traits/bad-sized.stderr9
-rw-r--r--src/test/ui/traits/bound/not-on-bare-trait.stderr4
-rw-r--r--src/test/ui/traits/issue-38404.rs (renamed from src/test/ui/issues/issue-38404.rs)0
-rw-r--r--src/test/ui/traits/issue-38404.stderr (renamed from src/test/ui/issues/issue-38404.stderr)0
-rw-r--r--src/test/ui/traits/issue-50480.rs (renamed from src/test/ui/issues/issue-50480.rs)0
-rw-r--r--src/test/ui/traits/issue-50480.stderr (renamed from src/test/ui/issues/issue-50480.stderr)0
-rw-r--r--src/test/ui/traits/issue-77982.stderr13
-rw-r--r--src/test/ui/traits/issue-85735.stderr9
-rw-r--r--src/test/ui/traits/issue-97576.stderr6
-rw-r--r--src/test/ui/traits/mutual-recursion-issue-75860.stderr3
-rw-r--r--src/test/ui/traits/object/issue-44454-1.rs22
-rw-r--r--src/test/ui/traits/object/issue-44454-1.stderr10
-rw-r--r--src/test/ui/traits/object/issue-44454-2.rs22
-rw-r--r--src/test/ui/traits/object/issue-44454-2.stderr17
-rw-r--r--src/test/ui/traits/object/issue-44454-3.rs33
-rw-r--r--src/test/ui/traits/object/issue-44454-3.stderr11
-rw-r--r--src/test/ui/traits/static-method-generic-inference.stderr4
-rw-r--r--src/test/ui/traits/suggest-deferences/issue-39029.stderr3
-rw-r--r--src/test/ui/traits/suggest-deferences/root-obligation.stderr3
-rw-r--r--src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed14
-rw-r--r--src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs14
-rw-r--r--src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr15
-rw-r--r--src/test/ui/traits/suggest-where-clause.stderr12
-rw-r--r--src/test/ui/transmutability/issue-101739-2.stderr6
-rw-r--r--src/test/ui/tuple/wrong_argument_ice-3.stderr3
-rw-r--r--src/test/ui/tuple/wrong_argument_ice.stderr3
-rw-r--r--src/test/ui/type-alias-impl-trait/closures_in_branches.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57961.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57961.stderr2
-rw-r--r--src/test/ui/type-alias/issue-37515.rs (renamed from src/test/ui/issues/issue-37515.rs)0
-rw-r--r--src/test/ui/type-alias/issue-37515.stderr (renamed from src/test/ui/issues/issue-37515.stderr)0
-rw-r--r--src/test/ui/type/ascription/issue-34255-1.stderr5
-rw-r--r--src/test/ui/type/type-annotation-needed.stderr2
-rw-r--r--src/test/ui/type/type-ascription-instead-of-initializer.stderr3
-rw-r--r--src/test/ui/type/type-ascription-precedence.stderr7
-rw-r--r--src/test/ui/type/type-check/issue-40294.stderr8
-rw-r--r--src/test/ui/type/type-check/unknown_type_for_closure.stderr4
-rw-r--r--src/test/ui/type/type-path-err-node-types.stderr4
-rw-r--r--src/test/ui/type_length_limit.stderr3
-rw-r--r--src/test/ui/typeck/explain_clone_autoref.stderr4
-rw-r--r--src/test/ui/typeck/issue-104582.rs5
-rw-r--r--src/test/ui/typeck/issue-104582.stderr25
-rw-r--r--src/test/ui/typeck/issue-13853.stderr2
-rw-r--r--src/test/ui/typeck/issue-33575.rs (renamed from src/test/ui/issues/issue-33575.rs)0
-rw-r--r--src/test/ui/typeck/issue-33575.stderr (renamed from src/test/ui/issues/issue-33575.stderr)0
-rw-r--r--src/test/ui/typeck/issue-46112.stderr3
-rw-r--r--src/test/ui/typeck/issue-75883.stderr10
-rw-r--r--src/test/ui/typeck/issue-83693.stderr6
-rw-r--r--src/test/ui/typeck/issue-84768.stderr3
-rw-r--r--src/test/ui/typeck/issue-92481.rs14
-rw-r--r--src/test/ui/typeck/issue-92481.stderr60
-rw-r--r--src/test/ui/typeck/struct-enum-wrong-args.stderr9
-rw-r--r--src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr36
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr6
-rw-r--r--src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr3
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr4
-rw-r--r--src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr21
-rw-r--r--src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr20
-rw-r--r--src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr20
-rw-r--r--src/test/ui/union/union-derive-clone.mirunsafeck.stderr3
-rw-r--r--src/test/ui/union/union-derive-clone.thirunsafeck.stderr3
-rw-r--r--src/test/ui/union/union-derive-eq.mirunsafeck.stderr3
-rw-r--r--src/test/ui/union/union-derive-eq.thirunsafeck.stderr3
-rw-r--r--src/test/ui/unique-object-noncopyable.stderr8
-rw-r--r--src/test/ui/unique-pinned-nocopy.stderr8
-rw-r--r--src/test/ui/unop-move-semantics.stderr6
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.stderr2
-rw-r--r--src/test/ui/unsized-locals/double-move.stderr2
-rw-r--r--src/test/ui/unsized/issue-71659.stderr6
-rw-r--r--src/test/ui/use/use-after-move-self-based-on-type.stderr2
-rw-r--r--src/test/ui/use/use-after-move-self.stderr2
-rw-r--r--src/test/ui/walk-struct-literal-with.stderr2
-rw-r--r--src/test/ui/wf/hir-wf-canonicalized.rs18
-rw-r--r--src/test/ui/wf/hir-wf-canonicalized.stderr32
-rw-r--r--src/test/ui/wf/hir-wf-check-erase-regions.stderr6
-rw-r--r--src/test/ui/wf/wf-impl-self-type.stderr3
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_include_file.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs32
-rw-r--r--src/tools/compiletest/src/runtest.rs8
-rw-r--r--src/tools/miri/src/machine.rs20
-rw-r--r--src/tools/rustfmt/src/attr.rs12
-rw-r--r--src/tools/tidy/src/deps.rs6
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--triagebot.toml2
1012 files changed, 13064 insertions, 8455 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b93166b80a5..b29b3a41803 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -430,7 +430,7 @@ jobs:
             os: windows-latest-xl
           - name: dist-x86_64-msvc
             env:
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler"
+              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler --set rust.lto=thin"
               SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths
               DIST_REQUIRE_ALL_TOOLS: 1
             os: windows-latest-xl
diff --git a/Cargo.lock b/Cargo.lock
index 37bbe95d633..5d05a09f038 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -809,9 +809,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.84"
+version = "0.1.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "989b2c1ca6e90ad06fdc69d1d1862fa28d27a977be6d92ae2fa762cf61fe0b10"
+checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -4627,9 +4627,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.36.3"
+version = "0.36.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e"
+checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
 dependencies = [
  "bitflags",
  "errno",
diff --git a/RELEASES.md b/RELEASES.md
index 5c1990bb6c9..770dee7b546 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,94 @@
+Version 1.66.0 (2022-12-15)
+==========================
+
+Language
+--------
+- [Permit specifying explicit discriminants on all `repr(Int)` enums](https://github.com/rust-lang/rust/pull/95710/)
+  ```rust
+  #[repr(u8)]
+  enum Foo {
+      A(u8) = 0,
+      B(i8) = 1,
+      C(bool) = 42,
+  }
+  ```
+- [Allow transmutes between the same type differing only in lifetimes](https://github.com/rust-lang/rust/pull/101520/)
+- [Change constant evaluation errors from a deny-by-default lint to a hard error](https://github.com/rust-lang/rust/pull/102091/)
+- [Trigger `must_use` on `impl Trait` for supertraits](https://github.com/rust-lang/rust/pull/102287/)
+  This makes `impl ExactSizeIterator` respect the existing `#[must_use]` annotation on `Iterator`.
+- [Allow `..=X` in patterns](https://github.com/rust-lang/rust/pull/102275/)
+- [Uplift `clippy::for_loops_over_fallibles` lint into rustc](https://github.com/rust-lang/rust/pull/99696/)
+- [Stabilize `sym` operands in inline assembly](https://github.com/rust-lang/rust/pull/103168/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101912/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+  This is a soundness fix which may break code that was erroneously relying on this behavior.
+
+Compiler
+--------
+- [Add armv5te-none-eabi and thumbv5te-none-eabi tier 3 targets](https://github.com/rust-lang/rust/pull/101329/)
+  - Refer to Rust's [platform support page][platform-support-doc] for more
+    information on Rust's tiered platform support.
+- [Add support for linking against macOS universal libraries](https://github.com/rust-lang/rust/pull/98736)
+
+Libraries
+---------
+- [Fix `#[derive(Default)]` on a generic `#[default]` enum adding unnecessary `Default` bounds](https://github.com/rust-lang/rust/pull/101040/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101821/)
+
+Stabilized APIs
+---------------
+
+- [`proc_macro::Span::source_text`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.source_text)
+- [`uX::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed}`](https://doc.rust-lang.org/stable/std/primitive.u8.html#method.checked_add_signed)
+- [`iX::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_add_unsigned)
+- [`iX::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_sub_unsigned)
+- [`BTreeSet::{first, last, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html#method.first)
+- [`BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.first_key_value)
+- [Add `AsFd` implementations for stdio lock types on WASI.](https://github.com/rust-lang/rust/pull/101768/)
+- [`impl TryFrom<Vec<T>> for Box<[T; N]>`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#impl-TryFrom%3CVec%3CT%2C%20Global%3E%3E-for-Box%3C%5BT%3B%20N%5D%2C%20Global%3E)
+- [`core::hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html)
+- [`Duration::try_from_secs_{f32,f64}`](https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.try_from_secs_f32)
+- [`Option::unzip`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unzip)
+- [`std::os::fd`](https://doc.rust-lang.org/stable/std/os/fd/index.html)
+
+
+Rustdoc
+-------
+
+- [Add Rustdoc warning for invalid HTML tags in the documentation](https://github.com/rust-lang/rust/pull/101720/)
+
+Cargo
+-----
+
+- [Added `cargo remove` to remove dependencies from Cargo.toml](https://doc.rust-lang.org/nightly/cargo/commands/cargo-remove.html)
+- [`cargo publish` now waits for the new version to be downloadable before exiting](https://github.com/rust-lang/cargo/pull/11062)
+
+See [detailed release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-166-2022-12-15) for more.
+
+Compatibility Notes
+-------------------
+
+- [Only apply `ProceduralMasquerade` hack to older versions of `rental`](https://github.com/rust-lang/rust/pull/94063/)
+- [Don't export `__heap_base` and `__data_end` on wasm32-wasi.](https://github.com/rust-lang/rust/pull/102385/)
+- [Don't export `__wasm_init_memory` on WebAssembly.](https://github.com/rust-lang/rust/pull/102426/)
+- [Only export `__tls_*` on wasm32-unknown-unknown.](https://github.com/rust-lang/rust/pull/102440/)
+- [Don't link to `libresolv` in libstd on Darwin](https://github.com/rust-lang/rust/pull/102766/)
+- [Update libstd's libc to 0.2.135 (to make `libstd` no longer pull in `libiconv.dylib` on Darwin)](https://github.com/rust-lang/rust/pull/103277/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+  This is a soundness fix which may break code that was erroneously relying on this behavior.
+- [Make `order_dependent_trait_objects` show up in future-breakage reports](https://github.com/rust-lang/rust/pull/102635/)
+- [Change std::process::Command spawning to default to inheriting the parent's signal mask](https://github.com/rust-lang/rust/pull/101077/)
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Enable BOLT for LLVM compilation](https://github.com/rust-lang/rust/pull/94381/)
+- [Enable LTO for rustc_driver.so](https://github.com/rust-lang/rust/pull/101403/)
+
 Version 1.65.0 (2022-11-03)
 ==========================
 
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index e14c9ea9a5d..8c71332bfab 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1,6 +1,5 @@
 #![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))]
 
-use std::convert::{TryFrom, TryInto};
 use std::fmt;
 #[cfg(feature = "nightly")]
 use std::iter::Step;
@@ -803,12 +802,9 @@ impl Integer {
     pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
         let dl = cx.data_layout();
 
-        for candidate in [I8, I16, I32, I64, I128] {
-            if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() {
-                return Some(candidate);
-            }
-        }
-        None
+        [I8, I16, I32, I64, I128].into_iter().find(|&candidate| {
+            wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes()
+        })
     }
 
     /// Find the largest integer with the given alignment or less.
diff --git a/compiler/rustc_apfloat/src/ieee.rs b/compiler/rustc_apfloat/src/ieee.rs
index 3db8adb2a24..2286712f025 100644
--- a/compiler/rustc_apfloat/src/ieee.rs
+++ b/compiler/rustc_apfloat/src/ieee.rs
@@ -2,7 +2,6 @@ use crate::{Category, ExpInt, IEK_INF, IEK_NAN, IEK_ZERO};
 use crate::{Float, FloatConvert, ParseError, Round, Status, StatusAnd};
 
 use core::cmp::{self, Ordering};
-use core::convert::TryFrom;
 use core::fmt::{self, Write};
 use core::marker::PhantomData;
 use core::mem;
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 46dbbd83d19..4fae5ef845f 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -28,7 +28,7 @@ use smallvec::SmallVec;
 use std::alloc::Layout;
 use std::cell::{Cell, RefCell};
 use std::cmp;
-use std::marker::{PhantomData, Send};
+use std::marker::PhantomData;
 use std::mem::{self, MaybeUninit};
 use std::ptr::{self, NonNull};
 use std::slice;
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 4d80f904ac4..f933b9b161c 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -33,7 +33,6 @@ 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};
-use std::convert::TryFrom;
 use std::fmt;
 use std::mem;
 use thin_vec::{thin_vec, ThinVec};
@@ -1735,8 +1734,10 @@ pub enum StrStyle {
 /// A literal in a meta item.
 #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct MetaItemLit {
-    /// The original literal token as written in source code.
-    pub token_lit: token::Lit,
+    /// The original literal as written in the source code.
+    pub symbol: Symbol,
+    /// The original suffix as written in the source code.
+    pub suffix: Option<Symbol>,
     /// The "semantic" representation of the literal lowered from the original tokens.
     /// Strings are unescaped, hexadecimal forms are eliminated, etc.
     pub kind: LitKind,
@@ -1746,13 +1747,14 @@ pub struct MetaItemLit {
 /// Similar to `MetaItemLit`, but restricted to string literals.
 #[derive(Clone, Copy, Encodable, Decodable, Debug)]
 pub struct StrLit {
-    /// The original literal token as written in source code.
-    pub style: StrStyle,
+    /// The original literal as written in source code.
     pub symbol: Symbol,
+    /// The original suffix as written in source code.
     pub suffix: Option<Symbol>,
-    pub span: Span,
-    /// The unescaped "semantic" representation of the literal lowered from the original token.
+    /// The semantic (unescaped) representation of the literal.
     pub symbol_unescaped: Symbol,
+    pub style: StrStyle,
+    pub span: Span,
 }
 
 impl StrLit {
@@ -1798,8 +1800,9 @@ pub enum LitKind {
     /// A string literal (`"foo"`). The symbol is unescaped, and so may differ
     /// from the original token's symbol.
     Str(Symbol, StrStyle),
-    /// A byte string (`b"foo"`).
-    ByteStr(Lrc<[u8]>),
+    /// A byte string (`b"foo"`). Not stored as a symbol because it might be
+    /// non-utf8, and symbols only allow utf8 strings.
+    ByteStr(Lrc<[u8]>, StrStyle),
     /// A byte char (`b'f'`).
     Byte(u8),
     /// A character literal (`'a'`).
@@ -1824,7 +1827,7 @@ impl LitKind {
 
     /// Returns `true` if this literal is byte literal string.
     pub fn is_bytestr(&self) -> bool {
-        matches!(self, LitKind::ByteStr(_))
+        matches!(self, LitKind::ByteStr(..))
     }
 
     /// Returns `true` if this is a numeric literal.
@@ -2463,7 +2466,7 @@ pub enum ModKind {
     Unloaded,
 }
 
-#[derive(Copy, Clone, Encodable, Decodable, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
 pub struct ModSpans {
     /// `inner_span` covers the body of the module; for a file module, its the whole file.
     /// For an inline module, its the span inside the `{ ... }`, not including the curly braces.
@@ -2471,12 +2474,6 @@ pub struct ModSpans {
     pub inject_use_span: Span,
 }
 
-impl Default for ModSpans {
-    fn default() -> ModSpans {
-        ModSpans { inner_span: Default::default(), inject_use_span: Default::default() }
-    }
-}
-
 /// Foreign module declaration.
 ///
 /// E.g., `extern { .. }` or `extern "C" { .. }`.
@@ -3101,7 +3098,7 @@ mod size_asserts {
     static_assert_size!(ItemKind, 112);
     static_assert_size!(LitKind, 24);
     static_assert_size!(Local, 72);
-    static_assert_size!(MetaItemLit, 48);
+    static_assert_size!(MetaItemLit, 40);
     static_assert_size!(Param, 40);
     static_assert_size!(Pat, 88);
     static_assert_size!(Path, 24);
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 057cc26b579..d99f6ed2c1c 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -1,15 +1,15 @@
 //! Functions dealing with attributes and meta items.
 
-use crate::ast;
 use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
 use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
 use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
-use crate::ast::{Path, PathSegment, StrStyle, DUMMY_NODE_ID};
+use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
 use crate::ptr::P;
 use crate::token::{self, CommentKind, Delimiter, Token};
 use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
 use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
 use crate::util::comments;
+use crate::util::literal::escape_string_symbol;
 use rustc_data_structures::sync::WorkerLocal;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -321,18 +321,6 @@ impl Attribute {
     }
 }
 
-/* Constructors */
-
-pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
-    mk_name_value_item(ident, LitKind::Str(str, ast::StrStyle::Cooked), str_span)
-}
-
-pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem {
-    let lit = MetaItemLit { token_lit: kind.to_token_lit(), kind, span: lit_span };
-    let span = ident.span.to(lit_span);
-    MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span }
-}
-
 pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
 
 #[cfg(debug_assertions)]
@@ -408,7 +396,7 @@ pub fn mk_attr_name_value_str(
     val: Symbol,
     span: Span,
 ) -> Attribute {
-    let lit = LitKind::Str(val, StrStyle::Cooked).to_token_lit();
+    let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
     let expr = P(Expr {
         id: DUMMY_NODE_ID,
         kind: ExprKind::Lit(lit),
diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs
index 30481eddf91..4b2850336a0 100644
--- a/compiler/rustc_ast/src/ptr.rs
+++ b/compiler/rustc_ast/src/ptr.rs
@@ -22,7 +22,6 @@
 //!   Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated.
 
 use std::fmt::{self, Debug, Display};
-use std::iter::FromIterator;
 use std::ops::{Deref, DerefMut};
 use std::{slice, vec};
 
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index c0cc4e79a3d..7b8c0d79a17 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -114,7 +114,7 @@ impl Lit {
                 if let NtExpr(expr) | NtLiteral(expr) = &**nt
                 && let ast::ExprKind::Lit(token_lit) = expr.kind =>
             {
-                Some(token_lit.clone())
+                Some(token_lit)
             }
             _ => None,
         }
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 482c302950f..29a5eb4b7c5 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -362,7 +362,7 @@ impl TokenStream {
     }
 }
 
-impl iter::FromIterator<TokenTree> for TokenStream {
+impl FromIterator<TokenTree> for TokenStream {
     fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
         TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
     }
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index f6f186b5107..0daeecb53a8 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -1,11 +1,31 @@
 //! Code related to parsing literals.
 
-use crate::ast::{self, LitKind, MetaItemLit};
+use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
 use crate::token::{self, Token};
 use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
-use std::ascii;
+use std::{ascii, fmt, str};
+
+// Escapes a string, represented as a symbol. Reuses the original symbol,
+// avoiding interning, if no changes are required.
+pub fn escape_string_symbol(symbol: Symbol) -> Symbol {
+    let s = symbol.as_str();
+    let escaped = s.escape_default().to_string();
+    if s == escaped { symbol } else { Symbol::intern(&escaped) }
+}
+
+// Escapes a char.
+pub fn escape_char_symbol(ch: char) -> Symbol {
+    let s: String = ch.escape_default().map(Into::<char>::into).collect();
+    Symbol::intern(&s)
+}
+
+// Escapes a byte string.
+pub fn escape_byte_str_symbol(bytes: &[u8]) -> Symbol {
+    let s = bytes.escape_ascii().to_string();
+    Symbol::intern(&s)
+}
 
 #[derive(Debug)]
 pub enum LitError {
@@ -115,9 +135,9 @@ impl LitKind {
                     }
                 });
                 error?;
-                LitKind::ByteStr(buf.into())
+                LitKind::ByteStr(buf.into(), StrStyle::Cooked)
             }
-            token::ByteStrRaw(_) => {
+            token::ByteStrRaw(n) => {
                 let s = symbol.as_str();
                 let bytes = if s.contains('\r') {
                     let mut buf = Vec::with_capacity(s.len());
@@ -136,69 +156,95 @@ impl LitKind {
                     symbol.to_string().into_bytes()
                 };
 
-                LitKind::ByteStr(bytes.into())
+                LitKind::ByteStr(bytes.into(), StrStyle::Raw(n))
             }
             token::Err => LitKind::Err,
         })
     }
+}
 
-    /// Attempts to recover a token from semantic literal.
-    /// This function is used when the original token doesn't exist (e.g. the literal is created
-    /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
-    pub fn to_token_lit(&self) -> token::Lit {
-        let (kind, symbol, suffix) = match *self {
-            LitKind::Str(symbol, ast::StrStyle::Cooked) => {
-                // Don't re-intern unless the escaped string is different.
-                let s = symbol.as_str();
-                let escaped = s.escape_default().to_string();
-                let symbol = if s == escaped { symbol } else { Symbol::intern(&escaped) };
-                (token::Str, symbol, None)
-            }
-            LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None),
-            LitKind::ByteStr(ref bytes) => {
-                let string = bytes.escape_ascii().to_string();
-                (token::ByteStr, Symbol::intern(&string), None)
+impl fmt::Display for LitKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            LitKind::Byte(b) => {
+                let b: String = ascii::escape_default(b).map(Into::<char>::into).collect();
+                write!(f, "b'{}'", b)?;
             }
-            LitKind::Byte(byte) => {
-                let string: String = ascii::escape_default(byte).map(Into::<char>::into).collect();
-                (token::Byte, Symbol::intern(&string), None)
+            LitKind::Char(ch) => write!(f, "'{}'", escape_char_symbol(ch))?,
+            LitKind::Str(sym, StrStyle::Cooked) => write!(f, "\"{}\"", escape_string_symbol(sym))?,
+            LitKind::Str(sym, StrStyle::Raw(n)) => write!(
+                f,
+                "r{delim}\"{string}\"{delim}",
+                delim = "#".repeat(n as usize),
+                string = sym
+            )?,
+            LitKind::ByteStr(ref bytes, StrStyle::Cooked) => {
+                write!(f, "b\"{}\"", escape_byte_str_symbol(bytes))?
             }
-            LitKind::Char(ch) => {
-                let string: String = ch.escape_default().map(Into::<char>::into).collect();
-                (token::Char, Symbol::intern(&string), None)
+            LitKind::ByteStr(ref bytes, StrStyle::Raw(n)) => {
+                // Unwrap because raw byte string literals can only contain ASCII.
+                let symbol = str::from_utf8(bytes).unwrap();
+                write!(
+                    f,
+                    "br{delim}\"{string}\"{delim}",
+                    delim = "#".repeat(n as usize),
+                    string = symbol
+                )?;
             }
             LitKind::Int(n, ty) => {
-                let suffix = match ty {
-                    ast::LitIntType::Unsigned(ty) => Some(ty.name()),
-                    ast::LitIntType::Signed(ty) => Some(ty.name()),
-                    ast::LitIntType::Unsuffixed => None,
-                };
-                (token::Integer, sym::integer(n), suffix)
+                write!(f, "{}", n)?;
+                match ty {
+                    ast::LitIntType::Unsigned(ty) => write!(f, "{}", ty.name())?,
+                    ast::LitIntType::Signed(ty) => write!(f, "{}", ty.name())?,
+                    ast::LitIntType::Unsuffixed => {}
+                }
             }
             LitKind::Float(symbol, ty) => {
-                let suffix = match ty {
-                    ast::LitFloatType::Suffixed(ty) => Some(ty.name()),
-                    ast::LitFloatType::Unsuffixed => None,
-                };
-                (token::Float, symbol, suffix)
+                write!(f, "{}", symbol)?;
+                match ty {
+                    ast::LitFloatType::Suffixed(ty) => write!(f, "{}", ty.name())?,
+                    ast::LitFloatType::Unsuffixed => {}
+                }
             }
-            LitKind::Bool(value) => {
-                let symbol = if value { kw::True } else { kw::False };
-                (token::Bool, symbol, None)
+            LitKind::Bool(b) => write!(f, "{}", if b { "true" } else { "false" })?,
+            LitKind::Err => {
+                // This only shows up in places like `-Zunpretty=hir` output, so we
+                // don't bother to produce something useful.
+                write!(f, "<bad-literal>")?;
             }
-            // This only shows up in places like `-Zunpretty=hir` output, so we
-            // don't bother to produce something useful.
-            LitKind::Err => (token::Err, Symbol::intern("<bad-literal>"), None),
-        };
+        }
 
-        token::Lit::new(kind, symbol, suffix)
+        Ok(())
     }
 }
 
 impl MetaItemLit {
-    /// Converts token literal into a meta item literal.
+    /// Converts a token literal into a meta item literal.
     pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<MetaItemLit, LitError> {
-        Ok(MetaItemLit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span })
+        Ok(MetaItemLit {
+            symbol: token_lit.symbol,
+            suffix: token_lit.suffix,
+            kind: LitKind::from_token_lit(token_lit)?,
+            span,
+        })
+    }
+
+    /// Cheaply converts a meta item literal into a token literal.
+    pub fn as_token_lit(&self) -> token::Lit {
+        let kind = match self.kind {
+            LitKind::Bool(_) => token::Bool,
+            LitKind::Str(_, ast::StrStyle::Cooked) => token::Str,
+            LitKind::Str(_, ast::StrStyle::Raw(n)) => token::StrRaw(n),
+            LitKind::ByteStr(_, ast::StrStyle::Cooked) => token::ByteStr,
+            LitKind::ByteStr(_, ast::StrStyle::Raw(n)) => token::ByteStrRaw(n),
+            LitKind::Byte(_) => token::Byte,
+            LitKind::Char(_) => token::Char,
+            LitKind::Int(..) => token::Integer,
+            LitKind::Float(..) => token::Float,
+            LitKind::Err => token::Err,
+        };
+
+        token::Lit::new(kind, self.symbol, self.suffix)
     }
 
     /// Converts an arbitrary token into meta item literal.
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 24e2985cf56..e86e807279d 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -31,6 +31,44 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
         ensure_sufficient_stack(|| {
+            match &e.kind {
+                // Paranthesis expression does not have a HirId and is handled specially.
+                ExprKind::Paren(ex) => {
+                    let mut ex = self.lower_expr_mut(ex);
+                    // Include parens in span, but only if it is a super-span.
+                    if e.span.contains(ex.span) {
+                        ex.span = self.lower_span(e.span);
+                    }
+                    // Merge attributes into the inner expression.
+                    if !e.attrs.is_empty() {
+                        let old_attrs =
+                            self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
+                        self.attrs.insert(
+                            ex.hir_id.local_id,
+                            &*self.arena.alloc_from_iter(
+                                e.attrs
+                                    .iter()
+                                    .map(|a| self.lower_attr(a))
+                                    .chain(old_attrs.iter().cloned()),
+                            ),
+                        );
+                    }
+                    return ex;
+                }
+                // Desugar `ExprForLoop`
+                // from: `[opt_ident]: for <pat> in <head> <body>`
+                //
+                // This also needs special handling because the HirId of the returned `hir::Expr` will not
+                // correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
+                ExprKind::ForLoop(pat, head, body, opt_label) => {
+                    return self.lower_expr_for(e, pat, head, body, *opt_label);
+                }
+                _ => (),
+            }
+
+            let hir_id = self.lower_node_id(e.id);
+            self.lower_attrs(hir_id, &e.attrs);
+
             let kind = match &e.kind {
                 ExprKind::Box(inner) => hir::ExprKind::Box(self.lower_expr(inner)),
                 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
@@ -48,7 +86,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
                         if let [inner] = &args[..] && e.attrs.len() == 1 {
                             let kind = hir::ExprKind::Box(self.lower_expr(&inner));
-                            let hir_id = self.lower_node_id(e.id);
                             return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
                         } else {
                             self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
@@ -97,7 +134,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 }
                 ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan(
                     self.lower_span(e.span),
-                    LitKind::ByteStr(bytes.clone()),
+                    LitKind::ByteStr(bytes.clone(), StrStyle::Cooked),
                 )),
                 ExprKind::Cast(expr, ty) => {
                     let expr = self.lower_expr(expr);
@@ -147,7 +184,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ),
                 ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
                     *capture_clause,
-                    None,
+                    hir_id,
                     *closure_node_id,
                     None,
                     e.span,
@@ -184,6 +221,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             binder,
                             *capture_clause,
                             e.id,
+                            hir_id,
                             *closure_id,
                             fn_decl,
                             body,
@@ -279,39 +317,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
                 ExprKind::Err => hir::ExprKind::Err,
                 ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
-                ExprKind::Paren(ex) => {
-                    let mut ex = self.lower_expr_mut(ex);
-                    // Include parens in span, but only if it is a super-span.
-                    if e.span.contains(ex.span) {
-                        ex.span = self.lower_span(e.span);
-                    }
-                    // Merge attributes into the inner expression.
-                    if !e.attrs.is_empty() {
-                        let old_attrs =
-                            self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
-                        self.attrs.insert(
-                            ex.hir_id.local_id,
-                            &*self.arena.alloc_from_iter(
-                                e.attrs
-                                    .iter()
-                                    .map(|a| self.lower_attr(a))
-                                    .chain(old_attrs.iter().cloned()),
-                            ),
-                        );
-                    }
-                    return ex;
-                }
 
-                // Desugar `ExprForLoop`
-                // from: `[opt_ident]: for <pat> in <head> <body>`
-                ExprKind::ForLoop(pat, head, body, opt_label) => {
-                    return self.lower_expr_for(e, pat, head, body, *opt_label);
-                }
+                ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
+
                 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
             };
 
-            let hir_id = self.lower_node_id(e.id);
-            self.lower_attrs(hir_id, &e.attrs);
             hir::Expr { hir_id, kind, span: self.lower_span(e.span) }
         })
     }
@@ -576,7 +587,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     pub(super) fn make_async_expr(
         &mut self,
         capture_clause: CaptureBy,
-        outer_hir_id: Option<hir::HirId>,
+        outer_hir_id: hir::HirId,
         closure_node_id: NodeId,
         ret_ty: Option<hir::FnRetTy<'hir>>,
         span: Span,
@@ -669,8 +680,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             hir::ExprKind::Closure(c)
         };
 
-        let track_caller = outer_hir_id
-            .and_then(|id| self.attrs.get(&id.local_id))
+        let track_caller = self
+            .attrs
+            .get(&outer_hir_id.local_id)
             .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
 
         let hir_id = self.lower_node_id(closure_node_id);
@@ -985,6 +997,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         binder: &ClosureBinder,
         capture_clause: CaptureBy,
         closure_id: NodeId,
+        closure_hir_id: hir::HirId,
         inner_closure_id: NodeId,
         decl: &FnDecl,
         body: &Expr,
@@ -1018,9 +1031,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
                 let async_body = this.make_async_expr(
                     capture_clause,
-                    // FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]`
-                    // can be applied on async closures as well.
-                    None,
+                    closure_hir_id,
                     inner_closure_id,
                     async_ret_ty,
                     body.span,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index d73d6d3918e..73065ab5163 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1139,7 +1139,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
             let async_expr = this.make_async_expr(
                 CaptureBy::Value,
-                Some(fn_id),
+                fn_id,
                 closure_id,
                 None,
                 body.span,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 4fa18907fcd..d67ede6e130 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -456,8 +456,8 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> {
     }
 
     // Drop AST to free memory
-    std::mem::drop(ast_index);
-    sess.time("drop_ast", || std::mem::drop(krate));
+    drop(ast_index);
+    sess.time("drop_ast", || drop(krate));
 
     // Discard hygiene data, which isn't required after lowering to HIR.
     if !sess.opts.unstable_opts.keep_hygiene_data {
@@ -958,7 +958,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     lit
                 } else {
                     MetaItemLit {
-                        token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None),
+                        symbol: kw::Empty,
+                        suffix: None,
                         kind: LitKind::Err,
                         span: DUMMY_SP,
                     }
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 32f45f8b59e..039338f543c 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -630,7 +630,7 @@ fn check_incompatible_features(sess: &Session) {
             {
                 let spans = vec![f1_span, f2_span];
                 sess.struct_span_err(
-                    spans.clone(),
+                    spans,
                     &format!(
                         "features `{}` and `{}` are incompatible, using them at the same time \
                         is not allowed",
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index d3d8431c163..d0e4761a10d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -376,7 +376,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     }
 
     fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) {
-        self.print_token_literal(lit.token_lit, lit.span)
+        self.print_token_literal(lit.as_token_lit(), lit.span)
     }
 
     fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 4ed16e337d2..3b17f6dd627 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -2,6 +2,8 @@ use crate::pp::Breaks::Inconsistent;
 use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT};
 
 use rustc_ast::ptr::P;
+use rustc_ast::token;
+use rustc_ast::util::literal::escape_byte_str_symbol;
 use rustc_ast::util::parser::{self, AssocOp, Fixity};
 use rustc_ast::{self as ast, BlockCheckMode};
 
@@ -323,7 +325,7 @@ impl<'a> State<'a> {
                 self.print_token_literal(*token_lit, expr.span);
             }
             ast::ExprKind::IncludedBytes(bytes) => {
-                let lit = ast::LitKind::ByteStr(bytes.clone()).to_token_lit();
+                let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
                 self.print_token_literal(lit, expr.span)
             }
             ast::ExprKind::Cast(expr, ty) => {
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 5e3745f1735..72c0257756e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -697,8 +697,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     .map_bound(|p| p.predicates),
                 None,
             ),
-            ty::Opaque(did, substs) => {
-                find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*did), Some(*substs))
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*def_id), Some(*substs))
             }
             ty::Closure(_, substs) => match substs.as_closure().kind() {
                 ty::ClosureKind::Fn => Some(hir::Mutability::Not),
@@ -745,7 +745,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             err.span_suggestion_verbose(
                 span.shrink_to_hi(),
                 "consider cloning the value if the performance cost is acceptable",
-                ".clone()".to_string(),
+                ".clone()",
                 Applicability::MachineApplicable,
             );
         }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 4e2271a3067..cbd59005200 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1059,17 +1059,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     );
                     if self.fn_self_span_reported.insert(fn_span) {
                         err.span_note(
-                            // Check whether the source is accessible
-                            if self.infcx.tcx.sess.source_map().is_span_accessible(self_arg.span) {
-                                self_arg.span
-                            } else {
-                                fn_call_span
-                            },
+                            self_arg.span,
                             "calling this operator moves the left-hand side",
                         );
                     }
                 }
-                CallKind::Normal { self_arg, desugaring, is_option_or_result } => {
+                CallKind::Normal { self_arg, desugaring, method_did } => {
                     let self_arg = self_arg.unwrap();
                     if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
                         let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
@@ -1139,14 +1134,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             ),
                         );
                     }
+                    let tcx = self.infcx.tcx;
                     // Avoid pointing to the same function in multiple different
                     // error messages.
                     if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
+                        let func = tcx.def_path_str(method_did);
                         err.span_note(
                             self_arg.span,
-                            &format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
+                            &format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}")
                         );
                     }
+                    let parent_did = tcx.parent(method_did);
+                    let parent_self_ty = (tcx.def_kind(parent_did)
+                        == rustc_hir::def::DefKind::Impl)
+                        .then_some(parent_did)
+                        .and_then(|did| match tcx.type_of(did).kind() {
+                            ty::Adt(def, ..) => Some(def.did()),
+                            _ => None,
+                        });
+                    let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
+                        matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
+                    });
                     if is_option_or_result && maybe_reinitialized_locations_is_empty {
                         err.span_label(
                             var_span,
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 5a47f45677e..6db3c858ae7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -4,7 +4,7 @@ use rustc_middle::ty;
 use rustc_mir_dataflow::move_paths::{
     IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
 };
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
 
 use crate::diagnostics::{DescribePlaceOpt, UseSpans};
 use crate::prefixes::PrefixSet;
@@ -148,7 +148,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         match_span: Span,
         statement_span: Span,
     ) {
-        debug!("append_binding_error(match_place={:?}, match_span={:?})", match_place, match_span);
+        debug!(?match_place, ?match_span, "append_binding_error");
 
         let from_simple_let = match_place.is_none();
         let match_place = match_place.unwrap_or(move_from);
@@ -160,7 +160,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge
                         && match_span == *span
                     {
-                        debug!("appending local({:?}) to list", bind_to);
+                        debug!("appending local({bind_to:?}) to list");
                         if !binds_to.is_empty() {
                             binds_to.push(bind_to);
                         }
@@ -198,7 +198,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     } = ge
                     {
                         if match_span == *span && mpi == *other_mpi {
-                            debug!("appending local({:?}) to list", bind_to);
+                            debug!("appending local({bind_to:?}) to list");
                             binds_to.push(bind_to);
                             return;
                         }
@@ -410,15 +410,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diagnostic, span: Span) {
         match error {
             GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {
-                if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
-                    err.span_suggestion(
-                        span,
-                        "consider borrowing here",
-                        format!("&{snippet}"),
-                        Applicability::Unspecified,
-                    );
-                }
-
+                self.add_borrow_suggestions(err, span);
                 if binds_to.is_empty() {
                     let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
                     let place_desc = match self.describe_place(move_from.as_ref()) {
@@ -461,39 +453,75 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         }
     }
 
+    fn add_borrow_suggestions(&self, err: &mut Diagnostic, span: Span) {
+        match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
+            Ok(snippet) if snippet.starts_with('*') => {
+                err.span_suggestion_verbose(
+                    span.with_hi(span.lo() + BytePos(1)),
+                    "consider removing the dereference here",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            _ => {
+                err.span_suggestion_verbose(
+                    span.shrink_to_lo(),
+                    "consider borrowing here",
+                    "&".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
+    }
+
     fn add_move_error_suggestions(&self, err: &mut Diagnostic, binds_to: &[Local]) {
-        let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
+        let mut suggestions: Vec<(Span, String, String)> = Vec::new();
         for local in binds_to {
             let bind_to = &self.body.local_decls[*local];
             if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
                 VarBindingForm { pat_span, .. },
             )))) = bind_to.local_info
             {
-                if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
+                let Ok(pat_snippet) =
+                    self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
+                let Some(stripped) = pat_snippet.strip_prefix('&') else {
+                    suggestions.push((
+                        bind_to.source_info.span.shrink_to_lo(),
+                        "consider borrowing the pattern binding".to_string(),
+                        "ref ".to_string(),
+                    ));
+                    continue;
+                };
+                let inner_pat_snippet = stripped.trim_start();
+                let (pat_span, suggestion, to_remove) = if inner_pat_snippet.starts_with("mut")
+                    && inner_pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
                 {
-                    if let Some(stripped) = pat_snippet.strip_prefix('&') {
-                        let pat_snippet = stripped.trim_start();
-                        let (suggestion, to_remove) = if pat_snippet.starts_with("mut")
-                            && pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
-                        {
-                            (pat_snippet["mut".len()..].trim_start(), "&mut")
-                        } else {
-                            (pat_snippet, "&")
-                        };
-                        suggestions.push((pat_span, to_remove, suggestion.to_owned()));
-                    }
-                }
+                    let inner_pat_snippet = inner_pat_snippet["mut".len()..].trim_start();
+                    let pat_span = pat_span.with_hi(
+                        pat_span.lo()
+                            + BytePos((pat_snippet.len() - inner_pat_snippet.len()) as u32),
+                    );
+                    (pat_span, String::new(), "mutable borrow")
+                } else {
+                    let pat_span = pat_span.with_hi(
+                        pat_span.lo()
+                            + BytePos(
+                                (pat_snippet.len() - inner_pat_snippet.trim_start().len()) as u32,
+                            ),
+                    );
+                    (pat_span, String::new(), "borrow")
+                };
+                suggestions.push((
+                    pat_span,
+                    format!("consider removing the {to_remove}"),
+                    suggestion.to_string(),
+                ));
             }
         }
         suggestions.sort_unstable_by_key(|&(span, _, _)| span);
         suggestions.dedup_by_key(|&mut (span, _, _)| span);
-        for (span, to_remove, suggestion) in suggestions {
-            err.span_suggestion(
-                span,
-                &format!("consider removing the `{to_remove}`"),
-                suggestion,
-                Applicability::MachineApplicable,
-            );
+        for (span, msg, suggestion) in suggestions {
+            err.span_suggestion_verbose(span, &msg, suggestion, Applicability::MachineApplicable);
         }
     }
 
@@ -521,8 +549,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
         if binds_to.len() > 1 {
             err.note(
-                "move occurs because these variables have types that \
-                      don't implement the `Copy` trait",
+                "move occurs because these variables have types that don't implement the `Copy` \
+                 trait",
             );
         }
     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 9bc2e79e29b..f8ec5e5e799 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -504,7 +504,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
 
         let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
-        if let ty::Opaque(def_id, _) = *output_ty.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *output_ty.kind() {
             output_ty = self.infcx.tcx.type_of(def_id)
         };
 
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 90e2b6b698c..e9c98bdc514 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -747,27 +747,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Otherwise, we need to find the minimum remaining choice, if
         // any, and take that.
         debug!("choice_regions remaining are {:#?}", choice_regions);
-        let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
-            let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
-            let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
-            match (r1_outlives_r2, r2_outlives_r1) {
-                (true, true) => Some(r1.min(r2)),
-                (true, false) => Some(r2),
-                (false, true) => Some(r1),
-                (false, false) => None,
-            }
+        let Some(&min_choice) = choice_regions.iter().find(|&r1| {
+            choice_regions.iter().all(|&r2| {
+                self.universal_region_relations.outlives(r2, *r1)
+            })
+        }) else {
+            debug!("no choice region outlived by all others");
+            return false;
         };
-        let mut min_choice = choice_regions[0];
-        for &other_option in &choice_regions[1..] {
-            debug!(?min_choice, ?other_option,);
-            match min(min_choice, other_option) {
-                Some(m) => min_choice = m,
-                None => {
-                    debug!(?min_choice, ?other_option, "incomparable; no min choice",);
-                    return false;
-                }
-            }
-        }
 
         let min_choice_scc = self.constraint_sccs.scc(min_choice);
         debug!(?min_choice, ?min_choice_scc);
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index 95e38e4b053..dcf500ddbd3 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -32,7 +32,7 @@ pub fn expand(
             (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
         } else {
             ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
-            return vec![orig_item.clone()];
+            return vec![orig_item];
         };
 
     // Generate a bunch of new items using the AllocFnFactory
diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs
index 9ae65c641fd..7da9bdc38a2 100644
--- a/compiler/rustc_builtin_macros/src/concat.rs
+++ b/compiler/rustc_builtin_macros/src/concat.rs
@@ -4,8 +4,6 @@ use rustc_expand::base::{self, DummyResult};
 use rustc_session::errors::report_lit_error;
 use rustc_span::symbol::Symbol;
 
-use std::string::String;
-
 pub fn expand_concat(
     cx: &mut base::ExtCtxt<'_>,
     sp: rustc_span::Span,
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 70ce5a6c419..4f1a7d709ff 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -69,7 +69,7 @@ fn invalid_type_err(
         Ok(ast::LitKind::Int(_, _)) => {
             cx.span_err(span, "numeric literal is not a `u8`");
         }
-        Ok(ast::LitKind::ByteStr(_) | ast::LitKind::Byte(_)) => unreachable!(),
+        Ok(ast::LitKind::ByteStr(..) | ast::LitKind::Byte(_)) => unreachable!(),
         Err(err) => {
             report_lit_error(&cx.sess.parse_sess, err, token_lit, span);
         }
@@ -97,7 +97,7 @@ fn handle_array_element(
             )) if val <= u8::MAX.into() => Some(val as u8),
 
             Ok(ast::LitKind::Byte(val)) => Some(val),
-            Ok(ast::LitKind::ByteStr(_)) => {
+            Ok(ast::LitKind::ByteStr(..)) => {
                 if !*has_errors {
                     cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
                         .note("byte strings are treated as arrays of bytes")
@@ -174,7 +174,7 @@ pub fn expand_concat_bytes(
                 Ok(ast::LitKind::Byte(val)) => {
                     accumulator.push(val);
                 }
-                Ok(ast::LitKind::ByteStr(ref bytes)) => {
+                Ok(ast::LitKind::ByteStr(ref bytes, _)) => {
                     accumulator.extend_from_slice(&bytes);
                 }
                 _ => {
@@ -196,7 +196,7 @@ pub fn expand_concat_bytes(
         }
     }
     if !missing_literals.is_empty() {
-        let mut err = cx.struct_span_err(missing_literals.clone(), "expected a byte literal");
+        let mut err = cx.struct_span_err(missing_literals, "expected a byte literal");
         err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`");
         err.emit();
         return base::MacEager::expr(DummyResult::raw_expr(sp, true));
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index fa5a45730ac..2a8dc02849e 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -1,7 +1,7 @@
 use crate::cfg_eval::cfg_eval;
 
 use rustc_ast as ast;
-use rustc_ast::{token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
+use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
 use rustc_feature::AttributeTemplate;
@@ -130,9 +130,11 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
 }
 
 fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
-    let help_msg = match lit.token_lit.kind {
-        token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => {
-            format!("try using `#[derive({})]`", lit.token_lit.symbol)
+    let help_msg = match lit.kind {
+        ast::LitKind::Str(_, ast::StrStyle::Cooked)
+            if rustc_lexer::is_ident(lit.symbol.as_str()) =>
+        {
+            format!("try using `#[derive({})]`", lit.symbol)
         }
         _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
     };
diff --git a/compiler/rustc_codegen_cranelift/.cirrus.yml b/compiler/rustc_codegen_cranelift/.cirrus.yml
index 732edd66196..d627c2ee09c 100644
--- a/compiler/rustc_codegen_cranelift/.cirrus.yml
+++ b/compiler/rustc_codegen_cranelift/.cirrus.yml
@@ -12,8 +12,6 @@ task:
     folder: target
   prepare_script:
     - . $HOME/.cargo/env
-    - git config --global user.email "user@example.com"
-    - git config --global user.name "User"
     - ./y.rs prepare
   test_script:
     - . $HOME/.cargo/env
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index 5061010c86c..a6bb12a66a2 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -19,6 +19,7 @@ jobs:
     - name: Rustfmt
       run: |
         cargo fmt --check
+        rustfmt --check build_system/mod.rs
 
   build:
     runs-on: ${{ matrix.os }}
@@ -28,7 +29,7 @@ jobs:
       fail-fast: false
       matrix:
         include:
-          - os: ubuntu-latest
+          - os: ubuntu-20.04 # FIXME switch to ubuntu-22.04 once #1303 is fixed
             env:
               TARGET_TRIPLE: x86_64-unknown-linux-gnu
           - os: macos-latest
@@ -41,18 +42,22 @@ jobs:
           - os: ubuntu-latest
             env:
               TARGET_TRIPLE: aarch64-unknown-linux-gnu
+          # s390x requires QEMU 6.1 or greater, we could build it from source, but ubuntu 22.04 comes with 6.2 by default
+          - os: ubuntu-latest
+            env:
+              TARGET_TRIPLE: s390x-unknown-linux-gnu
 
     steps:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -60,9 +65,9 @@ jobs:
         key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Install MinGW toolchain and wine
@@ -78,11 +83,14 @@ jobs:
         sudo apt-get update
         sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user
 
-    - name: Prepare dependencies
+    - name: Install s390x toolchain and qemu
+      if: matrix.env.TARGET_TRIPLE == 's390x-unknown-linux-gnu'
       run: |
-        git config --global user.email "user@example.com"
-        git config --global user.name "User"
-        ./y.rs prepare
+        sudo apt-get update
+        sudo apt-get install -y gcc-s390x-linux-gnu qemu-user
+
+    - name: Prepare dependencies
+      run: ./y.rs prepare
 
     - name: Build without unstable features
       env:
@@ -110,7 +118,7 @@ jobs:
         ./y.rs test
 
     - name: Package prebuilt cg_clif
-      run: tar cvfJ cg_clif.tar.xz build
+      run: tar cvfJ cg_clif.tar.xz dist
 
     - name: Upload prebuilt cg_clif
       if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
@@ -121,7 +129,7 @@ jobs:
 
     - name: Upload prebuilt cg_clif (cross compile)
       if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v3
       with:
         name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
         path: cg_clif.tar.xz
@@ -147,13 +155,13 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -161,9 +169,9 @@ jobs:
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Set MinGW as the default toolchain
@@ -172,8 +180,6 @@ jobs:
 
     - name: Prepare dependencies
       run: |
-        git config --global user.email "user@example.com"
-        git config --global user.name "User"
         git config --global core.autocrlf false
         rustc y.rs -o y.exe -g
         ./y.exe prepare
@@ -198,24 +204,24 @@ jobs:
 
         # Enable extra checks
         $Env:CG_CLIF_ENABLE_VERIFIER=1
-        
+
         # WIP Disable some tests
-        
+
         # This fails due to some weird argument handling by hyperfine, not an actual regression
         # more of a build system issue
         (Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' |  Out-File config.txt
-        
-        # This fails with a different output than expected 
+
+        # This fails with a different output than expected
         (Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' |  Out-File config.txt
 
         ./y.exe test
 
     - name: Package prebuilt cg_clif
       # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
-      run: tar cvf cg_clif.tar build
+      run: tar cvf cg_clif.tar dist
 
     - name: Upload prebuilt cg_clif
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v3
       with:
         name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
         path: cg_clif.tar
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml b/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml
index 0a3e7ca073b..d0d58d2a7ea 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml
@@ -14,7 +14,7 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ubuntu-latest-cargo-installed-crates
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
index b8a98b83ebe..bef806318ef 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
@@ -11,13 +11,13 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -25,9 +25,9 @@ jobs:
         key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Prepare dependencies
@@ -49,13 +49,13 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -63,9 +63,9 @@ jobs:
         key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Prepare dependencies
diff --git a/compiler/rustc_codegen_cranelift/.gitignore b/compiler/rustc_codegen_cranelift/.gitignore
index fae09592c6a..b443fd58a1b 100644
--- a/compiler/rustc_codegen_cranelift/.gitignore
+++ b/compiler/rustc_codegen_cranelift/.gitignore
@@ -14,5 +14,6 @@ perf.data.old
 /build_sysroot/sysroot_src
 /build_sysroot/compiler-builtins
 /build_sysroot/rustc_version
+/dist
 /rust
 /download
diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json
index 13301bf20a5..bc914e37d2b 100644
--- a/compiler/rustc_codegen_cranelift/.vscode/settings.json
+++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json
@@ -4,16 +4,10 @@
     "rust-analyzer.imports.granularity.enforce": true,
     "rust-analyzer.imports.granularity.group": "module",
     "rust-analyzer.imports.prefix": "crate",
-    "rust-analyzer.cargo.features": ["unstable-features"],
+    "rust-analyzer.cargo.features": ["unstable-features", "__check_build_system_using_ra"],
     "rust-analyzer.linkedProjects": [
         "./Cargo.toml",
-        //"./build_sysroot/sysroot_src/library/std/Cargo.toml",
         {
-            "roots": [
-                "./example/mini_core.rs",
-                "./example/mini_core_hello_world.rs",
-                "./example/mod_bench.rs"
-            ],
             "crates": [
                 {
                     "root_module": "./example/mini_core.rs",
@@ -36,34 +30,11 @@
             ]
         },
         {
-            "roots": ["./example/std_example.rs"],
+            "sysroot_src": "./build_sysroot/sysroot_src/library",
             "crates": [
                 {
                     "root_module": "./example/std_example.rs",
-                    "edition": "2018",
-                    "deps": [{ "crate": 1, "name": "std" }],
-                    "cfg": [],
-                },
-                {
-                    "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
-                    "edition": "2018",
-                    "deps": [],
-                    "cfg": [],
-                },
-            ]
-        },
-        {
-            "roots": ["./y.rs"],
-            "crates": [
-                {
-                    "root_module": "./y.rs",
-                    "edition": "2018",
-                    "deps": [{ "crate": 1, "name": "std" }],
-                    "cfg": [],
-                },
-                {
-                    "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
-                    "edition": "2018",
+                    "edition": "2015",
                     "deps": [],
                     "cfg": [],
                 },
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index 3b406036c35..e4d3e9ca5ae 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -15,9 +15,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.60"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142"
+checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "arrayvec"
@@ -39,9 +39,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bumpalo"
-version = "3.11.0"
+version = "3.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
 
 [[package]]
 name = "byteorder"
@@ -57,24 +57,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a"
+checksum = "b62c772976416112fa4484cbd688cb6fb35fd430005c1c586224fc014018abad"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf"
+checksum = "9b40ed2dd13c2ac7e24f88a3090c68ad3414eb1d066a95f8f1f7b3b819cb4e46"
 dependencies = [
  "arrayvec",
  "bumpalo",
  "cranelift-bforest",
  "cranelift-codegen-meta",
  "cranelift-codegen-shared",
+ "cranelift-egraph",
  "cranelift-entity",
  "cranelift-isle",
  "gimli",
@@ -86,30 +87,44 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5"
+checksum = "bb927a8f1c27c34ee3759b6b0ffa528d2330405d5cc4511f0cab33fe2279f4b5"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e"
+checksum = "43dfa417b884a9ab488d95fd6b93b25e959321fe7bfd7a0a960ba5d7fb7ab927"
+
+[[package]]
+name = "cranelift-egraph"
+version = "0.90.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a66b39785efd8513d2cca967ede56d6cc57c8d7986a595c7c47d0c78de8dce"
+dependencies = [
+ "cranelift-entity",
+ "fxhash",
+ "hashbrown",
+ "indexmap",
+ "log",
+ "smallvec",
+]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103"
+checksum = "0637ffde963cb5d759bc4d454cfa364b6509e6c74cdaa21298add0ed9276f346"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc"
+checksum = "fb72b8342685e850cb037350418f62cc4fc55d6c2eb9c7ca01b82f9f1a6f3d56"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -119,15 +134,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293"
+checksum = "850579cb9e4b448f7c301f1e6e6cbad99abe3f1f1d878a4994cb66e33c6db8cd"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015"
+checksum = "9add822ad66dcbe152b5ab57de10240a2df4505099f2f6c27159acb711890bd4"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -138,14 +153,15 @@ dependencies = [
  "log",
  "region",
  "target-lexicon",
+ "wasmtime-jit-icache-coherence",
  "windows-sys",
 ]
 
 [[package]]
 name = "cranelift-module"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49"
+checksum = "406b772626fc2664864cf947f3895a23b619895c7fff635f3622e2d857f4492f"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -153,9 +169,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4"
+checksum = "2d0a279e5bcba3e0466c734d8d8eb6bfc1ad29e95c37f3e4955b492b5616335e"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -164,9 +180,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b"
+checksum = "39793c550f0c1d7db96c2fc1324583670c8143befe6edbfbaf1c68aba53be983"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -186,6 +202,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
+[[package]]
 name = "fxhash"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -196,9 +218,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
 dependencies = [
  "cfg-if",
  "libc",
@@ -211,7 +233,9 @@ version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
 dependencies = [
+ "fallible-iterator",
  "indexmap",
+ "stable_deref_trait",
 ]
 
 [[package]]
@@ -225,9 +249,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "1.9.1"
+version = "1.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
 dependencies = [
  "autocfg",
  "hashbrown",
@@ -235,15 +259,15 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.127"
+version = "0.2.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
 
 [[package]]
 name = "libloading"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
 dependencies = [
  "cfg-if",
  "winapi",
@@ -287,15 +311,15 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.13.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
 
 [[package]]
 name = "regalloc2"
-version = "0.3.2"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779"
+checksum = "91b2eab54204ea0117fe9a060537e0b07a4e72f7c7d182361ecc346cab2240e5"
 dependencies = [
  "fxhash",
  "log",
@@ -342,15 +366,21 @@ checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec"
 
 [[package]]
 name = "smallvec"
-version = "1.9.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
 [[package]]
 name = "target-lexicon"
-version = "0.12.4"
+version = "0.12.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
+checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
 
 [[package]]
 name = "version_check"
@@ -365,6 +395,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
+name = "wasmtime-jit-icache-coherence"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6bbabb309c06cc238ee91b1455b748c45f0bdcab0dda2c2db85b0a1e69fcb66"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index 0fdd5de118c..2b216ca072f 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -3,17 +3,24 @@ name = "rustc_codegen_cranelift"
 version = "0.1.0"
 edition = "2021"
 
+[[bin]]
+# This is used just to teach rust-analyzer how to check the build system. required-features is used
+# to disable it for regular builds.
+name = "y"
+path = "./y.rs"
+required-features = ["__check_build_system_using_ra"]
+
 [lib]
 crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.88.1"
-cranelift-module = "0.88.1"
-cranelift-native = "0.88.1"
-cranelift-jit = { version = "0.88.1", optional = true }
-cranelift-object = "0.88.1"
+cranelift-codegen = { version = "0.90.1", features = ["unwind", "all-arch"] }
+cranelift-frontend = "0.90.1"
+cranelift-module = "0.90.1"
+cranelift-native = "0.90.1"
+cranelift-jit = { version = "0.90.1", optional = true }
+cranelift-object = "0.90.1"
 target-lexicon = "0.12.0"
 gimli = { version = "0.26.0", default-features = false, features = ["write"]}
 object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
@@ -39,6 +46,7 @@ smallvec = "1.8.1"
 unstable-features = ["jit", "inline_asm"]
 jit = ["cranelift-jit", "libloading"]
 inline_asm = []
+__check_build_system_using_ra = []
 
 [package.metadata.rust-analyzer]
 rustc_private = true
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index 1e84c7fa365..0e9c77244d4 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -37,7 +37,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo
 In the directory with your project (where you can do the usual `cargo build`), run:
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif build
+$ $cg_clif_dir/dist/cargo-clif build
 ```
 
 This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
index f6a9cb67290..bba3210536e 100644
--- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.16.0"
+version = "0.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
 dependencies = [
  "compiler_builtins",
  "gimli",
@@ -33,26 +33,10 @@ dependencies = [
 ]
 
 [[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
-[[package]]
 name = "cc"
-version = "1.0.73"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
+version = "1.0.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
+checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
 
 [[package]]
 name = "cfg-if"
@@ -66,9 +50,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.82"
+version = "0.1.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
+checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -111,9 +95,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.25.0"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
@@ -145,9 +129,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.135"
+version = "0.2.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -164,12 +148,11 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.4.4"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
 dependencies = [
  "adler",
- "autocfg",
  "compiler_builtins",
  "rustc-std-workspace-alloc",
  "rustc-std-workspace-core",
@@ -177,9 +160,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.26.2"
+version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
 dependencies = [
  "compiler_builtins",
  "memchr",
@@ -192,7 +175,7 @@ name = "panic_abort"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if 0.1.10",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -203,7 +186,7 @@ name = "panic_unwind"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if 0.1.10",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -255,7 +238,7 @@ version = "0.0.0"
 dependencies = [
  "addr2line",
  "alloc",
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "dlmalloc",
@@ -277,7 +260,7 @@ dependencies = [
 name = "std_detect"
 version = "0.1.5"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "libc",
  "rustc-std-workspace-alloc",
@@ -299,7 +282,7 @@ dependencies = [
 name = "test"
 version = "0.0.0"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
  "core",
  "getopts",
  "libc",
@@ -325,7 +308,7 @@ name = "unwind"
 version = "0.0.0"
 dependencies = [
  "cc",
- "cfg-if 0.1.10",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
index fae5b271636..a081fdaa1c7 100644
--- a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
@@ -1,16 +1,21 @@
-use std::env;
 use std::path::Path;
 
 use super::build_sysroot;
 use super::config;
-use super::prepare;
-use super::utils::{cargo_command, spawn_and_wait};
+use super::path::Dirs;
+use super::prepare::GitRepo;
+use super::utils::{spawn_and_wait, CargoProject, Compiler};
 use super::SysrootKind;
 
+pub(crate) static ABI_CAFE_REPO: GitRepo =
+    GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
+
+static ABI_CAFE: CargoProject = CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe");
+
 pub(crate) fn run(
     channel: &str,
     sysroot_kind: SysrootKind,
-    target_dir: &Path,
+    dirs: &Dirs,
     cg_clif_dylib: &Path,
     host_triple: &str,
     target_triple: &str,
@@ -27,26 +32,25 @@ pub(crate) fn run(
 
     eprintln!("Building sysroot for abi-cafe");
     build_sysroot::build_sysroot(
+        dirs,
         channel,
         sysroot_kind,
-        target_dir,
         cg_clif_dylib,
         host_triple,
         target_triple,
     );
 
     eprintln!("Running abi-cafe");
-    let abi_cafe_path = prepare::ABI_CAFE.source_dir();
-    env::set_current_dir(abi_cafe_path.clone()).unwrap();
 
     let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
 
-    let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path);
+    let mut cmd = ABI_CAFE.run(&Compiler::host(), dirs);
     cmd.arg("--");
     cmd.arg("--pairs");
     cmd.args(pairs);
     cmd.arg("--add-rustc-codegen-backend");
     cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
+    cmd.current_dir(ABI_CAFE.source_dir(dirs));
 
     spawn_and_wait(cmd);
 }
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
index cda468bcfa2..fde8ef424cc 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
@@ -1,16 +1,19 @@
 use std::env;
 use std::path::PathBuf;
 
+use super::path::{Dirs, RelPath};
 use super::rustc_info::get_file_name;
-use super::utils::{cargo_command, is_ci};
+use super::utils::{is_ci, CargoProject, Compiler};
+
+static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
 
 pub(crate) fn build_backend(
+    dirs: &Dirs,
     channel: &str,
     host_triple: &str,
     use_unstable_features: bool,
 ) -> PathBuf {
-    let source_dir = std::env::current_dir().unwrap();
-    let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
+    let mut cmd = CG_CLIF.build(&Compiler::host(), dirs);
 
     cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
 
@@ -41,8 +44,8 @@ pub(crate) fn build_backend(
     eprintln!("[BUILD] rustc_codegen_cranelift");
     super::utils::spawn_and_wait(cmd);
 
-    source_dir
-        .join("target")
+    CG_CLIF
+        .target_dir(dirs)
         .join(host_triple)
         .join(channel)
         .join(get_file_name("rustc_codegen_cranelift", "dylib"))
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
index 856aecc49fd..cbbf09b9b97 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
@@ -1,57 +1,60 @@
 use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::process::{self, Command};
 
+use super::path::{Dirs, RelPath};
 use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
-use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
+use super::utils::{spawn_and_wait, try_hard_link, CargoProject, Compiler};
 use super::SysrootKind;
 
+static DIST_DIR: RelPath = RelPath::DIST;
+static BIN_DIR: RelPath = RelPath::DIST.join("bin");
+static LIB_DIR: RelPath = RelPath::DIST.join("lib");
+static RUSTLIB_DIR: RelPath = LIB_DIR.join("rustlib");
+
 pub(crate) fn build_sysroot(
+    dirs: &Dirs,
     channel: &str,
     sysroot_kind: SysrootKind,
-    target_dir: &Path,
     cg_clif_dylib_src: &Path,
     host_triple: &str,
     target_triple: &str,
 ) {
     eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
 
-    if target_dir.exists() {
-        fs::remove_dir_all(target_dir).unwrap();
-    }
-    fs::create_dir_all(target_dir.join("bin")).unwrap();
-    fs::create_dir_all(target_dir.join("lib")).unwrap();
+    DIST_DIR.ensure_fresh(dirs);
+    BIN_DIR.ensure_exists(dirs);
+    LIB_DIR.ensure_exists(dirs);
 
     // Copy the backend
-    let cg_clif_dylib_path = target_dir
-        .join(if cfg!(windows) {
-            // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
-            // binaries.
-            "bin"
-        } else {
-            "lib"
-        })
-        .join(get_file_name("rustc_codegen_cranelift", "dylib"));
+    let cg_clif_dylib_path = if cfg!(windows) {
+        // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
+        // binaries.
+        BIN_DIR
+    } else {
+        LIB_DIR
+    }
+    .to_path(dirs)
+    .join(get_file_name("rustc_codegen_cranelift", "dylib"));
     try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
 
     // Build and copy rustc and cargo wrappers
-    for wrapper in ["rustc-clif", "cargo-clif"] {
+    for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] {
         let wrapper_name = get_wrapper_file_name(wrapper, "bin");
 
         let mut build_cargo_wrapper_cmd = Command::new("rustc");
         build_cargo_wrapper_cmd
-            .arg(PathBuf::from("scripts").join(format!("{wrapper}.rs")))
+            .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
             .arg("-o")
-            .arg(target_dir.join(wrapper_name))
+            .arg(DIST_DIR.to_path(dirs).join(wrapper_name))
             .arg("-g");
         spawn_and_wait(build_cargo_wrapper_cmd);
     }
 
     let default_sysroot = super::rustc_info::get_default_sysroot();
 
-    let rustlib = target_dir.join("lib").join("rustlib");
-    let host_rustlib_lib = rustlib.join(host_triple).join("lib");
-    let target_rustlib_lib = rustlib.join(target_triple).join("lib");
+    let host_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(host_triple).join("lib");
+    let target_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(target_triple).join("lib");
     fs::create_dir_all(&host_rustlib_lib).unwrap();
     fs::create_dir_all(&target_rustlib_lib).unwrap();
 
@@ -112,24 +115,18 @@ pub(crate) fn build_sysroot(
             }
         }
         SysrootKind::Clif => {
-            build_clif_sysroot_for_triple(
-                channel,
-                target_dir,
-                host_triple,
-                &cg_clif_dylib_path,
-                None,
-            );
+            build_clif_sysroot_for_triple(dirs, channel, host_triple, &cg_clif_dylib_path, None);
 
             if host_triple != target_triple {
                 // When cross-compiling it is often necessary to manually pick the right linker
-                let linker = if target_triple == "aarch64-unknown-linux-gnu" {
-                    Some("aarch64-linux-gnu-gcc")
-                } else {
-                    None
+                let linker = match target_triple {
+                    "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu-gcc"),
+                    "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu-gcc"),
+                    _ => None,
                 };
                 build_clif_sysroot_for_triple(
+                    dirs,
                     channel,
-                    target_dir,
                     target_triple,
                     &cg_clif_dylib_path,
                     linker,
@@ -142,21 +139,26 @@ pub(crate) fn build_sysroot(
                 let file = file.unwrap().path();
                 let filename = file.file_name().unwrap().to_str().unwrap();
                 if filename.contains("std-") && !filename.contains(".rlib") {
-                    try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap()));
+                    try_hard_link(&file, LIB_DIR.to_path(dirs).join(file.file_name().unwrap()));
                 }
             }
         }
     }
 }
 
+// FIXME move to download/ or dist/
+pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = RelPath::BUILD_SYSROOT.join("rustc_version");
+pub(crate) static SYSROOT_SRC: RelPath = RelPath::BUILD_SYSROOT.join("sysroot_src");
+static STANDARD_LIBRARY: CargoProject = CargoProject::new(&RelPath::BUILD_SYSROOT, "build_sysroot");
+
 fn build_clif_sysroot_for_triple(
+    dirs: &Dirs,
     channel: &str,
-    target_dir: &Path,
     triple: &str,
     cg_clif_dylib_path: &Path,
     linker: Option<&str>,
 ) {
-    match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) {
+    match fs::read_to_string(SYSROOT_RUSTC_VERSION.to_path(dirs)) {
         Err(e) => {
             eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
             eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source");
@@ -174,7 +176,7 @@ fn build_clif_sysroot_for_triple(
         }
     }
 
-    let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel);
+    let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(triple).join(channel);
 
     if !super::config::get_bool("keep_sysroot") {
         // Cleanup the deps dir, but keep build scripts and the incremental cache for faster
@@ -185,27 +187,27 @@ fn build_clif_sysroot_for_triple(
     }
 
     // Build sysroot
-    let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot"));
     let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
     rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
-    rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap()));
+    rustflags.push_str(&format!(" --sysroot={}", DIST_DIR.to_path(dirs).to_str().unwrap()));
     if channel == "release" {
-        build_cmd.arg("--release");
         rustflags.push_str(" -Zmir-opt-level=3");
     }
     if let Some(linker) = linker {
         use std::fmt::Write;
         write!(rustflags, " -Clinker={}", linker).unwrap();
     }
-    build_cmd.env("RUSTFLAGS", rustflags);
+    let mut compiler = Compiler::with_triple(triple.to_owned());
+    compiler.rustflags = rustflags;
+    let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
+    if channel == "release" {
+        build_cmd.arg("--release");
+    }
     build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
     spawn_and_wait(build_cmd);
 
     // Copy all relevant files to the sysroot
-    for entry in
-        fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps"))
-            .unwrap()
-    {
+    for entry in fs::read_dir(build_dir.join("deps")).unwrap() {
         let entry = entry.unwrap();
         if let Some(ext) = entry.path().extension() {
             if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" {
@@ -216,7 +218,7 @@ fn build_clif_sysroot_for_triple(
         };
         try_hard_link(
             entry.path(),
-            target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()),
+            RUSTLIB_DIR.to_path(dirs).join(triple).join("lib").join(entry.file_name()),
         );
     }
 }
diff --git a/compiler/rustc_codegen_cranelift/build_system/mod.rs b/compiler/rustc_codegen_cranelift/build_system/mod.rs
index b25270d832c..1afc9a55c73 100644
--- a/compiler/rustc_codegen_cranelift/build_system/mod.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/mod.rs
@@ -8,20 +8,37 @@ mod abi_cafe;
 mod build_backend;
 mod build_sysroot;
 mod config;
+mod path;
 mod prepare;
 mod rustc_info;
 mod tests;
 mod utils;
 
+const USAGE: &str = r#"The build system of cg_clif.
+
+USAGE:
+    ./y.rs prepare [--out-dir DIR]
+    ./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+    ./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+
+OPTIONS:
+    --sysroot none|clif|llvm
+            Which sysroot libraries to use:
+            `none` will not include any standard library in the sysroot.
+            `clif` will build the standard library using Cranelift.
+            `llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM.
+
+    --out-dir DIR
+            Specify the directory in which the download, build and dist directories are stored.
+            By default this is the working directory.
+
+    --no-unstable-features
+            fSome features are not yet ready for production usage. This option will disable these
+            features. This includes the JIT mode and inline assembly support.
+"#;
+
 fn usage() {
-    eprintln!("Usage:");
-    eprintln!("  ./y.rs prepare");
-    eprintln!(
-        "  ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
-    );
-    eprintln!(
-        "  ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
-    );
+    eprintln!("{USAGE}");
 }
 
 macro_rules! arg_error {
@@ -34,6 +51,7 @@ macro_rules! arg_error {
 
 #[derive(PartialEq, Debug)]
 enum Command {
+    Prepare,
     Build,
     Test,
 }
@@ -48,8 +66,6 @@ pub(crate) enum SysrootKind {
 pub fn main() {
     env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1");
     env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
-    // The target dir is expected in the default location. Guard against the user changing it.
-    env::set_var("CARGO_TARGET_DIR", "target");
 
     if is_ci() {
         // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
@@ -58,13 +74,7 @@ pub fn main() {
 
     let mut args = env::args().skip(1);
     let command = match args.next().as_deref() {
-        Some("prepare") => {
-            if args.next().is_some() {
-                arg_error!("./y.rs prepare doesn't expect arguments");
-            }
-            prepare::prepare();
-            process::exit(0);
-        }
+        Some("prepare") => Command::Prepare,
         Some("build") => Command::Build,
         Some("test") => Command::Test,
         Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
@@ -75,15 +85,15 @@ pub fn main() {
         }
     };
 
-    let mut target_dir = PathBuf::from("build");
+    let mut out_dir = PathBuf::from(".");
     let mut channel = "release";
     let mut sysroot_kind = SysrootKind::Clif;
     let mut use_unstable_features = true;
     while let Some(arg) = args.next().as_deref() {
         match arg {
-            "--target-dir" => {
-                target_dir = PathBuf::from(args.next().unwrap_or_else(|| {
-                    arg_error!("--target-dir requires argument");
+            "--out-dir" => {
+                out_dir = PathBuf::from(args.next().unwrap_or_else(|| {
+                    arg_error!("--out-dir requires argument");
                 }))
             }
             "--debug" => channel = "debug",
@@ -101,7 +111,6 @@ pub fn main() {
             arg => arg_error!("Unexpected argument {}", arg),
         }
     }
-    target_dir = std::env::current_dir().unwrap().join(target_dir);
 
     let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") {
         host_triple
@@ -122,13 +131,43 @@ pub fn main() {
         host_triple.clone()
     };
 
-    let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features);
+    // FIXME allow changing the location of these dirs using cli arguments
+    let current_dir = std::env::current_dir().unwrap();
+    out_dir = current_dir.join(out_dir);
+    let dirs = path::Dirs {
+        source_dir: current_dir.clone(),
+        download_dir: out_dir.join("download"),
+        build_dir: out_dir.join("build"),
+        dist_dir: out_dir.join("dist"),
+    };
+
+    path::RelPath::BUILD.ensure_exists(&dirs);
+
+    {
+        // Make sure we always explicitly specify the target dir
+        let target =
+            path::RelPath::BUILD.join("target_dir_should_be_set_explicitly").to_path(&dirs);
+        env::set_var("CARGO_TARGET_DIR", &target);
+        let _ = std::fs::remove_file(&target);
+        std::fs::File::create(target).unwrap();
+    }
+
+    if command == Command::Prepare {
+        prepare::prepare(&dirs);
+        process::exit(0);
+    }
+
+    let cg_clif_dylib =
+        build_backend::build_backend(&dirs, channel, &host_triple, use_unstable_features);
     match command {
+        Command::Prepare => {
+            // Handled above
+        }
         Command::Test => {
             tests::run_tests(
+                &dirs,
                 channel,
                 sysroot_kind,
-                &target_dir,
                 &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
@@ -137,7 +176,7 @@ pub fn main() {
             abi_cafe::run(
                 channel,
                 sysroot_kind,
-                &target_dir,
+                &dirs,
                 &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
@@ -145,9 +184,9 @@ pub fn main() {
         }
         Command::Build => {
             build_sysroot::build_sysroot(
+                &dirs,
                 channel,
                 sysroot_kind,
-                &target_dir,
                 &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
diff --git a/compiler/rustc_codegen_cranelift/build_system/path.rs b/compiler/rustc_codegen_cranelift/build_system/path.rs
new file mode 100644
index 00000000000..e93981f1d64
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/build_system/path.rs
@@ -0,0 +1,70 @@
+use std::fs;
+use std::path::PathBuf;
+
+#[derive(Debug, Clone)]
+pub(crate) struct Dirs {
+    pub(crate) source_dir: PathBuf,
+    pub(crate) download_dir: PathBuf,
+    pub(crate) build_dir: PathBuf,
+    pub(crate) dist_dir: PathBuf,
+}
+
+#[doc(hidden)]
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum PathBase {
+    Source,
+    Download,
+    Build,
+    Dist,
+}
+
+impl PathBase {
+    fn to_path(self, dirs: &Dirs) -> PathBuf {
+        match self {
+            PathBase::Source => dirs.source_dir.clone(),
+            PathBase::Download => dirs.download_dir.clone(),
+            PathBase::Build => dirs.build_dir.clone(),
+            PathBase::Dist => dirs.dist_dir.clone(),
+        }
+    }
+}
+
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum RelPath {
+    Base(PathBase),
+    Join(&'static RelPath, &'static str),
+}
+
+impl RelPath {
+    pub(crate) const SOURCE: RelPath = RelPath::Base(PathBase::Source);
+    pub(crate) const DOWNLOAD: RelPath = RelPath::Base(PathBase::Download);
+    pub(crate) const BUILD: RelPath = RelPath::Base(PathBase::Build);
+    pub(crate) const DIST: RelPath = RelPath::Base(PathBase::Dist);
+
+    pub(crate) const SCRIPTS: RelPath = RelPath::SOURCE.join("scripts");
+    pub(crate) const BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot");
+    pub(crate) const PATCHES: RelPath = RelPath::SOURCE.join("patches");
+
+    pub(crate) const fn join(&'static self, suffix: &'static str) -> RelPath {
+        RelPath::Join(self, suffix)
+    }
+
+    pub(crate) fn to_path(&self, dirs: &Dirs) -> PathBuf {
+        match self {
+            RelPath::Base(base) => base.to_path(dirs),
+            RelPath::Join(base, suffix) => base.to_path(dirs).join(suffix),
+        }
+    }
+
+    pub(crate) fn ensure_exists(&self, dirs: &Dirs) {
+        fs::create_dir_all(self.to_path(dirs)).unwrap();
+    }
+
+    pub(crate) fn ensure_fresh(&self, dirs: &Dirs) {
+        let path = self.to_path(dirs);
+        if path.exists() {
+            fs::remove_dir_all(&path).unwrap();
+        }
+        fs::create_dir_all(path).unwrap();
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index 3111f62f6c2..8ac67e8f942 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -1,92 +1,75 @@
-use std::env;
 use std::ffi::OsStr;
 use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use super::build_sysroot::{SYSROOT_RUSTC_VERSION, SYSROOT_SRC};
+use super::path::{Dirs, RelPath};
 use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
-use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait};
-
-pub(crate) const ABI_CAFE: GitRepo =
-    GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
-
-pub(crate) const RAND: GitRepo =
-    GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
-
-pub(crate) const REGEX: GitRepo =
-    GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
-
-pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
-    "rust-lang",
-    "portable-simd",
-    "d5cd4a8112d958bd3a252327e0d069a6363249bd",
-    "portable-simd",
-);
-
-pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
-    "ebobby",
-    "simple-raytracer",
-    "804a7a21b9e673a482797aa289a18ed480e4d813",
-    "<none>",
-);
-
-pub(crate) fn prepare() {
-    if Path::new("download").exists() {
-        std::fs::remove_dir_all(Path::new("download")).unwrap();
+use super::utils::{copy_dir_recursively, spawn_and_wait, Compiler};
+
+pub(crate) fn prepare(dirs: &Dirs) {
+    if RelPath::DOWNLOAD.to_path(dirs).exists() {
+        std::fs::remove_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
     }
-    std::fs::create_dir_all(Path::new("download")).unwrap();
+    std::fs::create_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
 
-    prepare_sysroot();
+    prepare_sysroot(dirs);
 
     // FIXME maybe install this only locally?
     eprintln!("[INSTALL] hyperfine");
-    Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
+    Command::new("cargo")
+        .arg("install")
+        .arg("hyperfine")
+        .env_remove("CARGO_TARGET_DIR")
+        .spawn()
+        .unwrap()
+        .wait()
+        .unwrap();
 
-    ABI_CAFE.fetch();
-    RAND.fetch();
-    REGEX.fetch();
-    PORTABLE_SIMD.fetch();
-    SIMPLE_RAYTRACER.fetch();
+    super::abi_cafe::ABI_CAFE_REPO.fetch(dirs);
+    super::tests::RAND_REPO.fetch(dirs);
+    super::tests::REGEX_REPO.fetch(dirs);
+    super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
+    super::tests::SIMPLE_RAYTRACER_REPO.fetch(dirs);
 
     eprintln!("[LLVM BUILD] simple-raytracer");
-    let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir());
+    let host_compiler = Compiler::host();
+    let build_cmd = super::tests::SIMPLE_RAYTRACER.build(&host_compiler, dirs);
     spawn_and_wait(build_cmd);
     fs::copy(
-        SIMPLE_RAYTRACER
-            .source_dir()
-            .join("target")
+        super::tests::SIMPLE_RAYTRACER
+            .target_dir(dirs)
+            .join(&host_compiler.triple)
             .join("debug")
             .join(get_file_name("main", "bin")),
-        SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")),
+        RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
     )
     .unwrap();
 }
 
-fn prepare_sysroot() {
+fn prepare_sysroot(dirs: &Dirs) {
     let rustc_path = get_rustc_path();
     let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
-    let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src");
+    let sysroot_src = SYSROOT_SRC;
 
     assert!(sysroot_src_orig.exists());
 
-    if sysroot_src.exists() {
-        fs::remove_dir_all(&sysroot_src).unwrap();
-    }
-    fs::create_dir_all(sysroot_src.join("library")).unwrap();
+    sysroot_src.ensure_fresh(dirs);
+    fs::create_dir_all(sysroot_src.to_path(dirs).join("library")).unwrap();
     eprintln!("[COPY] sysroot src");
-    copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library"));
+    copy_dir_recursively(
+        &sysroot_src_orig.join("library"),
+        &sysroot_src.to_path(dirs).join("library"),
+    );
 
     let rustc_version = get_rustc_version();
-    fs::write(Path::new("build_sysroot").join("rustc_version"), &rustc_version).unwrap();
+    fs::write(SYSROOT_RUSTC_VERSION.to_path(dirs), &rustc_version).unwrap();
 
     eprintln!("[GIT] init");
-    let mut git_init_cmd = Command::new("git");
-    git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src);
-    spawn_and_wait(git_init_cmd);
-
-    init_git_repo(&sysroot_src);
+    init_git_repo(&sysroot_src.to_path(dirs));
 
-    apply_patches("sysroot", &sysroot_src);
+    apply_patches(dirs, "sysroot", &sysroot_src.to_path(dirs));
 }
 
 pub(crate) struct GitRepo {
@@ -100,7 +83,7 @@ enum GitRepoUrl {
 }
 
 impl GitRepo {
-    const fn github(
+    pub(crate) const fn github(
         user: &'static str,
         repo: &'static str,
         rev: &'static str,
@@ -109,21 +92,25 @@ impl GitRepo {
         GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
     }
 
-    pub(crate) fn source_dir(&self) -> PathBuf {
+    pub(crate) const fn source_dir(&self) -> RelPath {
         match self.url {
-            GitRepoUrl::Github { user: _, repo } => {
-                std::env::current_dir().unwrap().join("download").join(repo)
-            }
+            GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo),
         }
     }
 
-    fn fetch(&self) {
+    fn fetch(&self, dirs: &Dirs) {
         match self.url {
             GitRepoUrl::Github { user, repo } => {
-                clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev);
+                clone_repo_shallow_github(
+                    dirs,
+                    &self.source_dir().to_path(dirs),
+                    user,
+                    repo,
+                    self.rev,
+                );
             }
         }
-        apply_patches(self.patch_name, &self.source_dir());
+        apply_patches(dirs, self.patch_name, &self.source_dir().to_path(dirs));
     }
 }
 
@@ -142,18 +129,16 @@ fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
     spawn_and_wait(checkout_cmd);
 }
 
-fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) {
+fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo: &str, rev: &str) {
     if cfg!(windows) {
         // Older windows doesn't have tar or curl by default. Fall back to using git.
         clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
         return;
     }
 
-    let downloads_dir = std::env::current_dir().unwrap().join("download");
-
     let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
-    let archive_file = downloads_dir.join(format!("{}.tar.gz", rev));
-    let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
+    let archive_file = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}.tar.gz", rev));
+    let archive_dir = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}-{}", repo, rev));
 
     eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
 
@@ -169,7 +154,7 @@ fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &
 
     // Unpack tar archive
     let mut unpack_cmd = Command::new("tar");
-    unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir);
+    unpack_cmd.arg("xf").arg(&archive_file).current_dir(RelPath::DOWNLOAD.to_path(dirs));
     spawn_and_wait(unpack_cmd);
 
     // Rename unpacked dir to the expected name
@@ -191,12 +176,21 @@ fn init_git_repo(repo_dir: &Path) {
     spawn_and_wait(git_add_cmd);
 
     let mut git_commit_cmd = Command::new("git");
-    git_commit_cmd.arg("commit").arg("-m").arg("Initial commit").arg("-q").current_dir(repo_dir);
+    git_commit_cmd
+        .arg("-c")
+        .arg("user.name=Dummy")
+        .arg("-c")
+        .arg("user.email=dummy@example.com")
+        .arg("commit")
+        .arg("-m")
+        .arg("Initial commit")
+        .arg("-q")
+        .current_dir(repo_dir);
     spawn_and_wait(git_commit_cmd);
 }
 
-fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
-    let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
+fn get_patches(dirs: &Dirs, crate_name: &str) -> Vec<PathBuf> {
+    let mut patches: Vec<_> = fs::read_dir(RelPath::PATCHES.to_path(dirs))
         .unwrap()
         .map(|entry| entry.unwrap().path())
         .filter(|path| path.extension() == Some(OsStr::new("patch")))
@@ -215,19 +209,27 @@ fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
     patches
 }
 
-fn apply_patches(crate_name: &str, target_dir: &Path) {
+fn apply_patches(dirs: &Dirs, crate_name: &str, target_dir: &Path) {
     if crate_name == "<none>" {
         return;
     }
 
-    for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
+    for patch in get_patches(dirs, crate_name) {
         eprintln!(
             "[PATCH] {:?} <- {:?}",
             target_dir.file_name().unwrap(),
             patch.file_name().unwrap()
         );
         let mut apply_patch_cmd = Command::new("git");
-        apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir);
+        apply_patch_cmd
+            .arg("-c")
+            .arg("user.name=Dummy")
+            .arg("-c")
+            .arg("user.email=dummy@example.com")
+            .arg("am")
+            .arg(patch)
+            .arg("-q")
+            .current_dir(target_dir);
         spawn_and_wait(apply_patch_cmd);
     }
 }
diff --git a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
index 3c08b6fa389..8e5ab688e13 100644
--- a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
@@ -23,6 +23,16 @@ pub(crate) fn get_host_triple() -> String {
         .to_owned()
 }
 
+pub(crate) fn get_cargo_path() -> PathBuf {
+    let cargo_path = Command::new("rustup")
+        .stderr(Stdio::inherit())
+        .args(&["which", "cargo"])
+        .output()
+        .unwrap()
+        .stdout;
+    Path::new(String::from_utf8(cargo_path).unwrap().trim()).to_owned()
+}
+
 pub(crate) fn get_rustc_path() -> PathBuf {
     let rustc_path = Command::new("rustup")
         .stderr(Stdio::inherit())
@@ -33,6 +43,16 @@ pub(crate) fn get_rustc_path() -> PathBuf {
     Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
 }
 
+pub(crate) fn get_rustdoc_path() -> PathBuf {
+    let rustc_path = Command::new("rustup")
+        .stderr(Stdio::inherit())
+        .args(&["which", "rustdoc"])
+        .output()
+        .unwrap()
+        .stdout;
+    Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
+}
+
 pub(crate) fn get_default_sysroot() -> PathBuf {
     let default_sysroot = Command::new("rustc")
         .stderr(Stdio::inherit())
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index a414b60f4e0..1c372736ed6 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -1,15 +1,20 @@
 use super::build_sysroot;
 use super::config;
-use super::prepare;
-use super::rustc_info::get_wrapper_file_name;
-use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input};
-use build_system::SysrootKind;
+use super::path::{Dirs, RelPath};
+use super::prepare::GitRepo;
+use super::rustc_info::{get_cargo_path, get_wrapper_file_name};
+use super::utils::{
+    hyperfine_command, spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler,
+};
+use super::SysrootKind;
 use std::env;
 use std::ffi::OsStr;
 use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::process::Command;
 
+static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
+
 struct TestCase {
     config: &'static str,
     func: &'static dyn Fn(&TestRunner),
@@ -30,7 +35,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
             "--crate-type",
             "lib,dylib",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("build.example", &|runner| {
@@ -39,7 +44,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
             "--crate-type",
             "lib",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("jit.mini_core_hello_world", &|runner| {
@@ -51,7 +56,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
             "--cfg",
             "jit",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
         jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
         spawn_and_wait(jit_cmd);
@@ -65,7 +70,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
             "--cfg",
             "jit",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
         jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
         spawn_and_wait(jit_cmd);
@@ -79,7 +84,7 @@ const NO_SYSROOT_SUITE: &[TestCase] = &[
             "bin",
             "-g",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]);
     }),
@@ -94,7 +99,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []);
     }),
@@ -106,7 +111,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("issue_91827_extern_types", []);
     }),
@@ -116,7 +121,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "--crate-type",
             "lib",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("aot.alloc_example", &|runner| {
@@ -125,7 +130,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("alloc_example", []);
     }),
@@ -136,7 +141,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "-Cprefer-dynamic",
             "example/std_example.rs",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
 
         eprintln!("[JIT-lazy] std_example");
@@ -146,7 +151,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "-Cprefer-dynamic",
             "example/std_example.rs",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("aot.std_example", &|runner| {
@@ -155,7 +160,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("std_example", ["arg"]);
     }),
@@ -167,7 +172,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("dst_field_align", []);
     }),
@@ -178,7 +183,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "bin",
             "-Cpanic=abort",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("subslice-patterns-const-eval", []);
     }),
@@ -189,7 +194,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "bin",
             "-Cpanic=abort",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("track-caller-attribute", []);
     }),
@@ -200,7 +205,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "bin",
             "-Cpanic=abort",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("float-minmax-pass", []);
     }),
@@ -210,205 +215,252 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("mod_bench", []);
     }),
+    TestCase::new("aot.issue-72793", &|runner| {
+        runner.run_rustc([
+            "example/issue-72793.rs",
+            "--crate-type",
+            "bin",
+            "--target",
+            &runner.target_compiler.triple,
+        ]);
+        runner.run_out_command("issue-72793", []);
+    }),
 ];
 
+pub(crate) static RAND_REPO: GitRepo =
+    GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
+
+static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
+
+pub(crate) static REGEX_REPO: GitRepo =
+    GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
+
+static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir(), "regex");
+
+pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
+    "rust-lang",
+    "portable-simd",
+    "d5cd4a8112d958bd3a252327e0d069a6363249bd",
+    "portable-simd",
+);
+
+static PORTABLE_SIMD: CargoProject =
+    CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd");
+
+pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
+    "ebobby",
+    "simple-raytracer",
+    "804a7a21b9e673a482797aa289a18ed480e4d813",
+    "<none>",
+);
+
+pub(crate) static SIMPLE_RAYTRACER: CargoProject =
+    CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
+
+static LIBCORE_TESTS: CargoProject =
+    CargoProject::new(&RelPath::BUILD_SYSROOT.join("sysroot_src/library/core/tests"), "core_tests");
+
 const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
     TestCase::new("test.rust-random/rand", &|runner| {
-        runner.in_dir(prepare::RAND.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-
-            if runner.host_triple == runner.target_triple {
-                eprintln!("[TEST] rust-random/rand");
-                runner.run_cargo("test", ["--workspace"]);
-            } else {
-                eprintln!("[AOT] rust-random/rand");
-                runner.run_cargo("build", ["--workspace", "--tests"]);
-            }
-        });
+        spawn_and_wait(RAND.clean(&runner.target_compiler.cargo, &runner.dirs));
+
+        if runner.is_native {
+            eprintln!("[TEST] rust-random/rand");
+            let mut test_cmd = RAND.test(&runner.target_compiler, &runner.dirs);
+            test_cmd.arg("--workspace");
+            spawn_and_wait(test_cmd);
+        } else {
+            eprintln!("[AOT] rust-random/rand");
+            let mut build_cmd = RAND.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.arg("--workspace").arg("--tests");
+            spawn_and_wait(build_cmd);
+        }
     }),
     TestCase::new("bench.simple-raytracer", &|runner| {
-        runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| {
-            let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
-
-            if runner.host_triple == runner.target_triple {
-                eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
-                let prepare = runner.cargo_command("clean", []);
-
-                let llvm_build_cmd = cargo_command("cargo", "build", None, Path::new("."));
-
-                let cargo_clif = runner
-                    .root_dir
-                    .clone()
-                    .join("build")
-                    .join(get_wrapper_file_name("cargo-clif", "bin"));
-                let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new("."));
-
-                let bench_compile =
-                    hyperfine_command(1, run_runs, Some(prepare), llvm_build_cmd, clif_build_cmd);
-
-                spawn_and_wait(bench_compile);
-
-                eprintln!("[BENCH RUN] ebobby/simple-raytracer");
-                fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif"))
-                    .unwrap();
-
-                let bench_run = hyperfine_command(
-                    0,
-                    run_runs,
-                    None,
-                    Command::new("./raytracer_cg_llvm"),
-                    Command::new("./raytracer_cg_clif"),
-                );
-                spawn_and_wait(bench_run);
-            } else {
-                runner.run_cargo("clean", []);
-                eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
-                eprintln!("[COMPILE] ebobby/simple-raytracer");
-                runner.run_cargo("build", []);
-                eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
-            }
-        });
+        let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
+
+        if runner.is_native {
+            eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
+            let cargo_clif = RelPath::DIST
+                .to_path(&runner.dirs)
+                .join(get_wrapper_file_name("cargo-clif", "bin"));
+            let manifest_path = SIMPLE_RAYTRACER.manifest_path(&runner.dirs);
+            let target_dir = SIMPLE_RAYTRACER.target_dir(&runner.dirs);
+
+            let clean_cmd = format!(
+                "cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
+                manifest_path = manifest_path.display(),
+                target_dir = target_dir.display(),
+            );
+            let llvm_build_cmd = format!(
+                "cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
+                manifest_path = manifest_path.display(),
+                target_dir = target_dir.display(),
+            );
+            let clif_build_cmd = format!(
+                "{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
+                cargo_clif = cargo_clif.display(),
+                manifest_path = manifest_path.display(),
+                target_dir = target_dir.display(),
+            );
+
+            let bench_compile =
+                hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
+
+            spawn_and_wait(bench_compile);
+
+            eprintln!("[BENCH RUN] ebobby/simple-raytracer");
+            fs::copy(
+                target_dir.join("debug").join("main"),
+                RelPath::BUILD.to_path(&runner.dirs).join("raytracer_cg_clif"),
+            )
+            .unwrap();
+
+            let mut bench_run =
+                hyperfine_command(0, run_runs, None, "./raytracer_cg_llvm", "./raytracer_cg_clif");
+            bench_run.current_dir(RelPath::BUILD.to_path(&runner.dirs));
+            spawn_and_wait(bench_run);
+        } else {
+            spawn_and_wait(SIMPLE_RAYTRACER.clean(&runner.target_compiler.cargo, &runner.dirs));
+            eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
+            eprintln!("[COMPILE] ebobby/simple-raytracer");
+            spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs));
+            eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
+        }
     }),
     TestCase::new("test.libcore", &|runner| {
-        runner.in_dir(
-            std::env::current_dir()
-                .unwrap()
-                .join("build_sysroot")
-                .join("sysroot_src")
-                .join("library")
-                .join("core")
-                .join("tests"),
-            |runner| {
-                runner.run_cargo("clean", []);
-
-                if runner.host_triple == runner.target_triple {
-                    runner.run_cargo("test", []);
-                } else {
-                    eprintln!("Cross-Compiling: Not running tests");
-                    runner.run_cargo("build", ["--tests"]);
-                }
-            },
-        );
+        spawn_and_wait(LIBCORE_TESTS.clean(&runner.host_compiler.cargo, &runner.dirs));
+
+        if runner.is_native {
+            spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs));
+        } else {
+            eprintln!("Cross-Compiling: Not running tests");
+            let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.arg("--tests");
+            spawn_and_wait(build_cmd);
+        }
     }),
     TestCase::new("test.regex-shootout-regex-dna", &|runner| {
-        runner.in_dir(prepare::REGEX.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-
-            // newer aho_corasick versions throw a deprecation warning
-            let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
-
-            let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]);
-            build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
-            spawn_and_wait(build_cmd);
-
-            if runner.host_triple == runner.target_triple {
-                let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]);
-                run_cmd.env("RUSTFLAGS", lint_rust_flags);
-
-                let input =
-                    fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap();
-                let expected_path = PathBuf::from("examples/regexdna-output.txt");
-                let expected = fs::read_to_string(&expected_path).unwrap();
-
-                let output = spawn_and_wait_with_input(run_cmd, input);
-                // Make sure `[codegen mono items] start` doesn't poison the diff
-                let output = output
-                    .lines()
-                    .filter(|line| !line.contains("codegen mono items"))
-                    .chain(Some("")) // This just adds the trailing newline
-                    .collect::<Vec<&str>>()
-                    .join("\r\n");
-
-                let output_matches = expected.lines().eq(output.lines());
-                if !output_matches {
-                    let res_path = PathBuf::from("res.txt");
-                    fs::write(&res_path, &output).unwrap();
-
-                    if cfg!(windows) {
-                        println!("Output files don't match!");
-                        println!("Expected Output:\n{}", expected);
-                        println!("Actual Output:\n{}", output);
-                    } else {
-                        let mut diff = Command::new("diff");
-                        diff.arg("-u");
-                        diff.arg(res_path);
-                        diff.arg(expected_path);
-                        spawn_and_wait(diff);
-                    }
-
-                    std::process::exit(1);
+        spawn_and_wait(REGEX.clean(&runner.target_compiler.cargo, &runner.dirs));
+
+        // newer aho_corasick versions throw a deprecation warning
+        let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
+
+        let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
+        build_cmd.arg("--example").arg("shootout-regex-dna");
+        build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+        spawn_and_wait(build_cmd);
+
+        if runner.is_native {
+            let mut run_cmd = REGEX.run(&runner.target_compiler, &runner.dirs);
+            run_cmd.arg("--example").arg("shootout-regex-dna");
+            run_cmd.env("RUSTFLAGS", lint_rust_flags);
+
+            let input = fs::read_to_string(
+                REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"),
+            )
+            .unwrap();
+            let expected_path =
+                REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt");
+            let expected = fs::read_to_string(&expected_path).unwrap();
+
+            let output = spawn_and_wait_with_input(run_cmd, input);
+            // Make sure `[codegen mono items] start` doesn't poison the diff
+            let output = output
+                .lines()
+                .filter(|line| !line.contains("codegen mono items"))
+                .chain(Some("")) // This just adds the trailing newline
+                .collect::<Vec<&str>>()
+                .join("\r\n");
+
+            let output_matches = expected.lines().eq(output.lines());
+            if !output_matches {
+                let res_path = REGEX.source_dir(&runner.dirs).join("res.txt");
+                fs::write(&res_path, &output).unwrap();
+
+                if cfg!(windows) {
+                    println!("Output files don't match!");
+                    println!("Expected Output:\n{}", expected);
+                    println!("Actual Output:\n{}", output);
+                } else {
+                    let mut diff = Command::new("diff");
+                    diff.arg("-u");
+                    diff.arg(res_path);
+                    diff.arg(expected_path);
+                    spawn_and_wait(diff);
                 }
+
+                std::process::exit(1);
             }
-        });
+        }
     }),
     TestCase::new("test.regex", &|runner| {
-        runner.in_dir(prepare::REGEX.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-
-            // newer aho_corasick versions throw a deprecation warning
-            let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
-
-            if runner.host_triple == runner.target_triple {
-                let mut run_cmd = runner.cargo_command(
-                    "test",
-                    [
-                        "--tests",
-                        "--",
-                        "--exclude-should-panic",
-                        "--test-threads",
-                        "1",
-                        "-Zunstable-options",
-                        "-q",
-                    ],
-                );
-                run_cmd.env("RUSTFLAGS", lint_rust_flags);
-                spawn_and_wait(run_cmd);
-            } else {
-                eprintln!("Cross-Compiling: Not running tests");
-                let mut build_cmd =
-                    runner.cargo_command("build", ["--tests", "--target", &runner.target_triple]);
-                build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
-                spawn_and_wait(build_cmd);
-            }
-        });
+        spawn_and_wait(REGEX.clean(&runner.host_compiler.cargo, &runner.dirs));
+
+        // newer aho_corasick versions throw a deprecation warning
+        let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
+
+        if runner.is_native {
+            let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs);
+            run_cmd.args([
+                "--tests",
+                "--",
+                "--exclude-should-panic",
+                "--test-threads",
+                "1",
+                "-Zunstable-options",
+                "-q",
+            ]);
+            run_cmd.env("RUSTFLAGS", lint_rust_flags);
+            spawn_and_wait(run_cmd);
+        } else {
+            eprintln!("Cross-Compiling: Not running tests");
+            let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.arg("--tests");
+            build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+            spawn_and_wait(build_cmd);
+        }
     }),
     TestCase::new("test.portable-simd", &|runner| {
-        runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-            runner.run_cargo("build", ["--all-targets", "--target", &runner.target_triple]);
+        spawn_and_wait(PORTABLE_SIMD.clean(&runner.host_compiler.cargo, &runner.dirs));
 
-            if runner.host_triple == runner.target_triple {
-                runner.run_cargo("test", ["-q"]);
-            }
-        });
+        let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
+        build_cmd.arg("--all-targets");
+        spawn_and_wait(build_cmd);
+
+        if runner.is_native {
+            let mut test_cmd = PORTABLE_SIMD.test(&runner.target_compiler, &runner.dirs);
+            test_cmd.arg("-q");
+            spawn_and_wait(test_cmd);
+        }
     }),
 ];
 
 pub(crate) fn run_tests(
+    dirs: &Dirs,
     channel: &str,
     sysroot_kind: SysrootKind,
-    target_dir: &Path,
     cg_clif_dylib: &Path,
     host_triple: &str,
     target_triple: &str,
 ) {
-    let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string());
+    let runner = TestRunner::new(dirs.clone(), host_triple.to_string(), target_triple.to_string());
 
     if config::get_bool("testsuite.no_sysroot") {
         build_sysroot::build_sysroot(
+            dirs,
             channel,
             SysrootKind::None,
-            &target_dir,
             cg_clif_dylib,
             &host_triple,
             &target_triple,
         );
 
-        let _ = fs::remove_dir_all(Path::new("target").join("out"));
+        BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
         runner.run_testsuite(NO_SYSROOT_SUITE);
     } else {
         eprintln!("[SKIP] no_sysroot tests");
@@ -419,9 +471,9 @@ pub(crate) fn run_tests(
 
     if run_base_sysroot || run_extended_sysroot {
         build_sysroot::build_sysroot(
+            dirs,
             channel,
             sysroot_kind,
-            &target_dir,
             cg_clif_dylib,
             &host_triple,
             &target_triple,
@@ -442,40 +494,50 @@ pub(crate) fn run_tests(
 }
 
 struct TestRunner {
-    root_dir: PathBuf,
-    out_dir: PathBuf,
+    is_native: bool,
     jit_supported: bool,
-    rust_flags: String,
-    run_wrapper: Vec<String>,
-    host_triple: String,
-    target_triple: String,
+    dirs: Dirs,
+    host_compiler: Compiler,
+    target_compiler: Compiler,
 }
 
 impl TestRunner {
-    pub fn new(host_triple: String, target_triple: String) -> Self {
-        let root_dir = env::current_dir().unwrap();
-
-        let mut out_dir = root_dir.clone();
-        out_dir.push("target");
-        out_dir.push("out");
-
+    pub fn new(dirs: Dirs, host_triple: String, target_triple: String) -> Self {
         let is_native = host_triple == target_triple;
         let jit_supported =
             target_triple.contains("x86_64") && is_native && !host_triple.contains("windows");
 
-        let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
-        let mut run_wrapper = Vec::new();
+        let rustc_clif =
+            RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustc-clif", "bin"));
+        let rustdoc_clif =
+            RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustdoc-clif", "bin"));
+
+        let mut rustflags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
+        let mut runner = vec![];
 
         if !is_native {
             match target_triple.as_str() {
                 "aarch64-unknown-linux-gnu" => {
                     // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
-                    rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags);
-                    run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"];
+                    rustflags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rustflags);
+                    runner = vec![
+                        "qemu-aarch64".to_owned(),
+                        "-L".to_owned(),
+                        "/usr/aarch64-linux-gnu".to_owned(),
+                    ];
+                }
+                "s390x-unknown-linux-gnu" => {
+                    // We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
+                    rustflags = format!("-Clinker=s390x-linux-gnu-gcc{}", rustflags);
+                    runner = vec![
+                        "qemu-s390x".to_owned(),
+                        "-L".to_owned(),
+                        "/usr/s390x-linux-gnu".to_owned(),
+                    ];
                 }
                 "x86_64-pc-windows-gnu" => {
                     // We are cross-compiling for Windows. Run tests in wine.
-                    run_wrapper = vec!["wine"];
+                    runner = vec!["wine".to_owned()];
                 }
                 _ => {
                     println!("Unknown non-native platform");
@@ -484,19 +546,31 @@ impl TestRunner {
         }
 
         // FIXME fix `#[linkage = "extern_weak"]` without this
-        if host_triple.contains("darwin") {
-            rust_flags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rust_flags);
+        if target_triple.contains("darwin") {
+            rustflags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rustflags);
         }
 
-        Self {
-            root_dir,
-            out_dir,
-            jit_supported,
-            rust_flags,
-            run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(),
-            host_triple,
-            target_triple,
-        }
+        let host_compiler = Compiler {
+            cargo: get_cargo_path(),
+            rustc: rustc_clif.clone(),
+            rustdoc: rustdoc_clif.clone(),
+            rustflags: String::new(),
+            rustdocflags: String::new(),
+            triple: host_triple,
+            runner: vec![],
+        };
+
+        let target_compiler = Compiler {
+            cargo: get_cargo_path(),
+            rustc: rustc_clif,
+            rustdoc: rustdoc_clif,
+            rustflags: rustflags.clone(),
+            rustdocflags: rustflags,
+            triple: target_triple,
+            runner,
+        };
+
+        Self { is_native, jit_supported, dirs, host_compiler, target_compiler }
     }
 
     pub fn run_testsuite(&self, tests: &[TestCase]) {
@@ -516,29 +590,18 @@ impl TestRunner {
         }
     }
 
-    fn in_dir(&self, new: impl AsRef<Path>, callback: impl FnOnce(&TestRunner)) {
-        let current = env::current_dir().unwrap();
-
-        env::set_current_dir(new).unwrap();
-        callback(self);
-        env::set_current_dir(current).unwrap();
-    }
-
+    #[must_use]
     fn rustc_command<I, S>(&self, args: I) -> Command
     where
         I: IntoIterator<Item = S>,
         S: AsRef<OsStr>,
     {
-        let mut rustc_clif = self.root_dir.clone();
-        rustc_clif.push("build");
-        rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin"));
-
-        let mut cmd = Command::new(rustc_clif);
-        cmd.args(self.rust_flags.split_whitespace());
+        let mut cmd = Command::new(&self.target_compiler.rustc);
+        cmd.args(self.target_compiler.rustflags.split_whitespace());
         cmd.arg("-L");
-        cmd.arg(format!("crate={}", self.out_dir.display()));
+        cmd.arg(format!("crate={}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
         cmd.arg("--out-dir");
-        cmd.arg(format!("{}", self.out_dir.display()));
+        cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
         cmd.arg("-Cdebuginfo=2");
         cmd.args(args);
         cmd
@@ -559,15 +622,13 @@ impl TestRunner {
         let mut full_cmd = vec![];
 
         // Prepend the RUN_WRAPPER's
-        if !self.run_wrapper.is_empty() {
-            full_cmd.extend(self.run_wrapper.iter().cloned());
+        if !self.target_compiler.runner.is_empty() {
+            full_cmd.extend(self.target_compiler.runner.iter().cloned());
         }
 
-        full_cmd.push({
-            let mut out_path = self.out_dir.clone();
-            out_path.push(name);
-            out_path.to_str().unwrap().to_string()
-        });
+        full_cmd.push(
+            BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).join(name).to_str().unwrap().to_string(),
+        );
 
         for arg in args.into_iter() {
             full_cmd.push(arg.to_string());
@@ -581,30 +642,4 @@ impl TestRunner {
 
         spawn_and_wait(cmd);
     }
-
-    fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command
-    where
-        I: IntoIterator<Item = &'a str>,
-    {
-        let mut cargo_clif = self.root_dir.clone();
-        cargo_clif.push("build");
-        cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
-
-        let mut cmd = cargo_command(
-            cargo_clif,
-            subcommand,
-            if subcommand == "clean" { None } else { Some(&self.target_triple) },
-            Path::new("."),
-        );
-        cmd.args(args);
-        cmd.env("RUSTFLAGS", &self.rust_flags);
-        cmd
-    }
-
-    fn run_cargo<'a, I>(&self, subcommand: &str, args: I)
-    where
-        I: IntoIterator<Item = &'a str>,
-    {
-        spawn_and_wait(self.cargo_command(subcommand, args));
-    }
 }
diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs
index c627af4e62f..2be70e8e421 100644
--- a/compiler/rustc_codegen_cranelift/build_system/utils.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs
@@ -1,35 +1,138 @@
 use std::env;
 use std::fs;
 use std::io::Write;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::process::{self, Command, Stdio};
 
-pub(crate) fn cargo_command(
-    cargo: impl AsRef<Path>,
-    subcommand: &str,
-    triple: Option<&str>,
-    source_dir: &Path,
-) -> Command {
-    let mut cmd = Command::new(cargo.as_ref());
-    cmd.arg(subcommand)
-        .arg("--manifest-path")
-        .arg(source_dir.join("Cargo.toml"))
-        .arg("--target-dir")
-        .arg(source_dir.join("target"));
+use super::path::{Dirs, RelPath};
+use super::rustc_info::{get_cargo_path, get_host_triple, get_rustc_path, get_rustdoc_path};
+
+pub(crate) struct Compiler {
+    pub(crate) cargo: PathBuf,
+    pub(crate) rustc: PathBuf,
+    pub(crate) rustdoc: PathBuf,
+    pub(crate) rustflags: String,
+    pub(crate) rustdocflags: String,
+    pub(crate) triple: String,
+    pub(crate) runner: Vec<String>,
+}
+
+impl Compiler {
+    pub(crate) fn host() -> Compiler {
+        Compiler {
+            cargo: get_cargo_path(),
+            rustc: get_rustc_path(),
+            rustdoc: get_rustdoc_path(),
+            rustflags: String::new(),
+            rustdocflags: String::new(),
+            triple: get_host_triple(),
+            runner: vec![],
+        }
+    }
+
+    pub(crate) fn with_triple(triple: String) -> Compiler {
+        Compiler {
+            cargo: get_cargo_path(),
+            rustc: get_rustc_path(),
+            rustdoc: get_rustdoc_path(),
+            rustflags: String::new(),
+            rustdocflags: String::new(),
+            triple,
+            runner: vec![],
+        }
+    }
+}
+
+pub(crate) struct CargoProject {
+    source: &'static RelPath,
+    target: &'static str,
+}
+
+impl CargoProject {
+    pub(crate) const fn new(path: &'static RelPath, target: &'static str) -> CargoProject {
+        CargoProject { source: path, target }
+    }
+
+    pub(crate) fn source_dir(&self, dirs: &Dirs) -> PathBuf {
+        self.source.to_path(dirs)
+    }
+
+    pub(crate) fn manifest_path(&self, dirs: &Dirs) -> PathBuf {
+        self.source_dir(dirs).join("Cargo.toml")
+    }
+
+    pub(crate) fn target_dir(&self, dirs: &Dirs) -> PathBuf {
+        RelPath::BUILD.join(self.target).to_path(dirs)
+    }
 
-    if let Some(triple) = triple {
-        cmd.arg("--target").arg(triple);
+    fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command {
+        let mut cmd = Command::new(cargo);
+
+        cmd.arg(command)
+            .arg("--manifest-path")
+            .arg(self.manifest_path(dirs))
+            .arg("--target-dir")
+            .arg(self.target_dir(dirs));
+
+        cmd
+    }
+
+    fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command {
+        let mut cmd = self.base_cmd(command, &compiler.cargo, dirs);
+
+        cmd.arg("--target").arg(&compiler.triple);
+
+        cmd.env("RUSTC", &compiler.rustc);
+        cmd.env("RUSTDOC", &compiler.rustdoc);
+        cmd.env("RUSTFLAGS", &compiler.rustflags);
+        cmd.env("RUSTDOCFLAGS", &compiler.rustdocflags);
+        if !compiler.runner.is_empty() {
+            cmd.env(
+                format!("CARGO_TARGET_{}_RUNNER", compiler.triple.to_uppercase().replace('-', "_")),
+                compiler.runner.join(" "),
+            );
+        }
+
+        cmd
     }
 
-    cmd
+    #[must_use]
+    pub(crate) fn fetch(&self, cargo: impl AsRef<Path>, dirs: &Dirs) -> Command {
+        let mut cmd = Command::new(cargo.as_ref());
+
+        cmd.arg("fetch").arg("--manifest-path").arg(self.manifest_path(dirs));
+
+        cmd
+    }
+
+    #[must_use]
+    pub(crate) fn clean(&self, cargo: &Path, dirs: &Dirs) -> Command {
+        self.base_cmd("clean", cargo, dirs)
+    }
+
+    #[must_use]
+    pub(crate) fn build(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+        self.build_cmd("build", compiler, dirs)
+    }
+
+    #[must_use]
+    pub(crate) fn test(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+        self.build_cmd("test", compiler, dirs)
+    }
+
+    #[must_use]
+    pub(crate) fn run(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+        self.build_cmd("run", compiler, dirs)
+    }
 }
 
+#[must_use]
 pub(crate) fn hyperfine_command(
     warmup: u64,
     runs: u64,
-    prepare: Option<Command>,
-    a: Command,
-    b: Command,
+    prepare: Option<&str>,
+    a: &str,
+    b: &str,
 ) -> Command {
     let mut bench = Command::new("hyperfine");
 
@@ -42,10 +145,10 @@ pub(crate) fn hyperfine_command(
     }
 
     if let Some(prepare) = prepare {
-        bench.arg("--prepare").arg(format!("{:?}", prepare));
+        bench.arg("--prepare").arg(prepare);
     }
 
-    bench.arg(format!("{:?}", a)).arg(format!("{:?}", b));
+    bench.arg(a).arg(b);
 
     bench
 }
diff --git a/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh
index fedab2433aa..1760e5836ec 100755
--- a/compiler/rustc_codegen_cranelift/clean_all.sh
+++ b/compiler/rustc_codegen_cranelift/clean_all.sh
@@ -2,7 +2,7 @@
 set -e
 
 rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
-rm -rf target/ build/ perf.data{,.old} y.bin
+rm -rf target/ build/ dist/ perf.data{,.old} y.bin
 rm -rf download/
 
 # Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt
index 0d539191b12..258b67e9314 100644
--- a/compiler/rustc_codegen_cranelift/config.txt
+++ b/compiler/rustc_codegen_cranelift/config.txt
@@ -40,6 +40,7 @@ aot.subslice-patterns-const-eval
 aot.track-caller-attribute
 aot.float-minmax-pass
 aot.mod_bench
+aot.issue-72793
 
 testsuite.extended_sysroot
 test.rust-random/rand
diff --git a/compiler/rustc_codegen_cranelift/docs/usage.md b/compiler/rustc_codegen_cranelift/docs/usage.md
index 33f146e7ba2..4c2b0fa1704 100644
--- a/compiler/rustc_codegen_cranelift/docs/usage.md
+++ b/compiler/rustc_codegen_cranelift/docs/usage.md
@@ -9,7 +9,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo
 In the directory with your project (where you can do the usual `cargo build`), run:
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif build
+$ $cg_clif_dir/dist/cargo-clif build
 ```
 
 This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
@@ -19,7 +19,7 @@ This will build your project with rustc_codegen_cranelift instead of the usual L
 > You should prefer using the Cargo method.
 
 ```bash
-$ $cg_clif_dir/build/rustc-clif my_crate.rs
+$ $cg_clif_dir/dist/rustc-clif my_crate.rs
 ```
 
 ## Jit mode
@@ -32,20 +32,20 @@ In jit mode cg_clif will immediately execute your code without creating an execu
 > The jit mode will probably need cargo integration to make this possible.
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif jit
+$ $cg_clif_dir/dist/cargo-clif jit
 ```
 
 or
 
 ```bash
-$ $cg_clif_dir/build/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
+$ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
 ```
 
 There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
 first called.
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif lazy-jit
+$ $cg_clif_dir/dist/cargo-clif lazy-jit
 ```
 
 ## Shell
@@ -54,7 +54,7 @@ These are a few functions that allow you to easily run rust code from the shell
 
 ```bash
 function jit_naked() {
-    echo "$@" | $cg_clif_dir/build/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic
+    echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic
 }
 
 function jit() {
diff --git a/compiler/rustc_codegen_cranelift/example/issue-72793.rs b/compiler/rustc_codegen_cranelift/example/issue-72793.rs
new file mode 100644
index 00000000000..b1bb9b8e1e7
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/example/issue-72793.rs
@@ -0,0 +1,24 @@
+// Adapted from rustc ui test suite (ui/type-alias-impl-trait/issue-72793.rs)
+
+#![feature(type_alias_impl_trait)]
+
+trait T { type Item; }
+
+type Alias<'a> = impl T<Item = &'a ()>;
+
+struct S;
+impl<'a> T for &'a S {
+    type Item = &'a ();
+}
+
+fn filter_positive<'a>() -> Alias<'a> {
+    &S
+}
+
+fn with_positive(fun: impl Fn(Alias<'_>)) {
+    fun(filter_positive());
+}
+
+fn main() {
+    with_positive(|_| ());
+}
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 7f85b52f083..1f9db1eb2a9 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -19,6 +19,9 @@ pub trait Sized {}
 #[lang = "destruct"]
 pub trait Destruct {}
 
+#[lang = "tuple_trait"]
+pub trait Tuple {}
+
 #[lang = "unsize"]
 pub trait Unsize<T: ?Sized> {}
 
@@ -443,7 +446,7 @@ pub struct PhantomData<T: ?Sized>;
 
 #[lang = "fn_once"]
 #[rustc_paren_sugar]
-pub trait FnOnce<Args> {
+pub trait FnOnce<Args: Tuple> {
     #[lang = "fn_once_output"]
     type Output;
 
@@ -452,7 +455,7 @@ pub trait FnOnce<Args> {
 
 #[lang = "fn_mut"]
 #[rustc_paren_sugar]
-pub trait FnMut<Args>: FnOnce<Args> {
+pub trait FnMut<Args: Tuple>: FnOnce<Args> {
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
 }
 
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
index 215d3556a17..c00f8a2e0cd 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
@@ -171,8 +171,6 @@ fn main() {
 
     assert_eq!(slice_ptr as usize % 4, 0);
 
-    //return;
-
     unsafe {
         printf("Hello %s\n\0" as *const str as *const i8, "printf\0" as *const str as *const i8);
 
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index ad108c34992..8481d9c39a3 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -164,6 +164,8 @@ unsafe fn test_simd() {
     let cmp_eq = _mm_cmpeq_epi8(y, y);
     let cmp_lt = _mm_cmplt_epi8(y, y);
 
+    let (zero0, zero1) = std::mem::transmute::<_, (u64, u64)>(x);
+    assert_eq!((zero0, zero1), (0, 0));
     assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
     assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]);
     assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]);
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index c0a2e7a7883..d8f28dbcc15 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-10-23"
+channel = "nightly-2022-12-13"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_cranelift/rustfmt.toml b/compiler/rustc_codegen_cranelift/rustfmt.toml
index 2bd8f7d1bc1..ebeca8662a5 100644
--- a/compiler/rustc_codegen_cranelift/rustfmt.toml
+++ b/compiler/rustc_codegen_cranelift/rustfmt.toml
@@ -1,3 +1,5 @@
+ignore = ["y.rs"]
+
 # Matches rustfmt.toml of rustc
 version = "Two"
 use_small_heuristics = "Max"
diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
index e6f60d1c0cb..f782671fe36 100755
--- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
@@ -2,7 +2,7 @@
 #![forbid(unsafe_code)]/* This line is ignored by bash
 # This block is ignored by rustc
 pushd $(dirname "$0")/../
-RUSTC="$(pwd)/build/rustc-clif"
+RUSTC="$(pwd)/dist/rustc-clif"
 popd
 PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0
 #*/
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
new file mode 100644
index 00000000000..a19d72acfa8
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
@@ -0,0 +1,36 @@
+use std::env;
+use std::ffi::OsString;
+#[cfg(unix)]
+use std::os::unix::process::CommandExt;
+use std::path::PathBuf;
+use std::process::Command;
+
+fn main() {
+    let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap());
+
+    let cg_clif_dylib_path = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join(
+        env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
+    );
+
+    let mut args = std::env::args_os().skip(1).collect::<Vec<_>>();
+    args.push(OsString::from("-Cpanic=abort"));
+    args.push(OsString::from("-Zpanic-abort-tests"));
+    let mut codegen_backend_arg = OsString::from("-Zcodegen-backend=");
+    codegen_backend_arg.push(cg_clif_dylib_path);
+    args.push(codegen_backend_arg);
+    if !args.contains(&OsString::from("--sysroot")) {
+        args.push(OsString::from("--sysroot"));
+        args.push(OsString::from(sysroot.to_str().unwrap()));
+    }
+
+    // Ensure that the right toolchain is used
+    env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
+
+    #[cfg(unix)]
+    Command::new("rustdoc").args(args).exec();
+
+    #[cfg(not(unix))]
+    std::process::exit(
+        Command::new("rustdoc").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1),
+    );
+}
diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
index d6a37789599..6c64b7de7da 100644
--- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
@@ -27,24 +27,6 @@ index d95b5b7f17f..00b6f0e3635 100644
  [dev-dependencies]
  rand = "0.7"
  rand_xorshift = "0.2"
-diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
-index 8431aa7b818..a3ff7e68ce5 100644
---- a/src/tools/compiletest/src/runtest.rs
-+++ b/src/tools/compiletest/src/runtest.rs
-@@ -3489,12 +3489,7 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
-         let compiler_src_dir = base_dir.join("compiler");
-         normalize_path(&compiler_src_dir, "$(echo '$COMPILER_DIR')");
-
--        if let Some(virtual_rust_source_base_dir) =
--            option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from)
--        {
--            normalize_path(&virtual_rust_source_base_dir.join("library"), "$(echo '$SRC_DIR')");
--            normalize_path(&virtual_rust_source_base_dir.join("compiler"), "$(echo '$COMPILER_DIR')");
--        }
-+        normalize_path(&Path::new("$(cd ../build_sysroot/sysroot_src/library; pwd)"), "$(echo '$SRC_DIR')");
-
-         // Paths into the build directory
-         let test_build_dir = &self.config.build_base;
 EOF
 
 cat > config.toml <<EOF
@@ -54,7 +36,7 @@ changelog-seen = 2
 ninja = false
 
 [build]
-rustc = "$(pwd)/../build/rustc-clif"
+rustc = "$(pwd)/../dist/rustc-clif"
 cargo = "$(rustup which cargo)"
 full-bootstrap = true
 local-rebuild = true
@@ -69,6 +51,8 @@ popd
 # FIXME remove once inline asm is fully supported
 export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
 
+export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd build_sysroot/sysroot_src; pwd)"
+
 # Allow the testsuite to use llvm tools
 host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
 export LLVM_BIN_DIR="$(rustc --print sysroot)/lib/rustlib/$host_triple/bin"
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 9b5db3cf81f..04ad77ec97e 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -20,6 +20,7 @@ for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|// error-pat
 done
 
 git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
+git checkout -- src/test/ui/proc-macro/pretty-print-hack/
 
 # missing features
 # ================
@@ -30,6 +31,7 @@ rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abo
 
 # requires compiling with -Cpanic=unwind
 rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/
+rm -r src/test/run-make/test-benches
 
 # vendor intrinsics
 rm src/test/ui/sse2.rs # cpuid not supported, so sse2 not detected
@@ -64,6 +66,8 @@ rm src/test/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
 rm -r src/test/run-make/emit-named-files # requires full --emit support
 rm src/test/ui/abi/stack-probes.rs # stack probes not yet implemented
 rm src/test/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
+rm -r src/test/run-make/repr128-dwarf # debuginfo test
+rm src/test/codegen-units/item-collection/asm-sym.rs # requires support for sym in asm!()
 
 # optimization tests
 # ==================
@@ -82,20 +86,20 @@ rm src/test/ui/abi/stack-protector.rs # requires stack protector support
 rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
 rm src/test/ui/mir/mir_raw_fat_ptr.rs # same
 rm src/test/ui/consts/issue-33537.rs # same
+rm src/test/ui/layout/valid_range_oob.rs # different ICE message
 
 # doesn't work due to the way the rustc test suite is invoked.
 # should work when using ./x.py test the way it is intended
 # ============================================================
-rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/
+rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in dist/bin/
 rm -r src/test/run-make/unstable-flag-required # same
 rm -r src/test/run-make/rustdoc-* # same
 rm -r src/test/run-make/issue-88756-default-output # same
 rm -r src/test/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
+rm -r src/test/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere
 
 # genuine bugs
 # ============
-rm src/test/ui/allocator/no_std-alloc-error-handler-default.rs # missing rust_oom definition
-
 rm src/test/incremental/spike-neg1.rs # errors out for some reason
 rm src/test/incremental/spike-neg2.rs # same
 rm src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs # gives a stackoverflow before the backend runs
@@ -104,6 +108,8 @@ rm src/test/ui/type-alias-impl-trait/assoc-projection-ice.rs # produces ICE
 
 rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
 
+rm src/test/ui/runtime/out-of-stack.rs # SIGSEGV instead of SIGABRT for some reason (#1301)
+
 # bugs in the test suite
 # ======================
 rm src/test/ui/backtrace.rs # TODO warning
@@ -111,6 +117,8 @@ rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support
 rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
 # not sure if this is actually a bug in the test suite, but the symbol list shows the function without leading _ for some reason
 rm -r src/test/run-make/native-link-modifier-bundle
+rm src/test/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
+rm src/test/ui/dyn-star/dispatch-on-pin-mut.rs # TODO failed assertion in vtable::get_ptr_and_method_ref
 
 rm src/test/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
 
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 1e22537c2ba..65cc6b43767 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -56,13 +56,13 @@ pub(crate) fn conv_to_call_conv(c: Conv, default_call_conv: CallConv) -> CallCon
 
 pub(crate) fn get_function_sig<'tcx>(
     tcx: TyCtxt<'tcx>,
-    triple: &target_lexicon::Triple,
+    default_call_conv: CallConv,
     inst: Instance<'tcx>,
 ) -> Signature {
     assert!(!inst.substs.needs_infer());
     clif_sig_from_fn_abi(
         tcx,
-        CallConv::triple_default(triple),
+        default_call_conv,
         &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
     )
 }
@@ -74,7 +74,7 @@ pub(crate) fn import_function<'tcx>(
     inst: Instance<'tcx>,
 ) -> FuncId {
     let name = tcx.symbol_name(inst).name;
-    let sig = get_function_sig(tcx, module.isa().triple(), inst);
+    let sig = get_function_sig(tcx, module.target_config().default_call_conv, inst);
     match module.declare_function(name, Linkage::Import, &sig) {
         Ok(func_id) => func_id,
         Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
@@ -341,18 +341,16 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     destination: Place<'tcx>,
     target: Option<BasicBlock>,
 ) {
-    let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
-    let fn_sig =
-        fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
+    let func = codegen_operand(fx, func);
+    let fn_sig = func.layout().ty.fn_sig(fx.tcx);
 
     let ret_place = codegen_place(fx, destination);
 
     // Handle special calls like intrinsics and empty drop glue.
-    let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() {
-        let instance = ty::Instance::resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
-            .unwrap()
-            .unwrap()
-            .polymorphize(fx.tcx);
+    let instance = if let ty::FnDef(def_id, substs) = *func.layout().ty.kind() {
+        let instance =
+            ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
+                .polymorphize(fx.tcx);
 
         if fx.tcx.symbol_name(instance).name.starts_with("llvm.") {
             crate::intrinsics::codegen_llvm_intrinsic_call(
@@ -391,17 +389,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
         None
     };
 
-    let extra_args = &args[fn_sig.inputs().len()..];
+    let extra_args = &args[fn_sig.inputs().skip_binder().len()..];
     let extra_args = fx
         .tcx
         .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
     let fn_abi = if let Some(instance) = instance {
         RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
     } else {
-        RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args)
+        RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_sig, extra_args)
     };
 
-    let is_cold = if fn_sig.abi == Abi::RustCold {
+    let is_cold = if fn_sig.abi() == Abi::RustCold {
         true
     } else {
         instance
@@ -418,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     }
 
     // Unpack arguments tuple for closures
-    let mut args = if fn_sig.abi == Abi::RustCall {
+    let mut args = if fn_sig.abi() == Abi::RustCall {
         assert_eq!(args.len(), 2, "rust-call abi requires two arguments");
         let self_arg = codegen_call_argument_operand(fx, &args[0]);
         let pack_arg = codegen_call_argument_operand(fx, &args[1]);
@@ -486,7 +484,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
                 fx.add_comment(nop_inst, "indirect call");
             }
 
-            let func = codegen_operand(fx, func).load_scalar(fx);
+            let func = func.load_scalar(fx);
             let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
             let sig = fx.bcx.import_signature(sig);
 
@@ -517,11 +515,11 @@ pub(crate) fn codegen_terminator_call<'tcx>(
         };
 
         // FIXME find a cleaner way to support varargs
-        if fn_sig.c_variadic {
-            if !matches!(fn_sig.abi, Abi::C { .. }) {
+        if fn_sig.c_variadic() {
+            if !matches!(fn_sig.abi(), Abi::C { .. }) {
                 fx.tcx.sess.span_fatal(
                     source_info.span,
-                    &format!("Variadic call for non-C abi {:?}", fn_sig.abi),
+                    &format!("Variadic call for non-C abi {:?}", fn_sig.abi()),
                 );
             }
             let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs
index 12bb00d346d..8508227179a 100644
--- a/compiler/rustc_codegen_cranelift/src/allocator.rs
+++ b/compiler/rustc_codegen_cranelift/src/allocator.rs
@@ -66,7 +66,7 @@ fn codegen_inner(
         };
 
         let sig = Signature {
-            call_conv: CallConv::triple_default(module.isa().triple()),
+            call_conv: module.target_config().default_call_conv,
             params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
             returns: output.into_iter().map(AbiParam::new).collect(),
         };
@@ -104,7 +104,7 @@ fn codegen_inner(
     }
 
     let sig = Signature {
-        call_conv: CallConv::triple_default(module.isa().triple()),
+        call_conv: module.target_config().default_call_conv,
         params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
         returns: vec![],
     };
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 06813d7ec95..89d955e8bf2 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -59,7 +59,7 @@ pub(crate) fn codegen_fn<'tcx>(
 
     // Declare function
     let symbol_name = tcx.symbol_name(instance).name.to_string();
-    let sig = get_function_sig(tcx, module.isa().triple(), instance);
+    let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
     let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
 
     // Make the FunctionBuilder
@@ -390,11 +390,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                         _ => unreachable!("{:?}", targets),
                     };
 
-                    let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
                     let (discr, is_inverted) =
                         crate::optimize::peephole::maybe_unwrap_bool_not(&mut fx.bcx, discr);
                     let test_zero = if is_inverted { !test_zero } else { test_zero };
-                    let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
                     if let Some(taken) = crate::optimize::peephole::maybe_known_branch_taken(
                         &fx.bcx, discr, test_zero,
                     ) {
@@ -571,7 +569,7 @@ fn codegen_stmt<'tcx>(
                         UnOp::Not => match layout.ty.kind() {
                             ty::Bool => {
                                 let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
-                                CValue::by_val(fx.bcx.ins().bint(types::I8, res), layout)
+                                CValue::by_val(res, layout)
                             }
                             ty::Uint(_) | ty::Int(_) => {
                                 CValue::by_val(fx.bcx.ins().bnot(val), layout)
@@ -579,12 +577,6 @@ fn codegen_stmt<'tcx>(
                             _ => unreachable!("un op Not for {:?}", layout.ty),
                         },
                         UnOp::Neg => match layout.ty.kind() {
-                            ty::Int(IntTy::I128) => {
-                                // FIXME remove this case once ineg.i128 works
-                                let zero =
-                                    CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size));
-                                crate::num::codegen_int_binop(fx, BinOp::Sub, zero, operand)
-                            }
                             ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
                             ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
                             _ => unreachable!("un op Neg for {:?}", layout.ty),
diff --git a/compiler/rustc_codegen_cranelift/src/cast.rs b/compiler/rustc_codegen_cranelift/src/cast.rs
index bad5d1f08a9..5091c5a9fed 100644
--- a/compiler/rustc_codegen_cranelift/src/cast.rs
+++ b/compiler/rustc_codegen_cranelift/src/cast.rs
@@ -149,7 +149,7 @@ pub(crate) fn clif_int_or_float_cast(
         }
 
         let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
-        let zero = fx.bcx.ins().iconst(to_ty, 0);
+        let zero = type_zero_value(&mut fx.bcx, to_ty);
         fx.bcx.ins().select(is_not_nan, val, zero)
     } else if from_ty.is_float() && to_ty.is_float() {
         // float -> float
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 58959446578..2dcd42fbd8f 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -162,11 +162,20 @@ pub(crate) fn codegen_icmp_imm(
             }
         }
     } else {
-        let rhs = i64::try_from(rhs).expect("codegen_icmp_imm rhs out of range for <128bit int");
+        let rhs = rhs as i64; // Truncates on purpose in case rhs is actually an unsigned value
         fx.bcx.ins().icmp_imm(intcc, lhs, rhs)
     }
 }
 
+pub(crate) fn type_zero_value(bcx: &mut FunctionBuilder<'_>, ty: Type) -> Value {
+    if ty == types::I128 {
+        let zero = bcx.ins().iconst(types::I64, 0);
+        bcx.ins().iconcat(zero, zero)
+    } else {
+        bcx.ins().iconst(ty, 0)
+    }
+}
+
 pub(crate) fn type_min_max_value(
     bcx: &mut FunctionBuilder<'_>,
     ty: Type,
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index a6bde884084..dee6fb5b513 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -28,9 +28,7 @@ impl ConstantCx {
     }
 
     pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) {
-        //println!("todo {:?}", self.todo);
         define_all_allocs(tcx, module, &mut self);
-        //println!("done {:?}", self.done);
         self.done.clear();
     }
 }
@@ -268,16 +266,7 @@ fn data_id_for_static(
     def_id: DefId,
     definition: bool,
 ) -> DataId {
-    let rlinkage = tcx.codegen_fn_attrs(def_id).linkage;
-    let linkage = if definition {
-        crate::linkage::get_static_linkage(tcx, def_id)
-    } else if rlinkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
-        || rlinkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
-    {
-        Linkage::Preemptible
-    } else {
-        Linkage::Import
-    };
+    let attrs = tcx.codegen_fn_attrs(def_id);
 
     let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
     let symbol_name = tcx.symbol_name(instance).name;
@@ -289,22 +278,30 @@ fn data_id_for_static(
     };
     let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();
 
-    let attrs = tcx.codegen_fn_attrs(def_id);
+    if let Some(import_linkage) = attrs.import_linkage {
+        assert!(!definition);
 
-    let data_id = match module.declare_data(
-        &*symbol_name,
-        linkage,
-        is_mutable,
-        attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
-    ) {
-        Ok(data_id) => data_id,
-        Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
-            "attempt to declare `{symbol_name}` as static, but it was already declared as function"
-        )),
-        Err(err) => Err::<_, _>(err).unwrap(),
-    };
+        let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
+            || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
+        {
+            Linkage::Preemptible
+        } else {
+            Linkage::Import
+        };
+
+        let data_id = match module.declare_data(
+            &*symbol_name,
+            linkage,
+            is_mutable,
+            attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
+        ) {
+            Ok(data_id) => data_id,
+            Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
+                "attempt to declare `{symbol_name}` as static, but it was already declared as function"
+            )),
+            Err(err) => Err::<_, _>(err).unwrap(),
+        };
 
-    if rlinkage.is_some() {
         // Comment copied from https://github.com/rust-lang/rust/blob/45060c2a66dfd667f88bd8b94261b28a58d85bd5/src/librustc_codegen_llvm/consts.rs#L141
         // Declare an internal global `extern_with_linkage_foo` which
         // is initialized with the address of `foo`.  If `foo` is
@@ -326,10 +323,34 @@ fn data_id_for_static(
             Err(ModuleError::DuplicateDefinition(_)) => {}
             res => res.unwrap(),
         }
-        ref_data_id
-    } else {
-        data_id
+
+        return ref_data_id;
     }
+
+    let linkage = if definition {
+        crate::linkage::get_static_linkage(tcx, def_id)
+    } else if attrs.linkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
+        || attrs.linkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
+    {
+        Linkage::Preemptible
+    } else {
+        Linkage::Import
+    };
+
+    let data_id = match module.declare_data(
+        &*symbol_name,
+        linkage,
+        is_mutable,
+        attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
+    ) {
+        Ok(data_id) => data_id,
+        Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
+            "attempt to declare `{symbol_name}` as static, but it was already declared as function"
+        )),
+        Err(err) => Err::<_, _>(err).unwrap(),
+    };
+
+    data_id
 }
 
 fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut ConstantCx) {
@@ -348,8 +369,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                 (data_id, alloc, None)
             }
             TodoItem::Static(def_id) => {
-                //println!("static {:?}", def_id);
-
                 let section_name = tcx.codegen_fn_attrs(def_id).link_section;
 
                 let alloc = tcx.eval_static_initializer(def_id).unwrap();
@@ -359,7 +378,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
             }
         };
 
-        //("data_id {}", data_id);
         if cx.done.contains(&data_id) {
             continue;
         }
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
index d26392c4913..493359c743f 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
@@ -39,7 +39,9 @@ impl UnwindContext {
     }
 
     pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: &dyn TargetIsa) {
-        let unwind_info = if let Some(unwind_info) = context.create_unwind_info(isa).unwrap() {
+        let unwind_info = if let Some(unwind_info) =
+            context.compiled_code().unwrap().create_unwind_info(isa).unwrap()
+        {
             unwind_info
         } else {
             return;
diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs
index 97b395bcd05..3cbf313adf0 100644
--- a/compiler/rustc_codegen_cranelift/src/discriminant.rs
+++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs
@@ -1,6 +1,7 @@
 //! Handling of enum discriminants
 //!
-//! Adapted from <https://github.com/rust-lang/rust/blob/d760df5aea483aae041c9a241e7acacf48f75035/src/librustc_codegen_ssa/mir/place.rs>
+//! Adapted from <https://github.com/rust-lang/rust/blob/31c0645b9d2539f47eecb096142474b29dc542f7/compiler/rustc_codegen_ssa/src/mir/place.rs>
+//! (<https://github.com/rust-lang/rust/pull/104535>)
 
 use rustc_target::abi::{Int, TagEncoding, Variants};
 
@@ -47,13 +48,19 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
         } => {
             if variant_index != untagged_variant {
                 let niche = place.place_field(fx, mir::Field::new(tag_field));
+                let niche_type = fx.clif_type(niche.layout().ty).unwrap();
                 let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
-                let niche_value = ty::ScalarInt::try_from_uint(
-                    u128::from(niche_value).wrapping_add(niche_start),
-                    niche.layout().size,
-                )
-                .unwrap();
-                let niche_llval = CValue::const_val(fx, niche.layout(), niche_value);
+                let niche_value = (niche_value as u128).wrapping_add(niche_start);
+                let niche_value = match niche_type {
+                    types::I128 => {
+                        let lsb = fx.bcx.ins().iconst(types::I64, niche_value as u64 as i64);
+                        let msb =
+                            fx.bcx.ins().iconst(types::I64, (niche_value >> 64) as u64 as i64);
+                        fx.bcx.ins().iconcat(lsb, msb)
+                    }
+                    ty => fx.bcx.ins().iconst(ty, niche_value as i64),
+                };
+                let niche_llval = CValue::by_val(niche_value, niche.layout());
                 niche.write_cvalue(fx, niche_llval);
             }
         }
@@ -96,6 +103,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
         }
     };
 
+    let cast_to_size = dest_layout.layout.size();
     let cast_to = fx.clif_type(dest_layout.ty).unwrap();
 
     // Read the tag/niche-encoded discriminant from memory.
@@ -114,21 +122,128 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
             dest.write_cvalue(fx, res);
         }
         TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
-            // Rebase from niche values to discriminants, and check
-            // whether the result is in range for the niche variants.
-
-            // We first compute the "relative discriminant" (wrt `niche_variants`),
-            // that is, if `n = niche_variants.end() - niche_variants.start()`,
-            // we remap `niche_start..=niche_start + n` (which may wrap around)
-            // to (non-wrap-around) `0..=n`, to be able to check whether the
-            // discriminant corresponds to a niche variant with one comparison.
-            // We also can't go directly to the (variant index) discriminant
-            // and check that it is in the range `niche_variants`, because
-            // that might not fit in the same type, on top of needing an extra
-            // comparison (see also the comment on `let niche_discr`).
-            let relative_discr = if niche_start == 0 {
-                tag
+            let tag_size = tag_scalar.size(fx);
+            let max_unsigned = tag_size.unsigned_int_max();
+            let max_signed = tag_size.signed_int_max() as u128;
+            let min_signed = max_signed + 1;
+            let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
+            let niche_end = niche_start.wrapping_add(relative_max as u128) & max_unsigned;
+            let range = tag_scalar.valid_range(fx);
+
+            let sle = |lhs: u128, rhs: u128| -> bool {
+                // Signed and unsigned comparisons give the same results,
+                // except that in signed comparisons an integer with the
+                // sign bit set is less than one with the sign bit clear.
+                // Toggle the sign bit to do a signed comparison.
+                (lhs ^ min_signed) <= (rhs ^ min_signed)
+            };
+
+            // We have a subrange `niche_start..=niche_end` inside `range`.
+            // If the value of the tag is inside this subrange, it's a
+            // "niche value", an increment of the discriminant. Otherwise it
+            // indicates the untagged variant.
+            // A general algorithm to extract the discriminant from the tag
+            // is:
+            // relative_tag = tag - niche_start
+            // is_niche = relative_tag <= (ule) relative_max
+            // discr = if is_niche {
+            //     cast(relative_tag) + niche_variants.start()
+            // } else {
+            //     untagged_variant
+            // }
+            // However, we will likely be able to emit simpler code.
+
+            // Find the least and greatest values in `range`, considered
+            // both as signed and unsigned.
+            let (low_unsigned, high_unsigned) =
+                if range.start <= range.end { (range.start, range.end) } else { (0, max_unsigned) };
+            let (low_signed, high_signed) = if sle(range.start, range.end) {
+                (range.start, range.end)
             } else {
+                (min_signed, max_signed)
+            };
+
+            let niches_ule = niche_start <= niche_end;
+            let niches_sle = sle(niche_start, niche_end);
+            let cast_smaller = cast_to_size <= tag_size;
+
+            // In the algorithm above, we can change
+            // cast(relative_tag) + niche_variants.start()
+            // into
+            // cast(tag + (niche_variants.start() - niche_start))
+            // if either the casted type is no larger than the original
+            // type, or if the niche values are contiguous (in either the
+            // signed or unsigned sense).
+            let can_incr = cast_smaller || niches_ule || niches_sle;
+
+            let data_for_boundary_niche = || -> Option<(IntCC, u128)> {
+                if !can_incr {
+                    None
+                } else if niche_start == low_unsigned {
+                    Some((IntCC::UnsignedLessThanOrEqual, niche_end))
+                } else if niche_end == high_unsigned {
+                    Some((IntCC::UnsignedGreaterThanOrEqual, niche_start))
+                } else if niche_start == low_signed {
+                    Some((IntCC::SignedLessThanOrEqual, niche_end))
+                } else if niche_end == high_signed {
+                    Some((IntCC::SignedGreaterThanOrEqual, niche_start))
+                } else {
+                    None
+                }
+            };
+
+            let (is_niche, tagged_discr, delta) = if relative_max == 0 {
+                // Best case scenario: only one tagged variant. This will
+                // likely become just a comparison and a jump.
+                // The algorithm is:
+                // is_niche = tag == niche_start
+                // discr = if is_niche {
+                //     niche_start
+                // } else {
+                //     untagged_variant
+                // }
+                let is_niche = codegen_icmp_imm(fx, IntCC::Equal, tag, niche_start as i128);
+                let tagged_discr =
+                    fx.bcx.ins().iconst(cast_to, niche_variants.start().as_u32() as i64);
+                (is_niche, tagged_discr, 0)
+            } else if let Some((predicate, constant)) = data_for_boundary_niche() {
+                // The niche values are either the lowest or the highest in
+                // `range`. We can avoid the first subtraction in the
+                // algorithm.
+                // The algorithm is now this:
+                // is_niche = tag <= niche_end
+                // discr = if is_niche {
+                //     cast(tag + (niche_variants.start() - niche_start))
+                // } else {
+                //     untagged_variant
+                // }
+                // (the first line may instead be tag >= niche_start,
+                // and may be a signed or unsigned comparison)
+                // The arithmetic must be done before the cast, so we can
+                // have the correct wrapping behavior. See issue #104519 for
+                // the consequences of getting this wrong.
+                let is_niche = codegen_icmp_imm(fx, predicate, tag, constant as i128);
+                let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start);
+                let incr_tag = if delta == 0 {
+                    tag
+                } else {
+                    let delta = match fx.bcx.func.dfg.value_type(tag) {
+                        types::I128 => {
+                            let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
+                            let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
+                            fx.bcx.ins().iconcat(lsb, msb)
+                        }
+                        ty => fx.bcx.ins().iconst(ty, delta as i64),
+                    };
+                    fx.bcx.ins().iadd(tag, delta)
+                };
+
+                let cast_tag = clif_intcast(fx, incr_tag, cast_to, !niches_ule);
+
+                (is_niche, cast_tag, 0)
+            } else {
+                // The special cases don't apply, so we'll have to go with
+                // the general algorithm.
                 let niche_start = match fx.bcx.func.dfg.value_type(tag) {
                     types::I128 => {
                         let lsb = fx.bcx.ins().iconst(types::I64, niche_start as u64 as i64);
@@ -138,40 +253,40 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
                     }
                     ty => fx.bcx.ins().iconst(ty, niche_start as i64),
                 };
-                fx.bcx.ins().isub(tag, niche_start)
-            };
-            let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
-            let is_niche = {
-                codegen_icmp_imm(
+                let relative_discr = fx.bcx.ins().isub(tag, niche_start);
+                let cast_tag = clif_intcast(fx, relative_discr, cast_to, false);
+                let is_niche = crate::common::codegen_icmp_imm(
                     fx,
                     IntCC::UnsignedLessThanOrEqual,
                     relative_discr,
                     i128::from(relative_max),
-                )
+                );
+                (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
             };
 
-            // NOTE(eddyb) this addition needs to be performed on the final
-            // type, in case the niche itself can't represent all variant
-            // indices (e.g. `u8` niche with more than `256` variants,
-            // but enough uninhabited variants so that the remaining variants
-            // fit in the niche).
-            // In other words, `niche_variants.end - niche_variants.start`
-            // is representable in the niche, but `niche_variants.end`
-            // might not be, in extreme cases.
-            let niche_discr = {
-                let relative_discr = if relative_max == 0 {
-                    // HACK(eddyb) since we have only one niche, we know which
-                    // one it is, and we can avoid having a dynamic value here.
-                    fx.bcx.ins().iconst(cast_to, 0)
-                } else {
-                    clif_intcast(fx, relative_discr, cast_to, false)
+            let tagged_discr = if delta == 0 {
+                tagged_discr
+            } else {
+                let delta = match cast_to {
+                    types::I128 => {
+                        let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
+                        let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
+                        fx.bcx.ins().iconcat(lsb, msb)
+                    }
+                    ty => fx.bcx.ins().iconst(ty, delta as i64),
                 };
-                fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32()))
+                fx.bcx.ins().iadd(tagged_discr, delta)
             };
 
-            let untagged_variant =
-                fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()));
-            let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant);
+            let untagged_variant = if cast_to == types::I128 {
+                let zero = fx.bcx.ins().iconst(types::I64, 0);
+                let untagged_variant =
+                    fx.bcx.ins().iconst(types::I64, i64::from(untagged_variant.as_u32()));
+                fx.bcx.ins().iconcat(untagged_variant, zero)
+            } else {
+                fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()))
+            };
+            let discr = fx.bcx.ins().select(is_niche, tagged_discr, untagged_variant);
             let res = CValue::by_val(discr, dest_layout);
             dest.write_cvalue(fx, res);
         }
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 6a430b5215e..be1b8c9ead3 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -159,7 +159,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
 
     tcx.sess.abort_if_errors();
 
-    jit_module.finalize_definitions();
+    jit_module.finalize_definitions().unwrap();
     unsafe { cx.unwind_context.register_jit(&jit_module) };
 
     println!(
@@ -245,7 +245,11 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
             let backend_config = lazy_jit_state.backend_config.clone();
 
             let name = tcx.symbol_name(instance).name;
-            let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance);
+            let sig = crate::abi::get_function_sig(
+                tcx,
+                jit_module.target_config().default_call_conv,
+                instance,
+            );
             let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
 
             let current_ptr = jit_module.read_got_entry(func_id);
@@ -278,7 +282,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
             });
 
             assert!(cx.global_asm.is_empty());
-            jit_module.finalize_definitions();
+            jit_module.finalize_definitions().unwrap();
             unsafe { cx.unwind_context.register_jit(&jit_module) };
             jit_module.get_finalized_function(func_id)
         })
@@ -344,7 +348,7 @@ fn codegen_shim<'tcx>(
     let pointer_type = module.target_config().pointer_type();
 
     let name = tcx.symbol_name(inst).name;
-    let sig = crate::abi::get_function_sig(tcx, module.isa().triple(), inst);
+    let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst);
     let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap();
 
     let instance_ptr = Box::into_raw(Box::new(inst));
diff --git a/compiler/rustc_codegen_cranelift/src/driver/mod.rs b/compiler/rustc_codegen_cranelift/src/driver/mod.rs
index 8f5714ecb41..6e925cea277 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/mod.rs
@@ -24,7 +24,8 @@ fn predefine_mono_items<'tcx>(
                 MonoItem::Fn(instance) => {
                     let name = tcx.symbol_name(instance).name;
                     let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name));
-                    let sig = get_function_sig(tcx, module.isa().triple(), instance);
+                    let sig =
+                        get_function_sig(tcx, module.target_config().default_call_conv, instance);
                     let linkage = crate::linkage::get_clif_linkage(
                         mono_item,
                         linkage,
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index 783d426c30b..f722e52284f 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -8,135 +8,37 @@ use rustc_middle::ty::subst::SubstsRef;
 pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: &str,
-    _substs: SubstsRef<'tcx>,
+    substs: SubstsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
     target: Option<BasicBlock>,
 ) {
-    match intrinsic {
-        "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
-            // Spin loop hint
-        }
+    if intrinsic.starts_with("llvm.aarch64") {
+        return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(
+            fx, intrinsic, substs, args, ret, target,
+        );
+    }
+    if intrinsic.starts_with("llvm.x86") {
+        return llvm_x86::codegen_x86_llvm_intrinsic_call(fx, intrinsic, substs, args, ret, target);
+    }
 
-        // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
-        "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
+    match intrinsic {
+        _ if intrinsic.starts_with("llvm.ctlz.v") => {
             intrinsic_args!(fx, args => (a); intrinsic);
 
-            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
-            let lane_ty = fx.clif_type(lane_ty).unwrap();
-            assert!(lane_count <= 32);
-
-            let mut res = fx.bcx.ins().iconst(types::I32, 0);
-
-            for lane in (0..lane_count).rev() {
-                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
-
-                // cast float to int
-                let a_lane = match lane_ty {
-                    types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
-                    types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
-                    _ => a_lane,
-                };
-
-                // extract sign bit of an int
-                let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
-
-                // shift sign bit into result
-                let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
-                res = fx.bcx.ins().ishl_imm(res, 1);
-                res = fx.bcx.ins().bor(res, a_lane_sign);
-            }
-
-            let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
-            ret.write_cvalue(fx, res);
-        }
-        "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
-            let (x, y, kind) = match args {
-                [x, y, kind] => (x, y, kind),
-                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
-            };
-            let x = codegen_operand(fx, x);
-            let y = codegen_operand(fx, y);
-            let kind = crate::constant::mir_operand_get_const_val(fx, kind)
-                .expect("llvm.x86.sse2.cmp.* kind not const");
-
-            let flt_cc = match kind
-                .try_to_bits(Size::from_bytes(1))
-                .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
-            {
-                0 => FloatCC::Equal,
-                1 => FloatCC::LessThan,
-                2 => FloatCC::LessThanOrEqual,
-                7 => FloatCC::Ordered,
-                3 => FloatCC::Unordered,
-                4 => FloatCC::NotEqual,
-                5 => FloatCC::UnorderedOrGreaterThanOrEqual,
-                6 => FloatCC::UnorderedOrGreaterThan,
-                kind => unreachable!("kind {:?}", kind),
-            };
-
-            simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
-                let res_lane = match lane_ty.kind() {
-                    ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
-                    _ => unreachable!("{:?}", lane_ty),
-                };
-                bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().clz(lane)
             });
         }
-        "llvm.x86.sse2.psrli.d" => {
-            let (a, imm8) = match args {
-                [a, imm8] => (a, imm8),
-                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
-            };
-            let a = codegen_operand(fx, a);
-            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
-                .expect("llvm.x86.sse2.psrli.d imm8 not const");
 
-            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
-                .try_to_bits(Size::from_bytes(4))
-                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
-            {
-                imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
-                _ => fx.bcx.ins().iconst(types::I32, 0),
-            });
-        }
-        "llvm.x86.sse2.pslli.d" => {
-            let (a, imm8) = match args {
-                [a, imm8] => (a, imm8),
-                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
-            };
-            let a = codegen_operand(fx, a);
-            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
-                .expect("llvm.x86.sse2.psrli.d imm8 not const");
+        _ if intrinsic.starts_with("llvm.ctpop.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
 
-            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
-                .try_to_bits(Size::from_bytes(4))
-                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
-            {
-                imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
-                _ => fx.bcx.ins().iconst(types::I32, 0),
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().popcnt(lane)
             });
         }
-        "llvm.x86.sse2.storeu.dq" => {
-            intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
-            let mem_addr = mem_addr.load_scalar(fx);
-
-            // FIXME correctly handle the unalignment
-            let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
-            dest.write_cvalue(fx, a);
-        }
-        "llvm.x86.addcarry.64" => {
-            intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
-            let c_in = c_in.load_scalar(fx);
-
-            llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
-        }
-        "llvm.x86.subborrow.64" => {
-            intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
-            let b_in = b_in.load_scalar(fx);
 
-            llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
-        }
         _ => {
             fx.tcx
                 .sess
@@ -150,47 +52,3 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     let ret_block = fx.get_block(dest);
     fx.bcx.ins().jump(ret_block, &[]);
 }
-
-// llvm.x86.avx2.vperm2i128
-// llvm.x86.ssse3.pshuf.b.128
-// llvm.x86.avx2.pshuf.b
-// llvm.x86.avx2.psrli.w
-// llvm.x86.sse2.psrli.w
-
-fn llvm_add_sub<'tcx>(
-    fx: &mut FunctionCx<'_, '_, 'tcx>,
-    bin_op: BinOp,
-    ret: CPlace<'tcx>,
-    cb_in: Value,
-    a: CValue<'tcx>,
-    b: CValue<'tcx>,
-) {
-    assert_eq!(
-        a.layout().ty,
-        fx.tcx.types.u64,
-        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
-    );
-    assert_eq!(
-        b.layout().ty,
-        fx.tcx.types.u64,
-        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
-    );
-
-    // c + carry -> c + first intermediate carry or borrow respectively
-    let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
-    let c = int0.value_field(fx, mir::Field::new(0));
-    let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
-
-    // c + carry -> c + second intermediate carry or borrow respectively
-    let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
-    let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
-    let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
-    let (c, cb1) = int1.load_scalar_pair(fx);
-
-    // carry0 | carry1 -> carry or borrow respectively
-    let cb_out = fx.bcx.ins().bor(cb0, cb1);
-
-    let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
-    let val = CValue::by_val_pair(cb_out, c, layout);
-    ret.write_cvalue(fx, val);
-}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
new file mode 100644
index 00000000000..b431158d269
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
@@ -0,0 +1,222 @@
+//! Emulate AArch64 LLVM intrinsics
+
+use crate::intrinsics::*;
+use crate::prelude::*;
+
+use rustc_middle::ty::subst::SubstsRef;
+
+pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    intrinsic: &str,
+    _substs: SubstsRef<'tcx>,
+    args: &[mir::Operand<'tcx>],
+    ret: CPlace<'tcx>,
+    target: Option<BasicBlock>,
+) {
+    // llvm.aarch64.neon.sqshl.v*i*
+
+    match intrinsic {
+        "llvm.aarch64.isb" => {
+            fx.bcx.ins().fence();
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.abs.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().iabs(lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.cls.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().cls(lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.rbit.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().bitrev(lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+                crate::num::codegen_saturating_int_binop(fx, BinOp::Add, x_lane, y_lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqsub.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+                crate::num::codegen_saturating_int_binop(fx, BinOp::Sub, x_lane, y_lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.smax.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.umax.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.smaxv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.umaxv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.smin.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.umin.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sminv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.uminv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        /*
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sshl.v")
+            || intrinsic.starts_with("llvm.aarch64.neon.sqshl.v")
+            // FIXME split this one out once saturating is implemented
+            || intrinsic.starts_with("llvm.aarch64.neon.sqshlu.v") =>
+        {
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            simd_pair_for_each_lane(fx, a, b, ret, &|fx, _lane_ty, _res_lane_ty, a, b| {
+                // FIXME saturate?
+                fx.bcx.ins().ishl(a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqshrn.v") => {
+            let (a, imm32) = match args {
+                [a, imm32] => (a, imm32),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
+                .expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
+            {
+                imm32 if imm32 < 32 => fx.bcx.ins().sshr_imm(lane, i64::from(imm32 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqshrun.v") => {
+            let (a, imm32) = match args {
+                [a, imm32] => (a, imm32),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
+                .expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
+            {
+                imm32 if imm32 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm32 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+        */
+        _ => {
+            fx.tcx.sess.warn(&format!(
+                "unsupported AArch64 llvm intrinsic {}; replacing with trap",
+                intrinsic
+            ));
+            crate::trap::trap_unimplemented(fx, intrinsic);
+            return;
+        }
+    }
+
+    let dest = target.expect("all llvm intrinsics used by stdlib should return");
+    let ret_block = fx.get_block(dest);
+    fx.bcx.ins().jump(ret_block, &[]);
+}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
new file mode 100644
index 00000000000..7bc161fbe55
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -0,0 +1,197 @@
+//! Emulate x86 LLVM intrinsics
+
+use crate::intrinsics::*;
+use crate::prelude::*;
+
+use rustc_middle::ty::subst::SubstsRef;
+
+pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    intrinsic: &str,
+    _substs: SubstsRef<'tcx>,
+    args: &[mir::Operand<'tcx>],
+    ret: CPlace<'tcx>,
+    target: Option<BasicBlock>,
+) {
+    match intrinsic {
+        "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
+            // Spin loop hint
+        }
+
+        // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
+        "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
+            let lane_ty = fx.clif_type(lane_ty).unwrap();
+            assert!(lane_count <= 32);
+
+            let mut res = fx.bcx.ins().iconst(types::I32, 0);
+
+            for lane in (0..lane_count).rev() {
+                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
+
+                // cast float to int
+                let a_lane = match lane_ty {
+                    types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
+                    types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
+                    _ => a_lane,
+                };
+
+                // extract sign bit of an int
+                let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
+
+                // shift sign bit into result
+                let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
+                res = fx.bcx.ins().ishl_imm(res, 1);
+                res = fx.bcx.ins().bor(res, a_lane_sign);
+            }
+
+            let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
+            ret.write_cvalue(fx, res);
+        }
+        "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
+            let (x, y, kind) = match args {
+                [x, y, kind] => (x, y, kind),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let x = codegen_operand(fx, x);
+            let y = codegen_operand(fx, y);
+            let kind = crate::constant::mir_operand_get_const_val(fx, kind)
+                .expect("llvm.x86.sse2.cmp.* kind not const");
+
+            let flt_cc = match kind
+                .try_to_bits(Size::from_bytes(1))
+                .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
+            {
+                0 => FloatCC::Equal,
+                1 => FloatCC::LessThan,
+                2 => FloatCC::LessThanOrEqual,
+                7 => FloatCC::Ordered,
+                3 => FloatCC::Unordered,
+                4 => FloatCC::NotEqual,
+                5 => FloatCC::UnorderedOrGreaterThanOrEqual,
+                6 => FloatCC::UnorderedOrGreaterThan,
+                kind => unreachable!("kind {:?}", kind),
+            };
+
+            simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
+                let res_lane = match lane_ty.kind() {
+                    ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
+                    _ => unreachable!("{:?}", lane_ty),
+                };
+                bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
+            });
+        }
+        "llvm.x86.sse2.psrli.d" => {
+            let (a, imm8) = match args {
+                [a, imm8] => (a, imm8),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
+                .expect("llvm.x86.sse2.psrli.d imm8 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
+            {
+                imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+        "llvm.x86.sse2.pslli.d" => {
+            let (a, imm8) = match args {
+                [a, imm8] => (a, imm8),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
+                .expect("llvm.x86.sse2.psrli.d imm8 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
+            {
+                imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+        "llvm.x86.sse2.storeu.dq" => {
+            intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
+            let mem_addr = mem_addr.load_scalar(fx);
+
+            // FIXME correctly handle the unalignment
+            let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
+            dest.write_cvalue(fx, a);
+        }
+        "llvm.x86.addcarry.64" => {
+            intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
+            let c_in = c_in.load_scalar(fx);
+
+            llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
+        }
+        "llvm.x86.subborrow.64" => {
+            intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
+            let b_in = b_in.load_scalar(fx);
+
+            llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
+        }
+        _ => {
+            fx.tcx.sess.warn(&format!(
+                "unsupported x86 llvm intrinsic {}; replacing with trap",
+                intrinsic
+            ));
+            crate::trap::trap_unimplemented(fx, intrinsic);
+            return;
+        }
+    }
+
+    let dest = target.expect("all llvm intrinsics used by stdlib should return");
+    let ret_block = fx.get_block(dest);
+    fx.bcx.ins().jump(ret_block, &[]);
+}
+
+// llvm.x86.avx2.vperm2i128
+// llvm.x86.ssse3.pshuf.b.128
+// llvm.x86.avx2.pshuf.b
+// llvm.x86.avx2.psrli.w
+// llvm.x86.sse2.psrli.w
+
+fn llvm_add_sub<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    bin_op: BinOp,
+    ret: CPlace<'tcx>,
+    cb_in: Value,
+    a: CValue<'tcx>,
+    b: CValue<'tcx>,
+) {
+    assert_eq!(
+        a.layout().ty,
+        fx.tcx.types.u64,
+        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
+    );
+    assert_eq!(
+        b.layout().ty,
+        fx.tcx.types.u64,
+        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
+    );
+
+    // c + carry -> c + first intermediate carry or borrow respectively
+    let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
+    let c = int0.value_field(fx, mir::Field::new(0));
+    let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
+
+    // c + carry -> c + second intermediate carry or borrow respectively
+    let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
+    let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
+    let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
+    let (c, cb1) = int1.load_scalar_pair(fx);
+
+    // carry0 | carry1 -> carry or borrow respectively
+    let cb_out = fx.bcx.ins().bor(cb0, cb1);
+
+    let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
+    let val = CValue::by_val_pair(cb_out, c, layout);
+    ret.write_cvalue(fx, val);
+}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 0302b843aa2..7a380acf798 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -14,6 +14,8 @@ macro_rules! intrinsic_args {
 
 mod cpuid;
 mod llvm;
+mod llvm_aarch64;
+mod llvm_x86;
 mod simd;
 
 pub(crate) use cpuid::codegen_cpuid_call;
@@ -195,8 +197,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
         ty => ty,
     };
 
-    let val = fx.bcx.ins().bint(int_ty, val);
-    let mut res = fx.bcx.ins().ineg(val);
+    let mut res = fx.bcx.ins().bmask(int_ty, val);
 
     if ty.is_float() {
         res = fx.bcx.ins().bitcast(ty, res);
@@ -632,85 +633,15 @@ fn codegen_regular_intrinsic_call<'tcx>(
             ret.write_cvalue(fx, res);
         }
         sym::bswap => {
-            // FIXME(CraneStation/cranelift#794) add bswap instruction to cranelift
-            fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
-                match bcx.func.dfg.value_type(v) {
-                    types::I8 => v,
-
-                    // https://code.woboq.org/gcc/include/bits/byteswap.h.html
-                    types::I16 => {
-                        let tmp1 = bcx.ins().ishl_imm(v, 8);
-                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00);
-
-                        let tmp2 = bcx.ins().ushr_imm(v, 8);
-                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF);
-
-                        bcx.ins().bor(n1, n2)
-                    }
-                    types::I32 => {
-                        let tmp1 = bcx.ins().ishl_imm(v, 24);
-                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000);
-
-                        let tmp2 = bcx.ins().ishl_imm(v, 8);
-                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000);
-
-                        let tmp3 = bcx.ins().ushr_imm(v, 8);
-                        let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00);
-
-                        let tmp4 = bcx.ins().ushr_imm(v, 24);
-                        let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF);
-
-                        let or_tmp1 = bcx.ins().bor(n1, n2);
-                        let or_tmp2 = bcx.ins().bor(n3, n4);
-                        bcx.ins().bor(or_tmp1, or_tmp2)
-                    }
-                    types::I64 => {
-                        let tmp1 = bcx.ins().ishl_imm(v, 56);
-                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000_0000_0000u64 as i64);
-
-                        let tmp2 = bcx.ins().ishl_imm(v, 40);
-                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000_0000_0000u64 as i64);
-
-                        let tmp3 = bcx.ins().ishl_imm(v, 24);
-                        let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00_0000_0000u64 as i64);
-
-                        let tmp4 = bcx.ins().ishl_imm(v, 8);
-                        let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF_0000_0000u64 as i64);
-
-                        let tmp5 = bcx.ins().ushr_imm(v, 8);
-                        let n5 = bcx.ins().band_imm(tmp5, 0x0000_0000_FF00_0000u64 as i64);
-
-                        let tmp6 = bcx.ins().ushr_imm(v, 24);
-                        let n6 = bcx.ins().band_imm(tmp6, 0x0000_0000_00FF_0000u64 as i64);
-
-                        let tmp7 = bcx.ins().ushr_imm(v, 40);
-                        let n7 = bcx.ins().band_imm(tmp7, 0x0000_0000_0000_FF00u64 as i64);
-
-                        let tmp8 = bcx.ins().ushr_imm(v, 56);
-                        let n8 = bcx.ins().band_imm(tmp8, 0x0000_0000_0000_00FFu64 as i64);
-
-                        let or_tmp1 = bcx.ins().bor(n1, n2);
-                        let or_tmp2 = bcx.ins().bor(n3, n4);
-                        let or_tmp3 = bcx.ins().bor(n5, n6);
-                        let or_tmp4 = bcx.ins().bor(n7, n8);
-
-                        let or_tmp5 = bcx.ins().bor(or_tmp1, or_tmp2);
-                        let or_tmp6 = bcx.ins().bor(or_tmp3, or_tmp4);
-                        bcx.ins().bor(or_tmp5, or_tmp6)
-                    }
-                    types::I128 => {
-                        let (lo, hi) = bcx.ins().isplit(v);
-                        let lo = swap(bcx, lo);
-                        let hi = swap(bcx, hi);
-                        bcx.ins().iconcat(hi, lo)
-                    }
-                    ty => unreachable!("bswap {}", ty),
-                }
-            }
             intrinsic_args!(fx, args => (arg); intrinsic);
             let val = arg.load_scalar(fx);
 
-            let res = CValue::by_val(swap(&mut fx.bcx, val), arg.layout());
+            let res = if fx.bcx.func.dfg.value_type(val) == types::I8 {
+                val
+            } else {
+                fx.bcx.ins().bswap(val)
+            };
+            let res = CValue::by_val(res, arg.layout());
             ret.write_cvalue(fx, res);
         }
         sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
@@ -936,8 +867,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let old = fx.bcx.ins().atomic_cas(MemFlags::trusted(), ptr, test_old, new);
             let is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old);
 
-            let ret_val =
-                CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout());
+            let ret_val = CValue::by_val_pair(old, is_eq, ret.layout());
             ret.write_cvalue(fx, ret_val)
         }
 
@@ -1259,8 +1189,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
                 flags.set_notrap();
                 let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0);
                 let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0);
-                let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val);
-                fx.bcx.ins().bint(types::I8, eq)
+                fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val)
             } else {
                 // Just call `memcmp` (like slices do in core) when the
                 // size is too large or it's not a power-of-two.
@@ -1270,8 +1199,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
                 let returns = vec![AbiParam::new(types::I32)];
                 let args = &[lhs_ref, rhs_ref, bytes_val];
                 let cmp = fx.lib_call("memcmp", params, returns, args)[0];
-                let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0);
-                fx.bcx.ins().bint(types::I8, eq)
+                fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0)
             };
             ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
         }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 51fce8c854b..14f5e918739 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -112,10 +112,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                     _ => unreachable!(),
                 };
 
-                let ty = fx.clif_type(res_lane_ty).unwrap();
-
-                let res_lane = fx.bcx.ins().bint(ty, res_lane);
-                fx.bcx.ins().ineg(res_lane)
+                bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
             });
         }
 
@@ -716,7 +713,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
 
             let res_type =
                 Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap();
-            let mut res = fx.bcx.ins().iconst(res_type, 0);
+            let mut res = type_zero_value(&mut fx.bcx, res_type);
 
             let lanes = match fx.tcx.sess.target.endian {
                 Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>,
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index f7434633ea4..c10054e7f0d 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -65,7 +65,7 @@ pub(crate) fn maybe_create_entry_wrapper(
             returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
             call_conv: crate::conv_to_call_conv(
                 tcx.sess.target.options.entry_abi,
-                CallConv::triple_default(m.isa().triple()),
+                m.target_config().default_call_conv,
             ),
         };
 
@@ -75,7 +75,7 @@ pub(crate) fn maybe_create_entry_wrapper(
         let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);
 
         let main_name = tcx.symbol_name(instance).name;
-        let main_sig = get_function_sig(tcx, m.isa().triple(), instance);
+        let main_sig = get_function_sig(tcx, m.target_config().default_call_conv, instance);
         let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();
 
         let mut ctx = Context::new();
@@ -119,7 +119,7 @@ pub(crate) fn maybe_create_entry_wrapper(
                 .polymorphize(tcx);
 
                 let report_name = tcx.symbol_name(report).name;
-                let report_sig = get_function_sig(tcx, m.isa().triple(), report);
+                let report_sig = get_function_sig(tcx, m.target_config().default_call_conv, report);
                 let report_func_id =
                     m.declare_function(report_name, Linkage::Import, &report_sig).unwrap();
                 let report_func_ref = m.declare_func_in_func(report_func_id, &mut bcx.func);
diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs
index ecbab408ded..afacbec6445 100644
--- a/compiler/rustc_codegen_cranelift/src/num.rs
+++ b/compiler/rustc_codegen_cranelift/src/num.rs
@@ -49,7 +49,6 @@ fn codegen_compare_bin_op<'tcx>(
 ) -> CValue<'tcx> {
     let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
     let val = fx.bcx.ins().icmp(intcc, lhs, rhs);
-    let val = fx.bcx.ins().bint(types::I8, val);
     CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
 }
 
@@ -290,8 +289,6 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
         _ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs),
     };
 
-    let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
-
     let out_layout = fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()));
     CValue::by_val_pair(res, has_overflow, out_layout)
 }
@@ -368,7 +365,6 @@ pub(crate) fn codegen_float_binop<'tcx>(
                 _ => unreachable!(),
             };
             let val = fx.bcx.ins().fcmp(fltcc, lhs, rhs);
-            let val = fx.bcx.ins().bint(types::I8, val);
             return CValue::by_val(val, fx.layout_of(fx.tcx.types.bool));
         }
         _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs),
@@ -440,7 +436,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
             _ => panic!("bin_op {:?} on ptr", bin_op),
         };
 
-        CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool))
+        CValue::by_val(res, fx.layout_of(fx.tcx.types.bool))
     }
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs b/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
index d637b4d8929..7f45bbd8f28 100644
--- a/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
+++ b/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
@@ -3,19 +3,6 @@
 use cranelift_codegen::ir::{condcodes::IntCC, InstructionData, Opcode, Value, ValueDef};
 use cranelift_frontend::FunctionBuilder;
 
-/// If the given value was produced by a `bint` instruction, return it's input, otherwise return the
-/// given value.
-pub(crate) fn maybe_unwrap_bint(bcx: &mut FunctionBuilder<'_>, arg: Value) -> Value {
-    if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
-        match bcx.func.dfg[arg_inst] {
-            InstructionData::Unary { opcode: Opcode::Bint, arg } => arg,
-            _ => arg,
-        }
-    } else {
-        arg
-    }
-}
-
 /// If the given value was produced by the lowering of `Rvalue::Not` return the input and true,
 /// otherwise return the given value and false.
 pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) {
@@ -48,13 +35,6 @@ pub(crate) fn maybe_known_branch_taken(
     };
 
     match bcx.func.dfg[arg_inst] {
-        InstructionData::UnaryBool { opcode: Opcode::Bconst, imm } => {
-            if test_zero {
-                Some(!imm)
-            } else {
-                Some(imm)
-            }
-        }
         InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {
             if test_zero {
                 Some(imm.bits() == 0)
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 34746ff6b66..fe8af21ac6d 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -392,7 +392,7 @@ impl<'tcx> CPlace<'tcx> {
         local: Local,
         layout: TyAndLayout<'tcx>,
     ) -> CPlace<'tcx> {
-        let var = Variable::with_u32(fx.next_ssa_var);
+        let var = Variable::from_u32(fx.next_ssa_var);
         fx.next_ssa_var += 1;
         fx.bcx.declare_var(var, fx.clif_type(layout.ty).unwrap());
         CPlace { inner: CPlaceInner::Var(local, var), layout }
@@ -403,9 +403,9 @@ impl<'tcx> CPlace<'tcx> {
         local: Local,
         layout: TyAndLayout<'tcx>,
     ) -> CPlace<'tcx> {
-        let var1 = Variable::with_u32(fx.next_ssa_var);
+        let var1 = Variable::from_u32(fx.next_ssa_var);
         fx.next_ssa_var += 1;
-        let var2 = Variable::with_u32(fx.next_ssa_var);
+        let var2 = Variable::from_u32(fx.next_ssa_var);
         fx.next_ssa_var += 1;
 
         let (ty1, ty2) = fx.clif_pair_type(layout.ty).unwrap();
@@ -515,9 +515,7 @@ impl<'tcx> CPlace<'tcx> {
                 | (types::F32, types::I32)
                 | (types::I64, types::F64)
                 | (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data),
-                _ if src_ty.is_vector() && dst_ty.is_vector() => {
-                    fx.bcx.ins().raw_bitcast(dst_ty, data)
-                }
+                _ if src_ty.is_vector() && dst_ty.is_vector() => fx.bcx.ins().bitcast(dst_ty, data),
                 _ if src_ty.is_vector() || dst_ty.is_vector() => {
                     // FIXME do something more efficient for transmutes between vectors and integers.
                     let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
@@ -590,7 +588,10 @@ impl<'tcx> CPlace<'tcx> {
                 return;
             }
             CPlaceInner::VarPair(_local, var1, var2) => {
-                let (data1, data2) = CValue(from.0, dst_layout).load_scalar_pair(fx);
+                let (ptr, meta) = from.force_stack(fx);
+                assert!(meta.is_none());
+                let (data1, data2) =
+                    CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx);
                 let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap();
                 transmute_value(fx, var1, data1, dst_ty1);
                 transmute_value(fx, var2, data2, dst_ty2);
diff --git a/compiler/rustc_codegen_cranelift/test.sh b/compiler/rustc_codegen_cranelift/test.sh
index 3d929a1d50c..13e7784539d 100755
--- a/compiler/rustc_codegen_cranelift/test.sh
+++ b/compiler/rustc_codegen_cranelift/test.sh
@@ -1,2 +1,2 @@
 #!/usr/bin/env bash
-exec ./y.rs test
+exec ./y.rs test "$@"
diff --git a/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs
index f177b91c2c4..02e1e21ade1 100755
--- a/compiler/rustc_codegen_cranelift/y.rs
+++ b/compiler/rustc_codegen_cranelift/y.rs
@@ -3,7 +3,7 @@
 # This block is ignored by rustc
 set -e
 echo "[BUILD] y.rs" 1>&2
-rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1
+rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021
 exec ${0/.rs/.bin} $@
 */
 
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 782f6856654..effb2de4827 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1119,18 +1119,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // TODO(antoyo)
     }
 
-    fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> {
-        let field1 = self.context.new_field(None, self.u8_type.make_pointer(), "landing_pad_field_1");
-        let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
-        let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
-        self.current_func().new_local(None, struct_type.as_type(), "landing_pad")
-            .to_rvalue()
+    fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+        (
+            self.current_func().new_local(None, self.u8_type.make_pointer(), "landing_pad0")
+                .to_rvalue(),
+            self.current_func().new_local(None, self.i32_type, "landing_pad1").to_rvalue(),
+        )
         // TODO(antoyo): Properly implement unwinding.
         // the above is just to make the compilation work as it seems
         // rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort.
     }
 
-    fn resume(&mut self, _exn: RValue<'gcc>) {
+    fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
         // TODO(bjorn3): Properly implement unwinding.
         self.unreachable();
     }
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 0aee1a1439b..36aba5bb740 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -15,8 +15,8 @@ use crate::errors::{
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
 use rustc_codegen_ssa::back::archive::{
-    get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
-    ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
+    get_native_object_symbols, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
+    ArchiveBuilderBuilder, UnknownArchiveKind,
 };
 
 use rustc_session::cstore::DllImport;
@@ -66,13 +66,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
         archive: &Path,
         skip: Box<dyn FnMut(&str) -> bool + 'static>,
     ) -> io::Result<()> {
-        let mut archive = archive.to_path_buf();
-        if self.sess.target.llvm_target.contains("-apple-macosx") {
-            if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? {
-                archive = new_archive
-            }
-        }
-        let archive_ro = match ArchiveRO::open(&archive) {
+        let archive_ro = match ArchiveRO::open(archive) {
             Ok(ar) => ar,
             Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
         };
@@ -80,7 +74,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
             return Ok(());
         }
         self.additions.push(Addition::Archive {
-            path: archive,
+            path: archive.to_path_buf(),
             archive: archive_ro,
             skip: Box::new(skip),
         });
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 3fa21355b7f..e20dc906bce 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -133,6 +133,10 @@ fn prepare_lto(
         }
     }
 
+    // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
+    // __llvm_profile_runtime, therefore we won't know until link time if this symbol
+    // should have default visibility.
+    symbols_below_threshold.push(CString::new("__llvm_profile_counter_bias").unwrap());
     Ok((symbols_below_threshold, upstream_modules))
 }
 
@@ -206,7 +210,7 @@ pub(crate) fn run_thin(
 }
 
 pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBuffer) {
-    let name = module.name.clone();
+    let name = module.name;
     let buffer = ThinBuffer::new(module.module_llvm.llmod(), true);
     (name, buffer)
 }
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 83bffb20e0c..853a8b82853 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -979,15 +979,20 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn cleanup_landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value) -> &'ll Value {
+    fn cleanup_landing_pad(&mut self, pers_fn: &'ll Value) -> (&'ll Value, &'ll Value) {
+        let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
         let landing_pad = self.landing_pad(ty, pers_fn, 1 /* FIXME should this be 0? */);
         unsafe {
             llvm::LLVMSetCleanup(landing_pad, llvm::True);
         }
-        landing_pad
+        (self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1))
     }
 
-    fn resume(&mut self, exn: &'ll Value) {
+    fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) {
+        let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
+        let mut exn = self.const_undef(ty);
+        exn = self.insert_value(exn, exn0, 0);
+        exn = self.insert_value(exn, exn1, 1);
         unsafe {
             llvm::LLVMBuildResume(self.llbuilder, exn);
         }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 2f5dd519b26..907517bf6ce 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -424,7 +424,9 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         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])
+        let type_checked_load =
+            self.call_intrinsic("llvm.type.checked.load", &[llvtable, vtable_byte_offset, typeid]);
+        self.extract_value(type_checked_load, 0)
     }
 
     fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value {
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 58558fb8c4b..5266d8858d4 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -14,7 +14,7 @@ use tempfile::Builder as TempFileBuilder;
 
 use std::error::Error;
 use std::fs::File;
-use std::io::{self, Write};
+use std::io;
 use std::path::{Path, PathBuf};
 
 // Re-exporting for rustc_codegen_llvm::back::archive
@@ -116,12 +116,11 @@ impl<'a> ArArchiveBuilder<'a> {
     }
 }
 
-fn try_filter_fat_archs(
+fn try_filter_fat_archs<'a>(
     archs: object::read::Result<&[impl FatArch]>,
     target_arch: object::Architecture,
-    archive_path: &Path,
-    archive_map_data: &[u8],
-) -> io::Result<Option<PathBuf>> {
+    archive_map_data: &'a [u8],
+) -> io::Result<Option<(&'a [u8], u64)>> {
     let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
 
     let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
@@ -129,38 +128,30 @@ fn try_filter_fat_archs(
         None => return Ok(None),
     };
 
-    let (mut new_f, extracted_path) = tempfile::Builder::new()
-        .suffix(archive_path.file_name().unwrap())
-        .tempfile()?
-        .keep()
-        .unwrap();
-
-    new_f.write_all(
+    Ok(Some((
         desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
-    )?;
-
-    Ok(Some(extracted_path))
+        desired.offset().into(),
+    )))
 }
 
-pub fn try_extract_macho_fat_archive(
+pub fn try_extract_macho_fat_archive<'a>(
     sess: &Session,
-    archive_path: &Path,
-) -> io::Result<Option<PathBuf>> {
-    let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
+    archive_bytes: &'a [u8],
+) -> io::Result<Option<(&'a [u8], u64)>> {
     let target_arch = match sess.target.arch.as_ref() {
         "aarch64" => object::Architecture::Aarch64,
         "x86_64" => object::Architecture::X86_64,
         _ => return Ok(None),
     };
 
-    match object::macho::FatHeader::parse(&*archive_map) {
+    match object::macho::FatHeader::parse(archive_bytes) {
         Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
-            let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
-            try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+            let archs = object::macho::FatHeader::parse_arch32(archive_bytes);
+            try_filter_fat_archs(archs, target_arch, archive_bytes)
         }
         Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
-            let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
-            try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+            let archs = object::macho::FatHeader::parse_arch64(archive_bytes);
+            try_filter_fat_archs(archs, target_arch, archive_bytes)
         }
         // Not a FatHeader at all, just return None.
         _ => Ok(None),
@@ -173,21 +164,24 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         archive_path: &Path,
         mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
     ) -> io::Result<()> {
-        let mut archive_path = archive_path.to_path_buf();
-        if self.sess.target.llvm_target.contains("-apple-macosx") {
-            if let Some(new_archive_path) =
-                try_extract_macho_fat_archive(&self.sess, &archive_path)?
-            {
-                archive_path = new_archive_path
-            }
-        }
-
+        let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
         if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
             return Ok(());
         }
 
-        let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
-        let archive = ArchiveFile::parse(&*archive_map)
+        let (archive_bytes, offset) = if self.sess.target.llvm_target.contains("-apple-macosx") {
+            if let Some((sub_archive, archive_offset)) =
+                try_extract_macho_fat_archive(&self.sess, &*archive_map)?
+            {
+                (sub_archive, Some(archive_offset))
+            } else {
+                (&*archive_map, None)
+            }
+        } else {
+            (&*archive_map, None)
+        };
+
+        let archive = ArchiveFile::parse(&*archive_bytes)
             .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
         let archive_index = self.src_archives.len();
 
@@ -196,9 +190,13 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
             let file_name = String::from_utf8(entry.name().to_vec())
                 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
             if !skip(&file_name) {
+                let mut range = entry.file_range();
+                if let Some(offset) = offset {
+                    range.0 += offset;
+                }
                 self.entries.push((
                     file_name.into_bytes(),
-                    ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
+                    ArchiveEntry::FromArchive { archive_index, file_range: range },
                 ));
             }
         }
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 4f396e970ad..664697e0eda 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -41,7 +41,6 @@ use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType};
 use rustc_target::abi::{Align, Size, VariantIdx};
 
 use std::collections::BTreeSet;
-use std::convert::TryFrom;
 use std::time::{Duration, Instant};
 
 use itertools::Itertools;
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
new file mode 100644
index 00000000000..c7f2e1966c1
--- /dev/null
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -0,0 +1,688 @@
+use rustc_ast::{ast, MetaItemKind, NestedMetaItem};
+use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
+use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
+use rustc_middle::mir::mono::Linkage;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::{self as ty, DefIdTree, TyCtxt};
+use rustc_session::{lint, parse::feature_err};
+use rustc_span::{sym, Span};
+use rustc_target::spec::{abi, SanitizerSet};
+
+use crate::target_features::from_target_feature;
+use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe};
+
+fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
+    use rustc_middle::mir::mono::Linkage::*;
+
+    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+    // applicable to variable declarations and may not really make sense for
+    // Rust code in the first place but allow them anyway and trust that the
+    // user knows what they're doing. Who knows, unanticipated use cases may pop
+    // up in the future.
+    //
+    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+    // and don't have to be, LLVM treats them as no-ops.
+    match name {
+        "appending" => Appending,
+        "available_externally" => AvailableExternally,
+        "common" => Common,
+        "extern_weak" => ExternalWeak,
+        "external" => External,
+        "internal" => Internal,
+        "linkonce" => LinkOnceAny,
+        "linkonce_odr" => LinkOnceODR,
+        "private" => Private,
+        "weak" => WeakAny,
+        "weak_odr" => WeakODR,
+        _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
+    }
+}
+
+fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
+    if cfg!(debug_assertions) {
+        let def_kind = tcx.def_kind(did);
+        assert!(
+            def_kind.has_codegen_attrs(),
+            "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
+        );
+    }
+
+    let did = did.expect_local();
+    let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
+    let mut codegen_fn_attrs = CodegenFnAttrs::new();
+    if tcx.should_inherit_track_caller(did) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
+    }
+
+    let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
+
+    let mut inline_span = None;
+    let mut link_ordinal_span = None;
+    let mut no_sanitize_span = None;
+    for attr in attrs.iter() {
+        if attr.has_name(sym::cold) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
+        } else if attr.has_name(sym::rustc_allocator) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
+        } else if attr.has_name(sym::ffi_returns_twice) {
+            if tcx.is_foreign_item(did) {
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
+            } else {
+                // `#[ffi_returns_twice]` is only allowed `extern fn`s.
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0724,
+                    "`#[ffi_returns_twice]` may only be used on foreign functions"
+                )
+                .emit();
+            }
+        } else if attr.has_name(sym::ffi_pure) {
+            if tcx.is_foreign_item(did) {
+                if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
+                    // `#[ffi_const]` functions cannot be `#[ffi_pure]`
+                    struct_span_err!(
+                        tcx.sess,
+                        attr.span,
+                        E0757,
+                        "`#[ffi_const]` function cannot be `#[ffi_pure]`"
+                    )
+                    .emit();
+                } else {
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
+                }
+            } else {
+                // `#[ffi_pure]` is only allowed on foreign functions
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0755,
+                    "`#[ffi_pure]` may only be used on foreign functions"
+                )
+                .emit();
+            }
+        } else if attr.has_name(sym::ffi_const) {
+            if tcx.is_foreign_item(did) {
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
+            } else {
+                // `#[ffi_const]` is only allowed on foreign functions
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0756,
+                    "`#[ffi_const]` may only be used on foreign functions"
+                )
+                .emit();
+            }
+        } else if attr.has_name(sym::rustc_nounwind) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+        } else if attr.has_name(sym::rustc_reallocator) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
+        } else if attr.has_name(sym::rustc_deallocator) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
+        } else if attr.has_name(sym::rustc_allocator_zeroed) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
+        } else if attr.has_name(sym::naked) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
+        } else if attr.has_name(sym::no_mangle) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
+        } else if attr.has_name(sym::no_coverage) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
+        } else if attr.has_name(sym::rustc_std_internal_symbol) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+        } else if attr.has_name(sym::used) {
+            let inner = attr.meta_item_list();
+            match inner.as_deref() {
+                Some([item]) if item.has_name(sym::linker) => {
+                    if !tcx.features().used_with_arg {
+                        feature_err(
+                            &tcx.sess.parse_sess,
+                            sym::used_with_arg,
+                            attr.span,
+                            "`#[used(linker)]` is currently unstable",
+                        )
+                        .emit();
+                    }
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
+                }
+                Some([item]) if item.has_name(sym::compiler) => {
+                    if !tcx.features().used_with_arg {
+                        feature_err(
+                            &tcx.sess.parse_sess,
+                            sym::used_with_arg,
+                            attr.span,
+                            "`#[used(compiler)]` is currently unstable",
+                        )
+                        .emit();
+                    }
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
+                }
+                Some(_) => {
+                    tcx.sess.emit_err(ExpectedUsedSymbol { span: attr.span });
+                }
+                None => {
+                    // Unfortunately, unconditionally using `llvm.used` causes
+                    // issues in handling `.init_array` with the gold linker,
+                    // but using `llvm.compiler.used` caused a nontrival amount
+                    // of unintentional ecosystem breakage -- particularly on
+                    // Mach-O targets.
+                    //
+                    // As a result, we emit `llvm.compiler.used` only on ELF
+                    // targets. This is somewhat ad-hoc, but actually follows
+                    // our pre-LLVM 13 behavior (prior to the ecosystem
+                    // breakage), and seems to match `clang`'s behavior as well
+                    // (both before and after LLVM 13), possibly because they
+                    // have similar compatibility concerns to us. See
+                    // https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
+                    // and following comments for some discussion of this, as
+                    // well as the comments in `rustc_codegen_llvm` where these
+                    // flags are handled.
+                    //
+                    // Anyway, to be clear: this is still up in the air
+                    // somewhat, and is subject to change in the future (which
+                    // is a good thing, because this would ideally be a bit
+                    // more firmed up).
+                    let is_like_elf = !(tcx.sess.target.is_like_osx
+                        || tcx.sess.target.is_like_windows
+                        || tcx.sess.target.is_like_wasm);
+                    codegen_fn_attrs.flags |= if is_like_elf {
+                        CodegenFnAttrFlags::USED
+                    } else {
+                        CodegenFnAttrFlags::USED_LINKER
+                    };
+                }
+            }
+        } else if attr.has_name(sym::cmse_nonsecure_entry) {
+            if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0776,
+                    "`#[cmse_nonsecure_entry]` requires C ABI"
+                )
+                .emit();
+            }
+            if !tcx.sess.target.llvm_target.contains("thumbv8m") {
+                struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
+                    .emit();
+            }
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
+        } else if attr.has_name(sym::thread_local) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
+        } else if attr.has_name(sym::track_caller) {
+            if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
+                struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
+                    .emit();
+            }
+            if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
+                feature_err(
+                    &tcx.sess.parse_sess,
+                    sym::closure_track_caller,
+                    attr.span,
+                    "`#[track_caller]` on closures is currently unstable",
+                )
+                .emit();
+            }
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
+        } else if attr.has_name(sym::export_name) {
+            if let Some(s) = attr.value_str() {
+                if s.as_str().contains('\0') {
+                    // `#[export_name = ...]` will be converted to a null-terminated string,
+                    // so it may not contain any null characters.
+                    struct_span_err!(
+                        tcx.sess,
+                        attr.span,
+                        E0648,
+                        "`export_name` may not contain null characters"
+                    )
+                    .emit();
+                }
+                codegen_fn_attrs.export_name = Some(s);
+            }
+        } else if attr.has_name(sym::target_feature) {
+            if !tcx.is_closure(did.to_def_id())
+                && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
+            {
+                if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
+                    // The `#[target_feature]` attribute is allowed on
+                    // WebAssembly targets on all functions, including safe
+                    // ones. Other targets require that `#[target_feature]` is
+                    // only applied to unsafe functions (pending the
+                    // `target_feature_11` feature) because on most targets
+                    // execution of instructions that are not supported is
+                    // considered undefined behavior. For WebAssembly which is a
+                    // 100% safe target at execution time it's not possible to
+                    // execute undefined instructions, and even if a future
+                    // feature was added in some form for this it would be a
+                    // deterministic trap. There is no undefined behavior when
+                    // executing WebAssembly so `#[target_feature]` is allowed
+                    // on safe functions (but again, only for WebAssembly)
+                    //
+                    // Note that this is also allowed if `actually_rustdoc` so
+                    // if a target is documenting some wasm-specific code then
+                    // it's not spuriously denied.
+                } else if !tcx.features().target_feature_11 {
+                    let mut err = feature_err(
+                        &tcx.sess.parse_sess,
+                        sym::target_feature_11,
+                        attr.span,
+                        "`#[target_feature(..)]` can only be applied to `unsafe` functions",
+                    );
+                    err.span_label(tcx.def_span(did), "not an `unsafe` function");
+                    err.emit();
+                } else {
+                    check_target_feature_trait_unsafe(tcx, did, attr.span);
+                }
+            }
+            from_target_feature(
+                tcx,
+                attr,
+                supported_target_features,
+                &mut codegen_fn_attrs.target_features,
+            );
+        } else if attr.has_name(sym::linkage) {
+            if let Some(val) = attr.value_str() {
+                let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
+                if tcx.is_foreign_item(did) {
+                    codegen_fn_attrs.import_linkage = linkage;
+                } else {
+                    codegen_fn_attrs.linkage = linkage;
+                }
+            }
+        } else if attr.has_name(sym::link_section) {
+            if let Some(val) = attr.value_str() {
+                if val.as_str().bytes().any(|b| b == 0) {
+                    let msg = format!(
+                        "illegal null byte in link_section \
+                         value: `{}`",
+                        &val
+                    );
+                    tcx.sess.span_err(attr.span, &msg);
+                } else {
+                    codegen_fn_attrs.link_section = Some(val);
+                }
+            }
+        } else if attr.has_name(sym::link_name) {
+            codegen_fn_attrs.link_name = attr.value_str();
+        } else if attr.has_name(sym::link_ordinal) {
+            link_ordinal_span = Some(attr.span);
+            if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
+                codegen_fn_attrs.link_ordinal = ordinal;
+            }
+        } else if attr.has_name(sym::no_sanitize) {
+            no_sanitize_span = Some(attr.span);
+            if let Some(list) = attr.meta_item_list() {
+                for item in list.iter() {
+                    if item.has_name(sym::address) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
+                    } else if item.has_name(sym::cfi) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
+                    } else if item.has_name(sym::kcfi) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
+                    } else if item.has_name(sym::memory) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
+                    } else if item.has_name(sym::memtag) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
+                    } else if item.has_name(sym::shadow_call_stack) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
+                    } else if item.has_name(sym::thread) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
+                    } else if item.has_name(sym::hwaddress) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
+                    } else {
+                        tcx.sess
+                            .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
+                            .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
+                            .emit();
+                    }
+                }
+            }
+        } else if attr.has_name(sym::instruction_set) {
+            codegen_fn_attrs.instruction_set = match attr.meta_kind() {
+                Some(MetaItemKind::List(ref items)) => match items.as_slice() {
+                    [NestedMetaItem::MetaItem(set)] => {
+                        let segments =
+                            set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
+                        match segments.as_slice() {
+                            [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
+                                if !tcx.sess.target.has_thumb_interworking {
+                                    struct_span_err!(
+                                        tcx.sess.diagnostic(),
+                                        attr.span,
+                                        E0779,
+                                        "target does not support `#[instruction_set]`"
+                                    )
+                                    .emit();
+                                    None
+                                } else if segments[1] == sym::a32 {
+                                    Some(InstructionSetAttr::ArmA32)
+                                } else if segments[1] == sym::t32 {
+                                    Some(InstructionSetAttr::ArmT32)
+                                } else {
+                                    unreachable!()
+                                }
+                            }
+                            _ => {
+                                struct_span_err!(
+                                    tcx.sess.diagnostic(),
+                                    attr.span,
+                                    E0779,
+                                    "invalid instruction set specified",
+                                )
+                                .emit();
+                                None
+                            }
+                        }
+                    }
+                    [] => {
+                        struct_span_err!(
+                            tcx.sess.diagnostic(),
+                            attr.span,
+                            E0778,
+                            "`#[instruction_set]` requires an argument"
+                        )
+                        .emit();
+                        None
+                    }
+                    _ => {
+                        struct_span_err!(
+                            tcx.sess.diagnostic(),
+                            attr.span,
+                            E0779,
+                            "cannot specify more than one instruction set"
+                        )
+                        .emit();
+                        None
+                    }
+                },
+                _ => {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0778,
+                        "must specify an instruction set"
+                    )
+                    .emit();
+                    None
+                }
+            };
+        } else if attr.has_name(sym::repr) {
+            codegen_fn_attrs.alignment = match attr.meta_item_list() {
+                Some(items) => match items.as_slice() {
+                    [item] => match item.name_value_literal() {
+                        Some((sym::align, literal)) => {
+                            let alignment = rustc_attr::parse_alignment(&literal.kind);
+
+                            match alignment {
+                                Ok(align) => Some(align),
+                                Err(msg) => {
+                                    struct_span_err!(
+                                        tcx.sess.diagnostic(),
+                                        attr.span,
+                                        E0589,
+                                        "invalid `repr(align)` attribute: {}",
+                                        msg
+                                    )
+                                    .emit();
+
+                                    None
+                                }
+                            }
+                        }
+                        _ => None,
+                    },
+                    [] => None,
+                    _ => None,
+                },
+                None => None,
+            };
+        }
+    }
+
+    codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
+        if !attr.has_name(sym::inline) {
+            return ia;
+        }
+        match attr.meta_kind() {
+            Some(MetaItemKind::Word) => InlineAttr::Hint,
+            Some(MetaItemKind::List(ref items)) => {
+                inline_span = Some(attr.span);
+                if items.len() != 1 {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0534,
+                        "expected one argument"
+                    )
+                    .emit();
+                    InlineAttr::None
+                } else if list_contains_name(&items, sym::always) {
+                    InlineAttr::Always
+                } else if list_contains_name(&items, sym::never) {
+                    InlineAttr::Never
+                } else {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        items[0].span(),
+                        E0535,
+                        "invalid argument"
+                    )
+                    .help("valid inline arguments are `always` and `never`")
+                    .emit();
+
+                    InlineAttr::None
+                }
+            }
+            Some(MetaItemKind::NameValue(_)) => ia,
+            None => ia,
+        }
+    });
+
+    codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
+        if !attr.has_name(sym::optimize) {
+            return ia;
+        }
+        let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
+        match attr.meta_kind() {
+            Some(MetaItemKind::Word) => {
+                err(attr.span, "expected one argument");
+                ia
+            }
+            Some(MetaItemKind::List(ref items)) => {
+                inline_span = Some(attr.span);
+                if items.len() != 1 {
+                    err(attr.span, "expected one argument");
+                    OptimizeAttr::None
+                } else if list_contains_name(&items, sym::size) {
+                    OptimizeAttr::Size
+                } else if list_contains_name(&items, sym::speed) {
+                    OptimizeAttr::Speed
+                } else {
+                    err(items[0].span(), "invalid argument");
+                    OptimizeAttr::None
+                }
+            }
+            Some(MetaItemKind::NameValue(_)) => ia,
+            None => ia,
+        }
+    });
+
+    // #73631: closures inherit `#[target_feature]` annotations
+    if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
+        let owner_id = tcx.parent(did.to_def_id());
+        if tcx.def_kind(owner_id).has_codegen_attrs() {
+            codegen_fn_attrs
+                .target_features
+                .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
+        }
+    }
+
+    // If a function uses #[target_feature] it can't be inlined into general
+    // purpose functions as they wouldn't have the right target features
+    // enabled. For that reason we also forbid #[inline(always)] as it can't be
+    // respected.
+    if !codegen_fn_attrs.target_features.is_empty() {
+        if codegen_fn_attrs.inline == InlineAttr::Always {
+            if let Some(span) = inline_span {
+                tcx.sess.span_err(
+                    span,
+                    "cannot use `#[inline(always)]` with \
+                     `#[target_feature]`",
+                );
+            }
+        }
+    }
+
+    if !codegen_fn_attrs.no_sanitize.is_empty() {
+        if codegen_fn_attrs.inline == InlineAttr::Always {
+            if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
+                let hir_id = tcx.hir().local_def_id_to_hir_id(did);
+                tcx.struct_span_lint_hir(
+                    lint::builtin::INLINE_NO_SANITIZE,
+                    hir_id,
+                    no_sanitize_span,
+                    "`no_sanitize` will have no effect after inlining",
+                    |lint| lint.span_note(inline_span, "inlining requested here"),
+                )
+            }
+        }
+    }
+
+    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
+        codegen_fn_attrs.inline = InlineAttr::Never;
+    }
+
+    // Weak lang items have the same semantics as "std internal" symbols in the
+    // sense that they're preserved through all our LTO passes and only
+    // strippable by the linker.
+    //
+    // Additionally weak lang items have predetermined symbol names.
+    if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+    }
+    if let Some((name, _)) = lang_items::extract(attrs)
+        && let Some(lang_item) = LangItem::from_name(name)
+        && let Some(link_name) = lang_item.link_name()
+    {
+        codegen_fn_attrs.export_name = Some(link_name);
+        codegen_fn_attrs.link_name = Some(link_name);
+    }
+    check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
+
+    // Internal symbols to the standard library all have no_mangle semantics in
+    // that they have defined symbol names present in the function name. This
+    // also applies to weak symbols where they all have known symbol names.
+    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
+    }
+
+    // Any linkage to LLVM intrinsics for now forcibly marks them all as never
+    // unwinds since LLVM sometimes can't handle codegen which `invoke`s
+    // intrinsic functions.
+    if let Some(name) = &codegen_fn_attrs.link_name {
+        if name.as_str().starts_with("llvm.") {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+        }
+    }
+
+    codegen_fn_attrs
+}
+
+/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
+/// applied to the method prototype.
+fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    if let Some(impl_item) = tcx.opt_associated_item(def_id)
+        && let ty::AssocItemContainer::ImplContainer = impl_item.container
+        && let Some(trait_item) = impl_item.trait_item_def_id
+    {
+        return tcx
+            .codegen_fn_attrs(trait_item)
+            .flags
+            .intersects(CodegenFnAttrFlags::TRACK_CALLER);
+    }
+
+    false
+}
+
+fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
+    use rustc_ast::{LitIntType, LitKind, MetaItemLit};
+    if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
+        feature_err(
+            &tcx.sess.parse_sess,
+            sym::raw_dylib,
+            attr.span,
+            "`#[link_ordinal]` is unstable on x86",
+        )
+        .emit();
+    }
+    let meta_item_list = attr.meta_item_list();
+    let meta_item_list = meta_item_list.as_deref();
+    let sole_meta_list = match meta_item_list {
+        Some([item]) => item.lit(),
+        Some(_) => {
+            tcx.sess
+                .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
+                .note("the attribute requires exactly one argument")
+                .emit();
+            return None;
+        }
+        _ => None,
+    };
+    if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
+        sole_meta_list
+    {
+        // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header,
+        // the ordinal must fit into 16 bits.  Similarly, the Ordinal field in COFFShortExport (defined
+        // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information
+        // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
+        //
+        // FIXME: should we allow an ordinal of 0?  The MSVC toolchain has inconsistent support for this:
+        // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies
+        // a zero ordinal.  However, llvm-dlltool is perfectly happy to generate an import library
+        // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import
+        // library produced by LLVM with an ordinal of 0, and it generates an .EXE.  (I don't know yet
+        // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
+        // about LINK.EXE failing.)
+        if *ordinal <= u16::MAX as u128 {
+            Some(*ordinal as u16)
+        } else {
+            let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
+            tcx.sess
+                .struct_span_err(attr.span, &msg)
+                .note("the value may not exceed `u16::MAX`")
+                .emit();
+            None
+        }
+    } else {
+        tcx.sess
+            .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
+            .note("an unsuffixed integer value, e.g., `1`, is expected")
+            .emit();
+        None
+    }
+}
+
+fn check_link_name_xor_ordinal(
+    tcx: TyCtxt<'_>,
+    codegen_fn_attrs: &CodegenFnAttrs,
+    inline_span: Option<Span>,
+) {
+    if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() {
+        return;
+    }
+    let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
+    if let Some(span) = inline_span {
+        tcx.sess.span_err(span, msg);
+    } else {
+        tcx.sess.err(msg);
+    }
+}
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
+}
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index b004fbf85a9..819c2678d6c 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -235,7 +235,7 @@ fn push_debuginfo_type_name<'tcx>(
                 let projection_bounds: SmallVec<[_; 4]> = trait_data
                     .projection_bounds()
                     .map(|bound| {
-                        let ExistentialProjection { item_def_id, term, .. } =
+                        let ExistentialProjection { def_id: item_def_id, term, .. } =
                             tcx.erase_late_bound_regions(bound);
                         // FIXME(associated_const_equality): allow for consts here
                         (item_def_id, term.ty().unwrap())
@@ -411,9 +411,8 @@ fn push_debuginfo_type_name<'tcx>(
         ty::Error(_)
         | ty::Infer(_)
         | ty::Placeholder(..)
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Bound(..)
-        | ty::Opaque(..)
         | ty::GeneratorWitness(..) => {
             bug!(
                 "debuginfo: Trying to create type name for \
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index e3b6fbf1bc7..0620000201f 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -548,3 +548,10 @@ pub struct ArchiveBuildFailure {
 pub struct UnknownArchiveKind<'a> {
     pub kind: &'a str,
 }
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_expected_used_symbol)]
+pub struct ExpectedUsedSymbol {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index def6390f6a3..0e6596d4ba7 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -42,6 +42,7 @@ use std::path::{Path, PathBuf};
 
 pub mod back;
 pub mod base;
+pub mod codegen_attrs;
 pub mod common;
 pub mod coverageinfo;
 pub mod debuginfo;
@@ -180,6 +181,7 @@ pub fn provide(providers: &mut Providers) {
     crate::back::symbol_export::provide(providers);
     crate::base::provide(providers);
     crate::target_features::provide(providers);
+    crate::codegen_attrs::provide(providers);
 }
 
 pub fn provide_extern(providers: &mut ExternProviders) {
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index cae46ebd2e9..d96ca921f1f 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -31,8 +31,7 @@ impl<'a, 'tcx> VirtualIndex {
             let typeid =
                 bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), expect_dyn_trait_in_self(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);
+            let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
             bx.pointercast(func, llty)
         } else {
             let ptr_align = bx.tcx().data_layout.pointer_align.abi;
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index f3f5ddb52d6..3860138018b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -289,16 +289,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             bx.cleanup_ret(funclet, None);
         } else {
             let slot = self.get_personality_slot(bx);
-            let lp0 = slot.project_field(bx, 0);
-            let lp0 = bx.load_operand(lp0).immediate();
-            let lp1 = slot.project_field(bx, 1);
-            let lp1 = bx.load_operand(lp1).immediate();
+            let exn0 = slot.project_field(bx, 0);
+            let exn0 = bx.load_operand(exn0).immediate();
+            let exn1 = slot.project_field(bx, 1);
+            let exn1 = bx.load_operand(exn1).immediate();
             slot.storage_dead(bx);
 
-            let mut lp = bx.const_undef(self.landing_pad_type());
-            lp = bx.insert_value(lp, lp0, 0);
-            lp = bx.insert_value(lp, lp1, 1);
-            bx.resume(lp);
+            bx.resume(exn0, exn1);
         }
     }
 
@@ -751,10 +748,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let (instance, mut llfn) = match *callee.layout.ty.kind() {
             ty::FnDef(def_id, substs) => (
                 Some(
-                    ty::Instance::resolve(bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs)
-                        .unwrap()
-                        .unwrap()
-                        .polymorphize(bx.tcx()),
+                    ty::Instance::expect_resolve(
+                        bx.tcx(),
+                        ty::ParamEnv::reveal_all(),
+                        def_id,
+                        substs,
+                    )
+                    .polymorphize(bx.tcx()),
                 ),
                 None,
             ),
@@ -1633,24 +1633,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
 
             let llpersonality = self.cx.eh_personality();
-            let llretty = self.landing_pad_type();
-            let lp = cleanup_bx.cleanup_landing_pad(llretty, llpersonality);
+            let (exn0, exn1) = cleanup_bx.cleanup_landing_pad(llpersonality);
 
             let slot = self.get_personality_slot(&mut cleanup_bx);
             slot.storage_live(&mut cleanup_bx);
-            Pair(cleanup_bx.extract_value(lp, 0), cleanup_bx.extract_value(lp, 1))
-                .store(&mut cleanup_bx, slot);
+            Pair(exn0, exn1).store(&mut cleanup_bx, slot);
 
             cleanup_bx.br(llbb);
             cleanup_llbb
         }
     }
 
-    fn landing_pad_type(&self) -> Bx::Type {
-        let cx = self.cx;
-        cx.type_struct(&[cx.type_i8p(), cx.type_i32()], false)
-    }
-
     fn unreachable_block(&mut self) -> Bx::BasicBlock {
         self.unreachable_block.unwrap_or_else(|| {
             let llbb = Bx::append_block(self.cx, self.llfn, "unreachable");
@@ -1670,8 +1663,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
 
             let llpersonality = self.cx.eh_personality();
-            let llretty = self.landing_pad_type();
-            bx.cleanup_landing_pad(llretty, llpersonality);
+            bx.cleanup_landing_pad(llpersonality);
 
             let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicNoUnwind);
             let fn_ty = bx.fn_decl_backend_type(&fn_abi);
@@ -1810,15 +1802,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         match (src.layout.abi, dst.layout.abi) {
             (abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => {
                 // HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers.
-                if (src_scalar.primitive() == abi::Pointer)
-                    == (dst_scalar.primitive() == abi::Pointer)
-                {
+                let src_is_ptr = src_scalar.primitive() == abi::Pointer;
+                let dst_is_ptr = dst_scalar.primitive() == abi::Pointer;
+                if src_is_ptr == dst_is_ptr {
                     assert_eq!(src.layout.size, dst.layout.size);
 
                     // NOTE(eddyb) the `from_immediate` and `to_immediate_scalar`
                     // conversions allow handling `bool`s the same as `u8`s.
                     let src = bx.from_immediate(src.immediate());
-                    let src_as_dst = bx.bitcast(src, bx.backend_type(dst.layout));
+                    // LLVM also doesn't like `bitcast`s between pointers in different address spaces.
+                    let src_as_dst = if src_is_ptr {
+                        bx.pointercast(src, bx.backend_type(dst.layout))
+                    } else {
+                        bx.bitcast(src, bx.backend_type(dst.layout))
+                    };
                     Immediate(bx.to_immediate_scalar(src_as_dst, dst_scalar)).store(bx, dst);
                     return;
                 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 9ad96f7a447..23196c8cbae 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -462,7 +462,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 assert!(bx.cx().tcx().is_static(def_id));
                 let static_ = bx.get_static(def_id);
                 let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
-                OperandRef::from_immediate_or_packed_pair(bx, static_, layout)
+                OperandRef { val: OperandValue::Immediate(static_), layout }
             }
             mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
             mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => {
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 301683e8e85..0dabe96b602 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -1,8 +1,19 @@
+use rustc_ast::ast;
+use rustc_attr::InstructionSetAttr;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::symbol::Symbol;
+use rustc_span::Span;
 
 /// Features that control behaviour of rustc, rather than the codegen.
 pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
@@ -322,15 +333,148 @@ pub fn tied_target_features(sess: &Session) -> &'static [&'static [&'static str]
     }
 }
 
-pub(crate) fn provide(providers: &mut Providers) {
-    providers.supported_target_features = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        if tcx.sess.opts.actually_rustdoc {
-            // rustdoc needs to be able to document functions that use all the features, so
-            // whitelist them all
-            all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
-        } else {
-            supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
-        }
+pub fn from_target_feature(
+    tcx: TyCtxt<'_>,
+    attr: &ast::Attribute,
+    supported_target_features: &FxHashMap<String, Option<Symbol>>,
+    target_features: &mut Vec<Symbol>,
+) {
+    let Some(list) = attr.meta_item_list() else { return };
+    let bad_item = |span| {
+        let msg = "malformed `target_feature` attribute input";
+        let code = "enable = \"..\"";
+        tcx.sess
+            .struct_span_err(span, msg)
+            .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
+            .emit();
     };
+    let rust_features = tcx.features();
+    for item in list {
+        // Only `enable = ...` is accepted in the meta-item list.
+        if !item.has_name(sym::enable) {
+            bad_item(item.span());
+            continue;
+        }
+
+        // Must be of the form `enable = "..."` (a string).
+        let Some(value) = item.value_str() else {
+            bad_item(item.span());
+            continue;
+        };
+
+        // We allow comma separation to enable multiple features.
+        target_features.extend(value.as_str().split(',').filter_map(|feature| {
+            let Some(feature_gate) = supported_target_features.get(feature) else {
+                let msg =
+                    format!("the feature named `{}` is not valid for this target", feature);
+                let mut err = tcx.sess.struct_span_err(item.span(), &msg);
+                err.span_label(
+                    item.span(),
+                    format!("`{}` is not valid for this target", feature),
+                );
+                if let Some(stripped) = feature.strip_prefix('+') {
+                    let valid = supported_target_features.contains_key(stripped);
+                    if valid {
+                        err.help("consider removing the leading `+` in the feature name");
+                    }
+                }
+                err.emit();
+                return None;
+            };
+
+            // Only allow features whose feature gates have been enabled.
+            let allowed = match feature_gate.as_ref().copied() {
+                Some(sym::arm_target_feature) => rust_features.arm_target_feature,
+                Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
+                Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
+                Some(sym::mips_target_feature) => rust_features.mips_target_feature,
+                Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
+                Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
+                Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
+                Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
+                Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
+                Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
+                Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
+                Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
+                Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
+                Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
+                Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
+                Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
+                Some(name) => bug!("unknown target feature gate {}", name),
+                None => true,
+            };
+            if !allowed {
+                feature_err(
+                    &tcx.sess.parse_sess,
+                    feature_gate.unwrap(),
+                    item.span(),
+                    &format!("the target feature `{}` is currently unstable", feature),
+                )
+                .emit();
+            }
+            Some(Symbol::intern(feature))
+        }));
+    }
+}
+
+/// Computes the set of target features used in a function for the purposes of
+/// inline assembly.
+fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
+    let mut target_features = tcx.sess.unstable_target_features.clone();
+    if tcx.def_kind(did).has_codegen_attrs() {
+        let attrs = tcx.codegen_fn_attrs(did);
+        target_features.extend(&attrs.target_features);
+        match attrs.instruction_set {
+            None => {}
+            Some(InstructionSetAttr::ArmA32) => {
+                target_features.remove(&sym::thumb_mode);
+            }
+            Some(InstructionSetAttr::ArmT32) => {
+                target_features.insert(sym::thumb_mode);
+            }
+        }
+    }
+
+    tcx.arena.alloc(target_features)
+}
+
+/// Checks the function annotated with `#[target_feature]` is not a safe
+/// trait method implementation, reporting an error if it is.
+pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(id);
+    let node = tcx.hir().get(hir_id);
+    if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
+        let parent_id = tcx.hir().get_parent_item(hir_id);
+        let parent_item = tcx.hir().expect_item(parent_id.def_id);
+        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
+            tcx.sess
+                .struct_span_err(
+                    attr_span,
+                    "`#[target_feature(..)]` cannot be applied to safe trait method",
+                )
+                .span_label(attr_span, "cannot be applied to safe trait method")
+                .span_label(tcx.def_span(id), "not an `unsafe` function")
+                .emit();
+        }
+    }
+}
+
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        supported_target_features: |tcx, cnum| {
+            assert_eq!(cnum, LOCAL_CRATE);
+            if tcx.sess.opts.actually_rustdoc {
+                // rustdoc needs to be able to document functions that use all the features, so
+                // whitelist them all
+                all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
+            } else {
+                supported_target_features(tcx.sess)
+                    .iter()
+                    .map(|&(a, b)| (a.to_string(), b))
+                    .collect()
+            }
+        },
+        asm_target_features,
+        ..*providers
+    }
 }
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index bc679a5dc87..194768d9466 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -271,8 +271,8 @@ pub trait BuilderMethods<'a, 'tcx>:
     fn set_personality_fn(&mut self, personality: Self::Value);
 
     // These are used by everyone except msvc
-    fn cleanup_landing_pad(&mut self, ty: Self::Type, pers_fn: Self::Value) -> Self::Value;
-    fn resume(&mut self, exn: Self::Value);
+    fn cleanup_landing_pad(&mut self, pers_fn: Self::Value) -> (Self::Value, Self::Value);
+    fn resume(&mut self, exn0: Self::Value, exn1: Self::Value);
 
     // These are used only by msvc
     fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index c60d6e4fed9..13472cc2bfa 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -86,6 +86,59 @@ impl<'tcx> ConstEvalErr<'tcx> {
         self.report_decorated(tcx, message, |_| {})
     }
 
+    #[instrument(level = "trace", skip(self, decorate))]
+    pub(super) fn decorate(&self, err: &mut Diagnostic, decorate: impl FnOnce(&mut Diagnostic)) {
+        trace!("reporting const eval failure at {:?}", self.span);
+        // Add some more context for select error types.
+        match self.error {
+            InterpError::Unsupported(
+                UnsupportedOpInfo::ReadPointerAsBytes
+                | UnsupportedOpInfo::PartialPointerOverwrite(_)
+                | UnsupportedOpInfo::PartialPointerCopy(_),
+            ) => {
+                err.help("this code performed an operation that depends on the underlying bytes representing a pointer");
+                err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported");
+            }
+            _ => {}
+        }
+        // Add spans for the stacktrace. Don't print a single-line backtrace though.
+        if self.stacktrace.len() > 1 {
+            // Helper closure to print duplicated lines.
+            let mut flush_last_line = |last_frame, times| {
+                if let Some((line, span)) = last_frame {
+                    err.span_note(span, &line);
+                    // Don't print [... additional calls ...] if the number of lines is small
+                    if times < 3 {
+                        for _ in 0..times {
+                            err.span_note(span, &line);
+                        }
+                    } else {
+                        err.span_note(
+                            span,
+                            format!("[... {} additional calls {} ...]", times, &line),
+                        );
+                    }
+                }
+            };
+
+            let mut last_frame = None;
+            let mut times = 0;
+            for frame_info in &self.stacktrace {
+                let frame = (frame_info.to_string(), frame_info.span);
+                if last_frame.as_ref() == Some(&frame) {
+                    times += 1;
+                } else {
+                    flush_last_line(last_frame, times);
+                    last_frame = Some(frame);
+                    times = 0;
+                }
+            }
+            flush_last_line(last_frame, times);
+        }
+        // Let the caller attach any additional information it wants.
+        decorate(err);
+    }
+
     /// Create a diagnostic for this const eval error.
     ///
     /// Sets the message passed in via `message` and adds span labels with detailed error
@@ -101,88 +154,30 @@ impl<'tcx> ConstEvalErr<'tcx> {
         message: &str,
         decorate: impl FnOnce(&mut Diagnostic),
     ) -> ErrorHandled {
-        let finish = |err: &mut Diagnostic, span_msg: Option<String>| {
-            trace!("reporting const eval failure at {:?}", self.span);
-            if let Some(span_msg) = span_msg {
-                err.span_label(self.span, span_msg);
-            }
-            // Add some more context for select error types.
-            match self.error {
-                InterpError::Unsupported(
-                    UnsupportedOpInfo::ReadPointerAsBytes
-                    | UnsupportedOpInfo::PartialPointerOverwrite(_)
-                    | UnsupportedOpInfo::PartialPointerCopy(_),
-                ) => {
-                    err.help("this code performed an operation that depends on the underlying bytes representing a pointer");
-                    err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported");
-                }
-                _ => {}
-            }
-            // Add spans for the stacktrace. Don't print a single-line backtrace though.
-            if self.stacktrace.len() > 1 {
-                // Helper closure to print duplicated lines.
-                let mut flush_last_line = |last_frame, times| {
-                    if let Some((line, span)) = last_frame {
-                        err.span_note(span, &line);
-                        // Don't print [... additional calls ...] if the number of lines is small
-                        if times < 3 {
-                            for _ in 0..times {
-                                err.span_note(span, &line);
-                            }
-                        } else {
-                            err.span_note(
-                                span,
-                                format!("[... {} additional calls {} ...]", times, &line),
-                            );
-                        }
-                    }
-                };
-
-                let mut last_frame = None;
-                let mut times = 0;
-                for frame_info in &self.stacktrace {
-                    let frame = (frame_info.to_string(), frame_info.span);
-                    if last_frame.as_ref() == Some(&frame) {
-                        times += 1;
-                    } else {
-                        flush_last_line(last_frame, times);
-                        last_frame = Some(frame);
-                        times = 0;
-                    }
-                }
-                flush_last_line(last_frame, times);
-            }
-            // Let the caller attach any additional information it wants.
-            decorate(err);
-        };
-
         debug!("self.error: {:?}", self.error);
         // Special handling for certain errors
         match &self.error {
             // Don't emit a new diagnostic for these errors
             err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
-                return ErrorHandled::TooGeneric;
-            }
-            err_inval!(AlreadyReported(error_reported)) => {
-                return ErrorHandled::Reported(*error_reported);
+                ErrorHandled::TooGeneric
             }
+            err_inval!(AlreadyReported(error_reported)) => ErrorHandled::Reported(*error_reported),
             err_inval!(Layout(LayoutError::SizeOverflow(_))) => {
                 // We must *always* hard error on these, even if the caller wants just a lint.
                 // The `message` makes little sense here, this is a more serious error than the
                 // caller thinks anyway.
                 // See <https://github.com/rust-lang/rust/pull/63152>.
                 let mut err = struct_error(tcx, &self.error.to_string());
-                finish(&mut err, None);
-                return ErrorHandled::Reported(err.emit());
+                self.decorate(&mut err, decorate);
+                ErrorHandled::Reported(err.emit())
             }
-            _ => {}
-        };
-
-        let err_msg = self.error.to_string();
-
-        // Report as hard error.
-        let mut err = struct_error(tcx, message);
-        finish(&mut err, Some(err_msg));
-        ErrorHandled::Reported(err.emit())
+            _ => {
+                // Report as hard error.
+                let mut err = struct_error(tcx, message);
+                err.span_label(self.span, self.error.to_string());
+                self.decorate(&mut err, decorate);
+                ErrorHandled::Reported(err.emit())
+            }
+        }
     }
 }
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 c27790d8887..18e01567ca3 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -1,5 +1,5 @@
+use crate::const_eval::CheckAlignment;
 use std::borrow::Cow;
-use std::convert::TryInto;
 
 use either::{Left, Right};
 
@@ -77,7 +77,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
             None => InternKind::Constant,
         }
     };
-    ecx.machine.check_alignment = false; // interning doesn't need to respect alignment
+    ecx.machine.check_alignment = CheckAlignment::No; // interning doesn't need to respect alignment
     intern_const_alloc_recursive(ecx, intern_kind, &ret)?;
     // we leave alignment checks off, since this `ecx` will not be used for further evaluation anyway
 
@@ -103,11 +103,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
         tcx,
         root_span,
         param_env,
-        CompileTimeInterpreter::new(
-            tcx.const_eval_limit(),
-            can_access_statics,
-            /*check_alignment:*/ false,
-        ),
+        CompileTimeInterpreter::new(tcx.const_eval_limit(), can_access_statics, CheckAlignment::No),
     )
 }
 
@@ -312,7 +308,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
         CompileTimeInterpreter::new(
             tcx.const_eval_limit(),
             /*can_access_statics:*/ is_static,
-            /*check_alignment:*/ tcx.sess.opts.unstable_opts.extra_const_ub_checks,
+            if tcx.sess.opts.unstable_opts.extra_const_ub_checks {
+                CheckAlignment::Error
+            } else {
+                CheckAlignment::FutureIncompat
+            },
         ),
     );
 
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 3dfded2d930..e006a62feea 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -1,9 +1,10 @@
 use rustc_hir::def::DefKind;
-use rustc_hir::LangItem;
+use rustc_hir::{LangItem, CRATE_HIR_ID};
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::PointerArithmetic;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::lint::builtin::INVALID_ALIGNMENT;
 use std::borrow::Borrow;
 use std::hash::Hash;
 use std::ops::ControlFlow;
@@ -47,14 +48,34 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
     pub(super) can_access_statics: bool,
 
     /// Whether to check alignment during evaluation.
-    pub(super) check_alignment: bool,
+    pub(super) check_alignment: CheckAlignment,
+}
+
+#[derive(Copy, Clone)]
+pub enum CheckAlignment {
+    /// Ignore alignment when following relocations.
+    /// This is mainly used in interning.
+    No,
+    /// Hard error when dereferencing a misaligned pointer.
+    Error,
+    /// Emit a future incompat lint when dereferencing a misaligned pointer.
+    FutureIncompat,
+}
+
+impl CheckAlignment {
+    pub fn should_check(&self) -> bool {
+        match self {
+            CheckAlignment::No => false,
+            CheckAlignment::Error | CheckAlignment::FutureIncompat => true,
+        }
+    }
 }
 
 impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
     pub(crate) fn new(
         const_eval_limit: Limit,
         can_access_statics: bool,
-        check_alignment: bool,
+        check_alignment: CheckAlignment,
     ) -> Self {
         CompileTimeInterpreter {
             steps_remaining: const_eval_limit.0,
@@ -309,7 +330,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
 
     #[inline(always)]
-    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
         ecx.machine.check_alignment
     }
 
@@ -318,6 +339,36 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
     }
 
+    fn alignment_check_failed(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        has: Align,
+        required: Align,
+        check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()> {
+        let err = err_ub!(AlignmentCheckFailed { has, required }).into();
+        match check {
+            CheckAlignment::Error => Err(err),
+            CheckAlignment::No => span_bug!(
+                ecx.cur_span(),
+                "`alignment_check_failed` called when no alignment check requested"
+            ),
+            CheckAlignment::FutureIncompat => {
+                let err = ConstEvalErr::new(ecx, err, None);
+                ecx.tcx.struct_span_lint_hir(
+                    INVALID_ALIGNMENT,
+                    ecx.stack().iter().find_map(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
+                    err.span,
+                    err.error.to_string(),
+                    |db| {
+                        err.decorate(db, |_| {});
+                        db
+                    },
+                );
+                Ok(())
+            }
+        }
+    }
+
     fn load_mir(
         ecx: &InterpCx<'mir, 'tcx, Self>,
         instance: ty::InstanceDef<'tcx>,
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index f4da1188395..498c0087387 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -142,12 +142,11 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
         | ty::Foreign(..)
         | ty::Infer(ty::FreshIntTy(_))
         | ty::Infer(ty::FreshFloatTy(_))
-        | ty::Projection(..)
+        // FIXME(oli-obk): we could look behind opaque types
+        | ty::Alias(..)
         | ty::Param(_)
         | ty::Bound(..)
         | ty::Placeholder(..)
-        // FIXME(oli-obk): we could look behind opaque types
-        | ty::Opaque(..)
         | ty::Infer(_)
         // FIXME(oli-obk): we can probably encode closures just like structs
         | ty::Closure(..)
@@ -307,11 +306,10 @@ pub fn valtree_to_const_value<'tcx>(
         | ty::Foreign(..)
         | ty::Infer(ty::FreshIntTy(_))
         | ty::Infer(ty::FreshFloatTy(_))
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Param(_)
         | ty::Bound(..)
         | ty::Placeholder(..)
-        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Closure(..)
         | ty::Generator(..)
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 269ae15d497..b1fdeb01b10 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -1,5 +1,4 @@
 use std::assert_matches::assert_matches;
-use std::convert::TryFrom;
 
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::{Float, FloatConvert};
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 0b2809f1d2c..f551b5c2911 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -248,6 +248,15 @@ impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> {
             Right(span) => span,
         }
     }
+
+    pub fn lint_root(&self) -> Option<hir::HirId> {
+        self.current_source_info().and_then(|source_info| {
+            match &self.body.source_scopes[source_info.scope].local_data {
+                mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
+                mir::ClearCrossCrate::Clear => None,
+            }
+        })
+    }
 }
 
 impl<'tcx> fmt::Display for FrameInfo<'tcx> {
@@ -954,12 +963,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // This deliberately does *not* honor `requires_caller_location` since it is used for much
         // more than just panics.
         for frame in stack.iter().rev() {
-            let lint_root = frame.current_source_info().and_then(|source_info| {
-                match &frame.body.source_scopes[source_info.scope].local_data {
-                    mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
-                    mir::ClearCrossCrate::Clear => None,
-                }
-            });
+            let lint_root = frame.lint_root();
             let span = frame.current_span();
 
             frames.push(FrameInfo { span, instance: frame.instance, lint_root });
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 7940efcd2b1..9b56757eb39 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -2,8 +2,6 @@
 //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
 //! and miri.
 
-use std::convert::TryFrom;
-
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::{
     self,
@@ -84,11 +82,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
             ty::Adt(ref adt, _) => {
                 ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx)
             }
-            ty::Projection(_)
-            | ty::Opaque(_, _)
-            | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Infer(_) => throw_inval!(TooGeneric),
+            ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
+                throw_inval!(TooGeneric)
+            }
             ty::Bound(_, _) => bug!("bound ty during ctfe"),
             ty::Bool
             | ty::Char
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
index 7d94a22c43d..77c7b4bacb8 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
@@ -1,5 +1,3 @@
-use std::convert::TryFrom;
-
 use rustc_ast::Mutability;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::TerminatorKind;
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 0604d5ee6fa..1d4ef20d065 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -10,9 +10,11 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi as CallAbi;
 
+use crate::const_eval::CheckAlignment;
+
 use super::{
     AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
     MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
@@ -122,7 +124,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     const PANIC_ON_ALLOC_FAIL: bool;
 
     /// Whether memory accesses should be alignment-checked.
-    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
+    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment;
 
     /// Whether, when checking alignment, we should look at the actual address and thus support
     /// custom alignment logic based on whatever the integer address happens to be.
@@ -130,6 +132,13 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// If this returns true, Provenance::OFFSET_IS_ADDR must be true.
     fn use_addr_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
+    fn alignment_check_failed(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        has: Align,
+        required: Align,
+        check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()>;
+
     /// Whether to enforce the validity invariant
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 528c1cb06c0..5b1ac6b2f65 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -18,6 +18,8 @@ use rustc_middle::mir::display_allocation;
 use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size};
 
+use crate::const_eval::CheckAlignment;
+
 use super::{
     alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx,
     InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
@@ -349,11 +351,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Option<(AllocId, Size, M::ProvenanceExtra)>> {
-        let align = M::enforce_alignment(&self).then_some(align);
         self.check_and_deref_ptr(
             ptr,
             size,
             align,
+            M::enforce_alignment(self),
             CheckInAllocMsg::MemoryAccessTest,
             |alloc_id, offset, prov| {
                 let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
@@ -373,10 +375,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         align: Align,
         msg: CheckInAllocMsg,
     ) -> InterpResult<'tcx> {
-        self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| {
-            let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
-            Ok((size, align, ()))
-        })?;
+        self.check_and_deref_ptr(
+            ptr,
+            size,
+            align,
+            CheckAlignment::Error,
+            msg,
+            |alloc_id, _, _| {
+                let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
+                Ok((size, align, ()))
+            },
+        )?;
         Ok(())
     }
 
@@ -388,7 +397,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         &self,
         ptr: Pointer<Option<M::Provenance>>,
         size: Size,
-        align: Option<Align>,
+        align: Align,
+        check: CheckAlignment,
         msg: CheckInAllocMsg,
         alloc_size: impl FnOnce(
             AllocId,
@@ -396,19 +406,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             M::ProvenanceExtra,
         ) -> InterpResult<'tcx, (Size, Align, T)>,
     ) -> InterpResult<'tcx, Option<T>> {
-        fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
-            if offset % align.bytes() == 0 {
-                Ok(())
-            } else {
-                // The biggest power of two through which `offset` is divisible.
-                let offset_pow2 = 1 << offset.trailing_zeros();
-                throw_ub!(AlignmentCheckFailed {
-                    has: Align::from_bytes(offset_pow2).unwrap(),
-                    required: align,
-                })
-            }
-        }
-
         Ok(match self.ptr_try_get_alloc_id(ptr) {
             Err(addr) => {
                 // We couldn't get a proper allocation. This is only okay if the access size is 0,
@@ -417,8 +414,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     throw_ub!(DanglingIntPointer(addr, msg));
                 }
                 // Must be aligned.
-                if let Some(align) = align {
-                    check_offset_align(addr, align)?;
+                if check.should_check() {
+                    self.check_offset_align(addr, align, check)?;
                 }
                 None
             }
@@ -441,16 +438,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
                 // Test align. Check this last; if both bounds and alignment are violated
                 // we want the error to be about the bounds.
-                if let Some(align) = align {
+                if check.should_check() {
                     if M::use_addr_for_alignment_check(self) {
                         // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
-                        check_offset_align(ptr.addr().bytes(), align)?;
+                        self.check_offset_align(ptr.addr().bytes(), align, check)?;
                     } else {
                         // Check allocation alignment and offset alignment.
                         if alloc_align.bytes() < align.bytes() {
-                            throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align });
+                            M::alignment_check_failed(self, alloc_align, align, check)?;
                         }
-                        check_offset_align(offset.bytes(), align)?;
+                        self.check_offset_align(offset.bytes(), align, check)?;
                     }
                 }
 
@@ -460,6 +457,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
         })
     }
+
+    fn check_offset_align(
+        &self,
+        offset: u64,
+        align: Align,
+        check: CheckAlignment,
+    ) -> InterpResult<'tcx> {
+        if offset % align.bytes() == 0 {
+            Ok(())
+        } else {
+            // The biggest power of two through which `offset` is divisible.
+            let offset_pow2 = 1 << offset.trailing_zeros();
+            M::alignment_check_failed(self, Align::from_bytes(offset_pow2).unwrap(), align, check)
+        }
+    }
 }
 
 /// Allocation accessors
@@ -560,11 +572,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
-        let align = M::enforce_alignment(self).then_some(align);
         let ptr_and_alloc = self.check_and_deref_ptr(
             ptr,
             size,
             align,
+            M::enforce_alignment(self),
             CheckInAllocMsg::MemoryAccessTest,
             |alloc_id, offset, prov| {
                 let alloc = self.get_alloc_raw(alloc_id)?;
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 1f1d0665139..949f95c5fa8 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -1,5 +1,3 @@
-use std::convert::TryFrom;
-
 use rustc_apfloat::Float;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index c47cfe8bb69..905eb71bb18 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -364,13 +364,8 @@ where
             .size_and_align_of_mplace(&mplace)?
             .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
         assert!(mplace.align <= align, "dynamic alignment less strict than static one?");
-        let align = M::enforce_alignment(self).then_some(align);
-        self.check_ptr_access_align(
-            mplace.ptr,
-            size,
-            align.unwrap_or(Align::ONE),
-            CheckInAllocMsg::DerefTest,
-        )?;
+        let align = if M::enforce_alignment(self).should_check() { align } else { Align::ONE };
+        self.check_ptr_access_align(mplace.ptr, size, align, CheckInAllocMsg::DerefTest)?;
         Ok(())
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index 2bc521d5bbe..e4f716c3194 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -1,6 +1,5 @@
 use rustc_middle::mir::interpret::InterpResult;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use std::convert::TryInto;
 use std::ops::ControlFlow;
 
 /// Checks whether a type contains generic parameters which require substitution.
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 0e85c7d11bc..f905d3fb479 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -4,7 +4,6 @@
 //! That's useful because it means other passes (e.g. promotion) can rely on `const`s
 //! to be const-safe.
 
-use std::convert::TryFrom;
 use std::fmt::{Display, Write};
 use std::num::NonZeroUsize;
 
@@ -602,8 +601,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
             | ty::Placeholder(..)
             | ty::Bound(..)
             | ty::Param(..)
-            | ty::Opaque(..)
-            | ty::Projection(..)
+            | ty::Alias(..)
             | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty),
         }
     }
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 64318f5f54d..bb897b95b2c 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -52,7 +52,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
         };
 
         let always_live_locals = always_storage_live_locals(body);
-        let storage_liveness = MaybeStorageLive::new(always_live_locals)
+        let storage_liveness = MaybeStorageLive::new(std::borrow::Cow::Owned(always_live_locals))
             .into_engine(tcx, body)
             .iterate_to_fixpoint()
             .into_results_cursor(body);
@@ -79,7 +79,7 @@ struct TypeChecker<'a, 'tcx> {
     param_env: ParamEnv<'tcx>,
     mir_phase: MirPhase,
     reachable_blocks: BitSet<BasicBlock>,
-    storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
+    storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>,
     place_cache: Vec<PlaceRef<'tcx>>,
     value_cache: Vec<u128>,
 }
@@ -241,7 +241,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 };
 
                 let kind = match parent_ty.ty.kind() {
-                    &ty::Opaque(def_id, substs) => {
+                    &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                         self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
                     }
                     kind => kind,
@@ -652,7 +652,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
                 }
                 let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind();
-                if !matches!(pty, ty::Adt(..) | ty::Generator(..) | ty::Opaque(..)) {
+                if !matches!(pty, ty::Adt(..) | ty::Generator(..) | ty::Alias(ty::Opaque, ..)) {
                     self.fail(
                         location,
                         format!(
diff --git a/compiler/rustc_const_eval/src/util/aggregate.rs b/compiler/rustc_const_eval/src/util/aggregate.rs
index c43de3368c6..10783c5ed1d 100644
--- a/compiler/rustc_const_eval/src/util/aggregate.rs
+++ b/compiler/rustc_const_eval/src/util/aggregate.rs
@@ -3,7 +3,6 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
 
-use std::convert::TryFrom;
 use std::iter::TrustedLen;
 
 /// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
diff --git a/compiler/rustc_const_eval/src/util/call_kind.rs b/compiler/rustc_const_eval/src/util/call_kind.rs
index b38a6c55138..38d9b044981 100644
--- a/compiler/rustc_const_eval/src/util/call_kind.rs
+++ b/compiler/rustc_const_eval/src/util/call_kind.rs
@@ -5,7 +5,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::{lang_items, LangItem};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AssocItemContainer, DefIdTree, Instance, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, DesugaringKind, Span};
 
@@ -39,9 +39,7 @@ pub enum CallKind<'tcx> {
     Normal {
         self_arg: Option<Ident>,
         desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
-        /// Whether the self type of the method call has an `.as_ref()` method.
-        /// Used for better diagnostics.
-        is_option_or_result: bool,
+        method_did: DefId,
     },
     /// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
     FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
@@ -133,16 +131,6 @@ pub fn call_kind<'tcx>(
         } else {
             None
         };
-        let parent_did = tcx.parent(method_did);
-        let parent_self_ty = (tcx.def_kind(parent_did) == rustc_hir::def::DefKind::Impl)
-            .then_some(parent_did)
-            .and_then(|did| match tcx.type_of(did).kind() {
-                ty::Adt(def, ..) => Some(def.did()),
-                _ => None,
-            });
-        let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
-            matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
-        });
-        CallKind::Normal { self_arg, desugaring, is_option_or_result }
+        CallKind::Normal { self_arg, desugaring, method_did }
     })
 }
diff --git a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs b/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs
index 6ca71223391..4ce107ea68d 100644
--- a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs
+++ b/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs
@@ -3,7 +3,7 @@ use rustc_middle::ty::{ParamEnv, TyCtxt};
 use rustc_session::Limit;
 use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
 
-use crate::const_eval::CompileTimeInterpreter;
+use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
 use crate::interpret::{InterpCx, MemoryKind, OpTy};
 
 /// Determines if this type permits "raw" initialization by just transmuting some memory into an
@@ -41,7 +41,7 @@ fn might_permit_raw_init_strict<'tcx>(
     let machine = CompileTimeInterpreter::new(
         Limit::new(0),
         /*can_access_statics:*/ false,
-        /*check_alignment:*/ true,
+        CheckAlignment::Error,
     );
 
     let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index 14c8c88028b..c4122f66498 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -58,8 +58,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
             // Types with identity (print the module path).
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Opaque(def_id, substs)
-            | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
diff --git a/compiler/rustc_data_structures/src/base_n.rs b/compiler/rustc_data_structures/src/base_n.rs
index 3c7bea27124..4567759c004 100644
--- a/compiler/rustc_data_structures/src/base_n.rs
+++ b/compiler/rustc_data_structures/src/base_n.rs
@@ -9,7 +9,7 @@ pub const MAX_BASE: usize = 64;
 pub const ALPHANUMERIC_ONLY: usize = 62;
 pub const CASE_INSENSITIVE: usize = 36;
 
-const BASE_64: &[u8; MAX_BASE as usize] =
+const BASE_64: &[u8; MAX_BASE] =
     b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
 
 #[inline]
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index d98f4e43fe8..b6e866f15ef 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -1,6 +1,5 @@
 use crate::stable_hasher;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::convert::TryInto;
 use std::hash::{Hash, Hasher};
 
 #[cfg(test)]
diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs
index 7099ca7eb88..b31092eca98 100644
--- a/compiler/rustc_data_structures/src/graph/scc/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs
@@ -9,7 +9,6 @@ use crate::fx::FxHashSet;
 use crate::graph::vec_graph::VecGraph;
 use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors};
 use rustc_index::vec::{Idx, IndexVec};
-use std::cmp::Ord;
 use std::ops::Range;
 
 #[cfg(test)]
diff --git a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
index e8efbd09a2c..94232bb7626 100644
--- a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
@@ -1,5 +1,3 @@
-use std::cmp::Ord;
-
 use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors};
 use rustc_index::vec::{Idx, IndexVec};
 
diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs
index 980a540ccba..d1d92b905b8 100644
--- a/compiler/rustc_data_structures/src/owning_ref/mod.rs
+++ b/compiler/rustc_data_structures/src/owning_ref/mod.rs
@@ -867,11 +867,9 @@ where
 /////////////////////////////////////////////////////////////////////////////
 
 use std::borrow::Borrow;
-use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
-use std::convert::From;
+use std::cmp::Ordering;
 use std::fmt::{self, Debug};
 use std::hash::{Hash, Hasher};
-use std::marker::{Send, Sync};
 
 impl<O, T: ?Sized> Deref for OwningRef<O, T> {
     type Target = T;
@@ -1096,7 +1094,6 @@ where
 // std types integration and convenience type defs
 /////////////////////////////////////////////////////////////////////////////
 
-use std::boxed::Box;
 use std::cell::{Ref, RefCell, RefMut};
 use std::rc::Rc;
 use std::sync::Arc;
diff --git a/compiler/rustc_data_structures/src/owning_ref/tests.rs b/compiler/rustc_data_structures/src/owning_ref/tests.rs
index 320c03d5139..a9b187c4ce0 100644
--- a/compiler/rustc_data_structures/src/owning_ref/tests.rs
+++ b/compiler/rustc_data_structures/src/owning_ref/tests.rs
@@ -3,7 +3,7 @@
 mod owning_ref {
     use super::super::OwningRef;
     use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef};
-    use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
+    use std::cmp::Ordering;
     use std::collections::hash_map::DefaultHasher;
     use std::collections::HashMap;
     use std::hash::{Hash, Hasher};
@@ -368,7 +368,7 @@ mod owning_handle {
 mod owning_ref_mut {
     use super::super::BoxRef;
     use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut};
-    use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
+    use std::cmp::Ordering;
     use std::collections::hash_map::DefaultHasher;
     use std::collections::HashMap;
     use std::hash::{Hash, Hasher};
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index aa7a01eed15..1d4014f05ac 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -86,7 +86,6 @@ use crate::fx::FxHashMap;
 
 use std::borrow::Borrow;
 use std::collections::hash_map::Entry;
-use std::convert::Into;
 use std::error::Error;
 use std::fs;
 use std::path::Path;
diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs
index d13313dfd0e..05f059c89d5 100644
--- a/compiler/rustc_data_structures/src/sorted_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map.rs
@@ -1,7 +1,6 @@
 use crate::stable_hasher::{HashStable, StableHasher, StableOrd};
 use std::borrow::Borrow;
 use std::cmp::Ordering;
-use std::iter::FromIterator;
 use std::mem;
 use std::ops::{Bound, Index, IndexMut, RangeBounds};
 
@@ -127,13 +126,13 @@ impl<K: Ord, V> SortedMap<K, V> {
     /// Iterate over the keys, sorted
     #[inline]
     pub fn keys(&self) -> impl Iterator<Item = &K> + ExactSizeIterator + DoubleEndedIterator {
-        self.data.iter().map(|&(ref k, _)| k)
+        self.data.iter().map(|(k, _)| k)
     }
 
     /// Iterate over values, sorted by key
     #[inline]
     pub fn values(&self) -> impl Iterator<Item = &V> + ExactSizeIterator + DoubleEndedIterator {
-        self.data.iter().map(|&(_, ref v)| v)
+        self.data.iter().map(|(_, v)| v)
     }
 
     #[inline]
@@ -223,7 +222,7 @@ impl<K: Ord, V> SortedMap<K, V> {
         K: Borrow<Q>,
         Q: Ord + ?Sized,
     {
-        self.data.binary_search_by(|&(ref x, _)| x.borrow().cmp(key))
+        self.data.binary_search_by(|(x, _)| x.borrow().cmp(key))
     }
 
     #[inline]
@@ -301,7 +300,7 @@ impl<K: Ord, V> FromIterator<(K, V)> for SortedMap<K, V> {
     fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
         let mut data: Vec<(K, V)> = iter.into_iter().collect();
 
-        data.sort_unstable_by(|&(ref k1, _), &(ref k2, _)| k1.cmp(k2));
+        data.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2));
         data.dedup_by(|&mut (ref k1, _), &mut (ref k2, _)| k1.cmp(k2) == Ordering::Equal);
 
         SortedMap { data }
diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
index c2f0ae32896..7af5c14942a 100644
--- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
@@ -1,7 +1,6 @@
 //! A variant of `SortedMap` that preserves insertion order.
 
 use std::hash::{Hash, Hasher};
-use std::iter::FromIterator;
 
 use crate::stable_hasher::{HashStable, StableHasher};
 use rustc_index::vec::{Idx, IndexVec};
diff --git a/compiler/rustc_data_structures/src/sso/either_iter.rs b/compiler/rustc_data_structures/src/sso/either_iter.rs
index 131eeef4582..bca6c0955b9 100644
--- a/compiler/rustc_data_structures/src/sso/either_iter.rs
+++ b/compiler/rustc_data_structures/src/sso/either_iter.rs
@@ -1,7 +1,5 @@
 use std::fmt;
-use std::iter::ExactSizeIterator;
 use std::iter::FusedIterator;
-use std::iter::Iterator;
 
 /// Iterator which may contain instance of
 /// one of two specific implementations.
diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs
index ec6a62016a8..7cdac581977 100644
--- a/compiler/rustc_data_structures/src/sso/map.rs
+++ b/compiler/rustc_data_structures/src/sso/map.rs
@@ -3,7 +3,6 @@ use crate::fx::FxHashMap;
 use arrayvec::ArrayVec;
 use std::fmt;
 use std::hash::Hash;
-use std::iter::FromIterator;
 use std::ops::Index;
 
 // For pointer-sized arguments arrays
diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs
index 406f0270dcc..a4b40138933 100644
--- a/compiler/rustc_data_structures/src/sso/set.rs
+++ b/compiler/rustc_data_structures/src/sso/set.rs
@@ -1,6 +1,5 @@
 use std::fmt;
 use std::hash::Hash;
-use std::iter::FromIterator;
 
 use super::map::SsoHashMap;
 
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index e4f47b22ac3..ed5341c40ef 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -138,7 +138,7 @@ cfg_if! {
             }
         }
 
-        pub use std::iter::Iterator as ParallelIterator;
+        pub use Iterator as ParallelIterator;
 
         pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
             t.into_iter()
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
index d44ccd368b3..b0315c93d93 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
@@ -76,7 +76,7 @@ where
     fn drop(&mut self) {
         // No need to drop the tag, as it's Copy
         unsafe {
-            std::mem::drop(P::from_usize(self.raw.pointer_raw()));
+            drop(P::from_usize(self.raw.pointer_raw()));
         }
     }
 }
diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs
index 86be0bd8775..2417df66bb9 100644
--- a/compiler/rustc_data_structures/src/vec_map.rs
+++ b/compiler/rustc_data_structures/src/vec_map.rs
@@ -1,6 +1,5 @@
 use std::borrow::Borrow;
 use std::fmt::Debug;
-use std::iter::FromIterator;
 use std::slice::Iter;
 use std::vec::IntoIter;
 
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index f06ca5a0733..711eed2b272 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -45,7 +45,6 @@ use rustc_target::json::ToJson;
 
 use std::borrow::Cow;
 use std::cmp::max;
-use std::default::Default;
 use std::env;
 use std::ffi::OsString;
 use std::fs;
diff --git a/compiler/rustc_error_codes/src/error_codes/E0492.md b/compiler/rustc_error_codes/src/error_codes/E0492.md
index 79e7c069a91..7c0719dc217 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0492.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0492.md
@@ -55,7 +55,6 @@ wrapper:
 
 ```
 use std::cell::Cell;
-use std::marker::Sync;
 
 struct NotThreadSafe<T> {
     value: Cell<T>,
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
index 4d1f9c1c901..db4c82b35c7 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
@@ -192,3 +192,5 @@ codegen_ssa_archive_build_failure =
 
 codegen_ssa_unknown_archive_kind =
     Don't know how to build archive of type: {$kind}
+
+codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
index a9ea161b93e..26cdf8a58f3 100644
--- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
@@ -20,6 +20,10 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
     .where_label = this `where` clause might not match the one in the trait
     .bounds_label = this bound might be missing in the impl
 
+hir_analysis_async_trait_impl_should_be_async =
+    method `{$method_name}` should be async because the method from the trait is async
+    .trait_item_label = required because the trait method is async
+
 hir_analysis_drop_impl_on_wrong_item =
     the `Drop` trait may only be implemented for local structs, enums, and unions
     .label = must be a struct, enum, or union in the current crate
@@ -101,8 +105,6 @@ hir_analysis_extern_crate_not_idiomatic =
     `extern crate` is not idiomatic in the new edition
     .suggestion = convert it to a `{$msg_code}`
 
-hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
-
 hir_analysis_const_impl_for_non_const_trait =
     const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
     .suggestion = mark `{$trait_name}` as const
diff --git a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
index 48ddb54b79e..243d10bfa06 100644
--- a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
@@ -21,3 +21,6 @@ monomorphize_large_assignments =
     moving {$size} bytes
     .label = value moved from here
     .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+monomorphize_couldnt_dump_mono_stats =
+    unexpected error occurred while dumping monomorphization stats: {$error}
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 06bb5edc090..585a54308c6 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -370,7 +370,11 @@ impl Diagnostic {
         self.set_span(after);
         for span_label in before.span_labels() {
             if let Some(label) = span_label.label {
-                self.span.push_span_label(after, label);
+                if span_label.is_primary {
+                    self.span.push_span_label(after, label);
+                } else {
+                    self.span.push_span_label(span_label.span, label);
+                }
             }
         }
         self
@@ -802,7 +806,7 @@ impl Diagnostic {
         debug_assert!(
             !(suggestions
                 .iter()
-                .flat_map(|suggs| suggs)
+                .flatten()
                 .any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())),
             "Span must not be empty and have no suggestion"
         );
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index cb39e997436..628cb90903f 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -59,7 +59,7 @@ into_diagnostic_arg_using_display!(
     i128,
     u128,
     std::io::Error,
-    std::boxed::Box<dyn std::error::Error>,
+    Box<dyn std::error::Error>,
     std::num::NonZeroU32,
     hir::Target,
     Edition,
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 4df2198fb0e..e2a0e436fd5 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1308,7 +1308,7 @@ impl EmitterWriter {
         //                see how it *looks* with
         //                very *weird* formats
         //                see?
-        for &(ref text, ref style) in msg.iter() {
+        for (text, style) in msg.iter() {
             let text = self.translate_message(text, args);
             let lines = text.split('\n').collect::<Vec<_>>();
             if lines.len() > 1 {
@@ -1370,7 +1370,7 @@ impl EmitterWriter {
                 buffer.append(0, ": ", header_style);
                 label_width += 2;
             }
-            for &(ref text, _) in msg.iter() {
+            for (text, _) in msg.iter() {
                 let text = self.translate_message(text, args);
                 // Account for newlines to align output to its label.
                 for (line, text) in normalize_whitespace(&text).lines().enumerate() {
@@ -1408,49 +1408,58 @@ impl EmitterWriter {
             if !sm.ensure_source_file_source_present(annotated_file.file.clone()) {
                 if !self.short_message {
                     // We'll just print an unannotated message.
-                    for (annotation_id, line) in annotated_file.lines.into_iter().enumerate() {
+                    for (annotation_id, line) in annotated_file.lines.iter().enumerate() {
                         let mut annotations = line.annotations.clone();
                         annotations.sort_by_key(|a| Reverse(a.start_col));
                         let mut line_idx = buffer.num_lines();
-                        buffer.append(
-                            line_idx,
-                            &format!(
-                                "{}:{}:{}",
-                                sm.filename_for_diagnostics(&annotated_file.file.name),
-                                sm.doctest_offset_line(&annotated_file.file.name, line.line_index),
-                                annotations[0].start_col + 1,
-                            ),
-                            Style::LineAndColumn,
-                        );
-                        if annotation_id == 0 {
-                            buffer.prepend(line_idx, "--> ", Style::LineNumber);
+
+                        let labels: Vec<_> = annotations
+                            .iter()
+                            .filter_map(|a| Some((a.label.as_ref()?, a.is_primary)))
+                            .filter(|(l, _)| !l.is_empty())
+                            .collect();
+
+                        if annotation_id == 0 || !labels.is_empty() {
+                            buffer.append(
+                                line_idx,
+                                &format!(
+                                    "{}:{}:{}",
+                                    sm.filename_for_diagnostics(&annotated_file.file.name),
+                                    sm.doctest_offset_line(
+                                        &annotated_file.file.name,
+                                        line.line_index
+                                    ),
+                                    annotations[0].start_col + 1,
+                                ),
+                                Style::LineAndColumn,
+                            );
+                            if annotation_id == 0 {
+                                buffer.prepend(line_idx, "--> ", Style::LineNumber);
+                            } else {
+                                buffer.prepend(line_idx, "::: ", Style::LineNumber);
+                            }
                             for _ in 0..max_line_num_len {
                                 buffer.prepend(line_idx, " ", Style::NoStyle);
                             }
                             line_idx += 1;
-                        };
-                        for (i, annotation) in annotations.into_iter().enumerate() {
-                            if let Some(label) = &annotation.label {
-                                let style = if annotation.is_primary {
-                                    Style::LabelPrimary
-                                } else {
-                                    Style::LabelSecondary
-                                };
-                                if annotation_id == 0 {
-                                    buffer.prepend(line_idx, " |", Style::LineNumber);
-                                    for _ in 0..max_line_num_len {
-                                        buffer.prepend(line_idx, " ", Style::NoStyle);
-                                    }
-                                    line_idx += 1;
-                                    buffer.append(line_idx + i, " = note: ", style);
-                                    for _ in 0..max_line_num_len {
-                                        buffer.prepend(line_idx, " ", Style::NoStyle);
-                                    }
-                                } else {
-                                    buffer.append(line_idx + i, ": ", style);
-                                }
-                                buffer.append(line_idx + i, label, style);
+                        }
+                        for (label, is_primary) in labels.into_iter() {
+                            let style = if is_primary {
+                                Style::LabelPrimary
+                            } else {
+                                Style::LabelSecondary
+                            };
+                            buffer.prepend(line_idx, " |", Style::LineNumber);
+                            for _ in 0..max_line_num_len {
+                                buffer.prepend(line_idx, " ", Style::NoStyle);
+                            }
+                            line_idx += 1;
+                            buffer.append(line_idx, " = note: ", style);
+                            for _ in 0..max_line_num_len {
+                                buffer.prepend(line_idx, " ", Style::NoStyle);
                             }
+                            buffer.append(line_idx, label, style);
+                            line_idx += 1;
                         }
                     }
                 }
@@ -2304,7 +2313,7 @@ impl FileWithAnnotatedLines {
         }
 
         // Find overlapping multiline annotations, put them at different depths
-        multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, usize::MAX - ml.line_end));
+        multiline_annotations.sort_by_key(|(_, ml)| (ml.line_start, usize::MAX - ml.line_end));
         for (_, ann) in multiline_annotations.clone() {
             for (_, a) in multiline_annotations.iter_mut() {
                 // Move all other multiline annotations overlapping with this one
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index eb0506c459a..518b5ec10f8 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -324,7 +324,7 @@ impl CodeSuggestion {
                         // Account for the difference between the width of the current code and the
                         // snippet being suggested, so that the *later* suggestions are correctly
                         // aligned on the screen.
-                        acc += len as isize - (cur_hi.col.0 - cur_lo.col.0) as isize;
+                        acc += len - (cur_hi.col.0 - cur_lo.col.0) as isize;
                     }
                     prev_hi = cur_hi;
                     prev_line = sf.get_line(prev_hi.line - 1);
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 6f159663e80..00453f78287 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -34,7 +34,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP};
 use smallvec::{smallvec, SmallVec};
 
-use std::default::Default;
 use std::iter;
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -1232,7 +1231,7 @@ pub fn expr_to_spanned_string<'a>(
     Err(match expr.kind {
         ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
             Ok(ast::LitKind::Str(s, style)) => return Ok((s, style, expr.span)),
-            Ok(ast::LitKind::ByteStr(_)) => {
+            Ok(ast::LitKind::ByteStr(..)) => {
                 let mut err = cx.struct_span_err(expr.span, err_msg);
                 let span = expr.span.shrink_to_lo();
                 err.span_suggestion(
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 4812bdd9dd8..ef50efb8125 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -1,8 +1,7 @@
 use crate::base::ExtCtxt;
-use rustc_ast::attr;
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
-use rustc_data_structures::sync::Lrc;
+use rustc_ast::{attr, token, util::literal};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
@@ -332,36 +331,36 @@ impl<'a> ExtCtxt<'a> {
         self.expr_struct(span, self.path_ident(span, id), fields)
     }
 
-    fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P<ast::Expr> {
-        let token_lit = lit_kind.to_token_lit();
-        self.expr(span, ast::ExprKind::Lit(token_lit))
+    pub fn expr_usize(&self, span: Span, n: usize) -> P<ast::Expr> {
+        let suffix = Some(ast::UintTy::Usize.name());
+        let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
-        self.expr_lit(
-            span,
-            ast::LitKind::Int(i as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)),
-        )
-    }
-
-    pub fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U32)))
+    pub fn expr_u32(&self, span: Span, n: u32) -> P<ast::Expr> {
+        let suffix = Some(ast::UintTy::U32.name());
+        let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Bool(value))
+    pub fn expr_bool(&self, span: Span, value: bool) -> P<ast::Expr> {
+        let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked))
+    pub fn expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr> {
+        let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_char(&self, sp: Span, ch: char) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Char(ch))
+    pub fn expr_char(&self, span: Span, ch: char) -> P<ast::Expr> {
+        let lit = token::Lit::new(token::Char, literal::escape_char_symbol(ch), None);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_byte_str(&self, sp: Span, bytes: Vec<u8>) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes)))
+    pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> {
+        let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
     /// `[expr1, expr2, ...]`
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 76165796117..768bdab8a54 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -6,6 +6,7 @@ use pm::{Delimiter, Level, LineColumn};
 use rustc_ast as ast;
 use rustc_ast::token;
 use rustc_ast::tokenstream::{self, Spacing::*, TokenStream};
+use rustc_ast::util::literal::escape_byte_str_symbol;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -526,7 +527,7 @@ impl server::TokenStream for Rustc<'_, '_> {
                 Ok(tokenstream::TokenStream::token_alone(token::Literal(*token_lit), expr.span))
             }
             ast::ExprKind::IncludedBytes(bytes) => {
-                let lit = ast::LitKind::ByteStr(bytes.clone()).to_token_lit();
+                let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
                 Ok(tokenstream::TokenStream::token_alone(token::TokenKind::Literal(lit), expr.span))
             }
             ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind {
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 8bc022e1e17..91825c29258 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -548,12 +548,7 @@ impl<'hir> Generics<'hir> {
     }
 
     pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'hir>> {
-        for param in self.params {
-            if name == param.name.ident().name {
-                return Some(param);
-            }
-        }
-        None
+        self.params.iter().find(|&param| name == param.name.ident().name)
     }
 
     pub fn spans(&self) -> MultiSpan {
diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs
index 6e2fbf96cbf..e870aa543d0 100644
--- a/compiler/rustc_hir/src/pat_util.rs
+++ b/compiler/rustc_hir/src/pat_util.rs
@@ -6,7 +6,7 @@ use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
-use std::iter::{Enumerate, ExactSizeIterator};
+use std::iter::Enumerate;
 
 pub struct EnumerateAndAdjust<I> {
     enumerate: Enumerate<I>,
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 66906b331da..71f26eb60c9 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -680,7 +680,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
 
         let poly_trait_ref =
-            ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
+            ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars);
 
         debug!(?poly_trait_ref, ?assoc_bindings);
         bounds.trait_bounds.push((poly_trait_ref, span, constness));
@@ -813,7 +813,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         if let Some(b) = trait_segment.args().bindings.first() {
             Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
         }
-        ty::TraitRef::new(trait_def_id, substs)
+        self.tcx().mk_trait_ref(trait_def_id, substs)
     }
 
     #[instrument(level = "debug", skip(self, span))]
@@ -1146,10 +1146,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
             debug!(?substs_trait_ref_and_assoc_item);
 
-            ty::ProjectionTy {
-                item_def_id: assoc_item.def_id,
-                substs: substs_trait_ref_and_assoc_item,
-            }
+            self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
         });
 
         if !speculative {
@@ -1195,7 +1192,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // the "projection predicate" for:
                 //
                 // `<T as Iterator>::Item = u32`
-                let assoc_item_def_id = projection_ty.skip_binder().item_def_id;
+                let assoc_item_def_id = projection_ty.skip_binder().def_id;
                 let def_kind = tcx.def_kind(assoc_item_def_id);
                 match (def_kind, term.unpack()) {
                     (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_))
@@ -1244,7 +1241,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 //
                 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
                 // parameter to have a skipped binder.
-                let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder()));
+                let param_ty = tcx.mk_ty(ty::Alias(ty::Projection, projection_ty.skip_binder()));
                 self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index fc0ca62090d..aa01feb3a1e 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -570,7 +570,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
                             assoc_item,
                             assoc_item,
                             default.span,
-                            ty::TraitRef { def_id: it.owner_id.to_def_id(), substs: trait_substs },
+                            tcx.mk_trait_ref(it.owner_id.to_def_id(), trait_substs),
                         );
                     }
                     _ => {}
@@ -1440,7 +1440,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E
                 impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypeCollector {
                     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                         match *t.kind() {
-                            ty::Opaque(def, _) => {
+                            ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
                                 self.0.push(def);
                                 ControlFlow::CONTINUE
                             }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index 1d6f9b29176..6b9ce9a4599 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -67,6 +67,10 @@ pub(crate) fn compare_impl_method<'tcx>(
         return;
     }
 
+    if let Err(_) = compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
+        return;
+    }
+
     if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
     {
         return;
@@ -323,6 +327,34 @@ fn compare_predicate_entailment<'tcx>(
     Ok(())
 }
 
+fn compare_asyncness<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_m: &ty::AssocItem,
+    impl_m_span: Span,
+    trait_m: &ty::AssocItem,
+    trait_item_span: Option<Span>,
+) -> Result<(), ErrorGuaranteed> {
+    if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
+        match tcx.fn_sig(impl_m.def_id).skip_binder().output().kind() {
+            ty::Alias(ty::Opaque, ..) => {
+                // allow both `async fn foo()` and `fn foo() -> impl Future`
+            }
+            ty::Error(rustc_errors::ErrorGuaranteed { .. }) => {
+                // We don't know if it's ok, but at least it's already an error.
+            }
+            _ => {
+                return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
+                    span: impl_m_span,
+                    method_name: trait_m.name,
+                    trait_item_span,
+                }));
+            }
+        };
+    }
+
+    Ok(())
+}
+
 #[instrument(skip(tcx), level = "debug", ret)]
 pub fn collect_trait_impl_trait_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -571,10 +603,10 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Projection(proj) = ty.kind()
-            && self.tcx().def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+        if let ty::Alias(ty::Projection, proj) = ty.kind()
+            && self.tcx().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
         {
-            if let Some((ty, _)) = self.types.get(&proj.item_def_id) {
+            if let Some((ty, _)) = self.types.get(&proj.def_id) {
                 return *ty;
             }
             //FIXME(RPITIT): Deny nested RPITIT in substs too
@@ -586,9 +618,9 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
                 span: self.span,
                 kind: TypeVariableOriginKind::MiscVariable,
             });
-            self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
+            self.types.insert(proj.def_id, (infer_ty, proj.substs));
             // Recurse into bounds
-            for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
+            for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.tcx(), proj.substs) {
                 let pred = pred.fold_with(self);
                 let pred = self.ocx.normalize(
                     &ObligationCause::misc(self.span, self.body_id),
@@ -601,7 +633,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
                     ObligationCause::new(
                         self.span,
                         self.body_id,
-                        ObligationCauseCode::BindingObligation(proj.item_def_id, pred_span),
+                        ObligationCauseCode::BindingObligation(proj.def_id, pred_span),
                     ),
                     self.param_env,
                     pred,
@@ -1734,8 +1766,8 @@ pub fn check_type_bounds<'tcx>(
     let normalize_param_env = {
         let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
         match impl_ty_value.kind() {
-            ty::Projection(proj)
-                if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs =>
+            ty::Alias(ty::Projection, proj)
+                if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs =>
             {
                 // Don't include this predicate if the projected type is
                 // exactly the same as the projection. This can occur in
@@ -1746,10 +1778,7 @@ pub fn check_type_bounds<'tcx>(
             _ => predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
-                        projection_ty: ty::ProjectionTy {
-                            item_def_id: trait_ty.def_id,
-                            substs: rebased_substs,
-                        },
+                        projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs),
                         term: impl_ty_value.into(),
                     },
                     bound_vars,
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 29255472a25..57f0cae12bb 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -352,11 +352,7 @@ fn bounds_from_generic_predicates<'tcx>(
         // insert the associated types where they correspond, but for now let's be "lazy" and
         // propose this instead of the following valid resugaring:
         // `T: Trait, Trait::Assoc = K` → `T: Trait<Assoc = K>`
-        where_clauses.push(format!(
-            "{} = {}",
-            tcx.def_path_str(p.projection_ty.item_def_id),
-            p.term,
-        ));
+        where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.def_id), p.term));
     }
     let where_clauses = if where_clauses.is_empty() {
         String::new()
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index b065ace6bf5..94d333c336e 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -31,7 +31,6 @@ use rustc_trait_selection::traits::{
 };
 
 use std::cell::LazyCell;
-use std::convert::TryInto;
 use std::iter;
 use std::ops::{ControlFlow, Deref};
 
@@ -760,7 +759,7 @@ impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
 
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match t.kind() {
-            ty::Projection(p) if p.item_def_id == self.gat => {
+            ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
                 for (idx, subst) in p.substs.iter().enumerate() {
                     match subst.unpack() {
                         GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => {
@@ -1593,12 +1592,12 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
     {
         for arg in fn_output.walk() {
             if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                && let ty::Projection(proj) = ty.kind()
-                && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
-                && tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id()
+                && let ty::Alias(ty::Projection, proj) = ty.kind()
+                && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
+                && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
             {
-                let span = tcx.def_span(proj.item_def_id);
-                let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
+                let span = tcx.def_span(proj.def_id);
+                let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
                 let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
                     let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
                     let normalized_bound = wfcx.normalize(span, None, bound);
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 2890c149b3a..6469f389bf9 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -223,7 +223,7 @@ impl<'tcx> InherentCollect<'tcx> {
             | ty::Tuple(..) => {
                 self.check_primitive_impl(item.owner_id.def_id, self_ty, items, ty.span)
             }
-            ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
+            ty::Alias(..) | ty::Param(_) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess,
                     ty.span,
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 72288e5bc76..0c4649cea14 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -17,28 +17,20 @@
 use crate::astconv::AstConv;
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::errors;
-use rustc_ast as ast;
-use rustc_ast::{MetaItemKind, NestedMetaItem};
-use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
-use rustc_hir::{lang_items, GenericParamKind, LangItem, Node};
+use rustc_hir::{GenericParamKind, Node};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
-use rustc_middle::mir::mono::Linkage;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, ToPredicate, Ty, TyCtxt};
-use rustc_session::lint;
-use rustc_session::parse::feature_err;
+use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
-use rustc_target::spec::{abi, SanitizerSet};
+use rustc_target::spec::abi;
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 use std::iter;
 
@@ -78,10 +70,7 @@ pub fn provide(providers: &mut Providers) {
         impl_polarity,
         is_foreign_item,
         generator_kind,
-        codegen_fn_attrs,
-        asm_target_features,
         collect_mod_item_types,
-        should_inherit_track_caller,
         ..*providers
     };
 }
@@ -500,7 +489,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
                         format!(
                             "{}::",
                             // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
-                            self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(),
+                            self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
                         ),
                         Applicability::MaybeIncorrect,
                     );
@@ -1455,797 +1444,3 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind>
         _ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
     }
 }
-
-fn from_target_feature(
-    tcx: TyCtxt<'_>,
-    attr: &ast::Attribute,
-    supported_target_features: &FxHashMap<String, Option<Symbol>>,
-    target_features: &mut Vec<Symbol>,
-) {
-    let Some(list) = attr.meta_item_list() else { return };
-    let bad_item = |span| {
-        let msg = "malformed `target_feature` attribute input";
-        let code = "enable = \"..\"";
-        tcx.sess
-            .struct_span_err(span, msg)
-            .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
-            .emit();
-    };
-    let rust_features = tcx.features();
-    for item in list {
-        // Only `enable = ...` is accepted in the meta-item list.
-        if !item.has_name(sym::enable) {
-            bad_item(item.span());
-            continue;
-        }
-
-        // Must be of the form `enable = "..."` (a string).
-        let Some(value) = item.value_str() else {
-            bad_item(item.span());
-            continue;
-        };
-
-        // We allow comma separation to enable multiple features.
-        target_features.extend(value.as_str().split(',').filter_map(|feature| {
-            let Some(feature_gate) = supported_target_features.get(feature) else {
-                let msg =
-                    format!("the feature named `{}` is not valid for this target", feature);
-                let mut err = tcx.sess.struct_span_err(item.span(), &msg);
-                err.span_label(
-                    item.span(),
-                    format!("`{}` is not valid for this target", feature),
-                );
-                if let Some(stripped) = feature.strip_prefix('+') {
-                    let valid = supported_target_features.contains_key(stripped);
-                    if valid {
-                        err.help("consider removing the leading `+` in the feature name");
-                    }
-                }
-                err.emit();
-                return None;
-            };
-
-            // Only allow features whose feature gates have been enabled.
-            let allowed = match feature_gate.as_ref().copied() {
-                Some(sym::arm_target_feature) => rust_features.arm_target_feature,
-                Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
-                Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
-                Some(sym::mips_target_feature) => rust_features.mips_target_feature,
-                Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
-                Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
-                Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
-                Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
-                Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
-                Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
-                Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
-                Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
-                Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
-                Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
-                Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
-                Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
-                Some(name) => bug!("unknown target feature gate {}", name),
-                None => true,
-            };
-            if !allowed {
-                feature_err(
-                    &tcx.sess.parse_sess,
-                    feature_gate.unwrap(),
-                    item.span(),
-                    &format!("the target feature `{}` is currently unstable", feature),
-                )
-                .emit();
-            }
-            Some(Symbol::intern(feature))
-        }));
-    }
-}
-
-fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
-    use rustc_middle::mir::mono::Linkage::*;
-
-    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
-    // applicable to variable declarations and may not really make sense for
-    // Rust code in the first place but allow them anyway and trust that the
-    // user knows what they're doing. Who knows, unanticipated use cases may pop
-    // up in the future.
-    //
-    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
-    // and don't have to be, LLVM treats them as no-ops.
-    match name {
-        "appending" => Appending,
-        "available_externally" => AvailableExternally,
-        "common" => Common,
-        "extern_weak" => ExternalWeak,
-        "external" => External,
-        "internal" => Internal,
-        "linkonce" => LinkOnceAny,
-        "linkonce_odr" => LinkOnceODR,
-        "private" => Private,
-        "weak" => WeakAny,
-        "weak_odr" => WeakODR,
-        _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
-    }
-}
-
-fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
-    if cfg!(debug_assertions) {
-        let def_kind = tcx.def_kind(did);
-        assert!(
-            def_kind.has_codegen_attrs(),
-            "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
-        );
-    }
-
-    let did = did.expect_local();
-    let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
-    let mut codegen_fn_attrs = CodegenFnAttrs::new();
-    if tcx.should_inherit_track_caller(did) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
-    }
-
-    let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
-
-    let mut inline_span = None;
-    let mut link_ordinal_span = None;
-    let mut no_sanitize_span = None;
-    for attr in attrs.iter() {
-        if attr.has_name(sym::cold) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
-        } else if attr.has_name(sym::rustc_allocator) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
-        } else if attr.has_name(sym::ffi_returns_twice) {
-            if tcx.is_foreign_item(did) {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
-            } else {
-                // `#[ffi_returns_twice]` is only allowed `extern fn`s.
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0724,
-                    "`#[ffi_returns_twice]` may only be used on foreign functions"
-                )
-                .emit();
-            }
-        } else if attr.has_name(sym::ffi_pure) {
-            if tcx.is_foreign_item(did) {
-                if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
-                    // `#[ffi_const]` functions cannot be `#[ffi_pure]`
-                    struct_span_err!(
-                        tcx.sess,
-                        attr.span,
-                        E0757,
-                        "`#[ffi_const]` function cannot be `#[ffi_pure]`"
-                    )
-                    .emit();
-                } else {
-                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
-                }
-            } else {
-                // `#[ffi_pure]` is only allowed on foreign functions
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0755,
-                    "`#[ffi_pure]` may only be used on foreign functions"
-                )
-                .emit();
-            }
-        } else if attr.has_name(sym::ffi_const) {
-            if tcx.is_foreign_item(did) {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
-            } else {
-                // `#[ffi_const]` is only allowed on foreign functions
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0756,
-                    "`#[ffi_const]` may only be used on foreign functions"
-                )
-                .emit();
-            }
-        } else if attr.has_name(sym::rustc_nounwind) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
-        } else if attr.has_name(sym::rustc_reallocator) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
-        } else if attr.has_name(sym::rustc_deallocator) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
-        } else if attr.has_name(sym::rustc_allocator_zeroed) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
-        } else if attr.has_name(sym::naked) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
-        } else if attr.has_name(sym::no_mangle) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
-        } else if attr.has_name(sym::no_coverage) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
-        } else if attr.has_name(sym::rustc_std_internal_symbol) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
-        } else if attr.has_name(sym::used) {
-            let inner = attr.meta_item_list();
-            match inner.as_deref() {
-                Some([item]) if item.has_name(sym::linker) => {
-                    if !tcx.features().used_with_arg {
-                        feature_err(
-                            &tcx.sess.parse_sess,
-                            sym::used_with_arg,
-                            attr.span,
-                            "`#[used(linker)]` is currently unstable",
-                        )
-                        .emit();
-                    }
-                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
-                }
-                Some([item]) if item.has_name(sym::compiler) => {
-                    if !tcx.features().used_with_arg {
-                        feature_err(
-                            &tcx.sess.parse_sess,
-                            sym::used_with_arg,
-                            attr.span,
-                            "`#[used(compiler)]` is currently unstable",
-                        )
-                        .emit();
-                    }
-                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
-                }
-                Some(_) => {
-                    tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
-                }
-                None => {
-                    // Unfortunately, unconditionally using `llvm.used` causes
-                    // issues in handling `.init_array` with the gold linker,
-                    // but using `llvm.compiler.used` caused a nontrival amount
-                    // of unintentional ecosystem breakage -- particularly on
-                    // Mach-O targets.
-                    //
-                    // As a result, we emit `llvm.compiler.used` only on ELF
-                    // targets. This is somewhat ad-hoc, but actually follows
-                    // our pre-LLVM 13 behavior (prior to the ecosystem
-                    // breakage), and seems to match `clang`'s behavior as well
-                    // (both before and after LLVM 13), possibly because they
-                    // have similar compatibility concerns to us. See
-                    // https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
-                    // and following comments for some discussion of this, as
-                    // well as the comments in `rustc_codegen_llvm` where these
-                    // flags are handled.
-                    //
-                    // Anyway, to be clear: this is still up in the air
-                    // somewhat, and is subject to change in the future (which
-                    // is a good thing, because this would ideally be a bit
-                    // more firmed up).
-                    let is_like_elf = !(tcx.sess.target.is_like_osx
-                        || tcx.sess.target.is_like_windows
-                        || tcx.sess.target.is_like_wasm);
-                    codegen_fn_attrs.flags |= if is_like_elf {
-                        CodegenFnAttrFlags::USED
-                    } else {
-                        CodegenFnAttrFlags::USED_LINKER
-                    };
-                }
-            }
-        } else if attr.has_name(sym::cmse_nonsecure_entry) {
-            if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0776,
-                    "`#[cmse_nonsecure_entry]` requires C ABI"
-                )
-                .emit();
-            }
-            if !tcx.sess.target.llvm_target.contains("thumbv8m") {
-                struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
-                    .emit();
-            }
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
-        } else if attr.has_name(sym::thread_local) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
-        } else if attr.has_name(sym::track_caller) {
-            if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
-                struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
-                    .emit();
-            }
-            if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
-                feature_err(
-                    &tcx.sess.parse_sess,
-                    sym::closure_track_caller,
-                    attr.span,
-                    "`#[track_caller]` on closures is currently unstable",
-                )
-                .emit();
-            }
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
-        } else if attr.has_name(sym::export_name) {
-            if let Some(s) = attr.value_str() {
-                if s.as_str().contains('\0') {
-                    // `#[export_name = ...]` will be converted to a null-terminated string,
-                    // so it may not contain any null characters.
-                    struct_span_err!(
-                        tcx.sess,
-                        attr.span,
-                        E0648,
-                        "`export_name` may not contain null characters"
-                    )
-                    .emit();
-                }
-                codegen_fn_attrs.export_name = Some(s);
-            }
-        } else if attr.has_name(sym::target_feature) {
-            if !tcx.is_closure(did.to_def_id())
-                && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
-            {
-                if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
-                    // The `#[target_feature]` attribute is allowed on
-                    // WebAssembly targets on all functions, including safe
-                    // ones. Other targets require that `#[target_feature]` is
-                    // only applied to unsafe functions (pending the
-                    // `target_feature_11` feature) because on most targets
-                    // execution of instructions that are not supported is
-                    // considered undefined behavior. For WebAssembly which is a
-                    // 100% safe target at execution time it's not possible to
-                    // execute undefined instructions, and even if a future
-                    // feature was added in some form for this it would be a
-                    // deterministic trap. There is no undefined behavior when
-                    // executing WebAssembly so `#[target_feature]` is allowed
-                    // on safe functions (but again, only for WebAssembly)
-                    //
-                    // Note that this is also allowed if `actually_rustdoc` so
-                    // if a target is documenting some wasm-specific code then
-                    // it's not spuriously denied.
-                } else if !tcx.features().target_feature_11 {
-                    let mut err = feature_err(
-                        &tcx.sess.parse_sess,
-                        sym::target_feature_11,
-                        attr.span,
-                        "`#[target_feature(..)]` can only be applied to `unsafe` functions",
-                    );
-                    err.span_label(tcx.def_span(did), "not an `unsafe` function");
-                    err.emit();
-                } else {
-                    check_target_feature_trait_unsafe(tcx, did, attr.span);
-                }
-            }
-            from_target_feature(
-                tcx,
-                attr,
-                supported_target_features,
-                &mut codegen_fn_attrs.target_features,
-            );
-        } else if attr.has_name(sym::linkage) {
-            if let Some(val) = attr.value_str() {
-                let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
-                if tcx.is_foreign_item(did) {
-                    codegen_fn_attrs.import_linkage = linkage;
-                } else {
-                    codegen_fn_attrs.linkage = linkage;
-                }
-            }
-        } else if attr.has_name(sym::link_section) {
-            if let Some(val) = attr.value_str() {
-                if val.as_str().bytes().any(|b| b == 0) {
-                    let msg = format!(
-                        "illegal null byte in link_section \
-                         value: `{}`",
-                        &val
-                    );
-                    tcx.sess.span_err(attr.span, &msg);
-                } else {
-                    codegen_fn_attrs.link_section = Some(val);
-                }
-            }
-        } else if attr.has_name(sym::link_name) {
-            codegen_fn_attrs.link_name = attr.value_str();
-        } else if attr.has_name(sym::link_ordinal) {
-            link_ordinal_span = Some(attr.span);
-            if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
-                codegen_fn_attrs.link_ordinal = ordinal;
-            }
-        } else if attr.has_name(sym::no_sanitize) {
-            no_sanitize_span = Some(attr.span);
-            if let Some(list) = attr.meta_item_list() {
-                for item in list.iter() {
-                    if item.has_name(sym::address) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
-                    } else if item.has_name(sym::cfi) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
-                    } else if item.has_name(sym::kcfi) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
-                    } else if item.has_name(sym::memory) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
-                    } else if item.has_name(sym::memtag) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
-                    } else if item.has_name(sym::shadow_call_stack) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
-                    } else if item.has_name(sym::thread) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
-                    } else if item.has_name(sym::hwaddress) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
-                    } else {
-                        tcx.sess
-                            .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
-                            .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
-                            .emit();
-                    }
-                }
-            }
-        } else if attr.has_name(sym::instruction_set) {
-            codegen_fn_attrs.instruction_set = match attr.meta_kind() {
-                Some(MetaItemKind::List(ref items)) => match items.as_slice() {
-                    [NestedMetaItem::MetaItem(set)] => {
-                        let segments =
-                            set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
-                        match segments.as_slice() {
-                            [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
-                                if !tcx.sess.target.has_thumb_interworking {
-                                    struct_span_err!(
-                                        tcx.sess.diagnostic(),
-                                        attr.span,
-                                        E0779,
-                                        "target does not support `#[instruction_set]`"
-                                    )
-                                    .emit();
-                                    None
-                                } else if segments[1] == sym::a32 {
-                                    Some(InstructionSetAttr::ArmA32)
-                                } else if segments[1] == sym::t32 {
-                                    Some(InstructionSetAttr::ArmT32)
-                                } else {
-                                    unreachable!()
-                                }
-                            }
-                            _ => {
-                                struct_span_err!(
-                                    tcx.sess.diagnostic(),
-                                    attr.span,
-                                    E0779,
-                                    "invalid instruction set specified",
-                                )
-                                .emit();
-                                None
-                            }
-                        }
-                    }
-                    [] => {
-                        struct_span_err!(
-                            tcx.sess.diagnostic(),
-                            attr.span,
-                            E0778,
-                            "`#[instruction_set]` requires an argument"
-                        )
-                        .emit();
-                        None
-                    }
-                    _ => {
-                        struct_span_err!(
-                            tcx.sess.diagnostic(),
-                            attr.span,
-                            E0779,
-                            "cannot specify more than one instruction set"
-                        )
-                        .emit();
-                        None
-                    }
-                },
-                _ => {
-                    struct_span_err!(
-                        tcx.sess.diagnostic(),
-                        attr.span,
-                        E0778,
-                        "must specify an instruction set"
-                    )
-                    .emit();
-                    None
-                }
-            };
-        } else if attr.has_name(sym::repr) {
-            codegen_fn_attrs.alignment = match attr.meta_item_list() {
-                Some(items) => match items.as_slice() {
-                    [item] => match item.name_value_literal() {
-                        Some((sym::align, literal)) => {
-                            let alignment = rustc_attr::parse_alignment(&literal.kind);
-
-                            match alignment {
-                                Ok(align) => Some(align),
-                                Err(msg) => {
-                                    struct_span_err!(
-                                        tcx.sess.diagnostic(),
-                                        attr.span,
-                                        E0589,
-                                        "invalid `repr(align)` attribute: {}",
-                                        msg
-                                    )
-                                    .emit();
-
-                                    None
-                                }
-                            }
-                        }
-                        _ => None,
-                    },
-                    [] => None,
-                    _ => None,
-                },
-                None => None,
-            };
-        }
-    }
-
-    codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
-        if !attr.has_name(sym::inline) {
-            return ia;
-        }
-        match attr.meta_kind() {
-            Some(MetaItemKind::Word) => InlineAttr::Hint,
-            Some(MetaItemKind::List(ref items)) => {
-                inline_span = Some(attr.span);
-                if items.len() != 1 {
-                    struct_span_err!(
-                        tcx.sess.diagnostic(),
-                        attr.span,
-                        E0534,
-                        "expected one argument"
-                    )
-                    .emit();
-                    InlineAttr::None
-                } else if list_contains_name(&items, sym::always) {
-                    InlineAttr::Always
-                } else if list_contains_name(&items, sym::never) {
-                    InlineAttr::Never
-                } else {
-                    struct_span_err!(
-                        tcx.sess.diagnostic(),
-                        items[0].span(),
-                        E0535,
-                        "invalid argument"
-                    )
-                    .help("valid inline arguments are `always` and `never`")
-                    .emit();
-
-                    InlineAttr::None
-                }
-            }
-            Some(MetaItemKind::NameValue(_)) => ia,
-            None => ia,
-        }
-    });
-
-    codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
-        if !attr.has_name(sym::optimize) {
-            return ia;
-        }
-        let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
-        match attr.meta_kind() {
-            Some(MetaItemKind::Word) => {
-                err(attr.span, "expected one argument");
-                ia
-            }
-            Some(MetaItemKind::List(ref items)) => {
-                inline_span = Some(attr.span);
-                if items.len() != 1 {
-                    err(attr.span, "expected one argument");
-                    OptimizeAttr::None
-                } else if list_contains_name(&items, sym::size) {
-                    OptimizeAttr::Size
-                } else if list_contains_name(&items, sym::speed) {
-                    OptimizeAttr::Speed
-                } else {
-                    err(items[0].span(), "invalid argument");
-                    OptimizeAttr::None
-                }
-            }
-            Some(MetaItemKind::NameValue(_)) => ia,
-            None => ia,
-        }
-    });
-
-    // #73631: closures inherit `#[target_feature]` annotations
-    if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
-        let owner_id = tcx.parent(did.to_def_id());
-        if tcx.def_kind(owner_id).has_codegen_attrs() {
-            codegen_fn_attrs
-                .target_features
-                .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
-        }
-    }
-
-    // If a function uses #[target_feature] it can't be inlined into general
-    // purpose functions as they wouldn't have the right target features
-    // enabled. For that reason we also forbid #[inline(always)] as it can't be
-    // respected.
-    if !codegen_fn_attrs.target_features.is_empty() {
-        if codegen_fn_attrs.inline == InlineAttr::Always {
-            if let Some(span) = inline_span {
-                tcx.sess.span_err(
-                    span,
-                    "cannot use `#[inline(always)]` with \
-                     `#[target_feature]`",
-                );
-            }
-        }
-    }
-
-    if !codegen_fn_attrs.no_sanitize.is_empty() {
-        if codegen_fn_attrs.inline == InlineAttr::Always {
-            if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
-                let hir_id = tcx.hir().local_def_id_to_hir_id(did);
-                tcx.struct_span_lint_hir(
-                    lint::builtin::INLINE_NO_SANITIZE,
-                    hir_id,
-                    no_sanitize_span,
-                    "`no_sanitize` will have no effect after inlining",
-                    |lint| lint.span_note(inline_span, "inlining requested here"),
-                )
-            }
-        }
-    }
-
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
-        codegen_fn_attrs.inline = InlineAttr::Never;
-    }
-
-    // Weak lang items have the same semantics as "std internal" symbols in the
-    // sense that they're preserved through all our LTO passes and only
-    // strippable by the linker.
-    //
-    // Additionally weak lang items have predetermined symbol names.
-    if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
-    }
-    if let Some((name, _)) = lang_items::extract(attrs)
-        && let Some(lang_item) = LangItem::from_name(name)
-        && let Some(link_name) = lang_item.link_name()
-    {
-        codegen_fn_attrs.export_name = Some(link_name);
-        codegen_fn_attrs.link_name = Some(link_name);
-    }
-    check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
-
-    // Internal symbols to the standard library all have no_mangle semantics in
-    // that they have defined symbol names present in the function name. This
-    // also applies to weak symbols where they all have known symbol names.
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
-    }
-
-    // Any linkage to LLVM intrinsics for now forcibly marks them all as never
-    // unwinds since LLVM sometimes can't handle codegen which `invoke`s
-    // intrinsic functions.
-    if let Some(name) = &codegen_fn_attrs.link_name {
-        if name.as_str().starts_with("llvm.") {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
-        }
-    }
-
-    codegen_fn_attrs
-}
-
-/// Computes the set of target features used in a function for the purposes of
-/// inline assembly.
-fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
-    let mut target_features = tcx.sess.unstable_target_features.clone();
-    if tcx.def_kind(did).has_codegen_attrs() {
-        let attrs = tcx.codegen_fn_attrs(did);
-        target_features.extend(&attrs.target_features);
-        match attrs.instruction_set {
-            None => {}
-            Some(InstructionSetAttr::ArmA32) => {
-                target_features.remove(&sym::thumb_mode);
-            }
-            Some(InstructionSetAttr::ArmT32) => {
-                target_features.insert(sym::thumb_mode);
-            }
-        }
-    }
-
-    tcx.arena.alloc(target_features)
-}
-
-/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
-/// applied to the method prototype.
-fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    if let Some(impl_item) = tcx.opt_associated_item(def_id)
-        && let ty::AssocItemContainer::ImplContainer = impl_item.container
-        && let Some(trait_item) = impl_item.trait_item_def_id
-    {
-        return tcx
-            .codegen_fn_attrs(trait_item)
-            .flags
-            .intersects(CodegenFnAttrFlags::TRACK_CALLER);
-    }
-
-    false
-}
-
-fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
-    use rustc_ast::{LitIntType, LitKind, MetaItemLit};
-    if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
-        feature_err(
-            &tcx.sess.parse_sess,
-            sym::raw_dylib,
-            attr.span,
-            "`#[link_ordinal]` is unstable on x86",
-        )
-        .emit();
-    }
-    let meta_item_list = attr.meta_item_list();
-    let meta_item_list = meta_item_list.as_deref();
-    let sole_meta_list = match meta_item_list {
-        Some([item]) => item.lit(),
-        Some(_) => {
-            tcx.sess
-                .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
-                .note("the attribute requires exactly one argument")
-                .emit();
-            return None;
-        }
-        _ => None,
-    };
-    if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
-        sole_meta_list
-    {
-        // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header,
-        // the ordinal must fit into 16 bits.  Similarly, the Ordinal field in COFFShortExport (defined
-        // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information
-        // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
-        //
-        // FIXME: should we allow an ordinal of 0?  The MSVC toolchain has inconsistent support for this:
-        // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies
-        // a zero ordinal.  However, llvm-dlltool is perfectly happy to generate an import library
-        // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import
-        // library produced by LLVM with an ordinal of 0, and it generates an .EXE.  (I don't know yet
-        // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
-        // about LINK.EXE failing.)
-        if *ordinal <= u16::MAX as u128 {
-            Some(*ordinal as u16)
-        } else {
-            let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
-            tcx.sess
-                .struct_span_err(attr.span, &msg)
-                .note("the value may not exceed `u16::MAX`")
-                .emit();
-            None
-        }
-    } else {
-        tcx.sess
-            .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
-            .note("an unsuffixed integer value, e.g., `1`, is expected")
-            .emit();
-        None
-    }
-}
-
-fn check_link_name_xor_ordinal(
-    tcx: TyCtxt<'_>,
-    codegen_fn_attrs: &CodegenFnAttrs,
-    inline_span: Option<Span>,
-) {
-    if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() {
-        return;
-    }
-    let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
-    if let Some(span) = inline_span {
-        tcx.sess.span_err(span, msg);
-    } else {
-        tcx.sess.err(msg);
-    }
-}
-
-/// Checks the function annotated with `#[target_feature]` is not a safe
-/// trait method implementation, reporting an error if it is.
-fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(id);
-    let node = tcx.hir().get(hir_id);
-    if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
-        let parent_id = tcx.hir().get_parent_item(hir_id);
-        let parent_item = tcx.hir().expect_item(parent_id.def_id);
-        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
-            tcx.sess
-                .struct_span_err(
-                    attr_span,
-                    "`#[target_feature(..)]` cannot be applied to safe trait method",
-                )
-                .span_label(attr_span, "cannot be applied to safe trait method")
-                .span_label(tcx.def_span(id), "not an `unsafe` function")
-                .emit();
-        }
-    }
-}
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
index 9a7b261fffd..b4ad3467e7d 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
@@ -1749,7 +1749,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
                 ty::Param(param_ty) => {
                     self.arg_is_constrained[param_ty.index as usize] = true;
                 }
-                ty::Projection(_) => return ControlFlow::Continue(()),
+                ty::Alias(ty::Projection, _) => return ControlFlow::Continue(()),
                 _ => (),
             }
             t.super_visit_with(self)
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 45e241f4e09..79d75231e5d 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -75,7 +75,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
 
     const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
 
-    // We use an `IndexSet` to preserves order of insertion.
+    // We use an `IndexSet` to preserve order of insertion.
     // Preserving the order of insertion is important here so as not to break UI tests.
     let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
 
@@ -97,11 +97,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
             | ItemKind::Struct(_, ref generics)
             | ItemKind::Union(_, ref generics) => *generics,
 
-            ItemKind::Trait(_, _, ref generics, ..) => {
-                is_trait = Some(ty::TraitRef::identity(tcx, def_id));
-                *generics
-            }
-            ItemKind::TraitAlias(ref generics, _) => {
+            ItemKind::Trait(_, _, ref generics, ..) | ItemKind::TraitAlias(ref generics, _) => {
                 is_trait = Some(ty::TraitRef::identity(tcx, def_id));
                 *generics
             }
@@ -406,14 +402,15 @@ pub(super) fn explicit_predicates_of<'tcx>(
             // For a predicate from a where clause to become a bound on an
             // associated type:
             // * It must use the identity substs of the item.
-            //     * Since any generic parameters on the item are not in scope,
-            //       this means that the item is not a GAT, and its identity
-            //       substs are the same as the trait's.
+            //   * We're in the scope of the trait, so we can't name any
+            //     parameters of the GAT. That means that all we need to
+            //     check are that the substs of the projection are the
+            //     identity substs of the trait.
             // * It must be an associated type for this trait (*not* a
             //   supertrait).
-            if let ty::Projection(projection) = ty.kind() {
+            if let ty::Alias(ty::Projection, projection) = ty.kind() {
                 projection.substs == trait_identity_substs
-                    && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id
+                    && tcx.associated_item(projection.def_id).container_id(tcx) == def_id
             } else {
                 false
             }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 9bd1715ce39..b678990f94e 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -52,7 +52,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
             // Using the ItemCtxt convert the HIR for the unresolved assoc type into a
             // ty which is a fully resolved projection.
             // For the code example above, this would mean converting Self::Assoc<3>
-            // into a ty::Projection(<Self as Foo>::Assoc<3>)
+            // into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>)
             let item_hir_id = tcx
                 .hir()
                 .parent_iter(hir_id)
@@ -68,8 +68,8 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
             // the def_id that this query was called with. We filter to only type and const args here
             // as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
             // but it can't hurt to be safe ^^
-            if let ty::Projection(projection) = ty.kind() {
-                let generics = tcx.generics_of(projection.item_def_id);
+            if let ty::Alias(ty::Projection, projection) = ty.kind() {
+                let generics = tcx.generics_of(projection.def_id);
 
                 let arg_index = segment
                     .args
@@ -666,7 +666,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
 
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let scope = tcx.hir().get_defining_scope(hir_id);
-    let mut locator = ConstraintLocator { def_id: def_id, tcx, found: None, typeck_types: vec![] };
+    let mut locator = ConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
 
     debug!(?scope);
 
@@ -803,7 +803,7 @@ fn find_opaque_ty_constraints_for_rpit(
     if let Some(concrete) = concrete {
         let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
         debug!(?scope);
-        let mut locator = ConstraintChecker { def_id: def_id, tcx, found: concrete };
+        let mut locator = ConstraintChecker { def_id, tcx, found: concrete };
 
         match tcx.hir().get(scope) {
             Node::Item(it) => intravisit::walk_item(&mut locator, it),
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index b4057df7896..95c971c0d78 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -59,7 +59,7 @@ struct ParameterCollector {
 impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match *t.kind() {
-            ty::Projection(..) if !self.include_nonconstraining => {
+            ty::Alias(ty::Projection, ..) if !self.include_nonconstraining => {
                 // projections are not injective
                 return ControlFlow::CONTINUE;
             }
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index c92ab749bc1..d383fcacb3a 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -52,6 +52,17 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
 }
 
 #[derive(Diagnostic)]
+#[diag(hir_analysis_async_trait_impl_should_be_async)]
+pub struct AsyncTraitImplShouldBeAsync {
+    #[primary_span]
+    // #[label]
+    pub span: Span,
+    #[label(trait_item_label)]
+    pub trait_item_span: Option<Span>,
+    pub method_name: Symbol,
+}
+
+#[derive(Diagnostic)]
 #[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
 pub struct DropImplOnWrongItem {
     #[primary_span]
@@ -254,13 +265,6 @@ pub struct ExternCrateNotIdiomatic {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_expected_used_symbol)]
-pub struct ExpectedUsedSymbol {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(hir_analysis_const_impl_for_non_const_trait)]
 pub struct ConstImplForNonConstTrait {
     #[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 90c6edb65e4..af8d7e85158 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -196,13 +196,13 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 }
             }
 
-            ty::Projection(obj) => {
+            ty::Alias(ty::Projection, obj) => {
                 // This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
                 // explicit predicates as well.
                 debug!("Projection");
                 check_explicit_predicates(
                     tcx,
-                    tcx.parent(obj.item_def_id),
+                    tcx.parent(obj.def_id),
                     obj.substs,
                     required_predicates,
                     explicit_map,
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 0409c7081dc..b51b740d08e 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -90,7 +90,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
                         // ```
                         //
                         // Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
-                        let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
+                        let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.def_id, proj_ty.substs);
                         required_predicates
                             .entry(ty::OutlivesPredicate(ty.into(), outlived_region))
                             .or_insert(span);
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 6ce0c18bf45..5e4d82b6fd5 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -249,14 +249,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_substs(current, def.did(), substs, variance);
             }
 
-            ty::Projection(ref data) => {
+            ty::Alias(_, ref data) => {
                 self.add_constraints_from_invariant_substs(current, data.substs, variance);
             }
 
-            ty::Opaque(_, substs) => {
-                self.add_constraints_from_invariant_substs(current, substs, variance);
-            }
-
             ty::Dynamic(data, r, _) => {
                 // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
                 let contra = self.contravariant(variance);
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 8b2719c2f8a..24008f88814 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -111,11 +111,13 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         #[instrument(level = "trace", skip(self), ret)]
         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             match t.kind() {
-                ty::Opaque(def_id, substs) => self.visit_opaque(*def_id, substs),
-                ty::Projection(proj)
-                    if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+                ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                    if matches!(
+                        self.tcx.def_kind(*def_id),
+                        DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
+                    ) =>
                 {
-                    self.visit_opaque(proj.item_def_id, proj.substs)
+                    self.visit_opaque(*def_id, substs)
                 }
                 _ => t.super_visit_with(self),
             }
@@ -158,7 +160,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         // instead of requiring an additional `+ 'a`.
         match pred.kind().skip_binder() {
             ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
-                trait_ref: ty::TraitRef { def_id: _, substs },
+                trait_ref: ty::TraitRef { def_id: _, substs, .. },
                 constness: _,
                 polarity: _,
             })) => {
@@ -167,7 +169,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
                 }
             }
             ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
-                projection_ty: ty::ProjectionTy { substs, item_def_id: _ },
+                projection_ty: ty::AliasTy { substs, .. },
                 term,
             })) => {
                 for subst in &substs[1..] {
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 94bab9f339d..29a6902ccb0 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1245,7 +1245,7 @@ impl<'a> State<'a> {
 
     fn print_literal(&mut self, lit: &hir::Lit) {
         self.maybe_print_comment(lit.span.lo());
-        self.word(lit.node.to_token_lit().to_string())
+        self.word(lit.node.to_string())
     }
 
     fn print_inline_asm(&mut self, asm: &hir::InlineAsm<'_>) {
@@ -1757,7 +1757,6 @@ impl<'a> State<'a> {
                 self.print_qpath(qpath, true);
                 self.popen();
                 if let Some(ddpos) = ddpos.as_opt_usize() {
-                    let ddpos = ddpos as usize;
                     self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
                     if ddpos != 0 {
                         self.word_space(",");
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index e25a9e9036a..ab12cae4e2b 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -212,7 +212,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.can_coerce(arm_ty, ret_ty)
                     && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
                     // The match arms need to unify for the case of `impl Trait`.
-                    && !matches!(ret_ty.kind(), ty::Opaque(..))
+                    && !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
             }
             _ => false,
         };
@@ -518,7 +518,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let substs = sig.output().walk().find_map(|arg| {
                     if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                        && let ty::Opaque(def_id, substs) = *ty.kind()
+                        && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind()
                         && def_id == rpit_def_id
                     {
                         Some(substs)
@@ -542,15 +542,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
                                 assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
                                 ty::PredicateKind::Clause(ty::Clause::Trait(
-                                    trait_pred.with_self_type(self.tcx, ty),
+                                    trait_pred.with_self_ty(self.tcx, ty),
                                 ))
                             }
                             ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => {
                                 assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty);
-                                proj_pred.projection_ty.substs = self.tcx.mk_substs_trait(
-                                    ty,
-                                    proj_pred.projection_ty.substs.iter().skip(1),
-                                );
+                                proj_pred = proj_pred.with_self_ty(self.tcx, ty);
                                 ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred))
                             }
                             _ => continue,
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index b09ddf80e2a..7a5191b77f1 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -521,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 callee_expr,
                 call_expr,
                 callee_ty,
-                pick,
+                &pick,
                 segment,
             );
             if pick.illegal_sized_bound.is_some() {
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 890a068a7be..b050ad20afb 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -38,7 +38,6 @@ use rustc_middle::mir::Mutability;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::cast::{CastKind, CastTy};
 use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef};
 use rustc_session::lint;
 use rustc_session::Session;
@@ -75,10 +74,8 @@ enum PointerKind<'tcx> {
     VTable(Option<DefId>),
     /// Slice
     Length,
-    /// The unsize info of this projection
-    OfProjection(ty::ProjectionTy<'tcx>),
-    /// The unsize info of this opaque ty
-    OfOpaque(DefId, SubstsRef<'tcx>),
+    /// The unsize info of this projection or opaque type
+    OfAlias(ty::AliasTy<'tcx>),
     /// The unsize info of this parameter
     OfParam(ty::ParamTy),
 }
@@ -118,8 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Pointers to foreign types are thin, despite being unsized
             ty::Foreign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
-            ty::Projection(pi) => Some(PointerKind::OfProjection(pi)),
-            ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
+            ty::Alias(_, pi) => Some(PointerKind::OfAlias(pi)),
             ty::Param(p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
             ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None,
@@ -976,11 +972,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
             Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast(Some("a vtable"))),
             Some(PointerKind::Length) => Err(CastError::IntToFatCast(Some("a length"))),
-            Some(
-                PointerKind::OfProjection(_)
-                | PointerKind::OfOpaque(_, _)
-                | PointerKind::OfParam(_),
-            ) => Err(CastError::IntToFatCast(None)),
+            Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
+                Err(CastError::IntToFatCast(None))
+            }
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 429cb60ba2b..5bd02dff73b 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -167,9 +167,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected_ty: Ty<'tcx>,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         match *expected_ty.kind() {
-            ty::Opaque(def_id, substs) => self.deduce_signature_from_predicates(
-                self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
-            ),
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
+                .deduce_signature_from_predicates(
+                    self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
+                ),
             ty::Dynamic(ref object_type, ..) => {
                 let sig = object_type.projection_bounds().find_map(|pb| {
                     let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
@@ -425,7 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // `deduce_expectations_from_expected_type` introduces
         // late-bound lifetimes defined elsewhere, which we now
         // anonymize away, so as not to confuse the user.
-        let bound_sig = self.tcx.anonymize_late_bound_regions(bound_sig);
+        let bound_sig = self.tcx.anonymize_bound_vars(bound_sig);
 
         let closure_sigs = self.closure_sigs(expr_def_id, body, bound_sig);
 
@@ -677,17 +678,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     get_future_output(obligation.predicate, obligation.cause.span)
                 })?
             }
-            ty::Opaque(def_id, substs) => self
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
                 .tcx
                 .bound_explicit_item_bounds(def_id)
                 .subst_iter_copied(self.tcx, substs)
                 .find_map(|(p, s)| get_future_output(p, s))?,
             ty::Error(_) => return None,
-            ty::Projection(proj)
-                if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            ty::Alias(ty::Projection, proj)
+                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
             {
                 self.tcx
-                    .bound_explicit_item_bounds(proj.item_def_id)
+                    .bound_explicit_item_bounds(proj.def_id)
                     .subst_iter_copied(self.tcx, proj.substs)
                     .find_map(|(p, s)| get_future_output(p, s))?
             }
@@ -743,11 +744,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // The `Future` trait has only one associated item, `Output`,
         // so check that this is what we see.
         let output_assoc_item = self.tcx.associated_item_def_ids(future_trait)[0];
-        if output_assoc_item != predicate.projection_ty.item_def_id {
+        if output_assoc_item != predicate.projection_ty.def_id {
             span_bug!(
                 cause_span,
                 "projecting associated item `{:?}` from future, which is not Output `{:?}`",
-                predicate.projection_ty.item_def_id,
+                predicate.projection_ty.def_id,
                 output_assoc_item,
             );
         }
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index f0b349f0c98..36cf4791492 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1805,7 +1805,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         {
             let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
             // Get the `impl Trait`'s `DefId`.
-            if let ty::Opaque(def_id, _) = ty.kind()
+            if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind()
                 // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
                 // get the `Trait`'s `DefId`.
                 && let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index ed87b94a040..866090260b2 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2391,7 +2391,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Param(param_ty) => {
                 self.point_at_param_definition(&mut err, param_ty);
             }
-            ty::Opaque(_, _) => {
+            ty::Alias(ty::Opaque, _) => {
                 self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs());
             }
             _ => {}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 952d2726259..1a4e6bf7638 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -716,7 +716,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if formal_ret.has_infer_types() {
             for ty in ret_ty.walk() {
                 if let ty::subst::GenericArgKind::Type(ty) = ty.unpack()
-                    && let ty::Opaque(def_id, _) = *ty.kind()
+                    && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind()
                     && let Some(def_id) = def_id.as_local()
                     && self.opaque_type_origin(def_id, DUMMY_SP).is_some() {
                     return None;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 60fec05d36d..8e520e563ff 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1169,7 +1169,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         match lit.node {
             ast::LitKind::Str(..) => tcx.mk_static_str(),
-            ast::LitKind::ByteStr(ref v) => {
+            ast::LitKind::ByteStr(ref v, _) => {
                 tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64))
             }
             ast::LitKind::Byte(_) => tcx.types.u8,
@@ -2124,7 +2124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                 }
-                ty::Opaque(new_def_id, _)
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
                 | ty::Closure(new_def_id, _)
                 | ty::FnDef(new_def_id, _) => {
                     def_id = new_def_id;
@@ -2132,19 +2132,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 _ => {
                     // Look for a user-provided impl of a `Fn` trait, and point to it.
                     let new_def_id = self.probe(|_| {
-                        let trait_ref = ty::TraitRef::new(
+                        let trait_ref = self.tcx.mk_trait_ref(
                             call_kind.to_def_id(self.tcx),
-                            self.tcx.mk_substs(
-                                [
-                                    ty::GenericArg::from(callee_ty),
-                                    self.next_ty_var(TypeVariableOrigin {
-                                        kind: TypeVariableOriginKind::MiscVariable,
-                                        span: rustc_span::DUMMY_SP,
-                                    })
-                                    .into(),
-                                ]
-                                .into_iter(),
-                            ),
+                            [
+                                callee_ty,
+                                self.next_ty_var(TypeVariableOrigin {
+                                    kind: TypeVariableOriginKind::MiscVariable,
+                                    span: rustc_span::DUMMY_SP,
+                                }),
+                            ],
                         );
                         let obligation = traits::Obligation::new(
                             self.tcx,
@@ -2217,7 +2213,7 @@ fn find_param_in_ty<'tcx>(ty: Ty<'tcx>, param_to_point_at: ty::GenericArg<'tcx>)
         if arg == param_to_point_at {
             return true;
         } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Projection(..) = ty.kind()
+            && let ty::Alias(ty::Projection, ..) = ty.kind()
         {
             // This logic may seem a bit strange, but typically when
             // we have a projection type in a function signature, the
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 4f92477b5d8..407d6ac8544 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -13,7 +13,9 @@ use rustc_hir_analysis::astconv::AstConv;
 use rustc_infer::infer;
 use rustc_infer::traits::{self, StatementAsExpression};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty};
+use rustc_middle::ty::{
+    self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
+};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -174,10 +176,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let fn_sig = substs.as_closure().sig();
                     Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..])))
                 }
-                ty::Opaque(def_id, substs) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
                         if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                        && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                         // args tuple will always be substs[1]
                         && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
                         {
@@ -194,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::Dynamic(data, _, ty::Dyn) => {
                     data.iter().find_map(|pred| {
                         if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
-                        && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
                         // for existential projection, substs are shifted over by 1
                         && let ty::Tuple(args) = proj.substs.type_at(0).kind()
                         {
@@ -212,7 +214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let def_id = self.tcx.generics_of(self.body_id.owner).type_param(&param, self.tcx).def_id;
                     self.tcx.predicates_of(self.body_id.owner).predicates.iter().find_map(|(pred, _)| {
                         if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                        && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                         && proj.projection_ty.self_ty() == found
                         // args tuple will always be substs[1]
                         && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
@@ -1276,18 +1278,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
             // Check that we're in fact trying to clone into the expected type
             && self.can_coerce(*pointee_ty, expected_ty)
+            && let trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty]))
             // And the expected type doesn't implement `Clone`
-            && !self.predicate_must_hold_considering_regions(&traits::Obligation {
-                cause: traits::ObligationCause::dummy(),
-                param_env: self.param_env,
-                recursion_depth: 0,
-                predicate: ty::Binder::dummy(ty::TraitRef {
-                    def_id: clone_trait_did,
-                    substs: self.tcx.mk_substs([expected_ty.into()].iter()),
-                })
-                .without_const()
-                .to_predicate(self.tcx),
-            })
+            && !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
+                self.tcx,
+                traits::ObligationCause::dummy(),
+                self.param_env,
+                trait_ref,
+            ))
         {
             diag.span_note(
                 callee_expr.span,
@@ -1295,6 +1293,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     "`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead"
                 ),
             );
+            let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id);
+            if let ty::Param(param) = expected_ty.kind()
+                && let Some(generics) = self.tcx.hir().get_generics(owner)
+            {
+                suggest_constraining_type_params(
+                    self.tcx,
+                    generics,
+                    diag,
+                    vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
+                );
+            } else {
+                self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
+            }
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 3b1518ff79b..93f2ceed777 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -563,7 +563,7 @@ fn check_must_not_suspend_ty<'tcx>(
         }
         ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did(), hir_id, data),
         // FIXME: support adding the attribute to TAITs
-        ty::Opaque(def, _) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
             let mut has_emitted = false;
             for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) {
                 // We only look at the `DefId`, so it is safe to skip the binder here.
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 03d0e7926de..218c54688aa 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -45,7 +45,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self_expr: &'tcx hir::Expr<'tcx>,
         call_expr: &'tcx hir::Expr<'tcx>,
         unadjusted_self_ty: Ty<'tcx>,
-        pick: probe::Pick<'tcx>,
+        pick: &probe::Pick<'tcx>,
         segment: &hir::PathSegment<'_>,
     ) -> ConfirmResult<'tcx> {
         debug!(
@@ -71,7 +71,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     fn confirm(
         &mut self,
         unadjusted_self_ty: Ty<'tcx>,
-        pick: probe::Pick<'tcx>,
+        pick: &probe::Pick<'tcx>,
         segment: &hir::PathSegment<'_>,
     ) -> ConfirmResult<'tcx> {
         // Adjust the self expression the user provided and obtain the adjusted type.
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index a2ca5c3b7b7..3f3af53d199 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -192,8 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.tcx.check_stability(pick.item.def_id, Some(call_expr.hir_id), span, None);
 
-        let result =
-            self.confirm_method(span, self_expr, call_expr, self_ty, pick.clone(), segment);
+        let result = self.confirm_method(span, self_expr, call_expr, self_ty, &pick, segment);
         debug!("result = {:?}", result);
 
         if let Some(span) = result.illegal_sized_bound {
@@ -210,7 +209,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ProbeScope::TraitsInScope,
                 ) {
                     Ok(ref new_pick) if pick.differs_from(new_pick) => {
-                        needs_mut = true;
+                        needs_mut = new_pick.self_ty.ref_mutability() != self_ty.ref_mutability();
                     }
                     _ => {}
                 }
@@ -286,7 +285,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.var_for_def(span, param)
         });
 
-        let trait_ref = ty::TraitRef::new(trait_def_id, substs);
+        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
 
         // Construct an obligation
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
@@ -327,7 +326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.var_for_def(span, param)
         });
 
-        let trait_ref = ty::TraitRef::new(trait_def_id, substs);
+        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
 
         // Construct an obligation
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index ae299cc9d13..b9e7830bf07 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -38,9 +38,9 @@ use rustc_trait_selection::traits::query::method_autoderef::{
 use rustc_trait_selection::traits::query::CanonicalTyGoal;
 use rustc_trait_selection::traits::NormalizeExt;
 use rustc_trait_selection::traits::{self, ObligationCause};
+use std::cell::RefCell;
 use std::cmp::max;
 use std::iter;
-use std::mem;
 use std::ops::Deref;
 
 use smallvec::{smallvec, SmallVec};
@@ -62,28 +62,29 @@ struct ProbeContext<'a, 'tcx> {
 
     /// This is the OriginalQueryValues for the steps queries
     /// that are answered in steps.
-    orig_steps_var_values: OriginalQueryValues<'tcx>,
+    orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
     steps: &'tcx [CandidateStep<'tcx>],
 
     inherent_candidates: Vec<Candidate<'tcx>>,
     extension_candidates: Vec<Candidate<'tcx>>,
     impl_dups: FxHashSet<DefId>,
 
-    /// Collects near misses when the candidate functions are missing a `self` keyword and is only
-    /// used for error reporting
-    static_candidates: Vec<CandidateSource>,
-
     /// When probing for names, include names that are close to the
-    /// requested name (by Levensthein distance)
+    /// requested name (by Levenshtein distance)
     allow_similar_names: bool,
 
     /// Some(candidate) if there is a private candidate
     private_candidate: Option<(DefKind, DefId)>,
 
+    /// Collects near misses when the candidate functions are missing a `self` keyword and is only
+    /// used for error reporting
+    static_candidates: RefCell<Vec<CandidateSource>>,
+
     /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
     /// for error reporting
-    unsatisfied_predicates:
+    unsatisfied_predicates: RefCell<
         Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
+    >,
 
     scope_expr_id: hir::HirId,
 }
@@ -334,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         op: OP,
     ) -> Result<R, MethodError<'tcx>>
     where
-        OP: FnOnce(ProbeContext<'a, 'tcx>) -> Result<R, MethodError<'tcx>>,
+        OP: FnOnce(ProbeContext<'_, 'tcx>) -> Result<R, MethodError<'tcx>>,
     {
         let mut orig_values = OriginalQueryValues::default();
         let param_env_and_self_ty = self.canonicalize_query(
@@ -445,7 +446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 mode,
                 method_name,
                 return_type,
-                orig_values,
+                &orig_values,
                 steps.steps,
                 scope_expr_id,
             );
@@ -539,7 +540,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         mode: Mode,
         method_name: Option<Ident>,
         return_type: Option<Ty<'tcx>>,
-        orig_steps_var_values: OriginalQueryValues<'tcx>,
+        orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
         steps: &'tcx [CandidateStep<'tcx>],
         scope_expr_id: hir::HirId,
     ) -> ProbeContext<'a, 'tcx> {
@@ -554,10 +555,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             impl_dups: FxHashSet::default(),
             orig_steps_var_values,
             steps,
-            static_candidates: Vec::new(),
             allow_similar_names: false,
             private_candidate: None,
-            unsatisfied_predicates: Vec::new(),
+            static_candidates: RefCell::new(Vec::new()),
+            unsatisfied_predicates: RefCell::new(Vec::new()),
             scope_expr_id,
         }
     }
@@ -566,8 +567,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         self.inherent_candidates.clear();
         self.extension_candidates.clear();
         self.impl_dups.clear();
-        self.static_candidates.clear();
         self.private_candidate = None;
+        self.static_candidates.borrow_mut().clear();
+        self.unsatisfied_predicates.borrow_mut().clear();
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -918,7 +920,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ) {
         debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
         let trait_substs = self.fresh_item_substs(trait_def_id);
-        let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
+        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, trait_substs);
 
         if self.tcx.is_trait_alias(trait_def_id) {
             // For trait aliases, assume all supertraits are relevant.
@@ -1003,9 +1005,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
         debug!("pick: actual search failed, assemble diagnostics");
 
-        let static_candidates = mem::take(&mut self.static_candidates);
+        let static_candidates = std::mem::take(self.static_candidates.get_mut());
         let private_candidate = self.private_candidate.take();
-        let unsatisfied_predicates = mem::take(&mut self.unsatisfied_predicates);
+        let unsatisfied_predicates = std::mem::take(self.unsatisfied_predicates.get_mut());
 
         // things failed, so lets look at all traits, for diagnostic purposes now:
         self.reset();
@@ -1050,7 +1052,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }))
     }
 
-    fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
+    fn pick_core(&self) -> Option<PickResult<'tcx>> {
         let pick = self.pick_all_method(Some(&mut vec![]));
 
         // In this case unstable picking is done by `pick_method`.
@@ -1065,11 +1067,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     }
 
     fn pick_all_method(
-        &mut self,
+        &self,
         mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
     ) -> Option<PickResult<'tcx>> {
-        let steps = self.steps.clone();
-        steps
+        self.steps
             .iter()
             .filter(|step| {
                 debug!("pick_all_method: step={:?}", step);
@@ -1123,7 +1124,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     /// to transparently pass `&mut` pointers, in particular, without consuming
     /// them for their entire lifetime.
     fn pick_by_value_method(
-        &mut self,
+        &self,
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
         unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
@@ -1151,7 +1152,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     }
 
     fn pick_autorefd_method(
-        &mut self,
+        &self,
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
         mutbl: hir::Mutability,
@@ -1177,7 +1178,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     /// special case for this is because going from `*mut T` to `*const T` with autoderefs and
     /// autorefs would require dereferencing the pointer, which is not safe.
     fn pick_const_ptr_method(
-        &mut self,
+        &self,
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
         unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
@@ -1202,7 +1203,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         })
     }
 
-    fn pick_method_with_unstable(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
+    fn pick_method_with_unstable(&self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
         debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty));
 
         let mut possibly_unsatisfied_predicates = Vec::new();
@@ -1213,7 +1214,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             debug!("searching {} candidates", kind);
             let res = self.consider_candidates(
                 self_ty,
-                candidates.iter(),
+                candidates,
                 &mut possibly_unsatisfied_predicates,
                 Some(&mut vec![]),
             );
@@ -1222,21 +1223,27 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             }
         }
 
-        debug!("searching unstable candidates");
-        let res = self.consider_candidates(
-            self_ty,
-            self.inherent_candidates.iter().chain(&self.extension_candidates),
-            &mut possibly_unsatisfied_predicates,
-            None,
-        );
-        if res.is_none() {
-            self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
+        for (kind, candidates) in
+            &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
+        {
+            debug!("searching unstable {kind} candidates");
+            let res = self.consider_candidates(
+                self_ty,
+                candidates,
+                &mut possibly_unsatisfied_predicates,
+                None,
+            );
+            if res.is_some() {
+                return res;
+            }
         }
-        res
+
+        self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
+        None
     }
 
     fn pick_method(
-        &mut self,
+        &self,
         self_ty: Ty<'tcx>,
         mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
     ) -> Option<PickResult<'tcx>> {
@@ -1254,7 +1261,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             debug!("searching {} candidates", kind);
             let res = self.consider_candidates(
                 self_ty,
-                candidates.iter(),
+                candidates,
                 &mut possibly_unsatisfied_predicates,
                 unstable_candidates.as_deref_mut(),
             );
@@ -1266,28 +1273,24 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         // `pick_method` may be called twice for the same self_ty if no stable methods
         // match. Only extend once.
         if unstable_candidates.is_some() {
-            self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
+            self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
         }
         None
     }
 
-    fn consider_candidates<'b, ProbesIter>(
+    fn consider_candidates(
         &self,
         self_ty: Ty<'tcx>,
-        probes: ProbesIter,
+        candidates: &[Candidate<'tcx>],
         possibly_unsatisfied_predicates: &mut Vec<(
             ty::Predicate<'tcx>,
             Option<ty::Predicate<'tcx>>,
             Option<ObligationCause<'tcx>>,
         )>,
         mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
-    ) -> Option<PickResult<'tcx>>
-    where
-        ProbesIter: Iterator<Item = &'b Candidate<'tcx>> + Clone,
-        'tcx: 'b,
-    {
-        let mut applicable_candidates: Vec<_> = probes
-            .clone()
+    ) -> Option<PickResult<'tcx>> {
+        let mut applicable_candidates: Vec<_> = candidates
+            .iter()
             .map(|probe| {
                 (probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
             })
@@ -1305,11 +1308,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
 
         if let Some(uc) = &mut unstable_candidates {
-            applicable_candidates.retain(|&(p, _)| {
+            applicable_candidates.retain(|&(candidate, _)| {
                 if let stability::EvalResult::Deny { feature, .. } =
-                    self.tcx.eval_stability(p.item.def_id, None, self.span, None)
+                    self.tcx.eval_stability(candidate.item.def_id, None, self.span, None)
                 {
-                    uc.push((p.clone(), feature));
+                    uc.push((candidate.clone(), feature));
                     return false;
                 }
                 true
@@ -1317,7 +1320,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
 
         if applicable_candidates.len() > 1 {
-            let sources = probes.map(|p| self.candidate_source(p, self_ty)).collect();
+            let sources = candidates.iter().map(|p| self.candidate_source(p, self_ty)).collect();
             return Some(Err(MethodError::Ambiguity(sources)));
         }
 
@@ -1701,7 +1704,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 self.mode,
                 self.method_name,
                 self.return_type,
-                self.orig_steps_var_values.clone(),
+                &self.orig_steps_var_values,
                 steps,
                 self.scope_expr_id,
             );
@@ -1763,8 +1766,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         // -- but this could be overcome.
     }
 
-    fn record_static_candidate(&mut self, source: CandidateSource) {
-        self.static_candidates.push(source);
+    fn record_static_candidate(&self, source: CandidateSource) {
+        self.static_candidates.borrow_mut().push(source);
     }
 
     #[instrument(level = "debug", skip(self))]
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index db93cfab2c0..63cec9216eb 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -25,7 +25,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
 use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
-use rustc_middle::ty::print::with_crate_prefix;
+use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
 use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
@@ -270,7 +270,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let tcx = self.tcx;
 
                 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
-                let ty_str = self.ty_to_string(rcvr_ty);
+                let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
                 let is_method = mode == Mode::MethodCall;
                 let item_kind = if is_method {
                     "method"
@@ -557,15 +557,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                         .chain(projection_ty.substs.iter().skip(1)),
                                 );
 
-                                let quiet_projection_ty = ty::ProjectionTy {
-                                    substs: substs_with_infer_self,
-                                    item_def_id: projection_ty.item_def_id,
-                                };
+                                let quiet_projection_ty =
+                                    tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
 
                                 let term = pred.skip_binder().term;
 
                                 let obligation = format!("{} = {}", projection_ty, term);
-                                let quiet = format!("{} = {}", quiet_projection_ty, term);
+                                let quiet = with_forced_trimmed_paths!(format!(
+                                    "{} = {}",
+                                    quiet_projection_ty, term
+                                ));
 
                                 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
                                 Some((obligation, projection_ty.self_ty()))
@@ -575,7 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 let self_ty = p.self_ty();
                                 let path = p.print_only_trait_path();
                                 let obligation = format!("{}: {}", self_ty, path);
-                                let quiet = format!("_: {}", path);
+                                let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
                                 bound_span_label(self_ty, &obligation, &quiet);
                                 Some((obligation, self_ty))
                             }
@@ -798,7 +799,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 (None, None)
                             };
                         let primary_message = primary_message.unwrap_or_else(|| format!(
-                            "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
+                            "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
+                             but its trait bounds were not satisfied"
                         ));
                         err.set_primary_message(&primary_message);
                         if let Some(label) = label {
@@ -895,7 +897,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                         }
                     } else {
-                        err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
+                        let ty_str = if ty_str.len() > 50 {
+                            String::new()
+                        } else {
+                            format!("on `{ty_str}` ")
+                        };
+                        err.span_label(span, format!(
+                            "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"
+                        ));
                     }
                 };
 
@@ -1843,7 +1852,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.suggest_derive(err, &preds);
     }
 
-    fn suggest_derive(
+    pub fn suggest_derive(
         &self,
         err: &mut Diagnostic,
         unsatisfied_predicates: &[(
@@ -1853,7 +1862,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         )],
     ) {
         let mut derives = Vec::<(String, Span, Symbol)>::new();
-        let mut traits = Vec::<Span>::new();
+        let mut traits = Vec::new();
         for (pred, _, _) in unsatisfied_predicates {
             let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
             let adt = match trait_pred.self_ty().ty_adt_def() {
@@ -1892,10 +1901,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     derives.push((self_name, self_span, diagnostic_name));
                 } else {
-                    traits.push(self.tcx.def_span(trait_pred.def_id()));
+                    traits.push(trait_pred.def_id());
                 }
             } else {
-                traits.push(self.tcx.def_span(trait_pred.def_id()));
+                traits.push(trait_pred.def_id());
             }
         }
         traits.sort();
@@ -1918,10 +1927,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let len = traits.len();
         if len > 0 {
-            let span: MultiSpan = traits.into();
+            let span =
+                MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
+            let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
+            for (i, &did) in traits.iter().enumerate().skip(1) {
+                if len > 2 {
+                    names.push_str(", ");
+                }
+                if i == len - 1 {
+                    names.push_str(" and ");
+                }
+                names.push('`');
+                names.push_str(&self.tcx.def_path_str(did));
+                names.push('`');
+            }
             err.span_note(
                 span,
-                &format!("the following trait{} must be implemented", pluralize!(len),),
+                &format!("the trait{} {} must be implemented", pluralize!(len), names),
             );
         }
 
@@ -1969,7 +1991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         | ty::Float(_)
                         | ty::Adt(_, _)
                         | ty::Str
-                        | ty::Projection(_)
+                        | ty::Alias(ty::Projection, _)
                         | ty::Param(_) => format!("{deref_ty}"),
                         // we need to test something like  <&[_]>::len or <(&[u32])>::len
                         // and Vec::function();
@@ -2269,7 +2291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             t.def_id() == info.def_id
                         }
                         ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
-                            p.projection_ty.item_def_id == info.def_id
+                            p.projection_ty.def_id == info.def_id
                         }
                         _ => false,
                     }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index decd317d9fc..6810353f9e7 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -386,7 +386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Byte string patterns behave the same way as array patterns
         // They can denote both statically and dynamically-sized byte arrays.
         let mut pat_ty = ty;
-        if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(_), .. }) = lt.kind {
+        if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind {
             let expected = self.structurally_resolved_type(span, expected);
             if let ty::Ref(_, inner_ty, _) = expected.kind()
                 && matches!(inner_ty.kind(), ty::Slice(_))
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 58ced6a1d3b..bb956ddc780 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -546,7 +546,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             impl<'tcx> ty::TypeVisitor<'tcx> for RecursionChecker {
                 type BreakTy = ();
                 fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-                    if let ty::Opaque(def_id, _) = *t.kind() {
+                    if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *t.kind() {
                         if def_id == self.def_id.to_def_id() {
                             return ControlFlow::Break(());
                         }
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index a8acaf6597a..d1d328128bc 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -30,8 +30,6 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
-use std::iter::FromIterator;
-use std::vec::Vec;
 
 const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk;
 const EXCEPT: Symbol = sym::except;
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 97ebed05855..1fd2b9b0d7b 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -113,7 +113,6 @@ use rustc_span::Symbol;
 
 use std::fs as std_fs;
 use std::io::{self, ErrorKind};
-use std::mem;
 use std::path::{Path, PathBuf};
 use std::time::{Duration, SystemTime, UNIX_EPOCH};
 
@@ -305,7 +304,7 @@ pub fn prepare_session_directory(
             }
 
             delete_session_dir_lock_file(sess, &lock_file_path);
-            mem::drop(directory_lock);
+            drop(directory_lock);
         }
     }
 }
@@ -864,7 +863,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
 
                     // Let's make it explicit that the file lock is released at this point,
                     // or rather, that we held on to it until here
-                    mem::drop(lock);
+                    drop(lock);
                 }
                 Err(_) => {
                     debug!(
@@ -898,7 +897,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
 
         // Let's make it explicit that the file lock is released at this point,
         // or rather, that we held on to it until here
-        mem::drop(lock);
+        drop(lock);
     }
 
     Ok(())
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 777112442f0..686cb6dac49 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -209,7 +209,7 @@ impl<T: Idx> BitSet<T> {
             self.words[start_word_index] |= !(start_mask - 1);
             // And all trailing bits (i.e. from 0..=end) in the end word,
             // including the end.
-            self.words[end_word_index] |= end_mask | end_mask - 1;
+            self.words[end_word_index] |= end_mask | (end_mask - 1);
         } else {
             self.words[start_word_index] |= end_mask | (end_mask - start_mask);
         }
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index 39aa27a23c1..c18a911b2fb 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -4,7 +4,6 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
 use std::fmt::Debug;
 use std::hash::Hash;
-use std::iter::FromIterator;
 use std::marker::PhantomData;
 use std::ops::{Index, IndexMut, RangeBounds};
 use std::slice;
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 74c4c65cc17..c4f11472d55 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -517,6 +517,6 @@ pub struct MismatchedStaticLifetime<'a> {
     pub expl: Option<note_and_explain::RegionExplanation<'a>>,
     #[subdiagnostic]
     pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
-    #[subdiagnostic(eager)]
+    #[subdiagnostic]
     pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
 }
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 4429e4f4362..e9186540a7b 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -411,7 +411,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyTraitRef<'tcx> {
     }
 }
 
-impl<'tcx> ToTrace<'tcx> for ty::ProjectionTy<'tcx> {
+impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
     fn to_trace(
         tcx: TyCtxt<'tcx>,
         cause: &ObligationCause<'tcx>,
@@ -419,8 +419,8 @@ impl<'tcx> ToTrace<'tcx> for ty::ProjectionTy<'tcx> {
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
-        let a_ty = tcx.mk_projection(a.item_def_id, a.substs);
-        let b_ty = tcx.mk_projection(b.item_def_id, b.substs);
+        let a_ty = tcx.mk_projection(a.def_id, a.substs);
+        let b_ty = tcx.mk_projection(b.def_id, b.substs);
         TypeTrace {
             cause: cause.clone(),
             values: Terms(ExpectedFound::new(a_is_expected, a_ty.into(), b_ty.into())),
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 3dc0d60b1eb..ec5221379d2 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -453,10 +453,9 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
             | ty::Dynamic(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Projection(..)
+            | ty::Alias(..)
             | ty::Foreign(..)
-            | ty::Param(..)
-            | ty::Opaque(..) => {
+            | ty::Param(..) => {
                 if t.flags().intersects(self.needs_canonical_flags) {
                     t.super_fold_with(self)
                 } else {
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index cf895ed0d3e..9a1c49c1aa6 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -675,7 +675,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 // relatable.
                 Ok(t)
             }
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 let s = self.relate(substs, substs)?;
                 Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
             }
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 8682f4d3b7a..46e7813d99e 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -100,11 +100,15 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
                 self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
             }
 
-            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => {
                 self.fields.infcx.super_combine_tys(self, a, b)?;
             }
-            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
-                if self.fields.define_opaque_types && did.is_local() =>
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if self.fields.define_opaque_types && def_id.is_local() =>
             {
                 self.fields.obligations.extend(
                     infcx
@@ -178,6 +182,11 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
+        // A binder is equal to itself if it's structually equal to itself
+        if a == b {
+            return Ok(a);
+        }
+
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
             self.fields.higher_ranked_sub(b, a, self.a_is_expected)?;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 987559d7e47..397fa43175f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -339,11 +339,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
 impl<'tcx> InferCtxt<'tcx> {
     pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         let (def_id, substs) = match *ty.kind() {
-            ty::Opaque(def_id, substs) => (def_id, substs),
-            ty::Projection(data)
-                if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                if matches!(
+                    self.tcx.def_kind(def_id),
+                    DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
+                ) =>
             {
-                (data.item_def_id, data.substs)
+                (def_id, substs)
             }
             _ => return None,
         };
@@ -357,7 +359,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     .kind()
                     .map_bound(|kind| match kind {
                         ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate))
-                            if projection_predicate.projection_ty.item_def_id == item_def_id =>
+                            if projection_predicate.projection_ty.def_id == item_def_id =>
                         {
                             projection_predicate.term.ty()
                         }
@@ -1730,7 +1732,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     let extra = expected == found;
                     let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
                         let mut s = match (extra, ty.kind()) {
-                            (true, ty::Opaque(def_id, _)) => {
+                            (true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
                                 let sm = self.tcx.sess.source_map();
                                 let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
                                 format!(
@@ -1740,12 +1742,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                     pos.col.to_usize() + 1,
                                 )
                             }
-                            (true, ty::Projection(proj))
-                                if self.tcx.def_kind(proj.item_def_id)
+                            (true, ty::Alias(ty::Projection, proj))
+                                if self.tcx.def_kind(proj.def_id)
                                     == DefKind::ImplTraitPlaceholder =>
                             {
                                 let sm = self.tcx.sess.source_map();
-                                let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
+                                let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
                                 format!(
                                     " (trait associated opaque type at <{}:{}:{}>)",
                                     sm.filename_for_diagnostics(&pos.file.name),
@@ -2383,7 +2385,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         // fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
                         // suggest:
                         // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-                        ty::Closure(_, _substs) | ty::Opaque(_, _substs) if return_impl_trait => {
+                        ty::Closure(..) | ty::Alias(ty::Opaque, ..) if return_impl_trait => {
                             new_binding_suggestion(&mut err, type_param_span);
                         }
                         _ => {
@@ -2765,7 +2767,7 @@ impl TyCategory {
     pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
         match *ty.kind() {
             ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
-            ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => Some((Self::Opaque, def_id)),
             ty::Generator(def_id, ..) => {
                 Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
             }
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 8ff1639a3a2..a4c36b4c9cd 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
@@ -20,7 +20,7 @@ use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
 use rustc_middle::ty::{self, DefIdTree, InferConst};
 use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span};
 use std::borrow::Cow;
 use std::iter;
@@ -79,7 +79,7 @@ impl InferenceDiagnosticsData {
 
     fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
         if in_type.is_ty_infer() {
-            "empty"
+            ""
         } else if self.name == "_" {
             // FIXME: Consider specializing this message if there is a single `_`
             // in the type.
@@ -183,13 +183,24 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
     printer
 }
 
-fn ty_to_string<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
+fn ty_to_string<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    ty: Ty<'tcx>,
+    called_method_def_id: Option<DefId>,
+) -> String {
     let printer = fmt_printer(infcx, Namespace::TypeNS);
     let ty = infcx.resolve_vars_if_possible(ty);
-    match ty.kind() {
+    match (ty.kind(), called_method_def_id) {
         // We don't want the regular output for `fn`s because it includes its path in
         // invalid pseudo-syntax, we want the `fn`-pointer output instead.
-        ty::FnDef(..) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+        (ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+        (_, Some(def_id))
+            if ty.is_ty_infer()
+                && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
+        {
+            "Vec<_>".to_string()
+        }
+        _ if ty.is_ty_infer() => "/* Type */".to_string(),
         // FIXME: The same thing for closures, but this only works when the closure
         // does not capture anything.
         //
@@ -213,7 +224,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
         .map(|args| {
             args.tuple_fields()
                 .iter()
-                .map(|arg| ty_to_string(infcx, arg))
+                .map(|arg| ty_to_string(infcx, arg, None))
                 .collect::<Vec<_>>()
                 .join(", ")
         })
@@ -221,7 +232,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
     let ret = if fn_sig.output().skip_binder().is_unit() {
         String::new()
     } else {
-        format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder()))
+        format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
     };
     format!("fn({}){}", args, ret)
 }
@@ -368,6 +379,7 @@ impl<'tcx> InferCtxt<'tcx> {
 }
 
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    #[instrument(level = "debug", skip(self, error_code))]
     pub fn emit_inference_failure_err(
         &self,
         body_id: Option<hir::BodyId>,
@@ -406,7 +418,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         let mut infer_subdiags = Vec::new();
         let mut multi_suggestions = Vec::new();
         match kind {
-            InferSourceKind::LetBinding { insert_span, pattern_name, ty } => {
+            InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
                 infer_subdiags.push(SourceKindSubdiag::LetLike {
                     span: insert_span,
                     name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
@@ -415,7 +427,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                     arg_name: arg_data.name,
                     kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
-                    type_name: ty_to_string(self, ty),
+                    type_name: ty_to_string(self, ty, def_id),
                 });
             }
             InferSourceKind::ClosureArg { insert_span, ty } => {
@@ -427,7 +439,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                     arg_name: arg_data.name,
                     kind: "closure",
-                    type_name: ty_to_string(self, ty),
+                    type_name: ty_to_string(self, ty, None),
                 });
             }
             InferSourceKind::GenericArg {
@@ -456,33 +468,39 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     parent_name,
                 });
 
-                let args = fmt_printer(self, Namespace::TypeNS)
-                    .comma_sep(generic_args.iter().copied().map(|arg| {
-                        if arg.is_suggestable(self.tcx, true) {
-                            return arg;
-                        }
+                let args = if self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn)
+                    == Some(generics_def_id)
+                {
+                    "Vec<_>".to_string()
+                } else {
+                    fmt_printer(self, Namespace::TypeNS)
+                        .comma_sep(generic_args.iter().copied().map(|arg| {
+                            if arg.is_suggestable(self.tcx, true) {
+                                return arg;
+                            }
 
-                        match arg.unpack() {
-                            GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
-                            GenericArgKind::Type(_) => self
-                                .next_ty_var(TypeVariableOrigin {
-                                    span: rustc_span::DUMMY_SP,
-                                    kind: TypeVariableOriginKind::MiscVariable,
-                                })
-                                .into(),
-                            GenericArgKind::Const(arg) => self
-                                .next_const_var(
-                                    arg.ty(),
-                                    ConstVariableOrigin {
+                            match arg.unpack() {
+                                GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
+                                GenericArgKind::Type(_) => self
+                                    .next_ty_var(TypeVariableOrigin {
                                         span: rustc_span::DUMMY_SP,
-                                        kind: ConstVariableOriginKind::MiscVariable,
-                                    },
-                                )
-                                .into(),
-                        }
-                    }))
-                    .unwrap()
-                    .into_buffer();
+                                        kind: TypeVariableOriginKind::MiscVariable,
+                                    })
+                                    .into(),
+                                GenericArgKind::Const(arg) => self
+                                    .next_const_var(
+                                        arg.ty(),
+                                        ConstVariableOrigin {
+                                            span: rustc_span::DUMMY_SP,
+                                            kind: ConstVariableOriginKind::MiscVariable,
+                                        },
+                                    )
+                                    .into(),
+                            }
+                        }))
+                        .unwrap()
+                        .into_buffer()
+                };
 
                 if !have_turbofish {
                     infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
@@ -520,7 +538,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ));
             }
             InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
-                let ty_info = ty_to_string(self, ty);
+                let ty_info = ty_to_string(self, ty, None);
                 multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
                     ty_info,
                     data,
@@ -608,6 +626,7 @@ enum InferSourceKind<'tcx> {
         insert_span: Span,
         pattern_name: Option<Ident>,
         ty: Ty<'tcx>,
+        def_id: Option<DefId>,
     },
     ClosureArg {
         insert_span: Span,
@@ -662,7 +681,7 @@ impl<'tcx> InferSourceKind<'tcx> {
                 if ty.is_closure() {
                     ("closure", closure_as_fn_str(infcx, ty))
                 } else if !ty.is_ty_infer() {
-                    ("normal", ty_to_string(infcx, ty))
+                    ("normal", ty_to_string(infcx, ty, None))
                 } else {
                     ("other", String::new())
                 }
@@ -788,10 +807,18 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
     /// Uses `fn source_cost` to determine whether this inference source is preferable to
     /// previous sources. We generally prefer earlier sources.
     #[instrument(level = "debug", skip(self))]
-    fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
+    fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
         let cost = self.source_cost(&new_source) + self.attempt;
         debug!(?cost);
         self.attempt += 1;
+        if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, ..}, .. }) = self.infer_source
+            && let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..} = new_source.kind
+            && ty.is_ty_infer()
+        {
+            // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
+            // `let x: _ = iter.collect();`, as this is a very common case.
+            *def_id = Some(did);
+        }
         if cost < self.infer_source_cost {
             self.infer_source_cost = cost;
             self.infer_source = Some(new_source);
@@ -852,7 +879,10 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
             match inner.unpack() {
                 GenericArgKind::Lifetime(_) => {}
                 GenericArgKind::Type(ty) => {
-                    if matches!(ty.kind(), ty::Opaque(..) | ty::Closure(..) | ty::Generator(..)) {
+                    if matches!(
+                        ty.kind(),
+                        ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::Generator(..)
+                    ) {
                         // Opaque types can't be named by the user right now.
                         //
                         // Both the generic arguments of closures and generators can
@@ -1089,6 +1119,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
                                 insert_span: local.pat.span.shrink_to_hi(),
                                 pattern_name: local.pat.simple_ident(),
                                 ty,
+                                def_id: None,
                             },
                         })
                     }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 1f554c81eff..fed9fda74bf 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -226,13 +226,11 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
             false
         };
 
-        let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef {
-            def_id: trait_def_id,
-            substs: expected_substs,
-        });
-        let actual_trait_ref = self
+        let expected_trait_ref = self
             .cx
-            .resolve_vars_if_possible(ty::TraitRef { def_id: trait_def_id, substs: actual_substs });
+            .resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, expected_substs));
+        let actual_trait_ref =
+            self.cx.resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, actual_substs));
 
         // Search the expected and actual trait references to see (a)
         // whether the sub/sup placeholders appear in them (sometimes
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 09f9aa3c842..9bd2202d260 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
@@ -330,7 +330,7 @@ pub fn suggest_new_region_bound(
                             Applicability::MaybeIncorrect,
                         );
                     }
-                    if let Some((param_span, param_ty)) = param.clone() {
+                    if let Some((param_span, ref param_ty)) = param {
                         err.span_suggestion_verbose(
                             param_span,
                             add_static_bound,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index 73b5a2cc4ad..30ca9f41d6e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -486,12 +486,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
                 StatementAsExpression::CorrectType
             }
-            (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _))
-                if last_def_id == exp_def_id =>
-            {
-                StatementAsExpression::CorrectType
-            }
-            (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => {
+            (
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, .. }),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, .. }),
+            ) if last_def_id == exp_def_id => StatementAsExpression::CorrectType,
+            (
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, substs: last_bounds, .. }),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, substs: exp_bounds, .. }),
+            ) => {
                 debug!(
                     "both opaque, likely future {:?} {:?} {:?} {:?}",
                     last_def_id, last_bounds, exp_def_id, exp_bounds
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index f6946929bd2..8f53b1ccdf4 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -205,12 +205,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
             | ty::Dynamic(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Projection(..)
+            | ty::Alias(..)
             | ty::Foreign(..)
             | ty::Param(..)
             | ty::Closure(..)
-            | ty::GeneratorWitness(..)
-            | ty::Opaque(..) => t.super_fold_with(self),
+            | ty::GeneratorWitness(..) => t.super_fold_with(self),
 
             ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
         }
diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs
index 7f27b35a54e..21b68ce9989 100644
--- a/compiler/rustc_infer/src/infer/glb.rs
+++ b/compiler/rustc_infer/src/infer/glb.rs
@@ -103,6 +103,11 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
+        // GLB of a binder and itself is just itself
+        if a == b {
+            return Ok(a);
+        }
+
         debug!("binders(a={:?}, b={:?})", a, b);
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             // When higher-ranked types are involved, computing the GLB is
diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs
index eba65361ae6..0ebc6d55bcb 100644
--- a/compiler/rustc_infer/src/infer/lattice.rs
+++ b/compiler/rustc_infer/src/infer/lattice.rs
@@ -105,11 +105,13 @@ where
             Ok(v)
         }
 
-        (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
-            infcx.super_combine_tys(this, a, b)
-        }
-        (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
-            if this.define_opaque_types() && did.is_local() =>
+        (
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+        ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
+        (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+        | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+            if this.define_opaque_types() && def_id.is_local() =>
         {
             this.add_obligations(
                 infcx
diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs
index 97ed4729bd0..c07ac1d3ace 100644
--- a/compiler/rustc_infer/src/infer/lub.rs
+++ b/compiler/rustc_infer/src/infer/lub.rs
@@ -103,6 +103,11 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
+        // LUB of a binder and itself is just itself
+        if a == b {
+            return Ok(a);
+        }
+
         debug!("binders(a={:?}, b={:?})", a, b);
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             // When higher-ranked types are involved, computing the LUB is
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 2ce7cd8beba..996148a7090 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -2014,31 +2014,54 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
     tcx: TyCtxt<'tcx>,
     substs: SubstsRef<'tcx>,
 ) -> SubstsRef<'tcx> {
-    tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
-        match arg.unpack() {
-            GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
-                tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+    struct ReplaceParamAndInferWithPlaceholder<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        idx: usize,
+    }
+
+    impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
+        fn tcx(&self) -> TyCtxt<'tcx> {
+            self.tcx
+        }
+
+        fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+            if let ty::Infer(_) = t.kind() {
+                self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::ROOT,
-                    name: ty::BoundVar::from_usize(idx),
+                    name: ty::BoundVar::from_usize({
+                        let idx = self.idx;
+                        self.idx += 1;
+                        idx
+                    }),
                 }))
-                .into()
+            } else {
+                t.super_fold_with(self)
             }
-            GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => {
-                let ty = ct.ty();
-                // If the type references param or infer, replace that too...
+        }
+
+        fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+            if let ty::ConstKind::Infer(_) = c.kind() {
+                let ty = c.ty();
+                // If the type references param or infer then ICE ICE ICE
                 if ty.has_non_region_param() || ty.has_non_region_infer() {
-                    bug!("const `{ct}`'s type should not reference params or types");
+                    bug!("const `{c}`'s type should not reference params or types");
                 }
-                tcx.mk_const(
+                self.tcx.mk_const(
                     ty::PlaceholderConst {
                         universe: ty::UniverseIndex::ROOT,
-                        name: ty::BoundVar::from_usize(idx),
+                        name: ty::BoundVar::from_usize({
+                            let idx = self.idx;
+                            self.idx += 1;
+                            idx
+                        }),
                     },
                     ty,
                 )
-                .into()
+            } else {
+                c.super_fold_with(self)
             }
-            _ => arg,
         }
-    }))
+    }
+
+    substs.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
 }
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index f6bc4db0d59..1f9d86a78d6 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -275,13 +275,13 @@ where
     ///   `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`.
     fn relate_projection_ty(
         &mut self,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        projection_ty: ty::AliasTy<'tcx>,
         value_ty: Ty<'tcx>,
     ) -> Ty<'tcx> {
         use rustc_span::DUMMY_SP;
 
         match *value_ty.kind() {
-            ty::Projection(other_projection_ty) => {
+            ty::Alias(ty::Projection, other_projection_ty) => {
                 let var = self.infcx.next_ty_var(TypeVariableOrigin {
                     kind: TypeVariableOriginKind::MiscVariable,
                     span: DUMMY_SP,
@@ -335,7 +335,9 @@ where
                 return Ok(value_ty);
             }
 
-            ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => {
+            ty::Alias(ty::Projection, projection_ty)
+                if D::normalization() == NormalizationStrategy::Lazy =>
+            {
                 return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
             }
 
@@ -406,8 +408,8 @@ where
             }
         };
         let (a, b) = match (a.kind(), b.kind()) {
-            (&ty::Opaque(..), _) => (a, generalize(b, false)?),
-            (_, &ty::Opaque(..)) => (generalize(a, true)?, b),
+            (&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?),
+            (_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b),
             _ => unreachable!(),
         };
         let cause = ObligationCause::dummy_with_span(self.delegate.span());
@@ -608,26 +610,30 @@ where
 
             (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
 
-            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
-                infcx.super_combine_tys(self, a, b).or_else(|err| {
-                    self.tcx().sess.delay_span_bug(
-                        self.delegate.span(),
-                        "failure to relate an opaque to itself should result in an error later on",
-                    );
-                    if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
-                })
-            }
-            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| {
+                self.tcx().sess.delay_span_bug(
+                    self.delegate.span(),
+                    "failure to relate an opaque to itself should result in an error later on",
+                );
+                if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
+            }),
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if def_id.is_local() =>
+            {
                 self.relate_opaques(a, b)
             }
 
-            (&ty::Projection(projection_ty), _)
+            (&ty::Alias(ty::Projection, projection_ty), _)
                 if D::normalization() == NormalizationStrategy::Lazy =>
             {
                 Ok(self.relate_projection_ty(projection_ty, b))
             }
 
-            (_, &ty::Projection(projection_ty))
+            (_, &ty::Alias(ty::Projection, projection_ty))
                 if D::normalization() == NormalizationStrategy::Lazy =>
             {
                 Ok(self.relate_projection_ty(projection_ty, a))
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 524f7a39ebb..a130fde47ed 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -66,7 +66,9 @@ impl<'tcx> InferCtxt<'tcx> {
             lt_op: |lt| lt,
             ct_op: |ct| ct,
             ty_op: |ty| match *ty.kind() {
-                ty::Opaque(def_id, _substs) if replace_opaque_type(def_id) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })
+                    if replace_opaque_type(def_id) =>
+                {
                     let def_span = self.tcx.def_span(def_id);
                     let span = if span.contains(def_span) { def_span } else { span };
                     let code = traits::ObligationCauseCode::OpaqueReturnType(None);
@@ -104,7 +106,7 @@ impl<'tcx> InferCtxt<'tcx> {
         }
         let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
         let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() {
-            ty::Opaque(def_id, substs) if def_id.is_local() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => {
                 let def_id = def_id.expect_local();
                 let origin = match self.defining_use_anchor {
                     DefiningAnchor::Bind(_) => {
@@ -147,18 +149,19 @@ impl<'tcx> InferCtxt<'tcx> {
                     DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span),
                     DefiningAnchor::Error => return None,
                 };
-                if let ty::Opaque(did2, _) = *b.kind() {
+                if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
                     // We could accept this, but there are various ways to handle this situation, and we don't
                     // want to make a decision on it right now. Likely this case is so super rare anyway, that
                     // no one encounters it in practice.
                     // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
                     // where it is of no concern, so we only check for TAITs.
-                    if let Some(OpaqueTyOrigin::TyAlias) =
-                        did2.as_local().and_then(|did2| self.opaque_type_origin(did2, cause.span))
+                    if let Some(OpaqueTyOrigin::TyAlias) = b_def_id
+                        .as_local()
+                        .and_then(|b_def_id| self.opaque_type_origin(b_def_id, cause.span))
                     {
                         self.tcx.sess.emit_err(OpaqueHiddenTypeDiag {
                             span: cause.span,
-                            hidden_type: self.tcx.def_span(did2),
+                            hidden_type: self.tcx.def_span(b_def_id),
                             opaque_type: self.tcx.def_span(def_id),
                         });
                     }
@@ -475,7 +478,7 @@ where
                 substs.as_generator().resume_ty().visit_with(self);
             }
 
-            ty::Opaque(def_id, ref substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref substs, .. }) => {
                 // Skip lifetime paramters that are not captures.
                 let variances = self.tcx.variances_of(*def_id);
 
@@ -486,11 +489,11 @@ where
                 }
             }
 
-            ty::Projection(proj)
-                if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            ty::Alias(ty::Projection, proj)
+                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
             {
                 // Skip lifetime paramters that are not captures.
-                let variances = self.tcx.variances_of(proj.item_def_id);
+                let variances = self.tcx.variances_of(proj.def_id);
 
                 for (v, s) in std::iter::zip(variances, proj.substs.iter()) {
                     if *v != ty::Variance::Bivariant {
@@ -563,9 +566,9 @@ impl<'tcx> InferCtxt<'tcx> {
                     // We can't normalize associated types from `rustc_infer`,
                     // but we can eagerly register inference variables for them.
                     // FIXME(RPITIT): Don't replace RPITITs with inference vars.
-                    ty::Projection(projection_ty)
+                    ty::Alias(ty::Projection, projection_ty)
                         if !projection_ty.has_escaping_bound_vars()
-                            && tcx.def_kind(projection_ty.item_def_id)
+                            && tcx.def_kind(projection_ty.def_id)
                                 != DefKind::ImplTraitPlaceholder =>
                     {
                         self.infer_projection(
@@ -578,17 +581,16 @@ impl<'tcx> InferCtxt<'tcx> {
                     }
                     // Replace all other mentions of the same opaque type with the hidden type,
                     // as the bounds must hold on the hidden type after all.
-                    ty::Opaque(def_id2, substs2)
+                    ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. })
                         if def_id.to_def_id() == def_id2 && substs == substs2 =>
                     {
                         hidden_ty
                     }
                     // FIXME(RPITIT): This can go away when we move to associated types
-                    ty::Projection(proj)
-                        if def_id.to_def_id() == proj.item_def_id && substs == proj.substs =>
-                    {
-                        hidden_ty
-                    }
+                    ty::Alias(
+                        ty::Projection,
+                        ty::AliasTy { def_id: def_id2, substs: substs2, .. },
+                    ) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty,
                     _ => ty,
                 },
                 lt_op: |lt| lt,
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index 14ee9f05190..aa2b5d067d2 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -23,7 +23,7 @@ pub enum Component<'tcx> {
     // is not in a position to judge which is the best technique, so
     // we just product the projection as a component and leave it to
     // the consumer to decide (but see `EscapingProjection` below).
-    Projection(ty::ProjectionTy<'tcx>),
+    Projection(ty::AliasTy<'tcx>),
 
     // In the case where a projection has escaping regions -- meaning
     // regions bound within the type itself -- we always use
@@ -130,7 +130,7 @@ fn compute_components<'tcx>(
             // outlives any other lifetime, which is unsound.
             // See https://github.com/rust-lang/rust/issues/84305 for
             // more details.
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 out.push(Component::Opaque(def_id, substs));
             },
 
@@ -142,7 +142,7 @@ fn compute_components<'tcx>(
             // trait-ref. Therefore, if we see any higher-ranked regions,
             // we simply fallback to the most restrictive rule, which
             // requires that `Pi: 'a` for all `i`.
-            ty::Projection(ref data) => {
+            ty::Alias(ty::Projection, ref data) => {
                 if !data.has_escaping_bound_vars() {
                     // best case: no escaping regions, so push the
                     // projection and skip the subtree (thus generating no
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 6ca884799aa..ccae7165d80 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -338,7 +338,7 @@ where
             substs,
             true,
             |ty| match *ty.kind() {
-                ty::Opaque(def_id, substs) => (def_id, substs),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
                 _ => bug!("expected only projection types from env, not {:?}", ty),
             },
         );
@@ -349,17 +349,19 @@ where
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
         region: ty::Region<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        projection_ty: ty::AliasTy<'tcx>,
     ) {
         self.generic_must_outlive(
             origin,
             region,
             GenericKind::Projection(projection_ty),
-            projection_ty.item_def_id,
+            projection_ty.def_id,
             projection_ty.substs,
             false,
             |ty| match ty.kind() {
-                ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs),
+                ty::Alias(ty::Projection, projection_ty) => {
+                    (projection_ty.def_id, projection_ty.substs)
+                }
                 _ => bug!("expected only projection types from env, not {:?}", ty),
             },
         );
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index f470b2eb8c1..136da4a3cb1 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -178,7 +178,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
             ),
             Component::Projection(projection_ty) => self.projection_opaque_bounds(
                 GenericKind::Projection(projection_ty),
-                projection_ty.item_def_id,
+                projection_ty.def_id,
                 projection_ty.substs,
                 visited,
             ),
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
index eb6deee291c..4667d99ff00 100644
--- a/compiler/rustc_infer/src/infer/projection.rs
+++ b/compiler/rustc_infer/src/infer/projection.rs
@@ -16,12 +16,12 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn infer_projection(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        projection_ty: ty::AliasTy<'tcx>,
         cause: ObligationCause<'tcx>,
         recursion_depth: usize,
         obligations: &mut Vec<PredicateObligation<'tcx>>,
     ) -> Ty<'tcx> {
-        let def_id = projection_ty.item_def_id;
+        let def_id = projection_ty.def_id;
         let ty_var = self.next_ty_var(TypeVariableOrigin {
             kind: TypeVariableOriginKind::NormalizeProjectionType,
             span: self.tcx.def_span(def_id),
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 985c5d360db..9a427ceacd0 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -169,7 +169,7 @@ pub struct Verify<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
 pub enum GenericKind<'tcx> {
     Param(ty::ParamTy),
-    Projection(ty::ProjectionTy<'tcx>),
+    Projection(ty::AliasTy<'tcx>),
     Opaque(DefId, SubstsRef<'tcx>),
 }
 
@@ -773,7 +773,7 @@ impl<'tcx> GenericKind<'tcx> {
     pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match *self {
             GenericKind::Param(ref p) => p.to_ty(tcx),
-            GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs),
+            GenericKind::Projection(ref p) => tcx.mk_projection(p.def_id, p.substs),
             GenericKind::Opaque(def_id, substs) => tcx.mk_opaque(def_id, substs),
         }
     }
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 2c6987cc3f4..bd38b52ba34 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -130,12 +130,16 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
                 Ok(self.tcx().ty_error_with_guaranteed(e))
             }
 
-            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => {
                 self.fields.infcx.super_combine_tys(self, a, b)?;
                 Ok(a)
             }
-            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
-                if self.fields.define_opaque_types && did.is_local() =>
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if self.fields.define_opaque_types && def_id.is_local() =>
             {
                 self.fields.obligations.extend(
                     infcx
@@ -213,6 +217,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
+        // A binder is always a subtype of itself if it's structually equal to itself
+        if a == b {
+            return Ok(a);
+        }
+
         self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
         Ok(a)
     }
diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs
index 5d22f9f972e..aade57be9fe 100644
--- a/compiler/rustc_infer/src/traits/project.rs
+++ b/compiler/rustc_infer/src/traits/project.rs
@@ -77,11 +77,11 @@ pub struct ProjectionCacheStorage<'tcx> {
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
 pub struct ProjectionCacheKey<'tcx> {
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::AliasTy<'tcx>,
 }
 
 impl<'tcx> ProjectionCacheKey<'tcx> {
-    pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self {
+    pub fn new(ty: ty::AliasTy<'tcx>) -> Self {
         Self { ty }
     }
 }
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 512e6079f43..8f0bd3a9abe 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -259,8 +259,7 @@ impl<'tcx> Elaborator<'tcx> {
                             Component::Projection(projection) => {
                                 // We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
                                 // With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
-                                let ty =
-                                    tcx.mk_projection(projection.item_def_id, projection.substs);
+                                let ty = tcx.mk_projection(projection.def_id, projection.substs);
                                 Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
                                     ty::OutlivesPredicate(ty, r_min),
                                 )))
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 2b8f6557c82..e903cb86dd2 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -25,7 +25,6 @@ use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrate
 use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
 
 use std::collections::{BTreeMap, BTreeSet};
-use std::iter::FromIterator;
 use std::num::NonZeroUsize;
 use std::path::{Path, PathBuf};
 
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 3fbabbc6344..50d6d5b9bab 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -34,7 +34,6 @@ pub use crate::cursor::Cursor;
 use self::LiteralKind::*;
 use self::TokenKind::*;
 use crate::cursor::EOF_CHAR;
-use std::convert::TryFrom;
 
 /// Parsed token.
 /// It doesn't contain information about data that has been parsed,
diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs
index e405013dcab..87c44638a8d 100644
--- a/compiler/rustc_lexer/src/unescape.rs
+++ b/compiler/rustc_lexer/src/unescape.rs
@@ -204,14 +204,13 @@ fn scan_escape(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError
                         })?;
                     }
                     Some(c) => {
-                        let digit =
+                        let digit: u32 =
                             c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?;
                         n_digits += 1;
                         if n_digits > 6 {
                             // Stop updating value since we're sure that it's incorrect already.
                             continue;
                         }
-                        let digit = digit as u32;
                         value = value * 16 + digit;
                     }
                 };
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 0932eee9237..43862570e80 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -3016,8 +3016,8 @@ impl ClashingExternDeclarations {
                         | (Closure(..), Closure(..))
                         | (Generator(..), Generator(..))
                         | (GeneratorWitness(..), GeneratorWitness(..))
-                        | (Projection(..), Projection(..))
-                        | (Opaque(..), Opaque(..)) => false,
+                        | (Alias(ty::Projection, ..), Alias(ty::Projection, ..))
+                        | (Alias(ty::Opaque, ..), Alias(ty::Opaque, ..)) => false,
 
                         // These definitely should have been caught above.
                         (Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index e6a0d7e60ca..40b2588388d 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -1258,7 +1258,7 @@ impl<'tcx> LateContext<'tcx> {
         tcx.associated_items(trait_id)
             .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
             .and_then(|assoc| {
-                let proj = tcx.mk_projection(assoc.def_id, tcx.mk_substs_trait(self_ty, []));
+                let proj = tcx.mk_projection(assoc.def_id, [self_ty]);
                 tcx.try_normalize_erasing_regions(self.param_env, proj).ok()
             })
     }
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 5d81370c35a..5f84d5c8b94 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -20,23 +20,23 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::{self as ast_visit, Visitor};
 use rustc_ast::{self as ast, walk_list, HasAttrs};
 use rustc_middle::ty::RegisteredTools;
-use rustc_session::lint::{BufferedEarlyLint, LintBuffer};
+use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
-macro_rules! run_early_passes { ($cx:expr, $f:ident, $($args:expr),*) => ({
-    for pass in $cx.passes.iter_mut() {
-        pass.$f(&$cx.context, $($args),*);
-    }
+macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
+    $cx.pass.$f(&$cx.context, $($args),*);
 }) }
 
-pub struct EarlyContextAndPasses<'a> {
+/// Implements the AST traversal for early lint passes. `T` provides the the
+/// `check_*` methods.
+pub struct EarlyContextAndPass<'a, T: EarlyLintPass> {
     context: EarlyContext<'a>,
-    passes: Vec<EarlyLintPassObject>,
+    pass: T,
 }
 
-impl<'a> EarlyContextAndPasses<'a> {
+impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
     // This always-inlined function is for the hot call site.
     #[inline(always)]
     fn inlined_check_id(&mut self, id: ast::NodeId) {
@@ -70,27 +70,27 @@ impl<'a> EarlyContextAndPasses<'a> {
 
         self.inlined_check_id(id);
         debug!("early context: enter_attrs({:?})", attrs);
-        run_early_passes!(self, enter_lint_attrs, attrs);
+        lint_callback!(self, enter_lint_attrs, attrs);
         f(self);
         debug!("early context: exit_attrs({:?})", attrs);
-        run_early_passes!(self, exit_lint_attrs, attrs);
+        lint_callback!(self, exit_lint_attrs, attrs);
         self.context.builder.pop(push);
     }
 }
 
-impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
+impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
     fn visit_param(&mut self, param: &'a ast::Param) {
         self.with_lint_attrs(param.id, &param.attrs, |cx| {
-            run_early_passes!(cx, check_param, param);
+            lint_callback!(cx, check_param, param);
             ast_visit::walk_param(cx, param);
         });
     }
 
     fn visit_item(&mut self, it: &'a ast::Item) {
         self.with_lint_attrs(it.id, &it.attrs, |cx| {
-            run_early_passes!(cx, check_item, it);
+            lint_callback!(cx, check_item, it);
             ast_visit::walk_item(cx, it);
-            run_early_passes!(cx, check_item_post, it);
+            lint_callback!(cx, check_item_post, it);
         })
     }
 
@@ -101,10 +101,10 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
     }
 
     fn visit_pat(&mut self, p: &'a ast::Pat) {
-        run_early_passes!(self, check_pat, p);
+        lint_callback!(self, check_pat, p);
         self.check_id(p.id);
         ast_visit::walk_pat(self, p);
-        run_early_passes!(self, check_pat_post, p);
+        lint_callback!(self, check_pat_post, p);
     }
 
     fn visit_pat_field(&mut self, field: &'a ast::PatField) {
@@ -120,7 +120,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
 
     fn visit_expr(&mut self, e: &'a ast::Expr) {
         self.with_lint_attrs(e.id, &e.attrs, |cx| {
-            run_early_passes!(cx, check_expr, e);
+            lint_callback!(cx, check_expr, e);
             ast_visit::walk_expr(cx, e);
         })
     }
@@ -141,7 +141,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
         // Note that statements get their attributes from
         // the AST struct that they wrap (e.g. an item)
         self.with_lint_attrs(s.id, s.attrs(), |cx| {
-            run_early_passes!(cx, check_stmt, s);
+            lint_callback!(cx, check_stmt, s);
             cx.check_id(s.id);
         });
         // The visitor for the AST struct wrapped
@@ -152,7 +152,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
     }
 
     fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) {
-        run_early_passes!(self, check_fn, fk, span, id);
+        lint_callback!(self, check_fn, fk, span, id);
         self.check_id(id);
         ast_visit::walk_fn(self, fk);
 
@@ -180,37 +180,37 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
 
     fn visit_variant(&mut self, v: &'a ast::Variant) {
         self.with_lint_attrs(v.id, &v.attrs, |cx| {
-            run_early_passes!(cx, check_variant, v);
+            lint_callback!(cx, check_variant, v);
             ast_visit::walk_variant(cx, v);
         })
     }
 
     fn visit_ty(&mut self, t: &'a ast::Ty) {
-        run_early_passes!(self, check_ty, t);
+        lint_callback!(self, check_ty, t);
         self.check_id(t.id);
         ast_visit::walk_ty(self, t);
     }
 
     fn visit_ident(&mut self, ident: Ident) {
-        run_early_passes!(self, check_ident, ident);
+        lint_callback!(self, check_ident, ident);
     }
 
     fn visit_local(&mut self, l: &'a ast::Local) {
         self.with_lint_attrs(l.id, &l.attrs, |cx| {
-            run_early_passes!(cx, check_local, l);
+            lint_callback!(cx, check_local, l);
             ast_visit::walk_local(cx, l);
         })
     }
 
     fn visit_block(&mut self, b: &'a ast::Block) {
-        run_early_passes!(self, check_block, b);
+        lint_callback!(self, check_block, b);
         self.check_id(b.id);
         ast_visit::walk_block(self, b);
     }
 
     fn visit_arm(&mut self, a: &'a ast::Arm) {
         self.with_lint_attrs(a.id, &a.attrs, |cx| {
-            run_early_passes!(cx, check_arm, a);
+            lint_callback!(cx, check_arm, a);
             ast_visit::walk_arm(cx, a);
         })
     }
@@ -229,19 +229,19 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
     }
 
     fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) {
-        run_early_passes!(self, check_generic_arg, arg);
+        lint_callback!(self, check_generic_arg, arg);
         ast_visit::walk_generic_arg(self, arg);
     }
 
     fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
         self.with_lint_attrs(param.id, &param.attrs, |cx| {
-            run_early_passes!(cx, check_generic_param, param);
+            lint_callback!(cx, check_generic_param, param);
             ast_visit::walk_generic_param(cx, param);
         });
     }
 
     fn visit_generics(&mut self, g: &'a ast::Generics) {
-        run_early_passes!(self, check_generics, g);
+        lint_callback!(self, check_generics, g);
         ast_visit::walk_generics(self, g);
     }
 
@@ -250,18 +250,18 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
     }
 
     fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
-        run_early_passes!(self, check_poly_trait_ref, t);
+        lint_callback!(self, check_poly_trait_ref, t);
         ast_visit::walk_poly_trait_ref(self, t);
     }
 
     fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
         self.with_lint_attrs(item.id, &item.attrs, |cx| match ctxt {
             ast_visit::AssocCtxt::Trait => {
-                run_early_passes!(cx, check_trait_item, item);
+                lint_callback!(cx, check_trait_item, item);
                 ast_visit::walk_assoc_item(cx, item, ctxt);
             }
             ast_visit::AssocCtxt::Impl => {
-                run_early_passes!(cx, check_impl_item, item);
+                lint_callback!(cx, check_impl_item, item);
                 ast_visit::walk_assoc_item(cx, item, ctxt);
             }
         });
@@ -282,20 +282,49 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
     }
 
     fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
-        run_early_passes!(self, check_attribute, attr);
+        lint_callback!(self, check_attribute, attr);
     }
 
     fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) {
-        run_early_passes!(self, check_mac_def, mac);
+        lint_callback!(self, check_mac_def, mac);
         self.check_id(id);
     }
 
     fn visit_mac_call(&mut self, mac: &'a ast::MacCall) {
-        run_early_passes!(self, check_mac, mac);
+        lint_callback!(self, check_mac, mac);
         ast_visit::walk_mac(self, mac);
     }
 }
 
+// Combines multiple lint passes into a single pass, at runtime. Each
+// `check_foo` method in `$methods` within this pass simply calls `check_foo`
+// once per `$pass`. Compare with `declare_combined_early_lint_pass`, which is
+// similar, but combines lint passes at compile time.
+struct RuntimeCombinedEarlyLintPass<'a> {
+    passes: &'a mut [EarlyLintPassObject],
+}
+
+#[allow(rustc::lint_pass_impl_without_macro)]
+impl LintPass for RuntimeCombinedEarlyLintPass<'_> {
+    fn name(&self) -> &'static str {
+        panic!()
+    }
+}
+
+macro_rules! impl_early_lint_pass {
+    ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => (
+        impl EarlyLintPass for RuntimeCombinedEarlyLintPass<'_> {
+            $(fn $f(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
+                for pass in self.passes.iter_mut() {
+                    pass.$f(context, $($param),*);
+                }
+            })*
+        }
+    )
+}
+
+crate::early_lint_methods!(impl_early_lint_pass, []);
+
 /// Early lints work on different nodes - either on the crate root, or on freshly loaded modules.
 /// This trait generalizes over those nodes.
 pub trait EarlyCheckNode<'a>: Copy {
@@ -303,7 +332,7 @@ pub trait EarlyCheckNode<'a>: Copy {
     fn attrs<'b>(self) -> &'b [ast::Attribute]
     where
         'a: 'b;
-    fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
+    fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
     where
         'a: 'b;
 }
@@ -318,13 +347,13 @@ impl<'a> EarlyCheckNode<'a> for &'a ast::Crate {
     {
         &self.attrs
     }
-    fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
+    fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
     where
         'a: 'b,
     {
-        run_early_passes!(cx, check_crate, self);
+        lint_callback!(cx, check_crate, self);
         ast_visit::walk_crate(cx, self);
-        run_early_passes!(cx, check_crate_post, self);
+        lint_callback!(cx, check_crate_post, self);
     }
 }
 
@@ -338,7 +367,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
     {
         self.1
     }
-    fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
+    fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
     where
         'a: 'b,
     {
@@ -356,21 +385,37 @@ pub fn check_ast_node<'a>(
     builtin_lints: impl EarlyLintPass + 'static,
     check_node: impl EarlyCheckNode<'a>,
 ) {
+    let context = EarlyContext::new(
+        sess,
+        !pre_expansion,
+        lint_store,
+        registered_tools,
+        lint_buffer.unwrap_or_default(),
+    );
+
+    // Note: `passes` is often empty. In that case, it's faster to run
+    // `builtin_lints` directly rather than bundling it up into the
+    // `RuntimeCombinedEarlyLintPass`.
     let passes =
         if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes };
-    let mut passes: Vec<EarlyLintPassObject> = passes.iter().map(|p| (p)()).collect();
-    passes.push(Box::new(builtin_lints));
-
-    let mut cx = EarlyContextAndPasses {
-        context: EarlyContext::new(
-            sess,
-            !pre_expansion,
-            lint_store,
-            registered_tools,
-            lint_buffer.unwrap_or_default(),
-        ),
-        passes,
-    };
+    if passes.is_empty() {
+        check_ast_node_inner(sess, check_node, context, builtin_lints);
+    } else {
+        let mut passes: Vec<_> = passes.iter().map(|mk_pass| (mk_pass)()).collect();
+        passes.push(Box::new(builtin_lints));
+        let pass = RuntimeCombinedEarlyLintPass { passes: &mut passes[..] };
+        check_ast_node_inner(sess, check_node, context, pass);
+    }
+}
+
+pub fn check_ast_node_inner<'a, T: EarlyLintPass>(
+    sess: &Session,
+    check_node: impl EarlyCheckNode<'a>,
+    context: EarlyContext<'_>,
+    pass: T,
+) {
+    let mut cx = EarlyContextAndPass { context, pass };
+
     cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
 
     // All of the buffered lints should have been emitted at this point.
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 8a50cb1f19e..e2876938d70 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -23,6 +23,7 @@ use rustc_hir::intravisit as hir_visit;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_session::lint::LintPass;
 use rustc_span::Span;
 
 use std::any::Any;
@@ -36,17 +37,17 @@ pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore {
 }
 
 macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
-    for pass in $cx.passes.iter_mut() {
-        pass.$f(&$cx.context, $($args),*);
-    }
+    $cx.pass.$f(&$cx.context, $($args),*);
 }) }
 
-struct LateContextAndPasses<'tcx> {
+/// Implements the AST traversal for late lint passes. `T` provides the the
+/// `check_*` methods.
+pub struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> {
     context: LateContext<'tcx>,
-    passes: Vec<LateLintPassObject<'tcx>>,
+    pass: T,
 }
 
-impl<'tcx> LateContextAndPasses<'tcx> {
+impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
     /// Merge the lints specified by any lint attributes into the
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
@@ -82,7 +83,7 @@ impl<'tcx> LateContextAndPasses<'tcx> {
     }
 }
 
-impl<'tcx> hir_visit::Visitor<'tcx> for LateContextAndPasses<'tcx> {
+impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPass<'tcx, T> {
     type NestedFilter = nested_filter::All;
 
     /// Because lints are scoped lexically, we want to walk nested
@@ -302,6 +303,35 @@ impl<'tcx> hir_visit::Visitor<'tcx> for LateContextAndPasses<'tcx> {
     }
 }
 
+// Combines multiple lint passes into a single pass, at runtime. Each
+// `check_foo` method in `$methods` within this pass simply calls `check_foo`
+// once per `$pass`. Compare with `declare_combined_late_lint_pass`, which is
+// similar, but combines lint passes at compile time.
+struct RuntimeCombinedLateLintPass<'a, 'tcx> {
+    passes: &'a mut [LateLintPassObject<'tcx>],
+}
+
+#[allow(rustc::lint_pass_impl_without_macro)]
+impl LintPass for RuntimeCombinedLateLintPass<'_, '_> {
+    fn name(&self) -> &'static str {
+        panic!()
+    }
+}
+
+macro_rules! impl_late_lint_pass {
+    ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => {
+        impl<'tcx> LateLintPass<'tcx> for RuntimeCombinedLateLintPass<'_, 'tcx> {
+            $(fn $f(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) {
+                for pass in self.passes.iter_mut() {
+                    pass.$f(context, $($param),*);
+                }
+            })*
+        }
+    };
+}
+
+crate::late_lint_methods!(impl_late_lint_pass, []);
+
 pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
     tcx: TyCtxt<'tcx>,
     module_def_id: LocalDefId,
@@ -319,11 +349,27 @@ pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
         only_module: true,
     };
 
+    // Note: `passes` is often empty. In that case, it's faster to run
+    // `builtin_lints` directly rather than bundling it up into the
+    // `RuntimeCombinedLateLintPass`.
     let mut passes: Vec<_> =
-        unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
-    passes.push(Box::new(builtin_lints));
+        unerased_lint_store(tcx).late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
+    if passes.is_empty() {
+        late_lint_mod_inner(tcx, module_def_id, context, builtin_lints);
+    } else {
+        passes.push(Box::new(builtin_lints));
+        let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
+        late_lint_mod_inner(tcx, module_def_id, context, pass);
+    }
+}
 
-    let mut cx = LateContextAndPasses { context, passes };
+fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
+    tcx: TyCtxt<'tcx>,
+    module_def_id: LocalDefId,
+    context: LateContext<'tcx>,
+    pass: T,
+) {
+    let mut cx = LateContextAndPass { context, pass };
 
     let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
     cx.process_mod(module, hir_id);
@@ -349,11 +395,26 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builti
         only_module: false,
     };
 
-    let mut passes =
-        unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>();
-    passes.push(Box::new(builtin_lints));
+    // Note: `passes` is often empty. In that case, it's faster to run
+    // `builtin_lints` directly rather than bundling it up into the
+    // `RuntimeCombinedLateLintPass`.
+    let mut passes: Vec<_> =
+        unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
+    if passes.is_empty() {
+        late_lint_crate_inner(tcx, context, builtin_lints);
+    } else {
+        passes.push(Box::new(builtin_lints));
+        let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
+        late_lint_crate_inner(tcx, context, pass);
+    }
+}
 
-    let mut cx = LateContextAndPasses { context, passes };
+fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
+    tcx: TyCtxt<'tcx>,
+    context: LateContext<'tcx>,
+    pass: T,
+) {
+    let mut cx = LateContextAndPass { context, pass };
 
     // Visit the whole crate.
     cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| {
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 1990a74841b..11022eb80ea 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -127,7 +127,6 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     late::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
 }
 
-// See the comment on `BuiltinCombinedEarlyLintPass`, which is similar.
 early_lint_methods!(
     declare_combined_early_lint_pass,
     [
@@ -138,9 +137,6 @@ early_lint_methods!(
     ]
 );
 
-// Declare `BuiltinCombinedEarlyLintPass`, a lint pass that combines multiple
-// lint passes into a single pass for maximum speed. Each `check_foo` method
-// within this pass simply calls `check_foo` once per listed lint.
 early_lint_methods!(
     declare_combined_early_lint_pass,
     [
@@ -168,7 +164,6 @@ early_lint_methods!(
 
 // FIXME: Make a separate lint type which does not require typeck tables.
 
-// See the comment on `BuiltinCombinedEarlyLintPass`, which is similar.
 late_lint_methods!(
     declare_combined_late_lint_pass,
     [
@@ -188,7 +183,6 @@ late_lint_methods!(
     ]
 );
 
-// See the comment on `BuiltinCombinedEarlyLintPass`, which is similar.
 late_lint_methods!(
     declare_combined_late_lint_pass,
     [
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 03d6f4fd926..42442cfb190 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
             let Some(proj_term) = proj.term.ty() else { continue };
 
             let proj_ty =
-                cx.tcx.mk_projection(proj.projection_ty.item_def_id, proj.projection_ty.substs);
+                cx.tcx.mk_projection(proj.projection_ty.def_id, proj.projection_ty.substs);
             // For every instance of the projection type in the bounds,
             // replace them with the term we're assigning to the associated
             // type in our opaque type.
@@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
             // with `impl Send: OtherTrait`.
             for (assoc_pred, assoc_pred_span) in cx
                 .tcx
-                .bound_explicit_item_bounds(proj.projection_ty.item_def_id)
+                .bound_explicit_item_bounds(proj.projection_ty.def_id)
                 .subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
             {
                 let assoc_pred = assoc_pred.fold_with(proj_replacer);
@@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                     // then we can emit a suggestion to add the bound.
                     let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
                         (
-                            ty::Opaque(def_id, _),
+                            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
                             ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)),
                         ) => Some(AddBound {
                             suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(),
diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs
index 00922cef384..5558156a4b9 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -95,6 +95,11 @@ macro_rules! expand_combined_late_lint_pass_methods {
     )
 }
 
+/// Combines multiple lints passes into a single lint pass, at compile time,
+/// for maximum speed. Each `check_foo` method in `$methods` within this pass
+/// simply calls `check_foo` once per `$pass`. Compare with
+/// `LateLintPassObjects`, which is similar, but combines lint passes at
+/// runtime.
 #[macro_export]
 macro_rules! declare_combined_late_lint_pass {
     ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
@@ -198,6 +203,11 @@ macro_rules! expand_combined_early_lint_pass_methods {
     )
 }
 
+/// Combines multiple lints passes into a single lint pass, at compile time,
+/// for maximum speed. Each `check_foo` method in `$methods` within this pass
+/// simply calls `check_foo` once per `$pass`. Compare with
+/// `EarlyLintPassObjects`, which is similar, but combines lint passes at
+/// runtime.
 #[macro_export]
 macro_rules! declare_combined_early_lint_pass {
     ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 297b509d402..8e27bc03c48 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -16,7 +16,6 @@ use rustc_target::abi::{Abi, Size, WrappingRange};
 use rustc_target::abi::{Integer, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
 
-use std::cmp;
 use std::iter;
 use std::ops::ControlFlow;
 
@@ -531,7 +530,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
             _ => {}
         };
 
-        fn is_valid<T: cmp::PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool {
+        fn is_valid<T: PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool {
             match binop.node {
                 hir::BinOpKind::Lt => v > min && v <= max,
                 hir::BinOpKind::Le => v >= min && v < max,
@@ -1140,18 +1139,20 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
             // While opaque types are checked for earlier, if a projection in a struct field
             // normalizes to an opaque type, then it will reach this branch.
-            ty::Opaque(..) => {
+            ty::Alias(ty::Opaque, ..) => {
                 FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_opaque, help: None }
             }
 
             // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
             //  so they are currently ignored for the purposes of this lint.
-            ty::Param(..) | ty::Projection(..) if matches!(self.mode, CItemKind::Definition) => {
+            ty::Param(..) | ty::Alias(ty::Projection, ..)
+                if matches!(self.mode, CItemKind::Definition) =>
+            {
                 FfiSafe
             }
 
             ty::Param(..)
-            | ty::Projection(..)
+            | ty::Alias(ty::Projection, ..)
             | ty::Infer(..)
             | ty::Bound(..)
             | ty::Error(_)
@@ -1206,7 +1207,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                     return ControlFlow::CONTINUE;
                 }
 
-                if let ty::Opaque(..) = ty.kind() {
+                if let ty::Alias(ty::Opaque, ..) = ty.kind() {
                     ControlFlow::Break(ty)
                 } else {
                     ty.super_visit_with(self)
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index dc352778f1d..d628a18dd01 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
 
         if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
             && let ty = cx.typeck_results().expr_ty(&await_expr)
-            && let ty::Opaque(future_def_id, _) = ty.kind()
+            && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
             && cx.tcx.ty_is_opaque_future(ty)
             // FIXME: This also includes non-async fns that return `impl Future`.
             && let async_fn_def_id = cx.tcx.parent(*future_def_id)
@@ -251,7 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                         .map(|inner| MustUsePath::Boxed(Box::new(inner)))
                 }
                 ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
-                ty::Opaque(def, _) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
                     elaborate_predicates_with_span(
                         cx.tcx,
                         cx.tcx.explicit_item_bounds(def).iter().cloned(),
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index df0e17dea3c..33cb35e60eb 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -911,8 +911,7 @@ declare_lint! {
 
 declare_lint! {
     /// The `trivial_casts` lint detects trivial casts which could be replaced
-    /// with coercion, which may require [type ascription] or a temporary
-    /// variable.
+    /// with coercion, which may require a temporary variable.
     ///
     /// ### Example
     ///
@@ -934,12 +933,14 @@ declare_lint! {
     /// with FFI interfaces or complex type aliases, where it triggers
     /// incorrectly, or in situations where it will be more difficult to
     /// clearly express the intent. It may be possible that this will become a
-    /// warning in the future, possibly with [type ascription] providing a
-    /// convenient way to work around the current issues. See [RFC 401] for
-    /// historical context.
-    ///
-    /// [type ascription]: https://github.com/rust-lang/rust/issues/23416
-    /// [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// warning in the future, possibly with an explicit syntax for coercions
+    /// providing a convenient way to work around the current issues.
+    /// See [RFC 401 (coercions)][rfc-401], [RFC 803 (type ascription)][rfc-803] and
+    /// [RFC 3307 (remove type ascription)][rfc-3307] for historical context.
+    ///
+    /// [rfc-401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// [rfc-803]: https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md
+    /// [rfc-3307]: https://github.com/rust-lang/rfcs/blob/master/text/3307-de-rfc-type-ascription.md
     pub TRIVIAL_CASTS,
     Allow,
     "detects trivial casts which could be removed"
@@ -967,12 +968,14 @@ declare_lint! {
     /// with FFI interfaces or complex type aliases, where it triggers
     /// incorrectly, or in situations where it will be more difficult to
     /// clearly express the intent. It may be possible that this will become a
-    /// warning in the future, possibly with [type ascription] providing a
-    /// convenient way to work around the current issues. See [RFC 401] for
-    /// historical context.
-    ///
-    /// [type ascription]: https://github.com/rust-lang/rust/issues/23416
-    /// [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// warning in the future, possibly with an explicit syntax for coercions
+    /// providing a convenient way to work around the current issues.
+    /// See [RFC 401 (coercions)][rfc-401], [RFC 803 (type ascription)][rfc-803] and
+    /// [RFC 3307 (remove type ascription)][rfc-3307] for historical context.
+    ///
+    /// [rfc-401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// [rfc-803]: https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md
+    /// [rfc-3307]: https://github.com/rust-lang/rfcs/blob/master/text/3307-de-rfc-type-ascription.md
     pub TRIVIAL_NUMERIC_CASTS,
     Allow,
     "detects trivial casts of numeric types which could be removed"
@@ -1017,6 +1020,44 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `invalid_alignment` lint detects dereferences of misaligned pointers during
+    /// constant evluation.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![feature(const_ptr_read)]
+    /// const FOO: () = unsafe {
+    ///     let x = &[0_u8; 4];
+    ///     let y = x.as_ptr().cast::<u32>();
+    ///     y.read(); // the address of a `u8` array is unknown and thus we don't know if
+    ///     // it is aligned enough for reading a `u32`.
+    /// };
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The compiler allowed dereferencing raw pointers irrespective of alignment
+    /// during const eval due to the const evaluator at the time not making it easy
+    /// or cheap to check. Now that it is both, this is not accepted anymore.
+    ///
+    /// Since it was undefined behaviour to begin with, this breakage does not violate
+    /// Rust's stability guarantees. Using undefined behaviour can cause arbitrary
+    /// behaviour, including failure to build.
+    ///
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub INVALID_ALIGNMENT,
+    Deny,
+    "raw pointers must be aligned before dereferencing",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #68585 <https://github.com/rust-lang/rust/issues/104616>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
+    };
+}
+
+declare_lint! {
     /// The `exported_private_dependencies` lint detects private dependencies
     /// that are exposed in a public interface.
     ///
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 1a3d458c300..2865ea89273 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -223,7 +223,11 @@ fromRust(LLVMRustCodeModel Model) {
   case LLVMRustCodeModel::Large:
     return CodeModel::Large;
   case LLVMRustCodeModel::None:
+#if LLVM_VERSION_LT(16, 0)
     return None;
+#else
+    return std::nullopt;
+#endif
   default:
     report_fatal_error("Bad CodeModel.");
   }
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 5831d4693f1..279b6991854 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -322,7 +322,13 @@ extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Asy
 }
 
 extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) {
-  return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, None));
+  return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg,
+#if LLVM_VERSION_LT(16, 0)
+                                              None
+#else
+                                              std::nullopt
+#endif
+                                              ));
 }
 
 #if LLVM_VERSION_GE(15, 0)
@@ -717,7 +723,11 @@ static std::optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
 #endif
   switch (Kind) {
   case LLVMRustChecksumKind::None:
+#if LLVM_VERSION_LT(16, 0)
     return None;
+#else
+    return std::nullopt;
+#endif
   case LLVMRustChecksumKind::MD5:
     return DIFile::ChecksumKind::CSK_MD5;
   case LLVMRustChecksumKind::SHA1:
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index 684835d8c5c..13f06fe7473 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -192,7 +192,7 @@ impl Mismatch {
         let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
 
         // If we're not in a "rustc_" crate, bail.
-        let Some(("rustc", slug_prefix)) = crate_name.split_once("_") else { return None };
+        let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
 
         let slug_name = slug.segments.first()?.ident.to_string();
         if !slug_name.starts_with(slug_prefix) {
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 9f2ac5112f1..82f6812026a 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -372,46 +372,21 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                 }
             }
             (Meta::Path(_), "subdiagnostic") => {
-                return Ok(quote! { #diag.subdiagnostic(#binding); });
+                if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() {
+                    let DiagnosticDeriveKind::Diagnostic { handler } = &self.parent.kind else {
+                        // No eager translation for lints.
+                        return Ok(quote! { #diag.subdiagnostic(#binding); });
+                    };
+                    return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
+                } else {
+                    return Ok(quote! { #diag.subdiagnostic(#binding); });
+                }
             }
-            (Meta::NameValue(_), "subdiagnostic") => {
+            (Meta::List(_), "subdiagnostic") => {
                 throw_invalid_attr!(attr, &meta, |diag| {
-                    diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
+                    diag.help("`subdiagnostic` does not support nested attributes")
                 })
             }
-            (Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
-                if nested.len() != 1 {
-                    throw_invalid_attr!(attr, &meta, |diag| {
-                        diag.help(
-                            "`eager` is the only supported nested attribute for `subdiagnostic`",
-                        )
-                    })
-                }
-
-                let handler = match &self.parent.kind {
-                    DiagnosticDeriveKind::Diagnostic { handler } => handler,
-                    DiagnosticDeriveKind::LintDiagnostic => {
-                        throw_invalid_attr!(attr, &meta, |diag| {
-                            diag.help("eager subdiagnostics are not supported on lints")
-                        })
-                    }
-                };
-
-                let nested_attr = nested.first().expect("pop failed for single element list");
-                match nested_attr {
-                    NestedMeta::Meta(meta @ Meta::Path(_))
-                        if meta.path().segments.last().unwrap().ident.to_string().as_str()
-                            == "eager" =>
-                    {
-                        return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
-                    }
-                    _ => {
-                        throw_invalid_nested_attr!(attr, nested_attr, |diag| {
-                            diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
-                        })
-                    }
-                }
-            }
             _ => (),
         }
 
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index af7b0793a95..4370d4bd758 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1527,13 +1527,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
                 {
                     if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
-                        if let rustc_span::FileName::Real(ref mut old_name) = name {
-                            if let rustc_span::RealFileName::LocalPath(local) = old_name {
-                                if let Ok(rest) = local.strip_prefix(real_dir) {
-                                    *old_name = rustc_span::RealFileName::Remapped {
-                                        local_path: None,
-                                        virtual_name: virtual_dir.join(rest),
-                                    };
+                        for subdir in ["library", "compiler"] {
+                            if let rustc_span::FileName::Real(ref mut old_name) = name {
+                                if let rustc_span::RealFileName::LocalPath(local) = old_name {
+                                    if let Ok(rest) = local.strip_prefix(real_dir.join(subdir)) {
+                                        *old_name = rustc_span::RealFileName::Remapped {
+                                            local_path: None,
+                                            virtual_name: virtual_dir.join(subdir).join(rest),
+                                        };
+                                    }
                                 }
                             }
                         }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 8b4c4bb2675..856f5bc4645 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1111,8 +1111,8 @@ fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) ->
     // associated types.
     tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| {
         if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Projection(data) = ty.kind()
-            && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+            && let ty::Alias(ty::Projection, data) = ty.kind()
+            && tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
         {
             true
         } else {
@@ -1337,24 +1337,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
-        let ast_item = tcx.hir().expect_trait_item(def_id.expect_local());
-        self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness);
+        let impl_defaultness = tcx.impl_defaultness(def_id.expect_local());
+        self.tables.impl_defaultness.set(def_id.index, impl_defaultness);
         let trait_item = tcx.associated_item(def_id);
         self.tables.assoc_container.set(def_id.index, trait_item.container);
 
         match trait_item.kind {
             ty::AssocKind::Const => {}
             ty::AssocKind::Fn => {
-                let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind else { bug!() };
-                match *m {
-                    hir::TraitFn::Required(ref names) => {
-                        record_array!(self.tables.fn_arg_names[def_id] <- *names)
-                    }
-                    hir::TraitFn::Provided(body) => {
-                        record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body))
-                    }
-                };
-                self.tables.asyncness.set(def_id.index, m_sig.header.asyncness);
+                record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id));
+                self.tables.asyncness.set(def_id.index, tcx.asyncness(def_id));
                 self.tables.constness.set(def_id.index, hir::Constness::NotConst);
             }
             ty::AssocKind::Type => {
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 29fe6110797..716655c7f14 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -7,7 +7,6 @@ use rustc_middle::ty::ParameterizedOverTcx;
 use rustc_serialize::opaque::FileEncoder;
 use rustc_serialize::Encoder as _;
 use rustc_span::hygiene::MacroKind;
-use std::convert::TryInto;
 use std::marker::PhantomData;
 use std::num::NonZeroUsize;
 
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index efa9464529e..0b55757eb03 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -3,7 +3,6 @@
 use rustc_macros::HashStable;
 use rustc_span::Symbol;
 
-use std::cmp::Ord;
 use std::fmt::{self, Debug, Formatter};
 
 rustc_index::newtype_index! {
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index d79cd8b7a8a..8fe349d9640 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -95,7 +95,6 @@ mod pointer;
 mod queries;
 mod value;
 
-use std::convert::TryFrom;
 use std::fmt;
 use std::io;
 use std::io::{Read, Write};
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 9c270ba1ec1..b0830991076 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -3,7 +3,6 @@ use super::{AllocId, InterpResult};
 use rustc_macros::HashStable;
 use rustc_target::abi::{HasDataLayout, Size};
 
-use std::convert::{TryFrom, TryInto};
 use std::fmt;
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index e6636e50e6e..88fb14eb359 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -1,4 +1,3 @@
-use std::convert::{TryFrom, TryInto};
 use std::fmt;
 
 use either::{Either, Left, Right};
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index a513444e1e0..bdaa586c698 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -36,7 +36,6 @@ use rustc_span::{Span, DUMMY_SP};
 use either::Either;
 
 use std::borrow::Cow;
-use std::convert::TryInto;
 use std::fmt::{self, Debug, Display, Formatter, Write};
 use std::ops::{ControlFlow, Index, IndexMut};
 use std::{iter, mem};
@@ -534,6 +533,11 @@ impl<'tcx> Body<'tcx> {
         };
         injection_phase > self.phase
     }
+
+    #[inline]
+    pub fn is_custom_mir(&self) -> bool {
+        self.injection_phase.is_some()
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -1848,7 +1852,7 @@ impl<'tcx> Operand<'tcx> {
     pub fn function_handle(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        substs: impl IntoIterator<Item = GenericArg<'tcx>>,
         span: Span,
     ) -> Self {
         let ty = tcx.mk_fn_def(def_id, substs);
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 15a24aa4ace..1e8d5f7eae8 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -200,6 +200,15 @@ impl<'tcx> MonoItem<'tcx> {
             MonoItem::GlobalAsm(..) => LOCAL_CRATE,
         }
     }
+
+    /// Returns the item's `DefId`
+    pub fn def_id(&self) -> DefId {
+        match *self {
+            MonoItem::Fn(Instance { def, .. }) => def.def_id(),
+            MonoItem::Static(def_id) => def_id,
+            MonoItem::GlobalAsm(item_id) => item_id.owner_id.to_def_id(),
+        }
+    }
 }
 
 impl<'tcx> fmt::Display for MonoItem<'tcx> {
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 143435cb2a1..d00b26a5a3d 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -250,7 +250,7 @@ pub enum ObligationCauseCode<'tcx> {
     TupleElem,
 
     /// This is the trait reference from the given projection.
-    ProjectionWf(ty::ProjectionTy<'tcx>),
+    ProjectionWf(ty::AliasTy<'tcx>),
 
     /// Must satisfy all of the where-clause predicates of the
     /// given item.
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index fb152b63f63..7380c62a669 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -12,7 +12,6 @@ use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir::def_id::DefId;
 use rustc_span::source_map::Span;
-use std::iter::FromIterator;
 
 pub mod type_op {
     use crate::ty::fold::TypeFoldable;
@@ -77,8 +76,7 @@ pub mod type_op {
     }
 }
 
-pub type CanonicalProjectionGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
+pub type CanonicalProjectionGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
 
 pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
 
@@ -219,6 +217,6 @@ pub struct NormalizationResult<'tcx> {
 pub enum OutlivesBound<'tcx> {
     RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
     RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
-    RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
+    RegionSubProjection(ty::Region<'tcx>, ty::AliasTy<'tcx>),
     RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>),
 }
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 7036c4a7b27..8ce06404de0 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -131,7 +131,7 @@ impl<'tcx> OverloadedDeref<'tcx> {
             .find(|m| m.kind == ty::AssocKind::Fn)
             .unwrap()
             .def_id;
-        tcx.mk_fn_def(method_def_id, tcx.mk_substs_trait(source, []))
+        tcx.mk_fn_def(method_def_id, [source])
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index f3186e1c30c..2a8a4d59888 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -2,7 +2,6 @@ use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_target::abi::Size;
-use std::convert::{TryFrom, TryInto};
 use std::fmt;
 use std::num::NonZeroU8;
 
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index becc2b805dd..d9721863a58 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,5 +1,3 @@
-use std::convert::TryInto;
-
 use super::Const;
 use crate::mir;
 use crate::mir::interpret::{AllocId, ConstValue, Scalar};
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 7d4971d1e9e..173c5ed4fee 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -4,8 +4,7 @@
 
 use crate::arena::Arena;
 use crate::dep_graph::{DepGraph, DepKindStruct};
-use crate::hir::place::Place as HirPlace;
-use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
+use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::struct_lint_level;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
 use crate::middle::resolve_lifetime;
@@ -18,14 +17,13 @@ use crate::thir::Thir;
 use crate::traits;
 use crate::ty::query::{self, TyCtxtAt};
 use crate::ty::{
-    self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
-    ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
-    GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
-    PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region,
-    RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy,
+    self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstS, DefIdTree, FloatTy, FloatVar,
+    FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
+    ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
+    ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy,
     Visibility,
 };
-use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
+use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -36,25 +34,20 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal};
-use rustc_data_structures::unord::UnordSet;
-use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::{
     DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LOCAL_CRATE};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
-use rustc_hir::hir_id::OwnerId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{
-    Constness, ExprKind, HirId, ImplItemKind, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet,
-    Node, TraitCandidate, TraitItemKind,
+    Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
 };
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable;
-use rustc_middle::mir::FakeReadCause;
 use rustc_query_system::dep_graph::DepNodeIndex;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
@@ -76,7 +69,6 @@ use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlag
 use std::any::Any;
 use std::borrow::Borrow;
 use std::cmp::Ordering;
-use std::collections::hash_map::{self, Entry};
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -84,8 +76,6 @@ use std::mem;
 use std::ops::{Bound, Deref};
 use std::sync::Arc;
 
-use super::{ImplPolarity, RvalueScopes};
-
 pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
     /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
     fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
@@ -116,7 +106,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>;
     type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>;
     type ListTy = &'tcx List<Ty<'tcx>>;
-    type ProjectionTy = ty::ProjectionTy<'tcx>;
+    type AliasTy = ty::AliasTy<'tcx>;
     type ParamTy = ParamTy;
     type BoundTy = ty::BoundTy;
     type PlaceholderType = ty::PlaceholderType;
@@ -285,666 +275,6 @@ pub struct CommonConsts<'tcx> {
     pub unit: Const<'tcx>,
 }
 
-pub struct LocalTableInContext<'a, V> {
-    hir_owner: OwnerId,
-    data: &'a ItemLocalMap<V>,
-}
-
-/// Validate that the given HirId (respectively its `local_id` part) can be
-/// safely used as a key in the maps of a TypeckResults. For that to be
-/// the case, the HirId must have the same `owner` as all the other IDs in
-/// this table (signified by `hir_owner`). Otherwise the HirId
-/// would be in a different frame of reference and using its `local_id`
-/// would result in lookup errors, or worse, in silently wrong data being
-/// stored/returned.
-#[inline]
-fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
-    if hir_id.owner != hir_owner {
-        invalid_hir_id_for_typeck_results(hir_owner, hir_id);
-    }
-}
-
-#[cold]
-#[inline(never)]
-fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
-    ty::tls::with(|tcx| {
-        bug!(
-            "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
-            tcx.hir().node_to_string(hir_id),
-            hir_id.owner,
-            hir_owner
-        )
-    });
-}
-
-impl<'a, V> LocalTableInContext<'a, V> {
-    pub fn contains_key(&self, id: hir::HirId) -> bool {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.contains_key(&id.local_id)
-    }
-
-    pub fn get(&self, id: hir::HirId) -> Option<&V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.get(&id.local_id)
-    }
-
-    pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
-        self.data.iter()
-    }
-}
-
-impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
-    type Output = V;
-
-    fn index(&self, key: hir::HirId) -> &V {
-        self.get(key).expect("LocalTableInContext: key not found")
-    }
-}
-
-pub struct LocalTableInContextMut<'a, V> {
-    hir_owner: OwnerId,
-    data: &'a mut ItemLocalMap<V>,
-}
-
-impl<'a, V> LocalTableInContextMut<'a, V> {
-    pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.get_mut(&id.local_id)
-    }
-
-    pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.entry(id.local_id)
-    }
-
-    pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.insert(id.local_id, val)
-    }
-
-    pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.remove(&id.local_id)
-    }
-}
-
-/// Whenever a value may be live across a generator yield, the type of that value winds up in the
-/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
-/// captured types that can be useful for diagnostics. In particular, it stores the span that
-/// caused a given type to be recorded, along with the scope that enclosed the value (which can
-/// be used to find the await that the value is live across).
-///
-/// For example:
-///
-/// ```ignore (pseudo-Rust)
-/// async move {
-///     let x: T = expr;
-///     foo.await
-///     ...
-/// }
-/// ```
-///
-/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
-/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
-#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct GeneratorInteriorTypeCause<'tcx> {
-    /// Type of the captured binding.
-    pub ty: Ty<'tcx>,
-    /// Span of the binding that was captured.
-    pub span: Span,
-    /// Span of the scope of the captured binding.
-    pub scope_span: Option<Span>,
-    /// Span of `.await` or `yield` expression.
-    pub yield_span: Span,
-    /// Expr which the type evaluated from.
-    pub expr: Option<hir::HirId>,
-}
-
-// This type holds diagnostic information on generators and async functions across crate boundaries
-// and is used to provide better error messages
-#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
-pub struct GeneratorDiagnosticData<'tcx> {
-    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
-    pub hir_owner: DefId,
-    pub nodes_types: ItemLocalMap<Ty<'tcx>>,
-    pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
-}
-
-#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
-pub struct TypeckResults<'tcx> {
-    /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
-    pub hir_owner: OwnerId,
-
-    /// Resolved definitions for `<T>::X` associated paths and
-    /// method calls, including those of overloaded operators.
-    type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
-
-    /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
-    /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
-    /// about the field you also need definition of the variant to which the field
-    /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
-    field_indices: ItemLocalMap<usize>,
-
-    /// Stores the types for various nodes in the AST. Note that this table
-    /// is not guaranteed to be populated outside inference. See
-    /// typeck::check::fn_ctxt for details.
-    node_types: ItemLocalMap<Ty<'tcx>>,
-
-    /// Stores the type parameters which were substituted to obtain the type
-    /// of this node. This only applies to nodes that refer to entities
-    /// parameterized by type parameters, such as generic fns, types, or
-    /// other items.
-    node_substs: ItemLocalMap<SubstsRef<'tcx>>,
-
-    /// This will either store the canonicalized types provided by the user
-    /// or the substitutions that the user explicitly gave (if any) attached
-    /// to `id`. These will not include any inferred values. The canonical form
-    /// is used to capture things like `_` or other unspecified values.
-    ///
-    /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
-    /// canonical substitutions would include only `for<X> { Vec<X> }`.
-    ///
-    /// See also `AscribeUserType` statement in MIR.
-    user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
-
-    /// Stores the canonicalized types provided by the user. See also
-    /// `AscribeUserType` statement in MIR.
-    pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
-
-    adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
-
-    /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
-    pat_binding_modes: ItemLocalMap<BindingMode>,
-
-    /// Stores the types which were implicitly dereferenced in pattern binding modes
-    /// for later usage in THIR lowering. For example,
-    ///
-    /// ```
-    /// match &&Some(5i32) {
-    ///     Some(n) => {},
-    ///     _ => {},
-    /// }
-    /// ```
-    /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
-    ///
-    /// See:
-    /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
-    pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
-
-    /// Records the reasons that we picked the kind of each closure;
-    /// not all closures are present in the map.
-    closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
-
-    /// For each fn, records the "liberated" types of its arguments
-    /// and return type. Liberated means that all bound regions
-    /// (including late-bound regions) are replaced with free
-    /// equivalents. This table is not used in codegen (since regions
-    /// are erased there) and hence is not serialized to metadata.
-    ///
-    /// This table also contains the "revealed" values for any `impl Trait`
-    /// that appear in the signature and whose values are being inferred
-    /// by this function.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// # use std::fmt::Debug;
-    /// fn foo(x: &u32) -> impl Debug { *x }
-    /// ```
-    ///
-    /// The function signature here would be:
-    ///
-    /// ```ignore (illustrative)
-    /// for<'a> fn(&'a u32) -> Foo
-    /// ```
-    ///
-    /// where `Foo` is an opaque type created for this function.
-    ///
-    ///
-    /// The *liberated* form of this would be
-    ///
-    /// ```ignore (illustrative)
-    /// fn(&'a u32) -> u32
-    /// ```
-    ///
-    /// Note that `'a` is not bound (it would be an `ReFree`) and
-    /// that the `Foo` opaque type is replaced by its hidden type.
-    liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
-
-    /// For each FRU expression, record the normalized types of the fields
-    /// of the struct - this is needed because it is non-trivial to
-    /// normalize while preserving regions. This table is used only in
-    /// MIR construction and hence is not serialized to metadata.
-    fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
-
-    /// For every coercion cast we add the HIR node ID of the cast
-    /// expression to this set.
-    coercion_casts: ItemLocalSet,
-
-    /// Set of trait imports actually used in the method resolution.
-    /// This is used for warning unused imports. During type
-    /// checking, this `Lrc` should not be cloned: it must have a ref-count
-    /// of 1 so that we can insert things into the set mutably.
-    pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
-
-    /// If any errors occurred while type-checking this body,
-    /// this field will be set to `Some(ErrorGuaranteed)`.
-    pub tainted_by_errors: Option<ErrorGuaranteed>,
-
-    /// All the opaque types that have hidden types set
-    /// by this function. We also store the
-    /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
-    /// even if they are only set in dead code (which doesn't show up in MIR).
-    pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
-
-    /// Tracks the minimum captures required for a closure;
-    /// see `MinCaptureInformationMap` for more details.
-    pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
-
-    /// Tracks the fake reads required for a closure and the reason for the fake read.
-    /// When performing pattern matching for closures, there are times we don't end up
-    /// reading places that are mentioned in a closure (because of _ patterns). However,
-    /// to ensure the places are initialized, we introduce fake reads.
-    /// Consider these two examples:
-    /// ``` (discriminant matching with only wildcard arm)
-    /// let x: u8;
-    /// let c = || match x { _ => () };
-    /// ```
-    /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
-    /// want to capture it. However, we do still want an error here, because `x` should have
-    /// to be initialized at the point where c is created. Therefore, we add a "fake read"
-    /// instead.
-    /// ``` (destructured assignments)
-    /// let c = || {
-    ///     let (t1, t2) = t;
-    /// }
-    /// ```
-    /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
-    /// we never capture `t`. This becomes an issue when we build MIR as we require
-    /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
-    /// issue by fake reading `t`.
-    pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
-
-    /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
-    /// by applying extended parameter rules.
-    /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
-    pub rvalue_scopes: RvalueScopes,
-
-    /// Stores the type, expression, span and optional scope span of all types
-    /// that are live across the yield of this generator (if a generator).
-    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
-
-    /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
-    /// as `&[u8]`, depending on the pattern  in which they are used.
-    /// This hashset records all instances where we behave
-    /// like this to allow `const_to_pat` to reliably handle this situation.
-    pub treat_byte_string_as_slice: ItemLocalSet,
-
-    /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
-    /// on closure size.
-    pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
-}
-
-impl<'tcx> TypeckResults<'tcx> {
-    pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
-        TypeckResults {
-            hir_owner,
-            type_dependent_defs: Default::default(),
-            field_indices: Default::default(),
-            user_provided_types: Default::default(),
-            user_provided_sigs: Default::default(),
-            node_types: Default::default(),
-            node_substs: Default::default(),
-            adjustments: Default::default(),
-            pat_binding_modes: Default::default(),
-            pat_adjustments: Default::default(),
-            closure_kind_origins: Default::default(),
-            liberated_fn_sigs: Default::default(),
-            fru_field_types: Default::default(),
-            coercion_casts: Default::default(),
-            used_trait_imports: Lrc::new(Default::default()),
-            tainted_by_errors: None,
-            concrete_opaque_types: Default::default(),
-            closure_min_captures: Default::default(),
-            closure_fake_reads: Default::default(),
-            rvalue_scopes: Default::default(),
-            generator_interior_types: ty::Binder::dummy(Default::default()),
-            treat_byte_string_as_slice: Default::default(),
-            closure_size_eval: Default::default(),
-        }
-    }
-
-    /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
-    pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
-        match *qpath {
-            hir::QPath::Resolved(_, ref path) => path.res,
-            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
-                .type_dependent_def(id)
-                .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
-        }
-    }
-
-    pub fn type_dependent_defs(
-        &self,
-    ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
-    }
-
-    pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
-    }
-
-    pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
-        self.type_dependent_def(id).map(|(_, def_id)| def_id)
-    }
-
-    pub fn type_dependent_defs_mut(
-        &mut self,
-    ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
-    }
-
-    pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
-    }
-
-    pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
-    }
-
-    pub fn field_index(&self, id: hir::HirId) -> usize {
-        self.field_indices().get(id).cloned().expect("no index for a field")
-    }
-
-    pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
-        self.field_indices().get(id).cloned()
-    }
-
-    pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
-    }
-
-    pub fn user_provided_types_mut(
-        &mut self,
-    ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
-    }
-
-    pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
-    }
-
-    pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
-    }
-
-    pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
-        let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
-            vec.iter()
-                .map(|item| {
-                    GeneratorInteriorTypeCause {
-                        ty: item.ty,
-                        span: item.span,
-                        scope_span: item.scope_span,
-                        yield_span: item.yield_span,
-                        expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
-                    }
-                })
-                .collect::<Vec<_>>()
-        });
-        GeneratorDiagnosticData {
-            generator_interior_types: generator_interior_type,
-            hir_owner: self.hir_owner.to_def_id(),
-            nodes_types: self.node_types.clone(),
-            adjustments: self.adjustments.clone(),
-        }
-    }
-
-    pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
-        self.node_type_opt(id).unwrap_or_else(|| {
-            bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
-        })
-    }
-
-    pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.node_types.get(&id.local_id).cloned()
-    }
-
-    pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
-    }
-
-    pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
-    }
-
-    pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.node_substs.get(&id.local_id).cloned()
-    }
-
-    /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
-    /// doesn't provide type parameter substitutions.
-    ///
-    /// [`expr_ty`]: TypeckResults::expr_ty
-    pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
-        self.node_type(pat.hir_id)
-    }
-
-    /// Returns the type of an expression as a monotype.
-    ///
-    /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
-    /// some cases, we insert `Adjustment` annotations such as auto-deref or
-    /// auto-ref.  The type returned by this function does not consider such
-    /// adjustments.  See `expr_ty_adjusted()` instead.
-    ///
-    /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
-    /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
-    /// instead of `fn(ty) -> T with T = isize`.
-    pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
-        self.node_type(expr.hir_id)
-    }
-
-    pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
-        self.node_type_opt(expr.hir_id)
-    }
-
-    pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
-    }
-
-    pub fn adjustments_mut(
-        &mut self,
-    ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
-    }
-
-    pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
-        validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
-        self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
-    }
-
-    /// Returns the type of `expr`, considering any `Adjustment`
-    /// entry recorded for that expression.
-    pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
-        self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
-    }
-
-    pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
-        self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
-    }
-
-    pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
-        // Only paths and method calls/overloaded operators have
-        // entries in type_dependent_defs, ignore the former here.
-        if let hir::ExprKind::Path(_) = expr.kind {
-            return false;
-        }
-
-        matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
-    }
-
-    pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
-        self.pat_binding_modes().get(id).copied().or_else(|| {
-            s.delay_span_bug(sp, "missing binding mode");
-            None
-        })
-    }
-
-    pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
-    }
-
-    pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
-    }
-
-    pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
-    }
-
-    pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
-    }
-
-    /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
-    /// by the closure.
-    pub fn closure_min_captures_flattened(
-        &self,
-        closure_def_id: LocalDefId,
-    ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
-        self.closure_min_captures
-            .get(&closure_def_id)
-            .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
-            .into_iter()
-            .flatten()
-    }
-
-    pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
-    }
-
-    pub fn closure_kind_origins_mut(
-        &mut self,
-    ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
-    }
-
-    pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
-    }
-
-    pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
-    }
-
-    pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
-    }
-
-    pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
-    }
-
-    pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
-        validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
-        self.coercion_casts.contains(&hir_id.local_id)
-    }
-
-    pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
-        self.coercion_casts.insert(id);
-    }
-
-    pub fn coercion_casts(&self) -> &ItemLocalSet {
-        &self.coercion_casts
-    }
-}
-
-rustc_index::newtype_index! {
-    pub struct UserTypeAnnotationIndex {
-        derive [HashStable]
-        DEBUG_FORMAT = "UserType({})",
-        const START_INDEX = 0,
-    }
-}
-
-/// Mapping of type annotation indices to canonical user type annotations.
-pub type CanonicalUserTypeAnnotations<'tcx> =
-    IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
-
-#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct CanonicalUserTypeAnnotation<'tcx> {
-    pub user_ty: Box<CanonicalUserType<'tcx>>,
-    pub span: Span,
-    pub inferred_ty: Ty<'tcx>,
-}
-
-/// Canonicalized user type annotation.
-pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
-
-impl<'tcx> CanonicalUserType<'tcx> {
-    /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
-    /// i.e., each thing is mapped to a canonical variable with the same index.
-    pub fn is_identity(&self) -> bool {
-        match self.value {
-            UserType::Ty(_) => false,
-            UserType::TypeOf(_, user_substs) => {
-                if user_substs.user_self_ty.is_some() {
-                    return false;
-                }
-
-                iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
-                    match kind.unpack() {
-                        GenericArgKind::Type(ty) => match ty.kind() {
-                            ty::Bound(debruijn, b) => {
-                                // We only allow a `ty::INNERMOST` index in substitutions.
-                                assert_eq!(*debruijn, ty::INNERMOST);
-                                cvar == b.var
-                            }
-                            _ => false,
-                        },
-
-                        GenericArgKind::Lifetime(r) => match *r {
-                            ty::ReLateBound(debruijn, br) => {
-                                // We only allow a `ty::INNERMOST` index in substitutions.
-                                assert_eq!(debruijn, ty::INNERMOST);
-                                cvar == br.var
-                            }
-                            _ => false,
-                        },
-
-                        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);
-                                cvar == b
-                            }
-                            _ => false,
-                        },
-                    }
-                })
-            }
-        }
-    }
-}
-
-/// A user-given type annotation attached to a constant. These arise
-/// from constants that are named via paths, like `Foo::<A>::new` and
-/// so forth.
-#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub enum UserType<'tcx> {
-    Ty(Ty<'tcx>),
-
-    /// The canonical type is the result of `type_of(def_id)` with the
-    /// given substitutions applied.
-    TypeOf(DefId, UserSubsts<'tcx>),
-}
-
 impl<'tcx> CommonTypes<'tcx> {
     fn new(
         interners: &CtxtInterners<'tcx>,
@@ -2145,8 +1475,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     Bound,
                     Param,
                     Infer,
-                    Projection,
-                    Opaque,
+                    Alias,
                     Foreign
                 )?;
 
@@ -2323,7 +1652,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Given a `ty`, return whether it's an `impl Future<...>`.
     pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
-        let ty::Opaque(def_id, _) = ty.kind() else { return false };
+        let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
         let future_trait = self.require_lang_item(LangItem::Future, None);
 
         self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
@@ -2567,15 +1896,35 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline]
-    pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        debug_assert_eq!(
-            self.generics_of(def_id).count(),
-            substs.len(),
-            "wrong number of generic parameters for {def_id:?}: {substs:?}",
-        );
+    pub fn mk_fn_def(
+        self,
+        def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> Ty<'tcx> {
+        let substs = self.check_substs(def_id, substs);
         self.mk_ty(FnDef(def_id, substs))
     }
 
+    #[inline(always)]
+    fn check_substs(
+        self,
+        _def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> SubstsRef<'tcx> {
+        let substs = substs.into_iter().map(Into::into);
+        #[cfg(debug_assertions)]
+        {
+            let n = self.generics_of(_def_id).count();
+            assert_eq!(
+                (n, Some(n)),
+                substs.size_hint(),
+                "wrong number of generic parameters for {_def_id:?}: {:?}",
+                substs.collect::<Vec<_>>(),
+            );
+        }
+        self.mk_substs(substs)
+    }
+
     #[inline]
     pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
         self.mk_ty(FnPtr(fty))
@@ -2592,13 +1941,12 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline]
-    pub fn mk_projection(self, item_def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        debug_assert_eq!(
-            self.generics_of(item_def_id).count(),
-            substs.len(),
-            "wrong number of generic parameters for {item_def_id:?}: {substs:?}",
-        );
-        self.mk_ty(Projection(ProjectionTy { item_def_id, substs }))
+    pub fn mk_projection(
+        self,
+        item_def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> Ty<'tcx> {
+        self.mk_ty(Alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)))
     }
 
     #[inline]
@@ -2668,7 +2016,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline]
     pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(Opaque(def_id, substs))
+        self.mk_ty(Alias(ty::Opaque, self.mk_alias_ty(def_id, substs)))
     }
 
     pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
@@ -2857,16 +2205,17 @@ impl<'tcx> TyCtxt<'tcx> {
         trait_def_id: DefId,
         substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
     ) -> ty::TraitRef<'tcx> {
-        let substs = substs.into_iter().map(Into::into);
-        let n = self.generics_of(trait_def_id).count();
-        debug_assert_eq!(
-            (n, Some(n)),
-            substs.size_hint(),
-            "wrong number of generic parameters for {trait_def_id:?}: {:?} \nDid you accidentally include the self-type in the params list?",
-            substs.collect::<Vec<_>>(),
-        );
-        let substs = self.mk_substs(substs);
-        ty::TraitRef::new(trait_def_id, substs)
+        let substs = self.check_substs(trait_def_id, substs);
+        ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () }
+    }
+
+    pub fn mk_alias_ty(
+        self,
+        def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> ty::AliasTy<'tcx> {
+        let substs = self.check_substs(def_id, substs);
+        ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
     }
 
     pub fn mk_bound_variable_kinds<
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 511d51cd670..8c22df7395f 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -3,7 +3,7 @@
 use std::ops::ControlFlow;
 
 use crate::ty::{
-    visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, InferTy,
+    visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
     PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
 };
 
@@ -457,11 +457,11 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
                 return ControlFlow::Break(());
             }
 
-            Opaque(did, _) => {
-                let parent = self.tcx.parent(*did);
+            Alias(Opaque, AliasTy { def_id, .. }) => {
+                let parent = self.tcx.parent(*def_id);
                 if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
-                    && let Opaque(parent_did, _) = self.tcx.type_of(parent).kind()
-                    && parent_did == did
+                    && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = self.tcx.type_of(parent).kind()
+                    && parent_opaque_def_id == def_id
                 {
                     // Okay
                 } else {
@@ -469,17 +469,6 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
                 }
             }
 
-            Dynamic(dty, _, _) => {
-                for pred in *dty {
-                    match pred.skip_binder() {
-                        ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => {
-                            // Okay
-                        }
-                        _ => return ControlFlow::Break(()),
-                    }
-                }
-            }
-
             Param(param) => {
                 // FIXME: It would be nice to make this not use string manipulation,
                 // but it's pretty hard to do this, since `ty::ParamTy` is missing
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index aa61c39b8d8..14d07608a78 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -1,6 +1,6 @@
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use crate::ty::diagnostics::suggest_constraining_type_param;
-use crate::ty::print::{FmtPrinter, Printer};
+use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
 use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
 use hir::def::DefKind;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
@@ -162,17 +162,29 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
             ),
             RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
             ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
-                report_maybe_different(
-                    f,
-                    &values.expected.sort_string(tcx),
-                    &values.found.sort_string(tcx),
-                )
+                let (mut expected, mut found) = with_forced_trimmed_paths!((
+                    values.expected.sort_string(tcx),
+                    values.found.sort_string(tcx),
+                ));
+                if expected == found {
+                    expected = values.expected.sort_string(tcx);
+                    found = values.found.sort_string(tcx);
+                }
+                report_maybe_different(f, &expected, &found)
             }),
             Traits(values) => ty::tls::with(|tcx| {
+                let (mut expected, mut found) = with_forced_trimmed_paths!((
+                    tcx.def_path_str(values.expected),
+                    tcx.def_path_str(values.found),
+                ));
+                if expected == found {
+                    expected = tcx.def_path_str(values.expected);
+                    found = tcx.def_path_str(values.found);
+                }
                 report_maybe_different(
                     f,
-                    &format!("trait `{}`", tcx.def_path_str(values.expected)),
-                    &format!("trait `{}`", tcx.def_path_str(values.found)),
+                    &format!("trait `{expected}`"),
+                    &format!("trait `{found}`"),
                 )
             }),
             IntMismatch(ref values) => {
@@ -325,9 +337,9 @@ impl<'tcx> Ty<'tcx> {
             ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
             ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
             ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
-            ty::Projection(_) => "associated type".into(),
+            ty::Alias(ty::Projection, _) => "associated type".into(),
             ty::Param(p) => format!("type parameter `{}`", p).into(),
-            ty::Opaque(..) => "opaque type".into(),
+            ty::Alias(ty::Opaque, ..) => "opaque type".into(),
             ty::Error(_) => "type error".into(),
         }
     }
@@ -363,9 +375,9 @@ impl<'tcx> Ty<'tcx> {
             ty::Tuple(..) => "tuple".into(),
             ty::Placeholder(..) => "higher-ranked type".into(),
             ty::Bound(..) => "bound type variable".into(),
-            ty::Projection(_) => "associated type".into(),
+            ty::Alias(ty::Projection, _) => "associated type".into(),
             ty::Param(_) => "type parameter".into(),
-            ty::Opaque(..) => "opaque type".into(),
+            ty::Alias(ty::Opaque, ..) => "opaque type".into(),
         }
     }
 }
@@ -388,7 +400,7 @@ impl<'tcx> TyCtxt<'tcx> {
                         diag.note("no two closures, even if identical, have the same type");
                         diag.help("consider boxing your closure and/or using it as a trait object");
                     }
-                    (ty::Opaque(..), ty::Opaque(..)) => {
+                    (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
                         // Issue #63167
                         diag.note("distinct uses of `impl Trait` result in different opaque types");
                     }
@@ -427,11 +439,11 @@ impl<'tcx> TyCtxt<'tcx> {
                              #traits-as-parameters",
                         );
                     }
-                    (ty::Projection(_), ty::Projection(_)) => {
+                    (ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => {
                         diag.note("an associated type was expected, but a different one was found");
                     }
-                    (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p))
-                        if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder =>
+                    (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
+                        if self.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
                     {
                         let generics = self.generics_of(body_owner_def_id);
                         let p_span = self.def_span(generics.type_param(p, self).def_id);
@@ -454,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> {
                             let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
                             let path =
                                 self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
-                            let item_name = self.item_name(proj.item_def_id);
+                            let item_name = self.item_name(proj.def_id);
                             let item_args = self.format_generic_args(assoc_substs);
 
                             let path = if path.ends_with('>') {
@@ -481,8 +493,8 @@ impl<'tcx> TyCtxt<'tcx> {
                             diag.note("you might be missing a type parameter or trait bound");
                         }
                     }
-                    (ty::Param(p), ty::Dynamic(..) | ty::Opaque(..))
-                    | (ty::Dynamic(..) | ty::Opaque(..), ty::Param(p)) => {
+                    (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
+                    | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
                         let generics = self.generics_of(body_owner_def_id);
                         let p_span = self.def_span(generics.type_param(p, self).def_id);
                         if !sp.contains(p_span) {
@@ -541,7 +553,7 @@ impl<T> Trait<T> for X {
                             diag.span_label(p_span, "this type parameter");
                         }
                     }
-                    (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+                    (ty::Alias(ty::Projection, proj_ty), _) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
                         self.expected_projection(
                             diag,
                             proj_ty,
@@ -550,7 +562,7 @@ impl<T> Trait<T> for X {
                             cause.code(),
                         );
                     }
-                    (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+                    (_, ty::Alias(ty::Projection, proj_ty)) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
                         let msg = format!(
                             "consider constraining the associated type `{}` to `{}`",
                             values.found, values.expected,
@@ -612,10 +624,10 @@ impl<T> Trait<T> for X {
         diag: &mut Diagnostic,
         msg: &str,
         body_owner_def_id: DefId,
-        proj_ty: &ty::ProjectionTy<'tcx>,
+        proj_ty: &ty::AliasTy<'tcx>,
         ty: Ty<'tcx>,
     ) -> bool {
-        let assoc = self.associated_item(proj_ty.item_def_id);
+        let assoc = self.associated_item(proj_ty.def_id);
         let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
         if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
             if let Some(hir_generics) = item.generics() {
@@ -668,7 +680,7 @@ impl<T> Trait<T> for X {
     fn expected_projection(
         self,
         diag: &mut Diagnostic,
-        proj_ty: &ty::ProjectionTy<'tcx>,
+        proj_ty: &ty::AliasTy<'tcx>,
         values: ExpectedFound<Ty<'tcx>>,
         body_owner_def_id: DefId,
         cause_code: &ObligationCauseCode<'_>,
@@ -691,7 +703,7 @@ impl<T> Trait<T> for X {
         );
         let impl_comparison =
             matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
-        let assoc = self.associated_item(proj_ty.item_def_id);
+        let assoc = self.associated_item(proj_ty.def_id);
         if !callable_scope || impl_comparison {
             // We do not want to suggest calling functions when the reason of the
             // type error is a comparison of an `impl` with its `trait` or when the
@@ -704,7 +716,7 @@ impl<T> Trait<T> for X {
                 diag,
                 assoc.container_id(self),
                 current_method_ident,
-                proj_ty.item_def_id,
+                proj_ty.def_id,
                 values.expected,
             );
             // Possibly suggest constraining the associated type to conform to the
@@ -763,11 +775,11 @@ fn foo(&self) -> Self::T { String::new() }
         self,
         diag: &mut Diagnostic,
         msg: &str,
-        proj_ty: &ty::ProjectionTy<'tcx>,
+        proj_ty: &ty::AliasTy<'tcx>,
         ty: Ty<'tcx>,
     ) -> bool {
-        let assoc = self.associated_item(proj_ty.item_def_id);
-        if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
+        let assoc = self.associated_item(proj_ty.def_id);
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
             let opaque_local_def_id = def_id.as_local();
             let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
                 match &self.hir().expect_item(opaque_local_def_id).kind {
@@ -816,7 +828,7 @@ fn foo(&self) -> Self::T { String::new() }
             .filter_map(|(_, item)| {
                 let method = self.fn_sig(item.def_id);
                 match *method.output().skip_binder().kind() {
-                    ty::Projection(ty::ProjectionTy { item_def_id, .. })
+                    ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
                         if item_def_id == proj_ty_item_def_id =>
                     {
                         Some((
@@ -998,15 +1010,17 @@ fn foo(&self) -> Self::T { String::new() }
         }
         let mut short;
         loop {
-            // Look for the longest properly trimmed path that still fits in lenght_limit.
-            short = FmtPrinter::new_with_limit(
-                self,
-                hir::def::Namespace::TypeNS,
-                rustc_session::Limit(type_limit),
-            )
-            .pretty_print_type(ty)
-            .expect("could not write to `String`")
-            .into_buffer();
+            // Look for the longest properly trimmed path that still fits in length_limit.
+            short = with_forced_trimmed_paths!(
+                FmtPrinter::new_with_limit(
+                    self,
+                    hir::def::Namespace::TypeNS,
+                    rustc_session::Limit(type_limit),
+                )
+                .pretty_print_type(ty)
+                .expect("could not write to `String`")
+                .into_buffer()
+            );
             if short.len() <= length_limit || type_limit == 0 {
                 break;
             }
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index c9c09c93a3e..f785fb5c4b9 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -6,28 +6,18 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::iter;
 
-use self::SimplifiedTypeGen::*;
+use self::SimplifiedType::*;
 
-pub type SimplifiedType = SimplifiedTypeGen<DefId>;
-
-/// See `simplify_type`
-///
-/// Note that we keep this type generic over the type of identifier it uses
-/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
-/// keys (in which case we use a DefPathHash as id-type) but in the general case
-/// the non-stable but fast to construct DefId-version is the better choice.
+/// See `simplify_type`.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
-pub enum SimplifiedTypeGen<D>
-where
-    D: Copy + Debug + Eq,
-{
+pub enum SimplifiedType {
     BoolSimplifiedType,
     CharSimplifiedType,
     IntSimplifiedType(ty::IntTy),
     UintSimplifiedType(ty::UintTy),
     FloatSimplifiedType(ty::FloatTy),
-    AdtSimplifiedType(D),
-    ForeignSimplifiedType(D),
+    AdtSimplifiedType(DefId),
+    ForeignSimplifiedType(DefId),
     StrSimplifiedType,
     ArraySimplifiedType,
     SliceSimplifiedType,
@@ -38,9 +28,9 @@ where
     /// A trait object, all of whose components are markers
     /// (e.g., `dyn Send + Sync`).
     MarkerTraitObjectSimplifiedType,
-    TraitSimplifiedType(D),
-    ClosureSimplifiedType(D),
-    GeneratorSimplifiedType(D),
+    TraitSimplifiedType(DefId),
+    ClosureSimplifiedType(DefId),
+    GeneratorSimplifiedType(DefId),
     GeneratorWitnessSimplifiedType(usize),
     FunctionSimplifiedType(usize),
     PlaceholderSimplifiedType,
@@ -126,7 +116,7 @@ pub fn simplify_type<'tcx>(
             TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
             TreatParams::AsInfer => None,
         },
-        ty::Opaque(..) | ty::Projection(_) => match treat_params {
+        ty::Alias(..) => match treat_params {
             // When treating `ty::Param` as a placeholder, projections also
             // don't unify with anything else as long as they are fully normalized.
             //
@@ -142,8 +132,8 @@ pub fn simplify_type<'tcx>(
     }
 }
 
-impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
-    pub fn def(self) -> Option<D> {
+impl SimplifiedType {
+    pub fn def(self) -> Option<DefId> {
         match self {
             AdtSimplifiedType(d)
             | ForeignSimplifiedType(d)
@@ -153,36 +143,6 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
             _ => None,
         }
     }
-
-    pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
-    where
-        F: Fn(D) -> U,
-        U: Copy + Debug + Eq,
-    {
-        match self {
-            BoolSimplifiedType => BoolSimplifiedType,
-            CharSimplifiedType => CharSimplifiedType,
-            IntSimplifiedType(t) => IntSimplifiedType(t),
-            UintSimplifiedType(t) => UintSimplifiedType(t),
-            FloatSimplifiedType(t) => FloatSimplifiedType(t),
-            AdtSimplifiedType(d) => AdtSimplifiedType(map(d)),
-            ForeignSimplifiedType(d) => ForeignSimplifiedType(map(d)),
-            StrSimplifiedType => StrSimplifiedType,
-            ArraySimplifiedType => ArraySimplifiedType,
-            SliceSimplifiedType => SliceSimplifiedType,
-            RefSimplifiedType(m) => RefSimplifiedType(m),
-            PtrSimplifiedType(m) => PtrSimplifiedType(m),
-            NeverSimplifiedType => NeverSimplifiedType,
-            MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
-            TupleSimplifiedType(n) => TupleSimplifiedType(n),
-            TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
-            ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
-            GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
-            GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
-            FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
-            PlaceholderSimplifiedType => PlaceholderSimplifiedType,
-        }
-    }
 }
 
 /// Given generic arguments from an obligation and an impl,
@@ -225,7 +185,7 @@ impl DeepRejectCtxt {
         match impl_ty.kind() {
             // Start by checking whether the type in the impl may unify with
             // pretty much everything. Just return `true` in that case.
-            ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
+            ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true,
             // These types only unify with inference variables or their own
             // variant.
             ty::Bool
@@ -323,8 +283,6 @@ impl DeepRejectCtxt {
                 _ => false,
             },
 
-            ty::Opaque(..) => true,
-
             // Impls cannot contain these types as these cannot be named directly.
             ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
 
@@ -344,7 +302,7 @@ impl DeepRejectCtxt {
             // projections can unify with other stuff.
             //
             // Looking forward to lazy normalization this is the safer strategy anyways.
-            ty::Projection(_) => true,
+            ty::Alias(..) => true,
 
             ty::Error(_) => true,
 
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 046a2660a1f..d283ccc3ad8 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -155,12 +155,12 @@ impl FlagComputation {
                 self.add_substs(substs);
             }
 
-            &ty::Projection(data) => {
+            &ty::Alias(ty::Projection, data) => {
                 self.add_flags(TypeFlags::HAS_TY_PROJECTION);
                 self.add_projection_ty(data);
             }
 
-            &ty::Opaque(_, substs) => {
+            &ty::Alias(ty::Opaque, ty::AliasTy { substs, .. }) => {
                 self.add_flags(TypeFlags::HAS_TY_OPAQUE);
                 self.add_substs(substs);
             }
@@ -345,7 +345,7 @@ impl FlagComputation {
         }
     }
 
-    fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) {
+    fn add_projection_ty(&mut self, projection_ty: ty::AliasTy<'_>) {
         self.add_substs(projection_ty.substs);
     }
 
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index d431d008ddf..09fee0c3f7c 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -583,36 +583,6 @@ impl<'tcx> TyCtxt<'tcx> {
         self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
     }
 
-    /// Rewrite any late-bound regions so that they are anonymous. Region numbers are
-    /// assigned starting at 0 and increasing monotonically in the order traversed
-    /// by the fold operation.
-    ///
-    /// The chief purpose of this function is to canonicalize regions so that two
-    /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
-    /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
-    /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
-    pub fn anonymize_late_bound_regions<T>(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T>
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        let mut counter = 0;
-        let inner = self
-            .replace_late_bound_regions(sig, |_| {
-                let br = ty::BoundRegion {
-                    var: ty::BoundVar::from_u32(counter),
-                    kind: ty::BrAnon(counter, None),
-                };
-                let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
-                counter += 1;
-                r
-            })
-            .0;
-        let bound_vars = self.mk_bound_variable_kinds(
-            (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
-        );
-        Binder::bind_with_vars(inner, bound_vars)
-    }
-
     /// Anonymize all bound variables in `value`, this is mostly used to improve caching.
     pub fn anonymize_bound_vars<T>(self, value: Binder<'tcx, T>) -> Binder<'tcx, T>
     where
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index ace81bc4f83..5d5089cec82 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -112,7 +112,7 @@ impl<'tcx> Ty<'tcx> {
                 InhabitedPredicate::True
             }
             Never => InhabitedPredicate::False,
-            Param(_) | Projection(_) => InhabitedPredicate::GenericType(self),
+            Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self),
             Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
             // use a query for more complex cases
             Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 586460986dd..35d369ffc89 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -385,6 +385,21 @@ impl<'tcx> Instance<'tcx> {
         )
     }
 
+    pub fn expect_resolve(
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        def_id: DefId,
+        substs: SubstsRef<'tcx>,
+    ) -> Instance<'tcx> {
+        match ty::Instance::resolve(tcx, param_env, def_id, substs) {
+            Ok(Some(instance)) => instance,
+            _ => bug!(
+                "failed to resolve instance for {}",
+                tcx.def_path_str_with_substs(def_id, substs)
+            ),
+        }
+    }
+
     // This should be kept up to date with `resolve`.
     pub fn resolve_opt_const_arg(
         tcx: TyCtxt<'tcx>,
@@ -525,7 +540,7 @@ impl<'tcx> Instance<'tcx> {
     pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
         let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
         let substs = tcx.intern_substs(&[ty.into()]);
-        Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
+        Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
     }
 
     #[instrument(level = "debug", skip(tcx), ret)]
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 488fd567846..7f66b993646 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -271,7 +271,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                 let non_zero = !ty.is_unsafe_ptr();
                 let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 match tail.kind() {
-                    ty::Param(_) | ty::Projection(_) => {
+                    ty::Param(_) | ty::Alias(ty::Projection, _) => {
                         debug_assert!(tail.has_non_region_param());
                         Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
                     }
@@ -349,7 +349,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                 }
             }
 
-            ty::Projection(_) | ty::Opaque(..) => {
+            ty::Alias(..) => {
                 let normalized = tcx.normalize_erasing_regions(param_env, ty);
                 if ty == normalized {
                     Err(err)
@@ -757,10 +757,9 @@ where
                     }
                 }
 
-                ty::Projection(_)
+                ty::Alias(..)
                 | ty::Bound(..)
                 | ty::Placeholder(..)
-                | ty::Opaque(..)
                 | ty::Param(_)
                 | ty::Infer(_)
                 | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 659d99f025d..7290f0ae7c0 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -64,6 +64,7 @@ use std::ops::ControlFlow;
 use std::{fmt, str};
 
 pub use crate::ty::diagnostics::*;
+pub use rustc_type_ir::AliasKind::*;
 pub use rustc_type_ir::DynKind::*;
 pub use rustc_type_ir::InferTy::*;
 pub use rustc_type_ir::RegionKind::*;
@@ -82,10 +83,8 @@ pub use self::consts::{
     Const, ConstInt, ConstKind, ConstS, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
-    tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
-    CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData,
-    GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults,
-    UserType, UserTypeAnnotationIndex,
+    tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
+    TyCtxtFeed,
 };
 pub use self::instance::{Instance, InstanceDef, ShortInstance};
 pub use self::list::List;
@@ -93,16 +92,20 @@ pub use self::parameterized::ParameterizedOverTcx;
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::BoundRegionKind::*;
 pub use self::sty::{
-    Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
+    AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
     BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
     EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
     FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
     InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
     PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
-    ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
-    VarianceDiagInfo,
+    Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
 };
 pub use self::trait_def::TraitDef;
+pub use self::typeck_results::{
+    CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
+    UserTypeAnnotationIndex,
+};
 
 pub mod _match;
 pub mod abstract_const;
@@ -143,6 +146,7 @@ mod parameterized;
 mod rvalue_scopes;
 mod structural_impls;
 mod sty;
+mod typeck_results;
 
 // Data types
 
@@ -235,7 +239,7 @@ pub struct ImplHeader<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
 
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
 pub enum ImplSubject<'tcx> {
     Trait(TraitRef<'tcx>),
     Inherent(Ty<'tcx>),
@@ -781,8 +785,8 @@ impl<'tcx> TraitPredicate<'tcx> {
         }
     }
 
-    pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        Self { trait_ref: self.trait_ref.with_self_type(tcx, self_ty), ..self }
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
     }
 
     pub fn def_id(self) -> DefId {
@@ -1010,7 +1014,7 @@ impl<'tcx> TermKind<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ProjectionPredicate<'tcx> {
-    pub projection_ty: ProjectionTy<'tcx>,
+    pub projection_ty: AliasTy<'tcx>,
     pub term: Term<'tcx>,
 }
 
@@ -1046,7 +1050,19 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
     /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
     pub fn projection_def_id(&self) -> DefId {
         // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().projection_ty.item_def_id
+        self.skip_binder().projection_ty.def_id
+    }
+}
+
+impl<'tcx> ProjectionPredicate<'tcx> {
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        Self {
+            projection_ty: tcx.mk_alias_ty(
+                self.projection_ty.def_id,
+                [self_ty.into()].into_iter().chain(self.projection_ty.substs.iter().skip(1)),
+            ),
+            ..self
+        }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index c7d6c6abd1c..a21e3961cb6 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -1,15 +1,10 @@
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::{DefId, DefIndex};
+use rustc_hir::def_id::DefIndex;
 use rustc_index::vec::{Idx, IndexVec};
 
-use crate::middle::exported_symbols::ExportedSymbol;
-use crate::mir::Body;
-use crate::ty::{
-    self, Clause, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty,
-};
+use crate::ty;
 
 pub trait ParameterizedOverTcx: 'static {
-    #[allow(unused_lifetimes)]
     type Value<'tcx>;
 }
 
@@ -67,7 +62,7 @@ trivially_parameterized_over_tcx! {
     ty::TraitDef,
     ty::Visibility<DefIndex>,
     ty::adjustment::CoerceUnsizedInfo,
-    ty::fast_reject::SimplifiedTypeGen<DefId>,
+    ty::fast_reject::SimplifiedType,
     rustc_ast::Attribute,
     rustc_ast::DelimArgs,
     rustc_attr::ConstStability,
@@ -100,29 +95,28 @@ trivially_parameterized_over_tcx! {
     rustc_type_ir::Variance,
 }
 
-// HACK(compiler-errors): This macro rule can only take an ident,
-// not a path, due to parsing ambiguity reasons. That means we gotta
-// import all of these types above.
+// HACK(compiler-errors): This macro rule can only take a fake path,
+// not a real, due to parsing ambiguity reasons.
 #[macro_export]
 macro_rules! parameterized_over_tcx {
-    ($($ident:ident),+ $(,)?) => {
+    ($($($fake_path:ident)::+),+ $(,)?) => {
         $(
-            impl $crate::ty::ParameterizedOverTcx for $ident<'static> {
-                type Value<'tcx> = $ident<'tcx>;
+            impl $crate::ty::ParameterizedOverTcx for $($fake_path)::+<'static> {
+                type Value<'tcx> = $($fake_path)::+<'tcx>;
             }
         )*
     }
 }
 
 parameterized_over_tcx! {
-    Ty,
-    FnSig,
-    GenericPredicates,
-    TraitRef,
-    Const,
-    Predicate,
-    Clause,
-    GeneratorDiagnosticData,
-    Body,
-    ExportedSymbol,
+    crate::middle::exported_symbols::ExportedSymbol,
+    crate::mir::Body,
+    ty::Ty,
+    ty::FnSig,
+    ty::GenericPredicates,
+    ty::TraitRef,
+    ty::Const,
+    ty::Predicate,
+    ty::Clause,
+    ty::GeneratorDiagnosticData,
 }
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 667298b9b5b..29bad33e4bc 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -169,10 +169,8 @@ pub trait Printer<'tcx>: Sized {
                 self.path_append(
                     |cx: Self| {
                         if trait_qualify_parent {
-                            let trait_ref = ty::TraitRef::new(
-                                parent_def_id,
-                                cx.tcx().intern_substs(parent_substs),
-                            );
+                            let trait_ref =
+                                cx.tcx().mk_trait_ref(parent_def_id, parent_substs.iter().copied());
                             cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
                         } else {
                             cx.print_def_path(parent_def_id, parent_substs)
@@ -275,10 +273,9 @@ fn characteristic_def_id_of_type_cached<'a>(
         | ty::Uint(_)
         | ty::Str
         | ty::FnPtr(_)
-        | ty::Projection(_)
+        | ty::Alias(..)
         | ty::Placeholder(..)
         | ty::Param(_)
-        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Bound(..)
         | ty::Error(_)
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 5303341ba44..a1d53506707 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -10,12 +10,13 @@ use rustc_data_structures::sso::SsoHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
 use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
+use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData};
 use rustc_hir::LangItem;
 use rustc_session::config::TrimmedDefPaths;
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_session::Limit;
 use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::FileNameDisplayPreference;
 use rustc_target::abi::Size;
 use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
@@ -23,7 +24,6 @@ use smallvec::SmallVec;
 use std::cell::Cell;
 use std::char;
 use std::collections::BTreeMap;
-use std::convert::TryFrom;
 use std::fmt::{self, Write as _};
 use std::iter;
 use std::ops::{ControlFlow, Deref, DerefMut};
@@ -63,6 +63,7 @@ thread_local! {
     static FORCE_IMPL_FILENAME_LINE: Cell<bool> = const { Cell::new(false) };
     static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
     static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
+    static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
     static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
     static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
 }
@@ -116,6 +117,7 @@ define_helper!(
     /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
     /// if no other `Vec` is found.
     fn with_no_trimmed_paths(NoTrimmedGuard, NO_TRIMMED_PATH);
+    fn with_forced_trimmed_paths(ForceTrimmedGuard, FORCE_TRIMMED_PATH);
     /// Prevent selection of visible paths. `Display` impl of DefId will prefer
     /// visible (public) reexports of types as paths.
     fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
@@ -295,11 +297,89 @@ pub trait PrettyPrinter<'tcx>:
         self.try_print_visible_def_path_recur(def_id, &mut callers)
     }
 
+    // Given a `DefId`, produce a short name. For types and traits, it prints *only* its name,
+    // For associated items on traits it prints out the trait's name and the associated item's name.
+    // For enum variants, if they have an unique name, then we only print the name, otherwise we
+    // print the enum name and the variant name. Otherwise, we do not print anything and let the
+    // caller use the `print_def_path` fallback.
+    fn force_print_trimmed_def_path(
+        mut self,
+        def_id: DefId,
+    ) -> Result<(Self::Path, bool), Self::Error> {
+        let key = self.tcx().def_key(def_id);
+        let visible_parent_map = self.tcx().visible_parent_map(());
+        let kind = self.tcx().def_kind(def_id);
+
+        let get_local_name = |this: &Self, name, def_id, key: DefKey| {
+            if let Some(visible_parent) = visible_parent_map.get(&def_id)
+                && let actual_parent = this.tcx().opt_parent(def_id)
+                && let DefPathData::TypeNs(_) = key.disambiguated_data.data
+                && Some(*visible_parent) != actual_parent
+            {
+                this
+                    .tcx()
+                    .module_children(visible_parent)
+                    .iter()
+                    .filter(|child| child.res.opt_def_id() == Some(def_id))
+                    .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore)
+                    .map(|child| child.ident.name)
+                    .unwrap_or(name)
+            } else {
+                name
+            }
+        };
+        if let DefKind::Variant = kind
+            && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id)
+        {
+            // If `Assoc` is unique, we don't want to talk about `Trait::Assoc`.
+            self.write_str(get_local_name(&self, *symbol, def_id, key).as_str())?;
+            return Ok((self, true));
+        }
+        if let Some(symbol) = key.get_opt_name() {
+            if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = kind
+                && let Some(parent) = self.tcx().opt_parent(def_id)
+                && let parent_key = self.tcx().def_key(parent)
+                && let Some(symbol) = parent_key.get_opt_name()
+            {
+                // Trait
+                self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?;
+                self.write_str("::")?;
+            } else if let DefKind::Variant = kind
+                && let Some(parent) = self.tcx().opt_parent(def_id)
+                && let parent_key = self.tcx().def_key(parent)
+                && let Some(symbol) = parent_key.get_opt_name()
+            {
+                // Enum
+
+                // For associated items and variants, we want the "full" path, namely, include
+                // the parent type in the path. For example, `Iterator::Item`.
+                self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?;
+                self.write_str("::")?;
+            } else if let DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Trait
+                | DefKind::TyAlias | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind
+            {
+            } else {
+                // If not covered above, like for example items out of `impl` blocks, fallback.
+                return Ok((self, false));
+            }
+            self.write_str(get_local_name(&self, symbol, def_id, key).as_str())?;
+            return Ok((self, true));
+        }
+        Ok((self, false))
+    }
+
     /// Try to see if this path can be trimmed to a unique symbol name.
     fn try_print_trimmed_def_path(
         mut self,
         def_id: DefId,
     ) -> Result<(Self::Path, bool), Self::Error> {
+        if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+            let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?;
+            if trimmed {
+                return Ok((s, true));
+            }
+            self = s;
+        }
         if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
             || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
             || NO_TRIMMED_PATH.with(|flag| flag.get())
@@ -639,17 +719,17 @@ pub trait PrettyPrinter<'tcx>:
             ty::Foreign(def_id) => {
                 p!(print_def_path(def_id, &[]));
             }
-            ty::Projection(ref data) => {
+            ty::Alias(ty::Projection, ref data) => {
                 if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
-                    && self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+                    && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
                 {
-                    return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs);
+                    return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
                 } else {
                     p!(print(data))
                 }
             }
             ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 // FIXME(eddyb) print this with `print_def_path`.
                 // We use verbose printing in 'NO_QUERIES' mode, to
                 // avoid needing to call `predicates_of`. This should
@@ -664,7 +744,9 @@ pub trait PrettyPrinter<'tcx>:
                 let parent = self.tcx().parent(def_id);
                 match self.tcx().def_kind(parent) {
                     DefKind::TyAlias | DefKind::AssocTy => {
-                        if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() {
+                        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
+                            *self.tcx().type_of(parent).kind()
+                        {
                             if d == def_id {
                                 // If the type alias directly starts with the `impl` of the
                                 // opaque type we're printing, then skip the `::{opaque#1}`.
@@ -737,11 +819,16 @@ pub trait PrettyPrinter<'tcx>:
                             p!("@", print_def_path(did.to_def_id(), substs));
                         } else {
                             let span = self.tcx().def_span(did);
+                            let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+                                FileNameDisplayPreference::Short
+                            } else {
+                                FileNameDisplayPreference::Remapped
+                            };
                             p!(write(
                                 "@{}",
                                 // This may end up in stderr diagnostics but it may also be emitted
                                 // into MIR. Hence we use the remapped path if available
-                                self.tcx().sess.source_map().span_to_embeddable_string(span)
+                                self.tcx().sess.source_map().span_to_string(span, preference)
                             ));
                         }
                     } else {
@@ -940,8 +1027,8 @@ pub trait PrettyPrinter<'tcx>:
                         // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
                         // unless we can find out what generator return type it comes from.
                         let term = if let Some(ty) = term.skip_binder().ty()
-                            && let ty::Projection(proj) = ty.kind()
-                            && let Some(assoc) = tcx.opt_associated_item(proj.item_def_id)
+                            && let ty::Alias(ty::Projection, proj) = ty.kind()
+                            && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
                             && assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
                             && assoc.name == rustc_span::sym::Return
                         {
@@ -2574,7 +2661,7 @@ define_print_and_forward_display! {
     }
 
     ty::ExistentialProjection<'tcx> {
-        let name = cx.tcx().associated_item(self.item_def_id).name;
+        let name = cx.tcx().associated_item(self.def_id).name;
         p!(write("{} = ", name), print(self.term))
     }
 
@@ -2661,8 +2748,8 @@ define_print_and_forward_display! {
       }
     }
 
-    ty::ProjectionTy<'tcx> {
-        p!(print_def_path(self.item_def_id, self.substs));
+    ty::AliasTy<'tcx> {
+        p!(print_def_path(self.def_id, self.substs));
     }
 
     ty::ClosureKind {
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index c759fb6d5e4..c4116558bd2 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -106,7 +106,7 @@ pub trait TypeRelation<'tcx>: Sized {
         T: Relate<'tcx>;
 }
 
-pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy {
+pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
         a: Self,
@@ -270,21 +270,17 @@ impl<'tcx> Relate<'tcx> for abi::Abi {
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: ty::ProjectionTy<'tcx>,
-        b: ty::ProjectionTy<'tcx>,
-    ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> {
-        if a.item_def_id != b.item_def_id {
-            Err(TypeError::ProjectionMismatched(expected_found(
-                relation,
-                a.item_def_id,
-                b.item_def_id,
-            )))
+        a: ty::AliasTy<'tcx>,
+        b: ty::AliasTy<'tcx>,
+    ) -> RelateResult<'tcx, ty::AliasTy<'tcx>> {
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let substs = relation.relate(a.substs, b.substs)?;
-            Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs })
+            Ok(relation.tcx().mk_alias_ty(a.def_id, substs))
         }
     }
 }
@@ -295,12 +291,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
         a: ty::ExistentialProjection<'tcx>,
         b: ty::ExistentialProjection<'tcx>,
     ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
-        if a.item_def_id != b.item_def_id {
-            Err(TypeError::ProjectionMismatched(expected_found(
-                relation,
-                a.item_def_id,
-                b.item_def_id,
-            )))
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let term = relation.relate_with_variance(
                 ty::Invariant,
@@ -314,7 +306,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
                 a.substs,
                 b.substs,
             )?;
-            Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term })
+            Ok(ty::ExistentialProjection { def_id: a.def_id, substs, term })
         }
     }
 }
@@ -330,7 +322,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
             Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let substs = relate_substs(relation, a.substs, b.substs)?;
-            Ok(ty::TraitRef { def_id: a.def_id, substs })
+            Ok(relation.tcx().mk_trait_ref(a.def_id, substs))
         }
     }
 }
@@ -351,7 +343,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
     }
 }
 
-#[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
+#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
 struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
 
 impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
@@ -559,14 +551,15 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
         }
 
         // these two are already handled downstream in case of lazy normalization
-        (&ty::Projection(a_data), &ty::Projection(b_data)) => {
+        (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => {
             let projection_ty = relation.relate(a_data, b_data)?;
-            Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
+            Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs))
         }
 
-        (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
-            if a_def_id == b_def_id =>
-        {
+        (
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
+        ) if a_def_id == b_def_id => {
             if relation.intercrate() {
                 // During coherence, opaque types should be treated as equal to each other, even if their generic params
                 // differ, as they could resolve to the same hidden type, even for different generic params.
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 9f70b4f1ffd..3c6800cf293 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -651,8 +651,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
             }
             ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
             ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?),
-            ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?),
-            ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?),
+            ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
 
             ty::Bool
             | ty::Char
@@ -697,8 +696,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
             ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
             ty::GeneratorWitness(ref types) => types.visit_with(visitor),
             ty::Closure(_did, ref substs) => substs.visit_with(visitor),
-            ty::Projection(ref data) => data.visit_with(visitor),
-            ty::Opaque(_, ref substs) => substs.visit_with(visitor),
+            ty::Alias(_, ref data) => data.visit_with(visitor),
 
             ty::Bool
             | ty::Char
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 9cbda95a4df..66aeebab88b 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -217,7 +217,7 @@ static_assert_size!(TyKind<'_>, 32);
 /// * `GR`: The "return type", which is the type of value returned upon
 ///   completion of the generator.
 /// * `GW`: The "generator witness".
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
 pub struct ClosureSubsts<'tcx> {
     /// Lifetime and type parameters from the enclosing function,
     /// concatenated with a tuple containing the types of the upvars.
@@ -348,7 +348,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
 }
 
 /// Similar to `ClosureSubsts`; see the above documentation for more.
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
 pub struct GeneratorSubsts<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
@@ -693,7 +693,7 @@ impl<'tcx> ExistentialPredicate<'tcx> {
         match (*self, *other) {
             (Trait(_), Trait(_)) => Ordering::Equal,
             (Projection(ref a), Projection(ref b)) => {
-                tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id))
+                tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
             }
             (AutoTrait(ref a), AutoTrait(ref b)) => {
                 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
@@ -816,14 +816,13 @@ impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> {
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
+    /// This field exists to prevent the creation of `TraitRef` without
+    /// calling [TyCtxt::mk_trait_ref].
+    pub(super) _use_mk_trait_ref_instead: (),
 }
 
 impl<'tcx> TraitRef<'tcx> {
-    pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
-        TraitRef { def_id, substs }
-    }
-
-    pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
         tcx.mk_trait_ref(
             self.def_id,
             [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)),
@@ -833,10 +832,7 @@ impl<'tcx> TraitRef<'tcx> {
     /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
     /// are the parameters defined on trait.
     pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> {
-        ty::Binder::dummy(TraitRef {
-            def_id,
-            substs: InternalSubsts::identity_for_item(tcx, def_id),
-        })
+        ty::Binder::dummy(tcx.mk_trait_ref(def_id, InternalSubsts::identity_for_item(tcx, def_id)))
     }
 
     #[inline]
@@ -850,7 +846,7 @@ impl<'tcx> TraitRef<'tcx> {
         substs: SubstsRef<'tcx>,
     ) -> ty::TraitRef<'tcx> {
         let defs = tcx.generics_of(trait_id);
-        ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) }
+        tcx.mk_trait_ref(trait_id, tcx.intern_substs(&substs[..defs.params.len()]))
     }
 }
 
@@ -980,8 +976,12 @@ where
     /// contain any bound vars that would be bound by the
     /// binder. This is commonly used to 'inject' a value T into a
     /// different binding level.
+    #[track_caller]
     pub fn dummy(value: T) -> Binder<'tcx, T> {
-        assert!(!value.has_escaping_bound_vars());
+        assert!(
+            !value.has_escaping_bound_vars(),
+            "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
+        );
         Binder(value, ty::List::empty())
     }
 
@@ -1128,28 +1128,52 @@ impl<'tcx, T> Binder<'tcx, Option<T>> {
     }
 }
 
-/// Represents the projection of an associated type. In explicit UFCS
-/// form this would be written `<T as Trait<..>>::N`.
+impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
+    pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
+        let bound_vars = self.1;
+        self.0.into_iter().map(|v| Binder(v, bound_vars))
+    }
+}
+
+/// Represents the projection of an associated type.
+///
+/// For a projection, this would be `<Ty as Trait<...>>::N`.
+///
+/// For an opaque type, there is no explicit syntax.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ProjectionTy<'tcx> {
-    /// The parameters of the associated item.
+pub struct AliasTy<'tcx> {
+    /// The parameters of the associated or opaque item.
+    ///
+    /// For a projection, these are the substitutions for the trait and the
+    /// GAT substitutions, if there are any.
+    ///
+    /// For RPIT the substitutions are for the generics of the function,
+    /// while for TAIT it is used for the generic parameters of the alias.
     pub substs: SubstsRef<'tcx>,
 
-    /// The `DefId` of the `TraitItem` for the associated type `N`.
+    /// The `DefId` of the `TraitItem` for the associated type `N` if this is a projection,
+    /// or the `OpaqueType` item if this is an opaque.
     ///
-    /// Note that this is not the `DefId` of the `TraitRef` containing this
-    /// associated type, which is in `tcx.associated_item(item_def_id).container`,
-    /// aka. `tcx.parent(item_def_id).unwrap()`.
-    pub item_def_id: DefId,
+    /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
+    /// underlying type if the type is an opaque.
+    ///
+    /// Note that if this is an associated type, this is not the `DefId` of the
+    /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
+    /// aka. `tcx.parent(def_id)`.
+    pub def_id: DefId,
+
+    /// This field exists to prevent the creation of `ProjectionTy` without using
+    /// [TyCtxt::mk_alias_ty].
+    pub(super) _use_mk_alias_ty_instead: (),
 }
 
-impl<'tcx> ProjectionTy<'tcx> {
+impl<'tcx> AliasTy<'tcx> {
     pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        match tcx.def_kind(self.item_def_id) {
-            DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id),
+        match tcx.def_kind(self.def_id) {
+            DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
             DefKind::ImplTraitPlaceholder => {
-                tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id))
+                tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
             }
             kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
         }
@@ -1162,11 +1186,11 @@ impl<'tcx> ProjectionTy<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
-        let def_id = tcx.parent(self.item_def_id);
-        assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
-        let trait_generics = tcx.generics_of(def_id);
+        debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst));
+        let trait_def_id = self.trait_def_id(tcx);
+        let trait_generics = tcx.generics_of(trait_def_id);
         (
-            ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
+            tcx.mk_trait_ref(trait_def_id, self.substs.truncate_to(tcx, trait_generics)),
             &self.substs[trait_generics.count()..],
         )
     }
@@ -1180,7 +1204,7 @@ impl<'tcx> ProjectionTy<'tcx> {
     /// as well.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
         let def_id = self.trait_def_id(tcx);
-        ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
+        tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
     }
 
     pub fn self_ty(&self) -> Ty<'tcx> {
@@ -1394,7 +1418,7 @@ impl From<BoundVar> for BoundTy {
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ExistentialProjection<'tcx> {
-    pub item_def_id: DefId,
+    pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
     pub term: Term<'tcx>,
 }
@@ -1407,7 +1431,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
     /// then this function would return an `exists T. T: Iterator` existential trait
     /// reference.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
-        let def_id = tcx.parent(self.item_def_id);
+        let def_id = tcx.parent(self.def_id);
         let subst_count = tcx.generics_of(def_id).count() - 1;
         let substs = tcx.intern_substs(&self.substs[..subst_count]);
         ty::ExistentialTraitRef { def_id, substs }
@@ -1422,10 +1446,8 @@ impl<'tcx> ExistentialProjection<'tcx> {
         debug_assert!(!self_ty.has_escaping_bound_vars());
 
         ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                item_def_id: self.item_def_id,
-                substs: tcx.mk_substs_trait(self_ty, self.substs),
-            },
+            projection_ty: tcx
+                .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs)),
             term: self.term,
         }
     }
@@ -1438,7 +1460,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
         projection_predicate.projection_ty.substs.type_at(0);
 
         Self {
-            item_def_id: projection_predicate.projection_ty.item_def_id,
+            def_id: projection_predicate.projection_ty.def_id,
             substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
             term: projection_predicate.term,
         }
@@ -1455,7 +1477,7 @@ impl<'tcx> PolyExistentialProjection<'tcx> {
     }
 
     pub fn item_def_id(&self) -> DefId {
-        self.skip_binder().item_def_id
+        self.skip_binder().def_id
     }
 }
 
@@ -1962,7 +1984,7 @@ impl<'tcx> Ty<'tcx> {
 
     #[inline]
     pub fn is_impl_trait(self) -> bool {
-        matches!(self.kind(), Opaque(..))
+        matches!(self.kind(), Alias(ty::Opaque, ..))
     }
 
     #[inline]
@@ -2029,7 +2051,7 @@ impl<'tcx> Ty<'tcx> {
             ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
             ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
 
-            ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => {
+            ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
                 let assoc_items = tcx.associated_item_def_ids(
                     tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
                 );
@@ -2109,7 +2131,7 @@ impl<'tcx> Ty<'tcx> {
 
             // type parameters only have unit metadata if they're sized, so return true
             // to make sure we double check this during confirmation
-            ty::Param(_) |  ty::Projection(_) | ty::Opaque(..) => (tcx.types.unit, true),
+            ty::Param(_) |  ty::Alias(..) => (tcx.types.unit, true),
 
             ty::Infer(ty::TyVar(_))
             | ty::Bound(..)
@@ -2185,7 +2207,7 @@ impl<'tcx> Ty<'tcx> {
 
             ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
 
-            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
+            ty::Alias(..) | ty::Param(_) => false,
 
             ty::Infer(ty::TyVar(_)) => false,
 
@@ -2241,9 +2263,12 @@ impl<'tcx> Ty<'tcx> {
             ty::Generator(..) | ty::GeneratorWitness(..) => false,
 
             // Might be, but not "trivial" so just giving the safe answer.
-            ty::Adt(..) | ty::Closure(..) | ty::Opaque(..) => false,
+            ty::Adt(..) | ty::Closure(..) => false,
+
+            // Needs normalization or revealing to determine, so no is the safe answer.
+            ty::Alias(..) => false,
 
-            ty::Projection(..) | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
+            ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
 
             ty::Bound(..) | ty::Placeholder(..) => {
                 bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a1b084a5e89..f8385c47016 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -252,7 +252,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArg<'tcx> {
     }
 }
 
-/// A substitution mapping generic parameters to new values.
+/// List of generic arguments that are gonna be used to substitute generic parameters.
 pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
 
 pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
new file mode 100644
index 00000000000..4fe85d4366f
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -0,0 +1,689 @@
+use crate::{
+    hir::place::Place as HirPlace,
+    infer::canonical::Canonical,
+    ty::{
+        self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
+        GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
+    },
+};
+use rustc_data_structures::{fx::FxHashMap, sync::Lrc, unord::UnordSet, vec_map::VecMap};
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir::{
+    def::{DefKind, Res},
+    def_id::{DefId, LocalDefId, LocalDefIdMap},
+    hir_id::OwnerId,
+    HirId, ItemLocalId, ItemLocalMap, ItemLocalSet,
+};
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_macros::HashStable;
+use rustc_middle::mir::FakeReadCause;
+use rustc_session::Session;
+use rustc_span::Span;
+use std::{
+    collections::hash_map::{self, Entry},
+    hash::Hash,
+    iter,
+};
+
+use super::RvalueScopes;
+
+#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
+pub struct TypeckResults<'tcx> {
+    /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
+    pub hir_owner: OwnerId,
+
+    /// Resolved definitions for `<T>::X` associated paths and
+    /// method calls, including those of overloaded operators.
+    type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
+
+    /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
+    /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
+    /// about the field you also need definition of the variant to which the field
+    /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
+    field_indices: ItemLocalMap<usize>,
+
+    /// Stores the types for various nodes in the AST. Note that this table
+    /// is not guaranteed to be populated outside inference. See
+    /// typeck::check::fn_ctxt for details.
+    node_types: ItemLocalMap<Ty<'tcx>>,
+
+    /// Stores the type parameters which were substituted to obtain the type
+    /// of this node. This only applies to nodes that refer to entities
+    /// parameterized by type parameters, such as generic fns, types, or
+    /// other items.
+    node_substs: ItemLocalMap<SubstsRef<'tcx>>,
+
+    /// This will either store the canonicalized types provided by the user
+    /// or the substitutions that the user explicitly gave (if any) attached
+    /// to `id`. These will not include any inferred values. The canonical form
+    /// is used to capture things like `_` or other unspecified values.
+    ///
+    /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
+    /// canonical substitutions would include only `for<X> { Vec<X> }`.
+    ///
+    /// See also `AscribeUserType` statement in MIR.
+    user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
+
+    /// Stores the canonicalized types provided by the user. See also
+    /// `AscribeUserType` statement in MIR.
+    pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
+
+    adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+
+    /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
+    pat_binding_modes: ItemLocalMap<BindingMode>,
+
+    /// Stores the types which were implicitly dereferenced in pattern binding modes
+    /// for later usage in THIR lowering. For example,
+    ///
+    /// ```
+    /// match &&Some(5i32) {
+    ///     Some(n) => {},
+    ///     _ => {},
+    /// }
+    /// ```
+    /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
+    ///
+    /// See:
+    /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
+    pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
+
+    /// Records the reasons that we picked the kind of each closure;
+    /// not all closures are present in the map.
+    closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
+
+    /// For each fn, records the "liberated" types of its arguments
+    /// and return type. Liberated means that all bound regions
+    /// (including late-bound regions) are replaced with free
+    /// equivalents. This table is not used in codegen (since regions
+    /// are erased there) and hence is not serialized to metadata.
+    ///
+    /// This table also contains the "revealed" values for any `impl Trait`
+    /// that appear in the signature and whose values are being inferred
+    /// by this function.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # use std::fmt::Debug;
+    /// fn foo(x: &u32) -> impl Debug { *x }
+    /// ```
+    ///
+    /// The function signature here would be:
+    ///
+    /// ```ignore (illustrative)
+    /// for<'a> fn(&'a u32) -> Foo
+    /// ```
+    ///
+    /// where `Foo` is an opaque type created for this function.
+    ///
+    ///
+    /// The *liberated* form of this would be
+    ///
+    /// ```ignore (illustrative)
+    /// fn(&'a u32) -> u32
+    /// ```
+    ///
+    /// Note that `'a` is not bound (it would be an `ReFree`) and
+    /// that the `Foo` opaque type is replaced by its hidden type.
+    liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
+
+    /// For each FRU expression, record the normalized types of the fields
+    /// of the struct - this is needed because it is non-trivial to
+    /// normalize while preserving regions. This table is used only in
+    /// MIR construction and hence is not serialized to metadata.
+    fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
+
+    /// For every coercion cast we add the HIR node ID of the cast
+    /// expression to this set.
+    coercion_casts: ItemLocalSet,
+
+    /// Set of trait imports actually used in the method resolution.
+    /// This is used for warning unused imports. During type
+    /// checking, this `Lrc` should not be cloned: it must have a ref-count
+    /// of 1 so that we can insert things into the set mutably.
+    pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
+
+    /// If any errors occurred while type-checking this body,
+    /// this field will be set to `Some(ErrorGuaranteed)`.
+    pub tainted_by_errors: Option<ErrorGuaranteed>,
+
+    /// All the opaque types that have hidden types set
+    /// by this function. We also store the
+    /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
+    /// even if they are only set in dead code (which doesn't show up in MIR).
+    pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
+
+    /// Tracks the minimum captures required for a closure;
+    /// see `MinCaptureInformationMap` for more details.
+    pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
+
+    /// Tracks the fake reads required for a closure and the reason for the fake read.
+    /// When performing pattern matching for closures, there are times we don't end up
+    /// reading places that are mentioned in a closure (because of _ patterns). However,
+    /// to ensure the places are initialized, we introduce fake reads.
+    /// Consider these two examples:
+    /// ``` (discriminant matching with only wildcard arm)
+    /// let x: u8;
+    /// let c = || match x { _ => () };
+    /// ```
+    /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
+    /// want to capture it. However, we do still want an error here, because `x` should have
+    /// to be initialized at the point where c is created. Therefore, we add a "fake read"
+    /// instead.
+    /// ``` (destructured assignments)
+    /// let c = || {
+    ///     let (t1, t2) = t;
+    /// }
+    /// ```
+    /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
+    /// we never capture `t`. This becomes an issue when we build MIR as we require
+    /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
+    /// issue by fake reading `t`.
+    pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
+
+    /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
+    /// by applying extended parameter rules.
+    /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
+    pub rvalue_scopes: RvalueScopes,
+
+    /// Stores the type, expression, span and optional scope span of all types
+    /// that are live across the yield of this generator (if a generator).
+    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+
+    /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
+    /// as `&[u8]`, depending on the pattern  in which they are used.
+    /// This hashset records all instances where we behave
+    /// like this to allow `const_to_pat` to reliably handle this situation.
+    pub treat_byte_string_as_slice: ItemLocalSet,
+
+    /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
+    /// on closure size.
+    pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
+}
+
+/// Whenever a value may be live across a generator yield, the type of that value winds up in the
+/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
+/// captured types that can be useful for diagnostics. In particular, it stores the span that
+/// caused a given type to be recorded, along with the scope that enclosed the value (which can
+/// be used to find the await that the value is live across).
+///
+/// For example:
+///
+/// ```ignore (pseudo-Rust)
+/// async move {
+///     let x: T = expr;
+///     foo.await
+///     ...
+/// }
+/// ```
+///
+/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
+/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
+#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub struct GeneratorInteriorTypeCause<'tcx> {
+    /// Type of the captured binding.
+    pub ty: Ty<'tcx>,
+    /// Span of the binding that was captured.
+    pub span: Span,
+    /// Span of the scope of the captured binding.
+    pub scope_span: Option<Span>,
+    /// Span of `.await` or `yield` expression.
+    pub yield_span: Span,
+    /// Expr which the type evaluated from.
+    pub expr: Option<hir::HirId>,
+}
+
+// This type holds diagnostic information on generators and async functions across crate boundaries
+// and is used to provide better error messages
+#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
+pub struct GeneratorDiagnosticData<'tcx> {
+    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+    pub hir_owner: DefId,
+    pub nodes_types: ItemLocalMap<Ty<'tcx>>,
+    pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+}
+
+impl<'tcx> TypeckResults<'tcx> {
+    pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
+        TypeckResults {
+            hir_owner,
+            type_dependent_defs: Default::default(),
+            field_indices: Default::default(),
+            user_provided_types: Default::default(),
+            user_provided_sigs: Default::default(),
+            node_types: Default::default(),
+            node_substs: Default::default(),
+            adjustments: Default::default(),
+            pat_binding_modes: Default::default(),
+            pat_adjustments: Default::default(),
+            closure_kind_origins: Default::default(),
+            liberated_fn_sigs: Default::default(),
+            fru_field_types: Default::default(),
+            coercion_casts: Default::default(),
+            used_trait_imports: Lrc::new(Default::default()),
+            tainted_by_errors: None,
+            concrete_opaque_types: Default::default(),
+            closure_min_captures: Default::default(),
+            closure_fake_reads: Default::default(),
+            rvalue_scopes: Default::default(),
+            generator_interior_types: ty::Binder::dummy(Default::default()),
+            treat_byte_string_as_slice: Default::default(),
+            closure_size_eval: Default::default(),
+        }
+    }
+
+    /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
+    pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
+        match *qpath {
+            hir::QPath::Resolved(_, ref path) => path.res,
+            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
+                .type_dependent_def(id)
+                .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
+        }
+    }
+
+    pub fn type_dependent_defs(
+        &self,
+    ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
+    }
+
+    pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
+    }
+
+    pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
+        self.type_dependent_def(id).map(|(_, def_id)| def_id)
+    }
+
+    pub fn type_dependent_defs_mut(
+        &mut self,
+    ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
+    }
+
+    pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
+    }
+
+    pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
+    }
+
+    pub fn field_index(&self, id: hir::HirId) -> usize {
+        self.field_indices().get(id).cloned().expect("no index for a field")
+    }
+
+    pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
+        self.field_indices().get(id).cloned()
+    }
+
+    pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
+    }
+
+    pub fn user_provided_types_mut(
+        &mut self,
+    ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
+    }
+
+    pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
+    }
+
+    pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
+    }
+
+    pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
+        let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
+            vec.iter()
+                .map(|item| {
+                    GeneratorInteriorTypeCause {
+                        ty: item.ty,
+                        span: item.span,
+                        scope_span: item.scope_span,
+                        yield_span: item.yield_span,
+                        expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
+                    }
+                })
+                .collect::<Vec<_>>()
+        });
+        GeneratorDiagnosticData {
+            generator_interior_types: generator_interior_type,
+            hir_owner: self.hir_owner.to_def_id(),
+            nodes_types: self.node_types.clone(),
+            adjustments: self.adjustments.clone(),
+        }
+    }
+
+    pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
+        self.node_type_opt(id).unwrap_or_else(|| {
+            bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
+        })
+    }
+
+    pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.node_types.get(&id.local_id).cloned()
+    }
+
+    pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
+    }
+
+    pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
+    }
+
+    pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.node_substs.get(&id.local_id).cloned()
+    }
+
+    /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
+    /// doesn't provide type parameter substitutions.
+    ///
+    /// [`expr_ty`]: TypeckResults::expr_ty
+    pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
+        self.node_type(pat.hir_id)
+    }
+
+    /// Returns the type of an expression as a monotype.
+    ///
+    /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
+    /// some cases, we insert `Adjustment` annotations such as auto-deref or
+    /// auto-ref.  The type returned by this function does not consider such
+    /// adjustments.  See `expr_ty_adjusted()` instead.
+    ///
+    /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
+    /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
+    /// instead of `fn(ty) -> T with T = isize`.
+    pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
+        self.node_type(expr.hir_id)
+    }
+
+    pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
+        self.node_type_opt(expr.hir_id)
+    }
+
+    pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
+    }
+
+    pub fn adjustments_mut(
+        &mut self,
+    ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
+    }
+
+    pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
+        validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
+        self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
+    }
+
+    /// Returns the type of `expr`, considering any `Adjustment`
+    /// entry recorded for that expression.
+    pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
+        self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
+    }
+
+    pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
+        self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
+    }
+
+    pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
+        // Only paths and method calls/overloaded operators have
+        // entries in type_dependent_defs, ignore the former here.
+        if let hir::ExprKind::Path(_) = expr.kind {
+            return false;
+        }
+
+        matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
+    }
+
+    pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
+        self.pat_binding_modes().get(id).copied().or_else(|| {
+            s.delay_span_bug(sp, "missing binding mode");
+            None
+        })
+    }
+
+    pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
+    }
+
+    pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
+    }
+
+    pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
+    }
+
+    pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
+    }
+
+    /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
+    /// by the closure.
+    pub fn closure_min_captures_flattened(
+        &self,
+        closure_def_id: LocalDefId,
+    ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
+        self.closure_min_captures
+            .get(&closure_def_id)
+            .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
+            .into_iter()
+            .flatten()
+    }
+
+    pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
+    }
+
+    pub fn closure_kind_origins_mut(
+        &mut self,
+    ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
+    }
+
+    pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
+    }
+
+    pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
+    }
+
+    pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
+    }
+
+    pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
+    }
+
+    pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
+        validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
+        self.coercion_casts.contains(&hir_id.local_id)
+    }
+
+    pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
+        self.coercion_casts.insert(id);
+    }
+
+    pub fn coercion_casts(&self) -> &ItemLocalSet {
+        &self.coercion_casts
+    }
+}
+
+/// Validate that the given HirId (respectively its `local_id` part) can be
+/// safely used as a key in the maps of a TypeckResults. For that to be
+/// the case, the HirId must have the same `owner` as all the other IDs in
+/// this table (signified by `hir_owner`). Otherwise the HirId
+/// would be in a different frame of reference and using its `local_id`
+/// would result in lookup errors, or worse, in silently wrong data being
+/// stored/returned.
+#[inline]
+fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+    if hir_id.owner != hir_owner {
+        invalid_hir_id_for_typeck_results(hir_owner, hir_id);
+    }
+}
+
+#[cold]
+#[inline(never)]
+fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+    ty::tls::with(|tcx| {
+        bug!(
+            "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
+            tcx.hir().node_to_string(hir_id),
+            hir_id.owner,
+            hir_owner
+        )
+    });
+}
+
+pub struct LocalTableInContext<'a, V> {
+    hir_owner: OwnerId,
+    data: &'a ItemLocalMap<V>,
+}
+
+impl<'a, V> LocalTableInContext<'a, V> {
+    pub fn contains_key(&self, id: hir::HirId) -> bool {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.contains_key(&id.local_id)
+    }
+
+    pub fn get(&self, id: hir::HirId) -> Option<&V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.get(&id.local_id)
+    }
+
+    pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
+        self.data.iter()
+    }
+}
+
+impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
+    type Output = V;
+
+    fn index(&self, key: hir::HirId) -> &V {
+        self.get(key).expect("LocalTableInContext: key not found")
+    }
+}
+
+pub struct LocalTableInContextMut<'a, V> {
+    hir_owner: OwnerId,
+    data: &'a mut ItemLocalMap<V>,
+}
+
+impl<'a, V> LocalTableInContextMut<'a, V> {
+    pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.get_mut(&id.local_id)
+    }
+
+    pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.entry(id.local_id)
+    }
+
+    pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.insert(id.local_id, val)
+    }
+
+    pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.remove(&id.local_id)
+    }
+}
+
+rustc_index::newtype_index! {
+    pub struct UserTypeAnnotationIndex {
+        derive [HashStable]
+        DEBUG_FORMAT = "UserType({})",
+        const START_INDEX = 0,
+    }
+}
+
+/// Mapping of type annotation indices to canonical user type annotations.
+pub type CanonicalUserTypeAnnotations<'tcx> =
+    IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
+
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct CanonicalUserTypeAnnotation<'tcx> {
+    pub user_ty: Box<CanonicalUserType<'tcx>>,
+    pub span: Span,
+    pub inferred_ty: Ty<'tcx>,
+}
+
+/// Canonicalized user type annotation.
+pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
+
+impl<'tcx> CanonicalUserType<'tcx> {
+    /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
+    /// i.e., each thing is mapped to a canonical variable with the same index.
+    pub fn is_identity(&self) -> bool {
+        match self.value {
+            UserType::Ty(_) => false,
+            UserType::TypeOf(_, user_substs) => {
+                if user_substs.user_self_ty.is_some() {
+                    return false;
+                }
+
+                iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
+                    match kind.unpack() {
+                        GenericArgKind::Type(ty) => match ty.kind() {
+                            ty::Bound(debruijn, b) => {
+                                // We only allow a `ty::INNERMOST` index in substitutions.
+                                assert_eq!(*debruijn, ty::INNERMOST);
+                                cvar == b.var
+                            }
+                            _ => false,
+                        },
+
+                        GenericArgKind::Lifetime(r) => match *r {
+                            ty::ReLateBound(debruijn, br) => {
+                                // We only allow a `ty::INNERMOST` index in substitutions.
+                                assert_eq!(debruijn, ty::INNERMOST);
+                                cvar == br.var
+                            }
+                            _ => false,
+                        },
+
+                        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);
+                                cvar == b
+                            }
+                            _ => false,
+                        },
+                    }
+                })
+            }
+        }
+    }
+}
+
+/// A user-given type annotation attached to a constant. These arise
+/// from constants that are named via paths, like `Foo::<A>::new` and
+/// so forth.
+#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub enum UserType<'tcx> {
+    Ty(Ty<'tcx>),
+
+    /// The canonical type is the result of `type_of(def_id)` with the
+    /// given substitutions applied.
+    TypeOf(DefId, UserSubsts<'tcx>),
+}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 9ea8dc6e69f..857f52c8a24 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -259,7 +259,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
                 ty::Tuple(_) => break,
 
-                ty::Projection(_) | ty::Opaque(..) => {
+                ty::Alias(..) => {
                     let normalized = normalize(ty);
                     if ty == normalized {
                         return ty;
@@ -332,8 +332,7 @@ impl<'tcx> TyCtxt<'tcx> {
                         break;
                     }
                 }
-                (ty::Projection(_) | ty::Opaque(..), _)
-                | (_, ty::Projection(_) | ty::Opaque(..)) => {
+                (ty::Alias(..), _) | (_, ty::Alias(..)) => {
                     // If either side is a projection, attempt to
                     // progress via normalization. (Should be safe to
                     // apply to both sides as normalization is
@@ -826,7 +825,7 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Opaque(def_id, substs) = *t.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() {
             self.expand_opaque_ty(def_id, substs).unwrap_or(t)
         } else if t.has_opaque_types() {
             t.super_fold_with(self)
@@ -938,10 +937,9 @@ impl<'tcx> Ty<'tcx> {
             | ty::Generator(..)
             | ty::GeneratorWitness(_)
             | ty::Infer(_)
-            | ty::Opaque(..)
+            | ty::Alias(..)
             | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Projection(_) => false,
+            | ty::Placeholder(_) => false,
         }
     }
 
@@ -978,10 +976,9 @@ impl<'tcx> Ty<'tcx> {
             | ty::Generator(..)
             | ty::GeneratorWitness(_)
             | ty::Infer(_)
-            | ty::Opaque(..)
+            | ty::Alias(..)
             | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Projection(_) => false,
+            | ty::Placeholder(_) => false,
         }
     }
 
@@ -1101,12 +1098,9 @@ impl<'tcx> Ty<'tcx> {
             //
             // FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
             // called for known, fully-monomorphized types.
-            ty::Projection(_)
-            | ty::Opaque(..)
-            | ty::Param(_)
-            | ty::Bound(..)
-            | ty::Placeholder(_)
-            | ty::Infer(_) => false,
+            ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => {
+                false
+            }
 
             ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
         }
@@ -1237,11 +1231,10 @@ pub fn needs_drop_components<'tcx>(
 
         // These require checking for `Copy` bounds or `Adt` destructors.
         ty::Adt(..)
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Param(_)
         | ty::Bound(..)
         | ty::Placeholder(..)
-        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Closure(..)
         | ty::Generator(..) => Ok(smallvec![ty]),
@@ -1265,13 +1258,12 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
         | ty::Never
         | ty::Foreign(_) => true,
 
-        ty::Opaque(..)
+        ty::Alias(..)
         | ty::Dynamic(..)
         | ty::Error(_)
         | ty::Bound(..)
         | ty::Param(_)
         | ty::Placeholder(_)
-        | ty::Projection(_)
         | ty::Infer(_) => false,
 
         // Not trivial because they have components, and instead of looking inside,
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 4cdfd9e5940..b302572f3ca 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -654,7 +654,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
         // ignore the inputs to a projection, as they may not appear
         // in the normalized form
         if self.just_constrained {
-            if let ty::Projection(..) | ty::Opaque(..) = t.kind() {
+            if let ty::Alias(..) = t.kind() {
                 return ControlFlow::CONTINUE;
             }
         }
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index 6eae94511e4..802925dfb04 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -1,4 +1,3 @@
-use std::convert::TryFrom;
 use std::fmt;
 
 use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar};
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 4fab5abe909..34dbb6e9f68 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -165,7 +165,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 stack.push(ty.into());
                 stack.push(lt.into());
             }
-            ty::Projection(data) => {
+            ty::Alias(_, data) => {
                 stack.extend(data.substs.iter().rev());
             }
             ty::Dynamic(obj, lt, _) => {
@@ -188,7 +188,6 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 }));
             }
             ty::Adt(_, substs)
-            | ty::Opaque(_, substs)
             | ty::Closure(_, substs)
             | ty::Generator(_, substs, _)
             | ty::FnDef(_, substs) => {
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 49d7136a2f1..2643d33cee0 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -231,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                         remainder_span,
                                         pattern,
                                         None,
-                                        Some((None, initializer_span)),
+                                        Some((Some(&destination), initializer_span)),
                                     );
                                     this.visit_primary_bindings(
                                         pattern,
@@ -373,7 +373,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // the case of `!`, no return value is required, as the block will never return.
             // Opaque types of empty bodies also need this unit assignment, in order to infer that their
             // type is actually unit. Otherwise there will be no defining use found in the MIR.
-            if destination_ty.is_unit() || matches!(destination_ty.kind(), ty::Opaque(..)) {
+            if destination_ty.is_unit()
+                || matches!(destination_ty.kind(), ty::Alias(ty::Opaque, ..))
+            {
                 // We only want to assign an implicit `()` as the return value of the block if the
                 // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
                 this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs
index eb021f47757..34fefb99e09 100644
--- a/compiler/rustc_mir_build/src/build/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/build/custom/mod.rs
@@ -20,11 +20,12 @@
 use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
+use rustc_hir::HirId;
 use rustc_index::vec::IndexVec;
 use rustc_middle::{
     mir::*,
     thir::*,
-    ty::{Ty, TyCtxt},
+    ty::{ParamEnv, Ty, TyCtxt},
 };
 use rustc_span::Span;
 
@@ -33,6 +34,7 @@ mod parse;
 pub(super) fn build_custom_mir<'tcx>(
     tcx: TyCtxt<'tcx>,
     did: DefId,
+    hir_id: HirId,
     thir: &Thir<'tcx>,
     expr: ExprId,
     params: &IndexVec<ParamId, Param<'tcx>>,
@@ -67,12 +69,16 @@ pub(super) fn build_custom_mir<'tcx>(
         parent_scope: None,
         inlined: None,
         inlined_parent_scope: None,
-        local_data: ClearCrossCrate::Clear,
+        local_data: ClearCrossCrate::Set(SourceScopeLocalData {
+            lint_root: hir_id,
+            safety: Safety::Safe,
+        }),
     });
     body.injection_phase = Some(parse_attribute(attr));
 
     let mut pctxt = ParseCtxt {
         tcx,
+        param_env: tcx.param_env(did),
         thir,
         source_scope: OUTERMOST_SOURCE_SCOPE,
         body: &mut body,
@@ -127,6 +133,7 @@ fn parse_attribute(attr: &Attribute) -> MirPhase {
 
 struct ParseCtxt<'tcx, 'body> {
     tcx: TyCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
     thir: &'body Thir<'tcx>,
     source_scope: SourceScope,
 
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 03206af33bf..2f26499a3b6 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -1,5 +1,11 @@
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
+use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::{mir::*, thir::*, ty};
+use rustc_span::Span;
+use rustc_target::abi::VariantIdx;
+
+use crate::build::custom::ParseError;
+use crate::build::expr::as_constant::as_constant_inner;
 
 use super::{parse_by_kind, PResult, ParseCtxt};
 
@@ -12,6 +18,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
             @call("mir_retag_raw", args) => {
                 Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?)))
             },
+            @call("mir_set_discriminant", args) => {
+                let place = self.parse_place(args[0])?;
+                let var = self.parse_integer_literal(args[1])? as u32;
+                Ok(StatementKind::SetDiscriminant {
+                    place: Box::new(place),
+                    variant_index: VariantIdx::from_u32(var),
+                })
+            },
             ExprKind::Assign { lhs, rhs } => {
                 let lhs = self.parse_place(*lhs)?;
                 let rhs = self.parse_rvalue(*rhs)?;
@@ -21,18 +35,60 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
     }
 
     pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
-        parse_by_kind!(self, expr_id, _, "terminator",
+        parse_by_kind!(self, expr_id, expr, "terminator",
             @call("mir_return", _args) => {
                 Ok(TerminatorKind::Return)
             },
             @call("mir_goto", args) => {
                 Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } )
             },
+            ExprKind::Match { scrutinee, arms } => {
+                let discr = self.parse_operand(*scrutinee)?;
+                self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t })
+            },
         )
     }
 
+    fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
+        let Some((otherwise, rest)) = arms.split_last() else {
+            return Err(ParseError {
+                span,
+                item_description: format!("no arms"),
+                expected: "at least one arm".to_string(),
+            })
+        };
+
+        let otherwise = &self.thir[*otherwise];
+        let PatKind::Wild = otherwise.pattern.kind else {
+            return Err(ParseError {
+                span: otherwise.span,
+                item_description: format!("{:?}", otherwise.pattern.kind),
+                expected: "wildcard pattern".to_string(),
+            })
+        };
+        let otherwise = self.parse_block(otherwise.body)?;
+
+        let mut values = Vec::new();
+        let mut targets = Vec::new();
+        for arm in rest {
+            let arm = &self.thir[*arm];
+            let PatKind::Constant { value } = arm.pattern.kind else {
+                return Err(ParseError {
+                    span: arm.pattern.span,
+                    item_description: format!("{:?}", arm.pattern.kind),
+                    expected: "constant pattern".to_string(),
+                })
+            };
+            values.push(value.eval_bits(self.tcx, self.param_env, arm.pattern.ty));
+            targets.push(self.parse_block(arm.body)?);
+        }
+
+        Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise))
+    }
+
     fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
         parse_by_kind!(self, expr_id, _, "rvalue",
+            @call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
             ExprKind::Borrow { borrow_kind, arg } => Ok(
                 Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
             ),
@@ -55,7 +111,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
             | ExprKind::ConstParam { .. }
             | ExprKind::ConstBlock { .. } => {
                 Ok(Operand::Constant(Box::new(
-                    crate::build::expr::as_constant::as_constant_inner(expr, |_| None, self.tcx)
+                    as_constant_inner(expr, |_| None, self.tcx)
                 )))
             },
             _ => self.parse_place(expr_id).map(Operand::Copy),
@@ -63,12 +119,42 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
     }
 
     fn parse_place(&self, expr_id: ExprId) -> PResult<Place<'tcx>> {
-        parse_by_kind!(self, expr_id, _, "place",
-            ExprKind::Deref { arg } => Ok(
-                self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx)
-            ),
-            _ => self.parse_local(expr_id).map(Place::from),
-        )
+        self.parse_place_inner(expr_id).map(|(x, _)| x)
+    }
+
+    fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> {
+        let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place",
+            @call("mir_field", args) => {
+                let (parent, ty) = self.parse_place_inner(args[0])?;
+                let field = Field::from_u32(self.parse_integer_literal(args[1])? as u32);
+                let field_ty = ty.field_ty(self.tcx, field);
+                let proj = PlaceElem::Field(field, field_ty);
+                let place = parent.project_deeper(&[proj], self.tcx);
+                return Ok((place, PlaceTy::from_ty(field_ty)));
+            },
+            @call("mir_variant", args) => {
+                (args[0], PlaceElem::Downcast(
+                    None,
+                    VariantIdx::from_u32(self.parse_integer_literal(args[1])? as u32)
+                ))
+            },
+            ExprKind::Deref { arg } => {
+                parse_by_kind!(self, *arg, _, "does not matter",
+                    @call("mir_make_place", args) => return self.parse_place_inner(args[0]),
+                    _ => (*arg, PlaceElem::Deref),
+                )
+            },
+            ExprKind::Index { lhs, index } => (*lhs, PlaceElem::Index(self.parse_local(*index)?)),
+            ExprKind::Field { lhs, name: field, .. } => (*lhs, PlaceElem::Field(*field, expr.ty)),
+            _ => {
+                let place = self.parse_local(expr_id).map(Place::from)?;
+                return Ok((place, PlaceTy::from_ty(expr.ty)))
+            },
+        );
+        let (parent, ty) = self.parse_place_inner(parent)?;
+        let place = parent.project_deeper(&[proj], self.tcx);
+        let ty = ty.projection_ty(self.tcx, proj);
+        Ok((place, ty))
     }
 
     fn parse_local(&self, expr_id: ExprId) -> PResult<Local> {
@@ -102,4 +188,16 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
             },
         )
     }
+
+    fn parse_integer_literal(&self, expr_id: ExprId) -> PResult<u128> {
+        parse_by_kind!(self, expr_id, expr, "constant",
+            ExprKind::Literal { .. }
+            | ExprKind::NamedConst { .. }
+            | ExprKind::NonHirLiteral { .. }
+            | ExprKind::ConstBlock { .. } => Ok({
+                let value = as_constant_inner(expr, |_| None, self.tcx);
+                value.literal.eval_bits(self.tcx, self.param_env, value.ty())
+            }),
+        )
+    }
 }
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 717c6231574..3b7ed818dc9 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -135,14 +135,14 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
             let allocation = tcx.intern_const_alloc(allocation);
             ConstValue::Slice { data: allocation, start: 0, end: s.len() }
         }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+        (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() => {
+        (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))
         }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 0814793f277..c7b3eb44dc5 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -142,7 +142,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let exchange_malloc = Operand::function_handle(
                     tcx,
                     tcx.require_lang_item(LangItem::ExchangeMalloc, Some(expr_span)),
-                    ty::List::empty(),
+                    [],
                     expr_span,
                 );
                 let storage = this.temp(tcx.mk_mut_ptr(tcx.types.u8), expr_span);
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index 00dbcaeb0c9..e9f327978aa 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -6,10 +6,8 @@ use rustc_middle::thir::*;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Builds a block of MIR statements to evaluate the THIR `expr`.
-    /// If the original expression was an AST statement,
-    /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
-    /// span of that statement (including its semicolon, if any).
-    /// The scope is used if a statement temporary must be dropped.
+    ///
+    /// The `statement_scope` is used if a statement temporary must be dropped.
     pub(crate) fn stmt_expr(
         &mut self,
         mut block: BasicBlock,
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index e90db2c7d05..7edcd46a34f 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -30,7 +30,6 @@ mod test;
 mod util;
 
 use std::borrow::Borrow;
-use std::convert::TryFrom;
 use std::mem;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 6d5a98342d2..de6a48f7cc4 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -838,8 +838,6 @@ fn trait_method<'tcx>(
     method_name: Symbol,
     substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
 ) -> ConstantKind<'tcx> {
-    let substs = tcx.mk_substs(substs.into_iter().map(Into::into));
-
     // The unhygienic comparison here is acceptable because this is only
     // used on known traits.
     let item = tcx
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index bd435f9ab00..cbd494862a0 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -7,7 +7,6 @@ use rustc_middle::thir::*;
 use rustc_middle::ty;
 use rustc_middle::ty::TypeVisitable;
 use smallvec::SmallVec;
-use std::convert::TryInto;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn field_match_pairs<'pat>(
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 007f3b55ec8..7af89dd472f 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -487,6 +487,7 @@ fn construct_fn<'tcx>(
         return custom::build_custom_mir(
             tcx,
             fn_def.did.to_def_id(),
+            fn_id,
             thir,
             expr,
             arguments,
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index fb1ea9ed300..3bb1f51650a 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -132,6 +132,18 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
     fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool {
         self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).0 == Level::Allow
     }
+
+    /// Handle closures/generators/inline-consts, which is unsafecked with their parent body.
+    fn visit_inner_body(&mut self, def: ty::WithOptConstParam<LocalDefId>) {
+        if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
+            let inner_thir = &inner_thir.borrow();
+            let hir_context = self.tcx.hir().local_def_id_to_hir_id(def.did);
+            let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self };
+            inner_visitor.visit_expr(&inner_thir[expr]);
+            // Unsafe blocks can be used in the inner body, make sure to take it into account
+            self.safety_context = inner_visitor.safety_context;
+        }
+    }
 }
 
 // Searches for accesses to layout constrained fields.
@@ -408,16 +420,11 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 } else {
                     ty::WithOptConstParam::unknown(closure_id)
                 };
-                let (closure_thir, expr) = self.tcx.thir_body(closure_def).unwrap_or_else(|_| {
-                    (self.tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0))
-                });
-                let closure_thir = &closure_thir.borrow();
-                let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
-                let mut closure_visitor =
-                    UnsafetyVisitor { thir: closure_thir, hir_context, ..*self };
-                closure_visitor.visit_expr(&closure_thir[expr]);
-                // Unsafe blocks can be used in closures, make sure to take it into account
-                self.safety_context = closure_visitor.safety_context;
+                self.visit_inner_body(closure_def);
+            }
+            ExprKind::ConstBlock { did, substs: _ } => {
+                let def_id = did.expect_local();
+                self.visit_inner_body(ty::WithOptConstParam::unknown(def_id));
             }
             ExprKind::Field { lhs, .. } => {
                 let lhs = &self.thir[lhs];
@@ -612,11 +619,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
         return;
     }
 
-    // Closures are handled by their owner, if it has a body
-    if tcx.is_closure(def.did.to_def_id()) {
-        let hir = tcx.hir();
-        let owner = hir.enclosing_body_owner(hir.local_def_id_to_hir_id(def.did));
-        tcx.ensure().thir_check_unsafety(owner);
+    // Closures and inline consts are handled by their owner, if it has a body
+    if tcx.is_typeck_child(def.did.to_def_id()) {
         return;
     }
 
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index a9ed945d4a1..57ae6a3652d 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -33,13 +33,13 @@ pub(crate) fn lit_to_const<'tcx>(
             let str_bytes = s.as_str().as_bytes();
             ty::ValTree::from_raw_bytes(tcx, str_bytes)
         }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
             if matches!(inner_ty.kind(), ty::Slice(_)) =>
         {
             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() => {
+        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
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 a21f6cd39f0..7e1f708b0d6 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
@@ -121,7 +121,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 ty::Dynamic(..) => {
                     "trait objects cannot be used in patterns".to_string()
                 }
-                ty::Opaque(..) => {
+                ty::Alias(ty::Opaque, ..) => {
                     "opaque types cannot be used in patterns".to_string()
                 }
                 ty::Closure(..) => {
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 d60e8722cb6..18e9c69c487 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -45,7 +45,7 @@
 use std::cell::Cell;
 use std::cmp::{self, max, min, Ordering};
 use std::fmt;
-use std::iter::{once, IntoIterator};
+use std::iter::once;
 use std::ops::RangeInclusive;
 
 use smallvec::{smallvec, SmallVec};
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 3e370a05376..8f80cb95e58 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -845,7 +845,7 @@ fn is_useful<'p, 'tcx>(
 
         // Opaque types can't get destructured/split, but the patterns can
         // actually hint at hidden types, so we use the patterns' types instead.
-        if let ty::Opaque(..) = ty.kind() {
+        if let ty::Alias(ty::Opaque, ..) = ty.kind() {
             if let Some(row) = rows.first() {
                 ty = row.head().ty();
             }
diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
index f102872cd2d..3224e13f7af 100644
--- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
+++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
@@ -29,56 +29,6 @@ where
     None
 }
 
-/// When enumerating the child fragments of a path, don't recurse into
-/// paths (1.) past arrays, slices, and pointers, nor (2.) into a type
-/// that implements `Drop`.
-///
-/// Places behind references or arrays are not tracked by elaboration
-/// and are always assumed to be initialized when accessible. As
-/// references and indexes can be reseated, trying to track them can
-/// only lead to trouble.
-///
-/// Places behind ADT's with a Drop impl are not tracked by
-/// elaboration since they can never have a drop-flag state that
-/// differs from that of the parent with the Drop impl.
-///
-/// In both cases, the contents can only be accessed if and only if
-/// their parents are initialized. This implies for example that there
-/// is no need to maintain separate drop flags to track such state.
-//
-// FIXME: we have to do something for moving slice patterns.
-fn place_contents_drop_state_cannot_differ<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    place: mir::Place<'tcx>,
-) -> bool {
-    let ty = place.ty(body, tcx).ty;
-    match ty.kind() {
-        ty::Array(..) => {
-            debug!(
-                "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
-                place, ty
-            );
-            false
-        }
-        ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => {
-            debug!(
-                "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
-                place, ty
-            );
-            true
-        }
-        ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
-            debug!(
-                "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
-                place, ty
-            );
-            true
-        }
-        _ => false,
-    }
-}
-
 pub fn on_lookup_result_bits<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
@@ -105,13 +55,58 @@ pub fn on_all_children_bits<'tcx, F>(
 ) where
     F: FnMut(MovePathIndex),
 {
+    #[inline]
     fn is_terminal_path<'tcx>(
         tcx: TyCtxt<'tcx>,
         body: &Body<'tcx>,
         move_data: &MoveData<'tcx>,
         path: MovePathIndex,
     ) -> bool {
-        place_contents_drop_state_cannot_differ(tcx, body, move_data.move_paths[path].place)
+        let place = move_data.move_paths[path].place;
+
+        // When enumerating the child fragments of a path, don't recurse into
+        // paths (1.) past arrays, slices, and pointers, nor (2.) into a type
+        // that implements `Drop`.
+        //
+        // Places behind references or arrays are not tracked by elaboration
+        // and are always assumed to be initialized when accessible. As
+        // references and indexes can be reseated, trying to track them can
+        // only lead to trouble.
+        //
+        // Places behind ADT's with a Drop impl are not tracked by
+        // elaboration since they can never have a drop-flag state that
+        // differs from that of the parent with the Drop impl.
+        //
+        // In both cases, the contents can only be accessed if and only if
+        // their parents are initialized. This implies for example that there
+        // is no need to maintain separate drop flags to track such state.
+        //
+        // FIXME: we have to do something for moving slice patterns.
+        let ty = place.ty(body, tcx).ty;
+        match ty.kind() {
+            ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
+                debug!(
+                    "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
+                    place, ty
+                );
+                true
+            }
+            ty::Array(..) => {
+                debug!(
+                    "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
+                    place, ty
+                );
+                false
+            }
+            ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => {
+                debug!(
+                    "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
+                    place, ty
+                );
+                true
+            }
+            _ => false,
+        }
     }
 
     fn on_all_children_bits<'tcx, F>(
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 8610792c0eb..7836ae2e7b7 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -614,7 +614,6 @@ where
         let drop_trait = tcx.require_lang_item(LangItem::Drop, None);
         let drop_fn = tcx.associated_item_def_ids(drop_trait)[0];
         let ty = self.place_ty(self.place);
-        let substs = tcx.mk_substs_trait(ty, []);
 
         let ref_ty =
             tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut });
@@ -632,7 +631,12 @@ where
             )],
             terminator: Some(Terminator {
                 kind: TerminatorKind::Call {
-                    func: Operand::function_handle(tcx, drop_fn, substs, self.source_info.span),
+                    func: Operand::function_handle(
+                        tcx,
+                        drop_fn,
+                        [ty.into()],
+                        self.source_info.span,
+                    ),
                     args: vec![Operand::Move(Place::from(ref_place))],
                     destination: unit_temp,
                     target: Some(succ),
diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
index f0e75c53ea1..8fdac7b2cf5 100644
--- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
@@ -26,7 +26,7 @@
 //! ## `PartialOrd`
 //!
 //! Given that they represent partially ordered sets, you may be surprised that [`JoinSemiLattice`]
-//! and [`MeetSemiLattice`] do not have [`PartialOrd`][std::cmp::PartialOrd] as a supertrait. This
+//! and [`MeetSemiLattice`] do not have [`PartialOrd`] as a supertrait. This
 //! is because most standard library types use lexicographic ordering instead of set inclusion for
 //! their `PartialOrd` impl. Since we do not actually need to compare lattice elements to run a
 //! dataflow analysis, there's no need for a newtype wrapper with a custom `PartialOrd` impl. The
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 18760b6c6fa..8d379b90a86 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -3,20 +3,21 @@ pub use super::*;
 use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor};
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
+use std::borrow::Cow;
 use std::cell::RefCell;
 
 #[derive(Clone)]
-pub struct MaybeStorageLive {
-    always_live_locals: BitSet<Local>,
+pub struct MaybeStorageLive<'a> {
+    always_live_locals: Cow<'a, BitSet<Local>>,
 }
 
-impl MaybeStorageLive {
-    pub fn new(always_live_locals: BitSet<Local>) -> Self {
+impl<'a> MaybeStorageLive<'a> {
+    pub fn new(always_live_locals: Cow<'a, BitSet<Local>>) -> Self {
         MaybeStorageLive { always_live_locals }
     }
 }
 
-impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive {
+impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
     type Domain = BitSet<Local>;
 
     const NAME: &'static str = "maybe_storage_live";
@@ -38,7 +39,7 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive {
     }
 }
 
-impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive {
+impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
     type Idx = Local;
 
     fn statement_effect(
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index e783d189137..9c22b5df73c 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -1,6 +1,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::hir_id::HirId;
 use rustc_hir::intravisit;
@@ -134,6 +135,28 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
         self.super_rvalue(rvalue, location);
     }
 
+    fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        if let Operand::Constant(constant) = op {
+            let maybe_uneval = match constant.literal {
+                ConstantKind::Val(..) | ConstantKind::Ty(_) => None,
+                ConstantKind::Unevaluated(uv, _) => Some(uv),
+            };
+
+            if let Some(uv) = maybe_uneval {
+                if uv.promoted.is_none() {
+                    let def_id = uv.def.def_id_for_type_of();
+                    if self.tcx.def_kind(def_id) == DefKind::InlineConst {
+                        let local_def_id = def_id.expect_local();
+                        let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
+                            self.tcx.unsafety_check_result(local_def_id);
+                        self.register_violations(violations, used_unsafe_blocks.iter().copied());
+                    }
+                }
+            }
+        }
+        self.super_operand(op, location);
+    }
+
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
         // On types with `scalar_valid_range`, prevent
         // * `&mut x.field`
@@ -410,6 +433,12 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> {
         intravisit::walk_block(self, block);
     }
 
+    fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+        if matches!(self.tcx.def_kind(c.def_id), DefKind::InlineConst) {
+            self.visit_body(self.tcx.hir().body(c.body))
+        }
+    }
+
     fn visit_fn(
         &mut self,
         fk: intravisit::FnKind<'tcx>,
@@ -471,7 +500,7 @@ fn unsafety_check_result<'tcx>(
     // `mir_built` force this.
     let body = &tcx.mir_built(def).borrow();
 
-    if body.should_skip() {
+    if body.is_custom_mir() {
         return tcx.arena.alloc(UnsafetyCheckResult {
             violations: Vec::new(),
             used_unsafe_blocks: FxHashSet::default(),
@@ -484,7 +513,7 @@ fn unsafety_check_result<'tcx>(
     let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
     checker.visit_body(&body);
 
-    let unused_unsafes = (!tcx.is_closure(def.did.to_def_id()))
+    let unused_unsafes = (!tcx.is_typeck_child(def.did.to_def_id()))
         .then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks));
 
     tcx.arena.alloc(UnsafetyCheckResult {
@@ -516,8 +545,8 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
 pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     debug!("check_unsafety({:?})", def_id);
 
-    // closures are handled by their parent fn.
-    if tcx.is_closure(def_id.to_def_id()) {
+    // closures and inline consts are handled by their parent fn.
+    if tcx.is_typeck_child(def_id.to_def_id()) {
         return;
     }
 
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index b0514e03356..044b7ce65bd 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -6,6 +6,7 @@ use std::cell::Cell;
 use either::Right;
 
 use rustc_ast::Mutability;
+use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
@@ -22,7 +23,7 @@ use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayo
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
 use rustc_span::{def_id::DefId, Span};
-use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
+use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout};
 use rustc_target::spec::abi::Abi as CallAbi;
 use rustc_trait_selection::traits;
 
@@ -186,16 +187,27 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
     type MemoryKind = !;
 
     #[inline(always)]
-    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
         // We do not check for alignment to avoid having to carry an `Align`
         // in `ConstValue::ByRef`.
-        false
+        CheckAlignment::No
     }
 
     #[inline(always)]
     fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         false // for now, we don't enforce validity
     }
+    fn alignment_check_failed(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        _has: Align,
+        _required: Align,
+        _check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()> {
+        span_bug!(
+            ecx.cur_span(),
+            "`alignment_check_failed` called when no alignment check requested"
+        )
+    }
 
     fn load_mir(
         _ecx: &InterpCx<'mir, 'tcx, Self>,
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index e9027387413..c75fe2327de 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -2,6 +2,7 @@
 //!
 //! Currently, this pass only propagates scalar values.
 
+use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::visit::{MutVisitor, Visitor};
@@ -10,6 +11,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, ValueOrPlace};
 use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects};
 use rustc_span::DUMMY_SP;
+use rustc_target::abi::Align;
 
 use crate::MirPass;
 
@@ -448,13 +450,21 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
     type MemoryKind = !;
     const PANIC_ON_ALLOC_FAIL: bool = true;
 
-    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
         unimplemented!()
     }
 
     fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         unimplemented!()
     }
+    fn alignment_check_failed(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        _has: Align,
+        _required: Align,
+        _check: CheckAlignment,
+    ) -> interpret::InterpResult<'tcx, ()> {
+        unimplemented!()
+    }
 
     fn find_mir_or_eval_fn(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 97485c4f57b..3e45319431c 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -132,15 +132,12 @@ use std::collections::hash_map::{Entry, OccupiedEntry};
 use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::{dump_mir, PassWhere};
 use rustc_middle::mir::{
     traversal, BasicBlock, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place,
     Rvalue, Statement, StatementKind, TerminatorKind,
 };
-use rustc_middle::mir::{
-    visit::{MutVisitor, PlaceContext, Visitor},
-    ProjectionElem,
-};
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::MaybeLiveLocals;
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
@@ -359,40 +356,45 @@ struct FilterInformation<'a, 'body, 'alloc, 'tcx> {
 // through these methods, and not directly.
 impl<'alloc> Candidates<'alloc> {
     /// Just `Vec::retain`, but the condition is inverted and we add debugging output
-    fn vec_remove_debug(
+    fn vec_filter_candidates(
         src: Local,
         v: &mut Vec<Local>,
-        mut f: impl FnMut(Local) -> bool,
+        mut f: impl FnMut(Local) -> CandidateFilter,
         at: Location,
     ) {
         v.retain(|dest| {
             let remove = f(*dest);
-            if remove {
+            if remove == CandidateFilter::Remove {
                 trace!("eliminating {:?} => {:?} due to conflict at {:?}", src, dest, at);
             }
-            !remove
+            remove == CandidateFilter::Keep
         });
     }
 
-    /// `vec_remove_debug` but for an `Entry`
-    fn entry_remove(
+    /// `vec_filter_candidates` but for an `Entry`
+    fn entry_filter_candidates(
         mut entry: OccupiedEntry<'_, Local, Vec<Local>>,
         p: Local,
-        f: impl FnMut(Local) -> bool,
+        f: impl FnMut(Local) -> CandidateFilter,
         at: Location,
     ) {
         let candidates = entry.get_mut();
-        Self::vec_remove_debug(p, candidates, f, at);
+        Self::vec_filter_candidates(p, candidates, f, at);
         if candidates.len() == 0 {
             entry.remove();
         }
     }
 
-    /// Removes all candidates `(p, q)` or `(q, p)` where `p` is the indicated local and `f(q)` is true.
-    fn remove_candidates_if(&mut self, p: Local, mut f: impl FnMut(Local) -> bool, at: Location) {
+    /// For all candidates `(p, q)` or `(q, p)` removes the candidate if `f(q)` says to do so
+    fn filter_candidates_by(
+        &mut self,
+        p: Local,
+        mut f: impl FnMut(Local) -> CandidateFilter,
+        at: Location,
+    ) {
         // Cover the cases where `p` appears as a `src`
         if let Entry::Occupied(entry) = self.c.entry(p) {
-            Self::entry_remove(entry, p, &mut f, at);
+            Self::entry_filter_candidates(entry, p, &mut f, at);
         }
         // And the cases where `p` appears as a `dest`
         let Some(srcs) = self.reverse.get_mut(&p) else {
@@ -401,18 +403,31 @@ impl<'alloc> Candidates<'alloc> {
         // We use `retain` here to remove the elements from the reverse set if we've removed the
         // matching candidate in the forward set.
         srcs.retain(|src| {
-            if !f(*src) {
+            if f(*src) == CandidateFilter::Keep {
                 return true;
             }
             let Entry::Occupied(entry) = self.c.entry(*src) else {
                 return false;
             };
-            Self::entry_remove(entry, *src, |dest| dest == p, at);
+            Self::entry_filter_candidates(
+                entry,
+                *src,
+                |dest| {
+                    if dest == p { CandidateFilter::Remove } else { CandidateFilter::Keep }
+                },
+                at,
+            );
             false
         });
     }
 }
 
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum CandidateFilter {
+    Keep,
+    Remove,
+}
+
 impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
     /// Filters the set of candidates to remove those that conflict.
     ///
@@ -460,7 +475,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
             for (i, statement) in data.statements.iter().enumerate().rev() {
                 self.at = Location { block, statement_index: i };
                 self.live.seek_after_primary_effect(self.at);
-                self.get_statement_write_info(&statement.kind);
+                self.write_info.for_statement(&statement.kind, self.body);
                 self.apply_conflicts();
             }
         }
@@ -469,80 +484,59 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
     fn apply_conflicts(&mut self) {
         let writes = &self.write_info.writes;
         for p in writes {
-            self.candidates.remove_candidates_if(
+            let other_skip = self.write_info.skip_pair.and_then(|(a, b)| {
+                if a == *p {
+                    Some(b)
+                } else if b == *p {
+                    Some(a)
+                } else {
+                    None
+                }
+            });
+            self.candidates.filter_candidates_by(
                 *p,
-                // It is possible that a local may be live for less than the
-                // duration of a statement This happens in the case of function
-                // calls or inline asm. Because of this, we also mark locals as
-                // conflicting when both of them are written to in the same
-                // statement.
-                |q| self.live.contains(q) || writes.contains(&q),
+                |q| {
+                    if Some(q) == other_skip {
+                        return CandidateFilter::Keep;
+                    }
+                    // It is possible that a local may be live for less than the
+                    // duration of a statement This happens in the case of function
+                    // calls or inline asm. Because of this, we also mark locals as
+                    // conflicting when both of them are written to in the same
+                    // statement.
+                    if self.live.contains(q) || writes.contains(&q) {
+                        CandidateFilter::Remove
+                    } else {
+                        CandidateFilter::Keep
+                    }
+                },
                 self.at,
             );
         }
     }
-
-    /// Gets the write info for the `statement`.
-    fn get_statement_write_info(&mut self, statement: &StatementKind<'tcx>) {
-        self.write_info.writes.clear();
-        match statement {
-            StatementKind::Assign(box (lhs, rhs)) => match rhs {
-                Rvalue::Use(op) => {
-                    if !lhs.is_indirect() {
-                        self.get_assign_use_write_info(*lhs, op);
-                        return;
-                    }
-                }
-                _ => (),
-            },
-            _ => (),
-        }
-
-        self.write_info.for_statement(statement);
-    }
-
-    fn get_assign_use_write_info(&mut self, lhs: Place<'tcx>, rhs: &Operand<'tcx>) {
-        // We register the writes for the operand unconditionally
-        self.write_info.add_operand(rhs);
-        // However, we cannot do the same thing for the `lhs` as that would always block the
-        // optimization. Instead, we consider removing candidates manually.
-        let Some(rhs) = rhs.place() else {
-            self.write_info.add_place(lhs);
-            return;
-        };
-        // Find out which candidate pair we should skip, if any
-        let Some((src, dest)) = places_to_candidate_pair(lhs, rhs, self.body) else {
-            self.write_info.add_place(lhs);
-            return;
-        };
-        self.candidates.remove_candidates_if(
-            lhs.local,
-            |other| {
-                // Check if this is the candidate pair that should not be removed
-                if (lhs.local == src && other == dest) || (lhs.local == dest && other == src) {
-                    return false;
-                }
-                // Otherwise, do the "standard" thing
-                self.live.contains(other)
-            },
-            self.at,
-        )
-    }
 }
 
 /// Describes where a statement/terminator writes to
 #[derive(Default, Debug)]
 struct WriteInfo {
     writes: Vec<Local>,
+    /// If this pair of locals is a candidate pair, completely skip processing it during this
+    /// statement. All other candidates are unaffected.
+    skip_pair: Option<(Local, Local)>,
 }
 
 impl WriteInfo {
-    fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>) {
+    fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>, body: &Body<'tcx>) {
+        self.reset();
         match statement {
             StatementKind::Assign(box (lhs, rhs)) => {
                 self.add_place(*lhs);
                 match rhs {
-                    Rvalue::Use(op) | Rvalue::Repeat(op, _) => {
+                    Rvalue::Use(op) => {
+                        self.add_operand(op);
+                        self.consider_skipping_for_assign_use(*lhs, op, body);
+                    }
+                    Rvalue::Repeat(op, _) => {
                         self.add_operand(op);
                     }
                     Rvalue::Cast(_, op, _)
@@ -586,8 +580,22 @@ impl WriteInfo {
         }
     }
 
+    fn consider_skipping_for_assign_use<'tcx>(
+        &mut self,
+        lhs: Place<'tcx>,
+        rhs: &Operand<'tcx>,
+        body: &Body<'tcx>,
+    ) {
+        let Some(rhs) = rhs.place() else {
+            return
+        };
+        if let Some(pair) = places_to_candidate_pair(lhs, rhs, body) {
+            self.skip_pair = Some(pair);
+        }
+    }
+
     fn for_terminator<'tcx>(&mut self, terminator: &TerminatorKind<'tcx>) {
-        self.writes.clear();
+        self.reset();
         match terminator {
             TerminatorKind::SwitchInt { discr: op, .. }
             | TerminatorKind::Assert { cond: op, .. } => {
@@ -657,15 +665,16 @@ impl WriteInfo {
             Operand::Copy(_) | Operand::Constant(_) => (),
         }
     }
+
+    fn reset(&mut self) {
+        self.writes.clear();
+        self.skip_pair = None;
+    }
 }
 
 /////////////////////////////////////////////////////
 // Candidate accumulation
 
-fn is_constant<'tcx>(place: Place<'tcx>) -> bool {
-    place.projection.iter().all(|p| !matches!(p, ProjectionElem::Deref | ProjectionElem::Index(_)))
-}
-
 /// If the pair of places is being considered for merging, returns the candidate which would be
 /// merged in order to accomplish this.
 ///
@@ -741,10 +750,6 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> {
             Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
         )) = &statement.kind
         {
-            if !is_constant(*lhs) || !is_constant(*rhs) {
-                return;
-            }
-
             let Some((src, dest)) = places_to_candidate_pair(*lhs, *rhs, self.body) else {
                 return;
             };
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index c08593afe9d..c097af61611 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -490,7 +490,7 @@ fn locals_live_across_suspend_points<'tcx>(
 
     // Calculate when MIR locals have live storage. This gives us an upper bound of their
     // lifetimes.
-    let mut storage_live = MaybeStorageLive::new(always_live_locals.clone())
+    let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals))
         .into_engine(tcx, body_ref)
         .iterate_to_fixpoint()
         .into_results_cursor(body_ref);
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 220cf7df9c6..9d560f5c837 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -849,7 +849,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
             };
 
             let kind = match parent_ty.ty.kind() {
-                &ty::Opaque(def_id, substs) => {
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
                 }
                 kind => kind,
diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs
index a159e617178..1708b287e56 100644
--- a/compiler/rustc_mir_transform/src/normalize_array_len.rs
+++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs
@@ -16,7 +16,8 @@ pub struct NormalizeArrayLen;
 
 impl<'tcx> MirPass<'tcx> for NormalizeArrayLen {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.mir_opt_level() >= 4
+        // See #105929
+        sess.mir_opt_level() >= 4 && sess.opts.unstable_opts.unsound_mir_opts
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 569e783fee8..6cabef92d8c 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -52,7 +52,11 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
 fn maybe_zst(ty: Ty<'_>) -> bool {
     match ty.kind() {
         // maybe ZST (could be more precise)
-        ty::Adt(..) | ty::Array(..) | ty::Closure(..) | ty::Tuple(..) | ty::Opaque(..) => true,
+        ty::Adt(..)
+        | ty::Array(..)
+        | ty::Closure(..)
+        | ty::Tuple(..)
+        | ty::Alias(ty::Opaque, ..) => true,
         // definitely ZST
         ty::FnDef(..) | ty::Never => true,
         // unreachable or can't be ZST
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index f92a0e826dc..f8b55c86287 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -336,8 +336,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         // we must subst the self_ty because it's
         // otherwise going to be TySelf and we can't index
         // or access fields of a Place of type TySelf.
-        let substs = tcx.mk_substs_trait(self_ty, []);
-        let sig = tcx.bound_fn_sig(def_id).subst(tcx, substs);
+        let sig = tcx.bound_fn_sig(def_id).subst(tcx, &[self_ty.into()]);
         let sig = tcx.erase_late_bound_regions(sig);
         let span = tcx.def_span(def_id);
 
@@ -417,10 +416,8 @@ impl<'tcx> CloneShimBuilder<'tcx> {
     ) {
         let tcx = self.tcx;
 
-        let substs = tcx.mk_substs_trait(ty, []);
-
         // `func == Clone::clone(&ty) -> ty`
-        let func_ty = tcx.mk_fn_def(self.def_id, substs);
+        let func_ty = tcx.mk_fn_def(self.def_id, [ty]);
         let func = Operand::Constant(Box::new(Constant {
             span: self.span,
             user_ty: None,
@@ -575,9 +572,8 @@ fn build_call_shim<'tcx>(
 
         // Create substitutions for the `Self` and `Args` generic parameters of the shim body.
         let arg_tup = tcx.mk_tup(untuple_args.iter());
-        let sig_substs = tcx.mk_substs_trait(ty, [ty::subst::GenericArg::from(arg_tup)]);
 
-        (Some(sig_substs), Some(untuple_args))
+        (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
     } else {
         (None, None)
     };
@@ -588,7 +584,7 @@ fn build_call_shim<'tcx>(
 
     assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
     let mut sig =
-        if let Some(sig_substs) = sig_substs { sig.subst(tcx, sig_substs) } else { sig.0 };
+        if let Some(sig_substs) = sig_substs { sig.subst(tcx, &sig_substs) } else { sig.0 };
 
     if let CallKind::Indirect(fnty) = call_kind {
         // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 475e2ec9a1d..8212a7b523b 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -35,7 +35,6 @@ use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Vis
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use smallvec::SmallVec;
-use std::convert::TryInto;
 
 pub struct SimplifyCfg {
     label: String,
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index cf7226a129c..10ea4d29cfe 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -931,10 +931,13 @@ fn visit_fn_use<'tcx>(
 ) {
     if let ty::FnDef(def_id, substs) = *ty.kind() {
         let instance = if is_direct_call {
-            ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
+            ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
         } else {
-            ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
-                .unwrap()
+            match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
+            {
+                Some(instance) => instance,
+                _ => bug!("failed to resolve instance for {ty}"),
+            }
         };
         visit_instance_use(tcx, instance, is_direct_call, source, output);
     }
@@ -1369,9 +1372,8 @@ fn create_mono_items_for_default_impls<'tcx>(
                                 trait_ref.substs[param.index as usize]
                             }
                         });
-                    let instance = ty::Instance::resolve(tcx, param_env, method.def_id, substs)
-                        .unwrap()
-                        .unwrap();
+                    let instance =
+                        ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
 
                     let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
                     if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance)
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index f1ca72de8db..f15cf54718e 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -77,3 +77,9 @@ pub struct SymbolAlreadyDefined {
     pub span: Option<Span>,
     pub symbol: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_couldnt_dump_mono_stats)]
+pub struct CouldntDumpMonoStats {
+    pub error: String,
+}
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 932edc6675f..38e1d98e44e 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -95,6 +95,11 @@
 mod default;
 mod merging;
 
+use std::cmp;
+use std::fs::{self, File};
+use std::io::{BufWriter, Write};
+use std::path::{Path, PathBuf};
+
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync;
 use rustc_hir::def_id::DefIdSet;
@@ -104,11 +109,12 @@ use rustc_middle::mir::mono::{CodegenUnit, Linkage};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
+use rustc_session::config::SwitchWithOptPath;
 use rustc_span::symbol::Symbol;
 
 use crate::collector::InliningMap;
 use crate::collector::{self, MonoItemCollectionMode};
-use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy};
+use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownPartitionStrategy};
 
 pub struct PartitioningCx<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -411,6 +417,15 @@ fn collect_and_partition_mono_items<'tcx>(
         })
         .collect();
 
+    // Output monomorphization stats per def_id
+    if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
+        if let Err(err) =
+            dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref())
+        {
+            tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
+        }
+    }
+
     if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
         let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
 
@@ -465,6 +480,67 @@ fn collect_and_partition_mono_items<'tcx>(
     (tcx.arena.alloc(mono_items), codegen_units)
 }
 
+/// Outputs stats about instantation counts and estimated size, per `MonoItem`'s
+/// def, to a file in the given output directory.
+fn dump_mono_items_stats<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    codegen_units: &[CodegenUnit<'tcx>],
+    output_directory: &Option<PathBuf>,
+    crate_name: Option<&str>,
+) -> Result<(), Box<dyn std::error::Error>> {
+    let output_directory = if let Some(ref directory) = output_directory {
+        fs::create_dir_all(directory)?;
+        directory
+    } else {
+        Path::new(".")
+    };
+
+    let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate"));
+    let output_path = output_directory.join(&filename);
+    let file = File::create(output_path)?;
+    let mut file = BufWriter::new(file);
+
+    // Gather instantiated mono items grouped by def_id
+    let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
+    for cgu in codegen_units {
+        for (&mono_item, _) in cgu.items() {
+            // Avoid variable-sized compiler-generated shims
+            if mono_item.is_user_defined() {
+                items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item);
+            }
+        }
+    }
+
+    // Output stats sorted by total instantiated size, from heaviest to lightest
+    let mut stats: Vec<_> = items_per_def_id
+        .into_iter()
+        .map(|(def_id, items)| {
+            let instantiation_count = items.len();
+            let size_estimate = items[0].size_estimate(tcx);
+            let total_estimate = instantiation_count * size_estimate;
+            (def_id, instantiation_count, size_estimate, total_estimate)
+        })
+        .collect();
+    stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate));
+
+    if !stats.is_empty() {
+        writeln!(
+            file,
+            "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
+        )?;
+        writeln!(file, "| --- | ---: | ---: | ---: |")?;
+        for (def_id, instantiation_count, size_estimate, total_estimate) in stats {
+            let item = with_no_trimmed_paths!(tcx.def_path_str(def_id));
+            writeln!(
+                file,
+                "| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |"
+            )?;
+        }
+    }
+
+    Ok(())
+}
+
 fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSet {
     let (items, cgus) = tcx.collect_and_partition_mono_items(());
     let mut visited = DefIdSet::default();
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 650076c2213..703ed09a254 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -20,7 +20,6 @@ use rustc_middle::ty::{
     Const, Ty, TyCtxt,
 };
 use rustc_span::symbol::sym;
-use std::convert::TryInto;
 use std::ops::ControlFlow;
 
 use crate::errors::UnusedGenericParams;
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index c7d239b647f..686454a8f18 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -6,7 +6,6 @@ use rustc_ast::attr;
 use rustc_ast::token::{self, Delimiter, Nonterminal};
 use rustc_errors::{error_code, fluent, Diagnostic, IntoDiagnostic, PResult};
 use rustc_span::{sym, BytePos, Span};
-use std::convert::TryInto;
 
 // Public for rustfmt usage
 #[derive(Debug)]
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index a084a701088..b97f22417cb 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -8,7 +8,6 @@ use rustc_errors::PResult;
 use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Span, DUMMY_SP};
 
-use std::convert::TryInto;
 use std::ops::Range;
 
 /// A wrapper type to ensure that the parser handles outer attributes correctly.
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index c316a4dd6b4..0191ab730c8 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -159,8 +159,6 @@ enum IsStandalone {
     Standalone,
     /// It's a subexpression, i.e., *not* standalone.
     Subexpr,
-    /// It's maybe standalone; we're not sure.
-    Maybe,
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -213,14 +211,8 @@ impl MultiSugg {
         err.multipart_suggestion(&self.msg, self.patches, self.applicability);
     }
 
-    /// Overrides individual messages and applicabilities.
-    fn emit_many(
-        err: &mut Diagnostic,
-        msg: &str,
-        applicability: Applicability,
-        suggestions: impl Iterator<Item = Self>,
-    ) {
-        err.multipart_suggestions(msg, suggestions.map(|s| s.patches), applicability);
+    fn emit_verbose(self, err: &mut Diagnostic) {
+        err.multipart_suggestion_verbose(&self.msg, self.patches, self.applicability);
     }
 }
 
@@ -1267,12 +1259,10 @@ impl<'a> Parser<'a> {
         &mut self,
         operand_expr: P<Expr>,
         op_span: Span,
-        prev_is_semi: bool,
+        start_stmt: bool,
     ) -> PResult<'a, P<Expr>> {
-        let standalone =
-            if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr };
+        let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr };
         let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
-
         self.recover_from_inc_dec(operand_expr, kind, op_span)
     }
 
@@ -1280,13 +1270,13 @@ impl<'a> Parser<'a> {
         &mut self,
         operand_expr: P<Expr>,
         op_span: Span,
+        start_stmt: bool,
     ) -> PResult<'a, P<Expr>> {
         let kind = IncDecRecovery {
-            standalone: IsStandalone::Maybe,
+            standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
             op: IncOrDec::Inc,
             fixity: UnaryFixity::Post,
         };
-
         self.recover_from_inc_dec(operand_expr, kind, op_span)
     }
 
@@ -1315,34 +1305,25 @@ impl<'a> Parser<'a> {
         };
 
         match kind.standalone {
-            IsStandalone::Standalone => self.inc_dec_standalone_suggest(kind, spans).emit(&mut err),
+            IsStandalone::Standalone => {
+                self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err)
+            }
             IsStandalone::Subexpr => {
                 let Ok(base_src) = self.span_to_snippet(base.span)
-                    else { return help_base_case(err, base) };
+                else { return help_base_case(err, base) };
                 match kind.fixity {
                     UnaryFixity::Pre => {
                         self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
                     }
                     UnaryFixity::Post => {
-                        self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
+                        // won't suggest since we can not handle the precedences
+                        // for example: `a + b++` has been parsed (a + b)++ and we can not suggest here
+                        if !matches!(base.kind, ExprKind::Binary(_, _, _)) {
+                            self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
+                        }
                     }
                 }
             }
-            IsStandalone::Maybe => {
-                let Ok(base_src) = self.span_to_snippet(base.span)
-                    else { return help_base_case(err, base) };
-                let sugg1 = match kind.fixity {
-                    UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, kind, spans),
-                    UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, kind, spans),
-                };
-                let sugg2 = self.inc_dec_standalone_suggest(kind, spans);
-                MultiSugg::emit_many(
-                    &mut err,
-                    "use `+= 1` instead",
-                    Applicability::Unspecified,
-                    [sugg1, sugg2].into_iter(),
-                )
-            }
         }
         Err(err)
     }
@@ -1392,7 +1373,6 @@ impl<'a> Parser<'a> {
         }
 
         patches.push((post_span, format!(" {}= 1", kind.op.chr())));
-
         MultiSugg {
             msg: format!("use `{}= 1` instead", kind.op.chr()),
             patches,
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index f6a6ed379a2..c0ed450b985 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -83,7 +83,7 @@ macro_rules! maybe_whole_expr {
 pub(super) enum LhsExpr {
     NotYetParsed,
     AttributesParsed(AttrWrapper),
-    AlreadyParsed(P<Expr>),
+    AlreadyParsed(P<Expr>, bool), // (expr, starts_statement)
 }
 
 impl From<Option<AttrWrapper>> for LhsExpr {
@@ -101,7 +101,7 @@ impl From<P<Expr>> for LhsExpr {
     ///
     /// This conversion does not allocate.
     fn from(expr: P<Expr>) -> Self {
-        LhsExpr::AlreadyParsed(expr)
+        LhsExpr::AlreadyParsed(expr, false)
     }
 }
 
@@ -173,7 +173,9 @@ impl<'a> Parser<'a> {
         min_prec: usize,
         lhs: LhsExpr,
     ) -> PResult<'a, P<Expr>> {
-        let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
+        let mut starts_stmt = false;
+        let mut lhs = if let LhsExpr::AlreadyParsed(expr, starts_statement) = lhs {
+            starts_stmt = starts_statement;
             expr
         } else {
             let attrs = match lhs {
@@ -292,7 +294,7 @@ impl<'a> Parser<'a> {
                 let op_span = self.prev_token.span.to(self.token.span);
                 // Eat the second `+`
                 self.bump();
-                lhs = self.recover_from_postfix_increment(lhs, op_span)?;
+                lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?;
                 continue;
             }
 
@@ -590,14 +592,15 @@ impl<'a> Parser<'a> {
             token::BinOp(token::Plus)
                 if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
             {
-                let prev_is_semi = this.prev_token == token::Semi;
+                let starts_stmt = this.prev_token == token::Semi
+                    || this.prev_token == token::CloseDelim(Delimiter::Brace);
                 let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
                 // Eat both `+`s.
                 this.bump();
                 this.bump();
 
                 let operand_expr = this.parse_dot_or_call_expr(Default::default())?;
-                this.recover_from_prefix_increment(operand_expr, pre_span, prev_is_semi)
+                this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
             }
             token::Ident(..) if this.token.is_keyword(kw::Box) => {
                 make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
@@ -1534,15 +1537,16 @@ impl<'a> Parser<'a> {
             && (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
                 || self.token.is_op())
         {
-            let lit = self.recover_unclosed_char(label_.ident, |self_| {
-                self_.sess.create_err(UnexpectedTokenAfterLabel {
-                    span: self_.token.span,
-                    remove_label: None,
-                    enclose_in_block: None,
-                })
-            });
+            let (lit, _) =
+                self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| {
+                    self_.sess.create_err(UnexpectedTokenAfterLabel {
+                        span: self_.token.span,
+                        remove_label: None,
+                        enclose_in_block: None,
+                    })
+                });
             consume_colon = false;
-            Ok(self.mk_expr(lo, ExprKind::Lit(lit.token_lit)))
+            Ok(self.mk_expr(lo, ExprKind::Lit(lit)))
         } else if !ate_colon
             && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
         {
@@ -1617,12 +1621,13 @@ impl<'a> Parser<'a> {
         Ok(expr)
     }
 
-    /// Emit an error when a char is parsed as a lifetime because of a missing quote
-    pub(super) fn recover_unclosed_char(
+    /// Emit an error when a char is parsed as a lifetime because of a missing quote.
+    pub(super) fn recover_unclosed_char<L>(
         &self,
         lifetime: Ident,
+        mk_lit_char: impl FnOnce(Symbol, Span) -> L,
         err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>,
-    ) -> ast::MetaItemLit {
+    ) -> L {
         if let Some(mut diag) =
             self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar)
         {
@@ -1644,11 +1649,7 @@ impl<'a> Parser<'a> {
                 .emit();
         }
         let name = lifetime.without_first_quote().name;
-        ast::MetaItemLit {
-            token_lit: token::Lit::new(token::LitKind::Char, name, None),
-            kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
-            span: lifetime.span,
-        }
+        mk_lit_char(name, lifetime.span)
     }
 
     /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
@@ -1764,8 +1765,8 @@ impl<'a> Parser<'a> {
             Some(lit) => match lit.kind {
                 ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
                     style,
-                    symbol: lit.token_lit.symbol,
-                    suffix: lit.token_lit.suffix,
+                    symbol: lit.symbol,
+                    suffix: lit.suffix,
                     span: lit.span,
                     symbol_unescaped,
                 }),
@@ -1775,7 +1776,23 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn handle_missing_lit(&mut self) -> PResult<'a, MetaItemLit> {
+    pub(crate) fn mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span) {
+        (token::Lit { symbol: name, suffix: None, kind: token::Char }, span)
+    }
+
+    fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
+        ast::MetaItemLit {
+            symbol: name,
+            suffix: None,
+            kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
+            span,
+        }
+    }
+
+    fn handle_missing_lit<L>(
+        &mut self,
+        mk_lit_char: impl FnOnce(Symbol, Span) -> L,
+    ) -> PResult<'a, L> {
         if let token::Interpolated(inner) = &self.token.kind {
             let expr = match inner.as_ref() {
                 token::NtExpr(expr) => Some(expr),
@@ -1799,7 +1816,7 @@ impl<'a> Parser<'a> {
         // On an error path, eagerly consider a lifetime to be an unclosed character lit
         if self.token.is_lifetime() {
             let lt = self.expect_lifetime();
-            Ok(self.recover_unclosed_char(lt.ident, err))
+            Ok(self.recover_unclosed_char(lt.ident, mk_lit_char, err))
         } else {
             Err(err(self))
         }
@@ -1808,11 +1825,13 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> {
         self.parse_opt_token_lit()
             .ok_or(())
-            .or_else(|()| self.handle_missing_lit().map(|lit| (lit.token_lit, lit.span)))
+            .or_else(|()| self.handle_missing_lit(Parser::mk_token_lit_char))
     }
 
     pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> {
-        self.parse_opt_meta_item_lit().ok_or(()).or_else(|()| self.handle_missing_lit())
+        self.parse_opt_meta_item_lit()
+            .ok_or(())
+            .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char))
     }
 
     fn recover_after_dot(&mut self) -> Option<Token> {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index ce4bc929c5c..7c2d01509de 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -22,7 +22,6 @@ use rustc_span::lev_distance::lev_distance;
 use rustc_span::source_map::{self, Span};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::DUMMY_SP;
-use std::convert::TryFrom;
 use std::mem;
 use thin_vec::ThinVec;
 use tracing::debug;
@@ -708,9 +707,9 @@ impl<'a> Parser<'a> {
             }
             match parse_item(self) {
                 Ok(None) => {
-                    let is_unnecessary_semicolon = !items.is_empty()
+                    let mut is_unnecessary_semicolon = !items.is_empty()
                         // When the close delim is `)` in a case like the following, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`,
-                        // but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`.
+                        // but the actual `token.kind` is `token::CloseDelim(Delimiter::Brace)`.
                         // This is because the `token.kind` of the close delim is treated as the same as
                         // that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
                         // Therefore, `token.kind` should not be compared here.
@@ -729,7 +728,13 @@ impl<'a> Parser<'a> {
                             .span_to_snippet(self.prev_token.span)
                             .map_or(false, |snippet| snippet == "}")
                         && self.token.kind == token::Semi;
-                    let semicolon_span = self.token.span;
+                    let mut semicolon_span = self.token.span;
+                    if !is_unnecessary_semicolon {
+                        // #105369, Detect spurious `;` before assoc fn body
+                        is_unnecessary_semicolon = self.token == token::OpenDelim(Delimiter::Brace)
+                            && self.prev_token.kind == token::Semi;
+                        semicolon_span = self.prev_token.span;
+                    }
                     // We have to bail or we'll potentially never make progress.
                     let non_item_span = self.token.span;
                     let is_let = self.token.is_keyword(kw::Let);
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index cbeec951e2d..a1981e11477 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -411,16 +411,20 @@ impl<'a> Parser<'a> {
         {
             // Recover a `'a` as a `'a'` literal
             let lt = self.expect_lifetime();
-            let lit = self.recover_unclosed_char(lt.ident, |self_| {
-                let expected = expected.unwrap_or("pattern");
-                let msg =
-                    format!("expected {}, found {}", expected, super::token_descr(&self_.token));
+            let (lit, _) =
+                self.recover_unclosed_char(lt.ident, Parser::mk_token_lit_char, |self_| {
+                    let expected = expected.unwrap_or("pattern");
+                    let msg = format!(
+                        "expected {}, found {}",
+                        expected,
+                        super::token_descr(&self_.token)
+                    );
 
-                let mut err = self_.struct_span_err(self_.token.span, &msg);
-                err.span_label(self_.token.span, format!("expected {}", expected));
-                err
-            });
-            PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit.token_lit)))
+                    let mut err = self_.struct_span_err(self_.token.span, &msg);
+                    err.span_label(self_.token.span, format!("expected {}", expected));
+                    err
+                });
+            PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit)))
         } else {
             // Try to parse everything else as literal with optional minus
             match self.parse_literal_maybe_minus() {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 42197e63797..bae7f2670cb 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -164,7 +164,7 @@ impl<'a> Parser<'a> {
             // Perform this outside of the `collect_tokens_trailing_token` closure,
             // since our outer attributes do not apply to this part of the expression
             let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
-                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
+                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true))
             })?;
             Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
         } else {
@@ -198,7 +198,7 @@ impl<'a> Parser<'a> {
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
             let e = self.maybe_recover_from_bad_qpath(e)?;
             let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
-            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?;
             StmtKind::Expr(e)
         };
         Ok(self.mk_stmt(lo.to(hi), kind))
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index a254c892478..72d38aeac7a 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -88,10 +88,7 @@ trait DefIdVisitor<'tcx> {
     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> {
         self.skeleton().visit_trait(trait_ref)
     }
-    fn visit_projection_ty(
-        &mut self,
-        projection: ty::ProjectionTy<'tcx>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<Self::BreakTy> {
         self.skeleton().visit_projection_ty(projection)
     }
     fn visit_predicates(
@@ -113,29 +110,25 @@ where
     V: DefIdVisitor<'tcx> + ?Sized,
 {
     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
-        let TraitRef { def_id, substs } = trait_ref;
+        let TraitRef { def_id, substs, .. } = trait_ref;
         self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
         if self.def_id_visitor.shallow() { ControlFlow::CONTINUE } else { substs.visit_with(self) }
     }
 
-    fn visit_projection_ty(
-        &mut self,
-        projection: ty::ProjectionTy<'tcx>,
-    ) -> ControlFlow<V::BreakTy> {
+    fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
         let tcx = self.def_id_visitor.tcx();
-        let (trait_ref, assoc_substs) = if tcx.def_kind(projection.item_def_id)
-            != DefKind::ImplTraitPlaceholder
-        {
-            projection.trait_ref_and_own_substs(tcx)
-        } else {
-            // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
-            let def_id = tcx.impl_trait_in_trait_parent(projection.item_def_id);
-            let trait_generics = tcx.generics_of(def_id);
-            (
-                ty::TraitRef { def_id, substs: projection.substs.truncate_to(tcx, trait_generics) },
-                &projection.substs[trait_generics.count()..],
-            )
-        };
+        let (trait_ref, assoc_substs) =
+            if tcx.def_kind(projection.def_id) != DefKind::ImplTraitPlaceholder {
+                projection.trait_ref_and_own_substs(tcx)
+            } else {
+                // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
+                let def_id = tcx.impl_trait_in_trait_parent(projection.def_id);
+                let trait_generics = tcx.generics_of(def_id);
+                (
+                    tcx.mk_trait_ref(def_id, projection.substs.truncate_to(tcx, trait_generics)),
+                    &projection.substs[trait_generics.count()..],
+                )
+            };
         self.visit_trait(trait_ref)?;
         if self.def_id_visitor.shallow() {
             ControlFlow::CONTINUE
@@ -214,7 +207,7 @@ where
                     }
                 }
             }
-            ty::Projection(proj) => {
+            ty::Alias(ty::Projection, proj) => {
                 if self.def_id_visitor.skip_assoc_tys() {
                     // Visitors searching for minimal visibility/reachability want to
                     // conservatively approximate associated types like `<Type as Trait>::Alias`
@@ -241,7 +234,7 @@ where
                     self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?;
                 }
             }
-            ty::Opaque(def_id, ..) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                 // Skip repeated `Opaque`s to avoid infinite recursion.
                 if self.visited_opaque_tys.insert(def_id) {
                     // The intent is to treat `impl Trait1 + Trait2` identically to
@@ -1308,15 +1301,15 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
             let is_local_static =
                 if let DefKind::Static(_) = kind { def_id.is_local() } else { false };
             if !self.item_is_accessible(def_id) && !is_local_static {
-                let sess = self.tcx.sess;
-                let sm = sess.source_map();
-                let name = match qpath {
-                    hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => {
-                        sm.span_to_snippet(qpath.span()).ok()
+                let name = match *qpath {
+                    hir::QPath::LangItem(it, ..) => {
+                        self.tcx.lang_items().get(it).map(|did| self.tcx.def_path_str(did))
                     }
+                    hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
                     hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
                 };
                 let kind = kind.descr(def_id);
+                let sess = self.tcx.sess;
                 let _ = match name {
                     Some(name) => {
                         sess.emit_err(ItemIsPrivate { span, kind, descr: (&name).into() })
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 38c7c6cce67..0e7d628c1eb 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -46,7 +46,7 @@ impl DepNodeIndex {
     pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1);
 }
 
-impl std::convert::From<DepNodeIndex> for QueryInvocationId {
+impl From<DepNodeIndex> for QueryInvocationId {
     #[inline]
     fn from(dep_node_index: DepNodeIndex) -> Self {
         QueryInvocationId(dep_node_index.as_u32())
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index 3b20ec70d73..d292f4beef2 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -22,7 +22,6 @@ use rustc_index::vec::{Idx, IndexVec};
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
 use rustc_serialize::{Decodable, Decoder, Encodable};
 use smallvec::SmallVec;
-use std::convert::TryInto;
 
 // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
 // unused so that we can store multiple index types in `CompressedHybridIndex`,
diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs
index 7a20eaceba0..cf2f04c7486 100644
--- a/compiler/rustc_query_system/src/error.rs
+++ b/compiler/rustc_query_system/src/error.rs
@@ -49,7 +49,7 @@ pub struct Cycle {
     #[primary_span]
     pub span: Span,
     pub stack_bottom: String,
-    #[subdiagnostic(eager)]
+    #[subdiagnostic]
     pub cycle_stack: Vec<CycleStack>,
     #[subdiagnostic]
     pub stack_count: StackCount,
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 4c4680b5d8e..f65846fc77f 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -9,7 +9,6 @@ use rustc_data_structures::sharded::Sharded;
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::sync::WorkerLocal;
 use rustc_index::vec::{Idx, IndexVec};
-use std::default::Default;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 49bbcf57804..701bbde6ad2 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -22,8 +22,8 @@ use {
     rustc_data_structures::{jobserver, OnDrop},
     rustc_rayon_core as rayon_core,
     rustc_span::DUMMY_SP,
-    std::iter::{self, FromIterator},
-    std::{mem, process},
+    std::iter,
+    std::process,
 };
 
 /// Represents a span and a query key.
@@ -247,7 +247,7 @@ impl QueryLatch {
             jobserver::release_thread();
             waiter.condvar.wait(&mut info);
             // Release the lock before we potentially block in `acquire_thread`
-            mem::drop(info);
+            drop(info);
             jobserver::acquire_thread();
         }
     }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index cf3e5946053..5b7a00101e9 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -566,6 +566,9 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
     /// FIXME #4948: Reuse ribs to avoid allocation.
     ribs: PerNS<Vec<Rib<'a>>>,
 
+    /// Previous poped `rib`, only used for diagnostic.
+    last_block_rib: Option<Rib<'a>>,
+
     /// The current set of local scopes, for labels.
     label_ribs: Vec<Rib<'a, NodeId>>,
 
@@ -873,6 +876,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                             // Ignore errors in function bodies if this is rustdoc
                             // Be sure not to set this until the function signature has been resolved.
                             let previous_state = replace(&mut this.in_func_body, true);
+                            // We only care block in the same function
+                            this.last_block_rib = None;
                             // Resolve the function body, potentially inside the body of an async closure
                             this.with_lifetime_rib(
                                 LifetimeRibKind::Elided(LifetimeRes::Infer),
@@ -1168,6 +1173,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 type_ns: vec![Rib::new(start_rib_kind)],
                 macro_ns: vec![Rib::new(start_rib_kind)],
             },
+            last_block_rib: None,
             label_ribs: Vec::new(),
             lifetime_ribs: Vec::new(),
             lifetime_elision_candidates: None,
@@ -3769,7 +3775,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             self.ribs[ValueNS].pop();
             self.label_ribs.pop();
         }
-        self.ribs[ValueNS].pop();
+        self.last_block_rib = self.ribs[ValueNS].pop();
         if anonymous_module.is_some() {
             self.ribs[TypeNS].pop();
         }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index d43983ea815..49bbe37ee43 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -623,6 +623,22 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 return (true, candidates);
             }
         }
+
+        // Try to find in last block rib
+        if let Some(rib) = &self.last_block_rib && let RibKind::NormalRibKind = rib.kind {
+            for (ident, &res) in &rib.bindings {
+                if let Res::Local(_) = res && path.len() == 1 &&
+                    ident.span.eq_ctxt(path[0].ident.span) &&
+                    ident.name == path[0].ident.name {
+                    err.span_help(
+                        ident.span,
+                        &format!("the binding `{}` is available in a different scope in the same function", path_str),
+                    );
+                    return (true, candidates);
+                }
+            }
+        }
+
         return (false, candidates);
     }
 
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index 7735c571310..6c310abf10a 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -36,7 +36,6 @@ use rustc_span::symbol::Ident;
 use rustc_span::*;
 
 use std::cell::Cell;
-use std::default::Default;
 use std::env;
 use std::fs::File;
 use std::io::BufWriter;
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 0afeb86fceb..0e0ebc79eb2 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -1,6 +1,5 @@
 use crate::leb128::{self, largest_max_leb128_len};
 use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::convert::TryInto;
 use std::fs::File;
 use std::io::{self, Write};
 use std::mem::MaybeUninit;
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 7a20100fd31..3bafd3730bd 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -32,7 +32,7 @@ use std::collections::btree_map::{
 use std::collections::{BTreeMap, BTreeSet};
 use std::fmt;
 use std::hash::Hash;
-use std::iter::{self, FromIterator};
+use std::iter;
 use std::path::{Path, PathBuf};
 use std::str::{self, FromStr};
 
@@ -875,18 +875,12 @@ pub struct PacRet {
     pub key: PAuthKey,
 }
 
-#[derive(Clone, Copy, Hash, Debug, PartialEq)]
+#[derive(Clone, Copy, Hash, Debug, PartialEq, Default)]
 pub struct BranchProtection {
     pub bti: bool,
     pub pac_ret: Option<PacRet>,
 }
 
-impl Default for BranchProtection {
-    fn default() -> Self {
-        BranchProtection { bti: false, pac_ret: None }
-    }
-}
-
 pub const fn default_lib_output() -> CrateType {
     CrateType::Rlib
 }
@@ -1875,7 +1869,7 @@ fn parse_opt_level(
         .into_iter()
         .flat_map(|(i, s)| {
             // NB: This can match a string without `=`.
-            if let Some("opt-level") = s.splitn(2, '=').next() { Some(i) } else { None }
+            if let Some("opt-level") = s.split('=').next() { Some(i) } else { None }
         })
         .max();
     if max_o > max_c {
@@ -1912,7 +1906,7 @@ fn select_debuginfo(
         .into_iter()
         .flat_map(|(i, s)| {
             // NB: This can match a string without `=`.
-            if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None }
+            if let Some("debuginfo") = s.split('=').next() { Some(i) } else { None }
         })
         .max();
     if max_g > max_c {
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index ee492f802a7..25d84506efa 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -176,7 +176,7 @@ impl ExprParenthesesNeeded {
 #[derive(Diagnostic)]
 #[diag(session_skipping_const_checks)]
 pub struct SkippingConstChecks {
-    #[subdiagnostic(eager)]
+    #[subdiagnostic]
     pub unleashed_features: Vec<UnleashedFeatureHelp>,
 }
 
@@ -291,20 +291,33 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
         s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
     }
 
-    // Try to lowercase the prefix if it's a valid base prefix.
-    fn fix_base_capitalisation(s: &str) -> Option<String> {
-        if let Some(stripped) = s.strip_prefix('B') {
-            Some(format!("0b{stripped}"))
-        } else if let Some(stripped) = s.strip_prefix('O') {
-            Some(format!("0o{stripped}"))
-        } else if let Some(stripped) = s.strip_prefix('X') {
-            Some(format!("0x{stripped}"))
+    // Try to lowercase the prefix if the prefix and suffix are valid.
+    fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
+        let mut chars = suffix.chars();
+
+        let base_char = chars.next().unwrap();
+        let base = match base_char {
+            'B' => 2,
+            'O' => 8,
+            'X' => 16,
+            _ => return None,
+        };
+
+        // check that the suffix contains only base-appropriate characters
+        let valid = prefix == "0"
+            && chars
+                .filter(|c| *c != '_')
+                .take_while(|c| *c != 'i' && *c != 'u')
+                .all(|c| c.to_digit(base).is_some());
+
+        if valid {
+            Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
         } else {
             None
         }
     }
 
-    let token::Lit { kind, suffix, .. } = lit;
+    let token::Lit { kind, symbol, suffix, .. } = lit;
     match err {
         // `LexerError` is an error, but it was already reported
         // by lexer, so here we don't report it the second time.
@@ -320,7 +333,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
             if looks_like_width_suffix(&['i', 'u'], suf) {
                 // If it looks like a width, try to be helpful.
                 sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
-            } else if let Some(fixed) = fix_base_capitalisation(suf) {
+            } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
                 sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
             } else {
                 sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 1b66773be6f..1855a49c1ec 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -3,7 +3,6 @@
 use smallvec::{smallvec, SmallVec};
 use std::env;
 use std::fs;
-use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 
 use crate::search_paths::{PathKind, SearchPath};
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index dab9c736d14..9e130287104 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1294,6 +1294,9 @@ options! {
         computed `block` spans (one span encompassing a block's terminator and \
         all statements). If `-Z instrument-coverage` is also enabled, create \
         an additional `.html` file showing the computed coverage spans."),
+    dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
+        parse_switch_with_opt_path, [UNTRACKED],
+        "output statistics about monomorphization collection (format: markdown)"),
     dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
         "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
     dylib_lto: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs
index d3c2c5113bc..26cd54210d0 100644
--- a/compiler/rustc_span/src/analyze_source_file.rs
+++ b/compiler/rustc_span/src/analyze_source_file.rs
@@ -175,7 +175,7 @@ cfg_if::cfg_if! {
             // There might still be a tail left to analyze
             let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
             if tail_start < src.len() {
-                analyze_source_file_generic(&src[tail_start as usize ..],
+                analyze_source_file_generic(&src[tail_start ..],
                                         src.len() - tail_start,
                                         output_offset + BytePos::from_usize(tail_start),
                                         lines,
@@ -219,7 +219,7 @@ fn analyze_source_file_generic(
     while i < scan_len {
         let byte = unsafe {
             // We verified that i < scan_len <= src.len()
-            *src_bytes.get_unchecked(i as usize)
+            *src_bytes.get_unchecked(i)
         };
 
         // How much to advance in order to get to the next UTF-8 char in the
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 335bfc3302f..2181c090027 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -259,6 +259,10 @@ impl RealFileName {
             FileNameDisplayPreference::Remapped => {
                 self.remapped_path_if_available().to_string_lossy()
             }
+            FileNameDisplayPreference::Short => self
+                .local_path_if_available()
+                .file_name()
+                .map_or_else(|| "".into(), |f| f.to_string_lossy()),
         }
     }
 }
@@ -302,6 +306,9 @@ pub enum FileNameDisplayPreference {
     /// Display the path before the application of rewrite rules provided via `--remap-path-prefix`.
     /// This is appropriate for use in user-facing output (such as diagnostics).
     Local,
+    /// Display only the filename, as a way to reduce the verbosity of the output.
+    /// This is appropriate for use in user-facing output (such as diagnostics).
+    Short,
 }
 
 pub struct FileNameDisplay<'a> {
@@ -1381,7 +1388,7 @@ impl<S: Encoder> Encodable<S> for SourceFile {
                     4 => {
                         raw_diffs = Vec::with_capacity(bytes_per_diff * num_diffs);
                         for diff in diff_iter {
-                            raw_diffs.extend_from_slice(&(diff.0 as u32).to_le_bytes());
+                            raw_diffs.extend_from_slice(&(diff.0).to_le_bytes());
                         }
                     }
                     _ => unreachable!(),
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 2ae57d9e56d..d9c87ac0ba8 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -15,11 +15,10 @@ pub use crate::*;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{AtomicU32, Lrc, MappedReadGuard, ReadGuard, RwLock};
+use std::cmp;
 use std::hash::Hash;
 use std::path::{Path, PathBuf};
 use std::sync::atomic::Ordering;
-use std::{clone::Clone, cmp};
-use std::{convert::TryFrom, unreachable};
 
 use std::fs;
 use std::io;
@@ -439,7 +438,11 @@ impl SourceMap {
         }
     }
 
-    fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPreference) -> String {
+    pub fn span_to_string(
+        &self,
+        sp: Span,
+        filename_display_pref: FileNameDisplayPreference,
+    ) -> String {
         if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
             return "no-location".to_string();
         }
@@ -447,12 +450,15 @@ impl SourceMap {
         let lo = self.lookup_char_pos(sp.lo());
         let hi = self.lookup_char_pos(sp.hi());
         format!(
-            "{}:{}:{}: {}:{}",
+            "{}:{}:{}{}",
             lo.file.name.display(filename_display_pref),
             lo.line,
             lo.col.to_usize() + 1,
-            hi.line,
-            hi.col.to_usize() + 1,
+            if let FileNameDisplayPreference::Short = filename_display_pref {
+                String::new()
+            } else {
+                format!(": {}:{}", hi.line, hi.col.to_usize() + 1)
+            }
         )
     }
 
@@ -942,7 +948,7 @@ impl SourceMap {
     /// Otherwise, the span reached to limit is returned.
     pub fn span_look_ahead(&self, span: Span, expect: Option<&str>, limit: Option<usize>) -> Span {
         let mut sp = span;
-        for _ in 0..limit.unwrap_or(100 as usize) {
+        for _ in 0..limit.unwrap_or(100_usize) {
             sp = self.next_point(sp);
             if let Ok(ref snippet) = self.span_to_snippet(sp) {
                 if expect.map_or(false, |es| snippet == es) {
@@ -1151,7 +1157,7 @@ impl FilePathMapping {
             // NOTE: We are iterating over the mapping entries from last to first
             //       because entries specified later on the command line should
             //       take precedence.
-            for &(ref from, ref to) in mapping.iter().rev() {
+            for (from, to) in mapping.iter().rev() {
                 debug!("Trying to apply {from:?} => {to:?}");
 
                 if let Ok(rest) = path.strip_prefix(from) {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 1fcf8c7a8bf..ace095736c9 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -9,7 +9,6 @@ use rustc_data_structures::sync::Lock;
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
-use std::cmp::{Ord, PartialEq, PartialOrd};
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::str;
@@ -828,6 +827,7 @@ symbols! {
         item_like_imports,
         iter,
         iter_repeat,
+        iterator_collect_fn,
         kcfi,
         keyword,
         kind,
@@ -1711,7 +1711,8 @@ impl fmt::Display for Ident {
     }
 }
 
-/// This is the most general way to print identifiers.
+/// The most general type to print identifiers.
+///
 /// AST pretty-printer is used as a fallback for turning AST structures into token streams for
 /// proc macros. Additionally, proc macros may stringify their input and expect it survive the
 /// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
@@ -1974,7 +1975,6 @@ pub mod kw {
 /// For example `sym::rustfmt` or `sym::u8`.
 pub mod sym {
     use super::Symbol;
-    use std::convert::TryInto;
 
     #[doc(inline)]
     pub use super::sym_generated::*;
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index c60a2f4671d..a59c9011ab2 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -216,8 +216,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
         match *ty.kind() {
             // Print all nominal types as paths (unlike `pretty_print_type`).
             ty::FnDef(def_id, substs)
-            | ty::Opaque(def_id, substs)
-            | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
 
@@ -287,11 +286,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
         // Similar to `pretty_path_qualified`, but for the other
         // types that are printed as paths (see `print_type` above).
         match self_ty.kind() {
-            ty::FnDef(..)
-            | ty::Opaque(..)
-            | ty::Projection(_)
-            | ty::Closure(..)
-            | ty::Generator(..)
+            ty::FnDef(..) | ty::Alias(..) | ty::Closure(..) | ty::Generator(..)
                 if trait_ref.is_none() =>
             {
                 self.print_type(self_ty)
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 87128e0f893..c9ddb084d63 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -240,7 +240,7 @@ fn encode_predicate<'tcx>(
             s.push_str(&encode_substs(tcx, trait_ref.substs, dict, options));
         }
         ty::ExistentialPredicate::Projection(projection) => {
-            let name = encode_ty_name(tcx, projection.item_def_id);
+            let name = encode_ty_name(tcx, projection.def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
             s.push_str(&encode_substs(tcx, projection.substs, dict, options));
             match projection.term.unpack() {
@@ -646,10 +646,9 @@ fn encode_ty<'tcx>(
         | ty::Error(..)
         | ty::GeneratorWitness(..)
         | ty::Infer(..)
-        | ty::Opaque(..)
+        | ty::Alias(..)
         | ty::Param(..)
-        | ty::Placeholder(..)
-        | ty::Projection(..) => {
+        | ty::Placeholder(..) => {
             bug!("encode_ty: unexpected `{:?}`", ty.kind());
         }
     };
@@ -799,10 +798,9 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
         | ty::Error(..)
         | ty::GeneratorWitness(..)
         | ty::Infer(..)
-        | ty::Opaque(..)
+        | ty::Alias(..)
         | ty::Param(..)
-        | ty::Placeholder(..)
-        | ty::Projection(..) => {
+        | ty::Placeholder(..) => {
             bug!("transform_ty: unexpected `{:?}`", ty.kind());
         }
     }
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 2cca480f271..4285aa62cb9 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -439,8 +439,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
             // Mangle all nominal types as paths.
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Opaque(def_id, substs)
-            | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => {
                 self = self.print_def_path(def_id, substs)?;
@@ -544,7 +543,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                         cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?;
                     }
                     ty::ExistentialPredicate::Projection(projection) => {
-                        let name = cx.tcx.associated_item(projection.item_def_id).name;
+                        let name = cx.tcx.associated_item(projection.def_id).name;
                         cx.push("p");
                         cx.push_ident(name.as_str());
                         cx = match projection.term.unpack() {
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index b69a0a645a4..dc2cc23ffb1 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -18,7 +18,6 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
-use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 
 #[macro_use]
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index fc6a2edabb7..44644c4733e 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -81,7 +81,7 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
         _ => os.into(),
     };
 
-    let platform_version: StaticCow<str> = match os.as_ref() {
+    let platform_version: StaticCow<str> = match os {
         "ios" => ios_lld_platform_version(),
         "tvos" => tvos_lld_platform_version(),
         "watchos" => watchos_lld_platform_version(),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 1db1d7e85ad..be994eda14c 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -45,9 +45,7 @@ use rustc_span::symbol::{sym, Symbol};
 use serde_json::Value;
 use std::borrow::Cow;
 use std::collections::BTreeMap;
-use std::convert::TryFrom;
 use std::hash::{Hash, Hasher};
-use std::iter::FromIterator;
 use std::ops::{Deref, DerefMut};
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
diff --git a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs
index e3eb9bccd5e..34934379c7e 100644
--- a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs
@@ -5,12 +5,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(
         LinkerFlavor::Unix(Cc::No),
-        &[
-            "-b64".into(),
-            "-bpT:0x100000000".into(),
-            "-bpD:0x110000000".into(),
-            "-bcdtors:all:0:s".into(),
-        ],
+        &["-b64", "-bpT:0x100000000", "-bpD:0x110000000", "-bcdtors:all:0:s"],
     );
 
     Target {
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 8e04da4f9be..aef2f8ff991 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -579,14 +579,14 @@ impl<'tcx> AutoTraitFinder<'tcx> {
     pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
         match ty.kind() {
             ty::Param(_) => true,
-            ty::Projection(p) => self.is_of_param(p.self_ty()),
+            ty::Alias(ty::Projection, p) => self.is_of_param(p.self_ty()),
             _ => false,
         }
     }
 
     fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
         if let Some(ty) = p.term().skip_binder().ty() {
-            matches!(ty.kind(), ty::Projection(proj) if proj == &p.skip_binder().projection_ty)
+            matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_ty)
         } else {
             false
         }
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 899e30275a0..7c569621cfe 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -659,7 +659,7 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
             | ty::RawPtr(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Projection(..) => self.found_non_local_ty(ty),
+            | ty::Alias(ty::Projection, ..) => self.found_non_local_ty(ty),
 
             ty::Param(..) => self.found_param_ty(ty),
 
@@ -704,7 +704,7 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
                 );
                 ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
             }
-            ty::Opaque(..) => {
+            ty::Alias(ty::Opaque, ..) => {
                 // This merits some explanation.
                 // Normally, opaque types are not involved when performing
                 // coherence checking, since it is illegal to directly
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
index 752b53fbc3f..0c1717cff33 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -1,52 +1,101 @@
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::InferCtxt;
+use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
+use rustc_infer::traits::util::elaborate_predicates_with_span;
 use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
-use rustc_span::DUMMY_SP;
+use rustc_middle::ty;
+use rustc_span::{Span, DUMMY_SP};
 
 use crate::traits::ObligationCtxt;
 
+pub enum Ambiguity {
+    DefId(DefId),
+    ParamEnv(Span),
+}
+
 pub fn recompute_applicable_impls<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligation: &TraitObligation<'tcx>,
-) -> Vec<DefId> {
+) -> Vec<Ambiguity> {
     let tcx = infcx.tcx;
     let param_env = obligation.param_env;
-    let dummy_cause = ObligationCause::dummy();
+
     let impl_may_apply = |impl_def_id| {
         let ocx = ObligationCtxt::new_in_snapshot(infcx);
         let placeholder_obligation =
             infcx.replace_bound_vars_with_placeholders(obligation.predicate);
         let obligation_trait_ref =
-            ocx.normalize(&dummy_cause, param_env, placeholder_obligation.trait_ref);
+            ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
 
         let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
         let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
         let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
 
-        if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) {
+        if let Err(_) =
+            ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
+        {
             return false;
         }
 
         let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
-        ocx.register_obligations(
-            impl_predicates
-                .predicates
-                .iter()
-                .map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)),
+        ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
+            Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
+        }));
+
+        ocx.select_where_possible().is_empty()
+    };
+
+    let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
+        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let placeholder_obligation =
+            infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+        let obligation_trait_ref =
+            ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
+
+        let param_env_predicate = infcx.replace_bound_vars_with_fresh_vars(
+            DUMMY_SP,
+            LateBoundRegionConversionTime::HigherRankedType,
+            poly_trait_predicate,
         );
+        let param_env_trait_ref =
+            ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
+
+        if let Err(_) =
+            ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref)
+        {
+            return false;
+        }
 
         ocx.select_where_possible().is_empty()
     };
 
-    let mut impls = Vec::new();
+    let mut ambiguities = Vec::new();
+
     tcx.for_each_relevant_impl(
         obligation.predicate.def_id(),
         obligation.predicate.skip_binder().trait_ref.self_ty(),
         |impl_def_id| {
-            if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) {
-                impls.push(impl_def_id)
+            if infcx.probe(|_| impl_may_apply(impl_def_id)) {
+                ambiguities.push(Ambiguity::DefId(impl_def_id))
             }
         },
     );
-    impls
+
+    let predicates =
+        tcx.predicates_of(obligation.cause.body_id.owner.to_def_id()).instantiate_identity(tcx);
+    for obligation in
+        elaborate_predicates_with_span(tcx, std::iter::zip(predicates.predicates, predicates.spans))
+    {
+        let kind = obligation.predicate.kind();
+        if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
+            && param_env_candidate_may_apply(kind.rebind(trait_pred))
+        {
+            if kind.rebind(trait_pred.trait_ref) == ty::TraitRef::identity(tcx, trait_pred.def_id()) {
+                ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id())))
+            } else {
+                ambiguities.push(Ambiguity::ParamEnv(obligation.cause.span))
+            }
+        }
+    }
+
+    ambiguities
 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
new file mode 100644
index 00000000000..cb373d65772
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
@@ -0,0 +1,74 @@
+use crate::infer::InferCtxt;
+
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub struct CollectAllMismatches<'a, 'tcx> {
+    pub infcx: &'a InferCtxt<'tcx>,
+    pub param_env: ty::ParamEnv<'tcx>,
+    pub errors: Vec<TypeError<'tcx>>,
+}
+
+impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
+    fn tag(&self) -> &'static str {
+        "CollectAllMismatches"
+    }
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+    fn intercrate(&self) -> bool {
+        false
+    }
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.param_env
+    }
+    fn a_is_expected(&self) -> bool {
+        true
+    } // irrelevant
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+    fn relate_with_variance<T: Relate<'tcx>>(
+        &mut self,
+        _: ty::Variance,
+        _: ty::VarianceDiagInfo<'tcx>,
+        a: T,
+        b: T,
+    ) -> RelateResult<'tcx, T> {
+        self.relate(a, b)
+    }
+    fn regions(
+        &mut self,
+        a: ty::Region<'tcx>,
+        _b: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        Ok(a)
+    }
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        if a == b || matches!(a.kind(), ty::Infer(_)) || matches!(b.kind(), ty::Infer(_)) {
+            return Ok(a);
+        }
+        relate::super_relate_tys(self, a, b).or_else(|e| {
+            self.errors.push(e);
+            Ok(a)
+        })
+    }
+    fn consts(
+        &mut self,
+        a: ty::Const<'tcx>,
+        b: ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+        if a == b {
+            return Ok(a);
+        }
+        relate::super_relate_consts(self, a, b) // could do something similar here for constants!
+    }
+    fn binders<T: Relate<'tcx>>(
+        &mut self,
+        a: ty::Binder<'tcx, T>,
+        b: ty::Binder<'tcx, T>,
+    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> {
+        Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
+    }
+}
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 dda7b2b2fa5..2dd2c568bab 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1,4 +1,5 @@
 mod ambiguity;
+pub mod method_chain;
 pub mod on_unimplemented;
 pub mod suggestions;
 
@@ -34,14 +35,14 @@ use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::print::{FmtPrinter, Print};
+use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
 use rustc_middle::ty::{
     self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
     TypeVisitable,
 };
 use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::sym;
 use rustc_span::{ExpnKind, Span, DUMMY_SP};
 use std::fmt;
 use std::iter;
@@ -536,7 +537,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             |err| {
                 self.note_obligation_cause_code(
                     err,
-                    &predicate,
+                    predicate,
                     obligation.param_env,
                     obligation.cause.code(),
                     &mut vec![],
@@ -597,6 +598,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 // can get a better error message by performing HIR-based well-formedness checking.
                 if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
                     root_obligation.cause.code().peel_derives()
+                    && !obligation.predicate.has_non_region_infer()
                 {
                     if let Some(cause) = self
                         .tcx
@@ -978,6 +980,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 trait_ref,
                                 obligation.cause.body_id,
                                 &mut err,
+                                true,
                             ) {
                                 // This is *almost* equivalent to
                                 // `obligation.cause.code().peel_derives()`, but it gives us the
@@ -1013,6 +1016,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                         trait_ref,
                                         obligation.cause.body_id,
                                         &mut err,
+                                        true,
                                     );
                                 }
                             }
@@ -1032,7 +1036,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             && self.fallback_has_occurred
                         {
                             let predicate = trait_predicate.map_bound(|trait_pred| {
-                                trait_pred.with_self_type(self.tcx, self.tcx.mk_unit())
+                                trait_pred.with_self_ty(self.tcx, self.tcx.mk_unit())
                             });
                             let unit_obligation = obligation.with(tcx, predicate);
                             if self.predicate_may_hold(&unit_obligation) {
@@ -1232,6 +1236,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     _ => None,
                 };
 
+                let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
                 let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
 
                 if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
@@ -1285,6 +1290,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         found_trait_ref,
                         expected_trait_ref,
                         obligation.cause.code(),
+                        found_node,
                     )
                 } else {
                     let (closure_span, closure_arg_span, found) = found_did
@@ -1430,6 +1436,7 @@ trait InferCtxtPrivExt<'tcx> {
         trait_ref: ty::PolyTraitRef<'tcx>,
         body_id: hir::HirId,
         err: &mut Diagnostic,
+        other: bool,
     ) -> bool;
 
     /// Gets the parent trait chain start
@@ -1480,7 +1487,7 @@ trait InferCtxtPrivExt<'tcx> {
     fn annotate_source_of_ambiguity(
         &self,
         err: &mut Diagnostic,
-        impls: &[DefId],
+        impls: &[ambiguity::Ambiguity],
         predicate: ty::Predicate<'tcx>,
     );
 
@@ -1586,7 +1593,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 {
                     self.note_obligation_cause_code(
                         &mut diag,
-                        &error.obligation.predicate,
+                        error.obligation.predicate,
                         error.obligation.param_env,
                         code,
                         &mut vec![],
@@ -1629,18 +1636,30 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     infer::LateBoundRegionConversionTime::HigherRankedType,
                     bound_predicate.rebind(data),
                 );
-                let normalized_ty = ocx.normalize(
-                    &obligation.cause,
-                    obligation.param_env,
-                    self.tcx
-                        .mk_projection(data.projection_ty.item_def_id, data.projection_ty.substs),
-                );
+                let unnormalized_term = match data.term.unpack() {
+                    ty::TermKind::Ty(_) => self
+                        .tcx
+                        .mk_projection(data.projection_ty.def_id, data.projection_ty.substs)
+                        .into(),
+                    ty::TermKind::Const(ct) => self
+                        .tcx
+                        .mk_const(
+                            ty::UnevaluatedConst {
+                                def: ty::WithOptConstParam::unknown(data.projection_ty.def_id),
+                                substs: data.projection_ty.substs,
+                            },
+                            ct.ty(),
+                        )
+                        .into(),
+                };
+                let normalized_term =
+                    ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
 
                 debug!(?obligation.cause, ?obligation.param_env);
 
-                debug!(?normalized_ty, data.ty = ?data.term);
+                debug!(?normalized_term, data.ty = ?data.term);
 
-                let is_normalized_ty_expected = !matches!(
+                let is_normalized_term_expected = !matches!(
                     obligation.cause.code().peel_derives(),
                     ObligationCauseCode::ItemObligation(_)
                         | ObligationCauseCode::BindingObligation(_, _)
@@ -1649,7 +1668,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         | ObligationCauseCode::ObjectCastObligation(..)
                         | ObligationCauseCode::OpaqueType
                 );
-                let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error());
 
                 // constrain inference variables a bit more to nested obligations from normalize so
                 // we can have more helpful errors.
@@ -1658,11 +1676,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 if let Err(new_err) = ocx.eq_exp(
                     &obligation.cause,
                     obligation.param_env,
-                    is_normalized_ty_expected,
-                    normalized_ty,
-                    expected_ty,
+                    is_normalized_term_expected,
+                    normalized_term,
+                    data.term,
                 ) {
-                    (Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)), new_err)
+                    (Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err)
                 } else {
                     (None, error.err)
                 }
@@ -1671,12 +1689,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             };
 
             let msg = values
-                .and_then(|(predicate, _, normalized_ty, expected_ty)| {
-                    self.maybe_detailed_projection_msg(
-                        predicate,
-                        normalized_ty.into(),
-                        expected_ty.into(),
-                    )
+                .and_then(|(predicate, _, normalized_term, expected_term)| {
+                    self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
                 })
                 .unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate));
             let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
@@ -1684,10 +1698,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             let secondary_span = match predicate.kind().skip_binder() {
                 ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => self
                     .tcx
-                    .opt_associated_item(proj.projection_ty.item_def_id)
+                    .opt_associated_item(proj.projection_ty.def_id)
                     .and_then(|trait_assoc_item| {
                         self.tcx
-                            .trait_of_item(proj.projection_ty.item_def_id)
+                            .trait_of_item(proj.projection_ty.def_id)
                             .map(|id| (trait_assoc_item, id))
                     })
                     .and_then(|(trait_assoc_item, id)| {
@@ -1743,21 +1757,26 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let trait_def_id = pred.projection_ty.trait_def_id(self.tcx);
         let self_ty = pred.projection_ty.self_ty();
 
-        if Some(pred.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() {
-            Some(format!(
-                "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it returns `{normalized_ty}`",
-                fn_kind = self_ty.prefix_string(self.tcx)
-            ))
-        } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
-            Some(format!(
-                "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it resolves to `{normalized_ty}`"
-            ))
-        } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
-            Some(format!(
-                "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it yields `{normalized_ty}`"
-            ))
-        } else {
-            None
+        with_forced_trimmed_paths! {
+            if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
+                Some(format!(
+                    "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it \
+                     returns `{normalized_ty}`",
+                    fn_kind = self_ty.prefix_string(self.tcx)
+                ))
+            } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
+                Some(format!(
+                    "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
+                     resolves to `{normalized_ty}`"
+                ))
+            } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
+                Some(format!(
+                    "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
+                     yields `{normalized_ty}`"
+                ))
+            } else {
+                None
+            }
         }
     }
 
@@ -1786,8 +1805,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 ty::Closure(..) => Some(9),
                 ty::Tuple(..) => Some(10),
                 ty::Param(..) => Some(11),
-                ty::Projection(..) => Some(12),
-                ty::Opaque(..) => Some(13),
+                ty::Alias(ty::Projection, ..) => Some(12),
+                ty::Alias(ty::Opaque, ..) => Some(13),
                 ty::Never => Some(14),
                 ty::Adt(..) => Some(15),
                 ty::Generator(..) => Some(16),
@@ -1885,7 +1904,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_ref: ty::PolyTraitRef<'tcx>,
         body_id: hir::HirId,
         err: &mut Diagnostic,
+        other: bool,
     ) -> bool {
+        let other = if other { "other " } else { "" };
         let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
             candidates.sort();
             candidates.dedup();
@@ -1936,7 +1957,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             candidates.dedup();
             let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
             err.help(&format!(
-                "the following other types implement trait `{}`:{}{}",
+                "the following {other}types implement trait `{}`:{}{}",
                 trait_ref.print_only_trait_path(),
                 candidates[..end].join(""),
                 if len > 9 { format!("\nand {} others", len - 8) } else { String::new() }
@@ -2077,8 +2098,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
     ) -> PredicateObligation<'tcx> {
-        let trait_pred = trait_ref_and_ty
-            .map_bound(|(tr, new_self_ty)| tr.with_self_type(self.tcx, new_self_ty));
+        let trait_pred =
+            trait_ref_and_ty.map_bound(|(tr, new_self_ty)| tr.with_self_ty(self.tcx, new_self_ty));
 
         Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred)
     }
@@ -2172,19 +2193,40 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 let mut selcx = SelectionContext::new(&self);
                 match selcx.select_from_obligation(&obligation) {
                     Ok(None) => {
-                        let impls = ambiguity::recompute_applicable_impls(self.infcx, &obligation);
+                        let ambiguities =
+                            ambiguity::recompute_applicable_impls(self.infcx, &obligation);
                         let has_non_region_infer =
                             trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer());
                         // It doesn't make sense to talk about applicable impls if there are more
                         // than a handful of them.
-                        if impls.len() > 1 && impls.len() < 5 && has_non_region_infer {
-                            self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
+                        if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
+                            if self.tainted_by_errors().is_some() && subst.is_none() {
+                                // If `subst.is_none()`, then this is probably two param-env
+                                // candidates or impl candidates that are equal modulo lifetimes.
+                                // Therefore, if we've already emitted an error, just skip this
+                                // one, since it's not particularly actionable.
+                                err.cancel();
+                                return;
+                            }
+                            self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
                         } else {
                             if self.tainted_by_errors().is_some() {
                                 err.cancel();
                                 return;
                             }
                             err.note(&format!("cannot satisfy `{}`", predicate));
+                            let impl_candidates = self.find_similar_impl_candidates(
+                                predicate.to_opt_poly_trait_pred().unwrap(),
+                            );
+                            if impl_candidates.len() < 10 {
+                                self.report_similar_impl_candidates(
+                                    impl_candidates,
+                                    trait_ref,
+                                    body_id.map(|id| id.hir_id).unwrap_or(obligation.cause.body_id),
+                                    &mut err,
+                                    false,
+                                );
+                            }
                         }
                     }
                     _ => {
@@ -2196,60 +2238,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
                 }
 
-                if let ObligationCauseCode::ItemObligation(def_id) | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code() {
-                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let Ok(snippet) = &self.tcx.sess.source_map().span_to_snippet(span)
-                    && let ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ExprBindingObligation(def_id, ..)
-                        = *obligation.cause.code()
+                if let ObligationCauseCode::ItemObligation(def_id)
+                | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code()
                 {
-                    let generics = self.tcx.generics_of(def_id);
-                    if generics.params.iter().any(|p| p.name != kw::SelfUpper)
-                        && !snippet.ends_with('>')
-                        && !generics.has_impl_trait()
-                        && !self.tcx.is_fn_trait(def_id)
-                    {
-                        // FIXME: To avoid spurious suggestions in functions where type arguments
-                        // where already supplied, we check the snippet to make sure it doesn't
-                        // end with a turbofish. Ideally we would have access to a `PathSegment`
-                        // instead. Otherwise we would produce the following output:
-                        //
-                        // error[E0283]: type annotations needed
-                        //   --> $DIR/issue-54954.rs:3:24
-                        //    |
-                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
-                        //    |                        |
-                        //    |                        cannot infer type
-                        //    |                        help: consider specifying the type argument
-                        //    |                        in the function call:
-                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
-                        // ...
-                        // LL |     const fn const_val<T: Sized>() -> usize {
-                        //    |                        - required by this bound in `Tt::const_val`
-                        //    |
-                        //    = note: cannot satisfy `_: Tt`
-
-                        // Clear any more general suggestions in favor of our specific one
-                        err.clear_suggestions();
-
-                        err.span_suggestion_verbose(
-                            span.shrink_to_hi(),
-                            &format!(
-                                "consider specifying the type argument{} in the function call",
-                                pluralize!(generics.params.len()),
-                            ),
-                            format!(
-                                "::<{}>",
-                                generics
-                                    .params
-                                    .iter()
-                                    .map(|p| p.name.to_string())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            ),
-                            Applicability::HasPlaceholders,
-                        );
-                    }
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
                 }
 
                 if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =
@@ -2320,18 +2312,19 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
 
                         if trait_impls.blanket_impls().is_empty()
-                            && let Some((impl_ty, _)) = trait_impls.non_blanket_impls().iter().next()
-                            && let Some(impl_def_id) = impl_ty.def() {
-                            let message = if trait_impls.non_blanket_impls().len() == 1 {
+                            && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
+                        {
+                            let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
+                            let message = if non_blanket_impl_count == 1 {
                                 "use the fully-qualified path to the only available implementation".to_string()
                             } else {
                                 format!(
                                     "use a fully-qualified path to a specific available implementation ({} found)",
-                                    trait_impls.non_blanket_impls().len()
+                                    non_blanket_impl_count
                                 )
                             };
                             let mut suggestions = vec![(
-                                trait_path_segment.ident.span.shrink_to_lo(),
+                                path.span.shrink_to_lo(),
                                 format!("<{} as ", self.tcx.type_of(impl_def_id))
                             )];
                             if let Some(generic_arg) = trait_path_segment.args {
@@ -2464,21 +2457,30 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     fn annotate_source_of_ambiguity(
         &self,
         err: &mut Diagnostic,
-        impls: &[DefId],
+        ambiguities: &[ambiguity::Ambiguity],
         predicate: ty::Predicate<'tcx>,
     ) {
         let mut spans = vec![];
         let mut crates = vec![];
         let mut post = vec![];
-        for def_id in impls {
-            match self.tcx.span_of_impl(*def_id) {
-                Ok(span) => spans.push(span),
-                Err(name) => {
-                    crates.push(name);
-                    if let Some(header) = to_pretty_impl_header(self.tcx, *def_id) {
-                        post.push(header);
+        let mut has_param_env = false;
+        for ambiguity in ambiguities {
+            match ambiguity {
+                ambiguity::Ambiguity::DefId(impl_def_id) => {
+                    match self.tcx.span_of_impl(*impl_def_id) {
+                        Ok(span) => spans.push(span),
+                        Err(name) => {
+                            crates.push(name);
+                            if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
+                                post.push(header);
+                            }
+                        }
                     }
                 }
+                ambiguity::Ambiguity::ParamEnv(span) => {
+                    has_param_env = true;
+                    spans.push(*span);
+                }
             }
         }
         let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect();
@@ -2502,7 +2504,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             return;
         }
 
-        let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
+        let msg = format!(
+            "multiple `impl`s{} satisfying `{}` found",
+            if has_param_env { " or `where` clauses" } else { "" },
+            predicate
+        );
         let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
             format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
         } else if post.len() == 1 {
@@ -2601,7 +2607,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
             self.note_obligation_cause_code(
                 err,
-                &obligation.predicate,
+                obligation.predicate,
                 obligation.param_env,
                 obligation.cause.code(),
                 &mut vec![],
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 443d57aaf3d..d47a5ea3e37 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1,8 +1,10 @@
+// ignore-tidy-filelength
+
 use super::{DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation};
 
 use crate::autoderef::Autoderef;
 use crate::infer::InferCtxt;
-use crate::traits::NormalizeExt;
+use crate::traits::{NormalizeExt, ObligationCtxt};
 
 use hir::def::CtorOf;
 use hir::HirId;
@@ -22,21 +24,24 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime};
 use rustc_middle::hir::map;
+use rustc_middle::ty::error::TypeError::{self, Sorts};
+use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable,
-    ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
+    IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
+    TypeSuperFoldable, TypeVisitable, TypeckResults,
 };
-use rustc_middle::ty::{TypeAndMut, TypeckResults};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use std::fmt;
+use std::ops::Deref;
 
+use super::method_chain::CollectAllMismatches;
 use super::InferCtxtPrivExt;
 use crate::infer::InferCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
 
 #[derive(Debug)]
 pub enum GeneratorInteriorOrUpvar {
@@ -254,6 +259,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         found: ty::PolyTraitRef<'tcx>,
         expected: ty::PolyTraitRef<'tcx>,
         cause: &ObligationCauseCode<'tcx>,
+        found_node: Option<Node<'_>>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
 
     fn note_conflicting_closure_bounds(
@@ -292,13 +298,13 @@ pub trait TypeErrCtxtExt<'tcx> {
     fn note_obligation_cause_code<T>(
         &self,
         err: &mut Diagnostic,
-        predicate: &T,
+        predicate: T,
         param_env: ty::ParamEnv<'tcx>,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display + ToPredicate<'tcx>;
+        T: ToPredicate<'tcx>;
 
     /// Suggest to await before try: future? => future.await?
     fn suggest_await_before_try(
@@ -329,6 +335,31 @@ pub trait TypeErrCtxtExt<'tcx> {
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     );
+    fn function_argument_obligation(
+        &self,
+        arg_hir_id: HirId,
+        err: &mut Diagnostic,
+        parent_code: &ObligationCauseCode<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        predicate: ty::Predicate<'tcx>,
+        call_hir_id: HirId,
+    );
+    fn point_at_chain(
+        &self,
+        expr: &hir::Expr<'_>,
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: Vec<TypeError<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
+        err: &mut Diagnostic,
+    );
+    fn probe_assoc_types_at_expr(
+        &self,
+        type_diffs: &[TypeError<'tcx>],
+        span: Span,
+        prev_ty: Ty<'tcx>,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;
 }
 
 fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
@@ -348,7 +379,7 @@ fn suggest_restriction<'tcx>(
     msg: &str,
     err: &mut Diagnostic,
     fn_sig: Option<&hir::FnSig<'_>>,
-    projection: Option<&ty::ProjectionTy<'_>>,
+    projection: Option<&ty::AliasTy<'_>>,
     trait_pred: ty::PolyTraitPredicate<'tcx>,
     // When we are dealing with a trait, `super_traits` will be `Some`:
     // Given `trait T: A + B + C {}`
@@ -474,7 +505,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let self_ty = trait_pred.skip_binder().self_ty();
         let (param_ty, projection) = match self_ty.kind() {
             ty::Param(_) => (true, None),
-            ty::Projection(projection) => (false, Some(projection)),
+            ty::Alias(ty::Projection, projection) => (false, Some(projection)),
             _ => (false, None),
         };
 
@@ -673,7 +704,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         // It only make sense when suggesting dereferences for arguments
-        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code()
+        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } = obligation.cause.code()
             else { return false; };
         let Some(typeck_results) = &self.typeck_results
             else { return false; };
@@ -752,12 +783,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         real_trait_pred_and_base_ty,
                     );
                     if self.predicate_may_hold(&obligation) {
-                        err.span_suggestion_verbose(
-                            span.shrink_to_lo(),
-                            "consider dereferencing here",
-                            "*",
-                            Applicability::MachineApplicable,
+                        let call_node = self.tcx.hir().get(*call_hir_id);
+                        let msg = "consider dereferencing here";
+                        let is_receiver = matches!(
+                            call_node,
+                            Node::Expr(hir::Expr {
+                                kind: hir::ExprKind::MethodCall(_, receiver_expr, ..),
+                                ..
+                            })
+                            if receiver_expr.hir_id == *arg_hir_id
                         );
+                        if is_receiver {
+                            err.multipart_suggestion_verbose(
+                                msg,
+                                vec![
+                                    (span.shrink_to_lo(), "(*".to_string()),
+                                    (span.shrink_to_hi(), ")".to_string()),
+                                ],
+                                Applicability::MachineApplicable,
+                            )
+                        } else {
+                            err.span_suggestion_verbose(
+                                span.shrink_to_lo(),
+                                msg,
+                                '*',
+                                Applicability::MachineApplicable,
+                            )
+                        };
                         return true;
                     }
                 }
@@ -834,10 +886,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
                 ))
             }
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
                     if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                    && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                     // args tuple will always be substs[1]
                     && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
                     {
@@ -854,7 +906,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ty::Dynamic(data, _, ty::Dyn) => {
                 data.iter().find_map(|pred| {
                     if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
-                    && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
                     // for existential projection, substs are shifted over by 1
                     && let ty::Tuple(args) = proj.substs.type_at(0).kind()
                     {
@@ -871,7 +923,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ty::Param(_) => {
                 obligation.param_env.caller_bounds().iter().find_map(|pred| {
                     if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                    && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                     && proj.projection_ty.self_ty() == found
                     // args tuple will always be substs[1]
                     && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
@@ -1574,7 +1626,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let trait_obj = if has_dyn { &snippet[4..] } else { &snippet };
         if only_never_return {
             // No return paths, probably using `panic!()` or similar.
-            // Suggest `-> T`, `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
+            // Suggest `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
             suggest_trait_object_return_type_alternatives(
                 err,
                 ret_ty.span,
@@ -1674,6 +1726,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         found: ty::PolyTraitRef<'tcx>,
         expected: ty::PolyTraitRef<'tcx>,
         cause: &ObligationCauseCode<'tcx>,
+        found_node: Option<Node<'_>>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         pub(crate) fn build_fn_sig_ty<'tcx>(
             infcx: &InferCtxt<'tcx>,
@@ -1735,6 +1788,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         self.note_conflicting_closure_bounds(cause, &mut err);
 
+        if let Some(found_node) = found_node {
+            hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
+        }
+
         err
     }
 
@@ -1755,10 +1812,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             && self.tcx.is_fn_trait(trait_pred.def_id())
         {
             let expected_self =
-                self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty()));
+                self.tcx.anonymize_bound_vars(pred.kind().rebind(trait_pred.self_ty()));
             let expected_substs = self
                 .tcx
-                .anonymize_late_bound_regions(pred.kind().rebind(trait_pred.trait_ref.substs));
+                .anonymize_bound_vars(pred.kind().rebind(trait_pred.trait_ref.substs));
 
             // Find another predicate whose self-type is equal to the expected self type,
             // but whose substs don't match.
@@ -1771,12 +1828,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             // Make sure that the self type matches
                             // (i.e. constraining this closure)
                             && expected_self
-                                == self.tcx.anonymize_late_bound_regions(
+                                == self.tcx.anonymize_bound_vars(
                                     pred.kind().rebind(trait_pred.self_ty()),
                                 )
                             // But the substs don't match (i.e. incompatible args)
                             && expected_substs
-                                != self.tcx.anonymize_late_bound_regions(
+                                != self.tcx.anonymize_bound_vars(
                                     pred.kind().rebind(trait_pred.trait_ref.substs),
                                 ) =>
                     {
@@ -2158,15 +2215,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path())
         };
 
-        let mut explain_yield = |interior_span: Span,
-                                 yield_span: Span,
-                                 scope_span: Option<Span>| {
-            let mut span = MultiSpan::from_span(yield_span);
-            if let Ok(snippet) = source_map.span_to_snippet(interior_span) {
-                // #70935: If snippet contains newlines, display "the value" instead
-                // so that we do not emit complex diagnostics.
-                let snippet = &format!("`{}`", snippet);
-                let snippet = if snippet.contains('\n') { "the value" } else { snippet };
+        let mut explain_yield =
+            |interior_span: Span, yield_span: Span, scope_span: Option<Span>| {
+                let mut span = MultiSpan::from_span(yield_span);
+                let snippet = match source_map.span_to_snippet(interior_span) {
+                    // #70935: If snippet contains newlines, display "the value" instead
+                    // so that we do not emit complex diagnostics.
+                    Ok(snippet) if !snippet.contains('\n') => format!("`{}`", snippet),
+                    _ => "the value".to_string(),
+                };
                 // note: future is not `Send` as this value is used across an await
                 //   --> $DIR/issue-70935-complex-spans.rs:13:9
                 //    |
@@ -2191,17 +2248,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     interior_span,
                     format!("has type `{}` which {}", target_ty, trait_explanation),
                 );
-                // If available, use the scope span to annotate the drop location.
-                let mut scope_note = None;
                 if let Some(scope_span) = scope_span {
                     let scope_span = source_map.end_point(scope_span);
 
                     let msg = format!("{} is later dropped here", snippet);
-                    if source_map.is_multiline(yield_span.between(scope_span)) {
-                        span.push_span_label(scope_span, msg);
-                    } else {
-                        scope_note = Some((scope_span, msg));
-                    }
+                    span.push_span_label(scope_span, msg);
                 }
                 err.span_note(
                     span,
@@ -2210,11 +2261,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         future_or_generator, trait_explanation, an_await_or_yield
                     ),
                 );
-                if let Some((span, msg)) = scope_note {
-                    err.span_note(span, &msg);
-                }
-            }
-        };
+            };
         match interior_or_upvar_span {
             GeneratorInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
                 if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
@@ -2336,7 +2383,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         debug!(?next_code);
         self.note_obligation_cause_code(
             err,
-            &obligation.predicate,
+            obligation.predicate,
             obligation.param_env,
             next_code.unwrap(),
             &mut Vec::new(),
@@ -2347,15 +2394,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     fn note_obligation_cause_code<T>(
         &self,
         err: &mut Diagnostic,
-        predicate: &T,
+        predicate: T,
         param_env: ty::ParamEnv<'tcx>,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display + ToPredicate<'tcx>,
+        T: ToPredicate<'tcx>,
     {
         let tcx = self.tcx;
+        let predicate = predicate.to_predicate(tcx);
         match *cause_code {
             ObligationCauseCode::ExprAssignable
             | ObligationCauseCode::MatchExpressionArm { .. }
@@ -2390,12 +2438,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 err.note("only the last element of a tuple may have a dynamically sized type");
             }
             ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{}` is well-formed", data,));
+                err.note(&format!("required so that the projection `{data}` is well-formed"));
             }
             ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
                 err.note(&format!(
-                    "required so that reference `{}` does not outlive its referent",
-                    ref_ty,
+                    "required so that reference `{ref_ty}` does not outlive its referent"
                 ));
             }
             ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
@@ -2412,6 +2459,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::BindingObligation(item_def_id, span)
             | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
                 let item_name = tcx.def_path_str(item_def_id);
+                let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
                 let mut multispan = MultiSpan::from(span);
                 let sm = tcx.sess.source_map();
                 if let Some(ident) = tcx.opt_item_ident(item_def_id) {
@@ -2424,9 +2472,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         multispan.push_span_label(ident.span, "required by a bound in this");
                     }
                 }
-                let descr = format!("required by a bound in `{}`", item_name);
+                let descr = format!("required by a bound in `{item_name}`");
                 if span.is_visible(sm) {
-                    let msg = format!("required by this bound in `{}`", item_name);
+                    let msg = format!("required by this bound in `{short_item_name}`");
                     multispan.push_span_label(span, msg);
                     err.span_note(multispan, &descr);
                 } else {
@@ -2500,6 +2548,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
             ObligationCauseCode::SizedArgumentType(sp) => {
                 if let Some(span) = sp {
+                    if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
+                        && let ty::Clause::Trait(trait_pred) = clause
+                        && let ty::Dynamic(..) = trait_pred.self_ty().kind()
+                    {
+                        let span = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+                            && snippet.starts_with("dyn ")
+                        {
+                            let pos = snippet.len() - snippet[3..].trim_start().len();
+                            span.with_hi(span.lo() + BytePos(pos as u32))
+                        } else {
+                            span.shrink_to_lo()
+                        };
+                        err.span_suggestion_verbose(
+                            span,
+                            "you can use `impl Trait` as the argument type",
+                            "impl ".to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                     err.span_suggestion_verbose(
                         span.shrink_to_lo(),
                         "function arguments must have a statically known size, borrowed types \
@@ -2622,7 +2689,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 Some(ident) => err.span_note(ident.span, &msg),
                                 None => err.note(&msg),
                             },
-                            ty::Opaque(def_id, _) => {
+                            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                                 // Avoid printing the future from `core::future::identity_future`, it's not helpful
                                 if tcx.parent(*def_id) == identity_future {
                                     break 'print;
@@ -2688,7 +2755,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     ensure_sufficient_stack(|| {
                         self.note_obligation_cause_code(
                             err,
-                            &parent_predicate,
+                            parent_predicate,
                             param_env,
                             &data.parent_code,
                             obligated_types,
@@ -2699,7 +2766,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     ensure_sufficient_stack(|| {
                         self.note_obligation_cause_code(
                             err,
-                            &parent_predicate,
+                            parent_predicate,
                             param_env,
                             cause_code.peel_derives(),
                             obligated_types,
@@ -2808,7 +2875,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
-                        &parent_predicate,
+                        parent_predicate,
                         param_env,
                         &data.parent_code,
                         obligated_types,
@@ -2823,7 +2890,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
-                        &parent_predicate,
+                        parent_predicate,
                         param_env,
                         &data.parent_code,
                         obligated_types,
@@ -2835,44 +2902,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 arg_hir_id,
                 call_hir_id,
                 ref parent_code,
+                ..
             } => {
-                let hir = self.tcx.hir();
-                if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) =
-                    hir.find(arg_hir_id)
-                {
-                    let parent_id = hir.get_parent_item(arg_hir_id);
-                    let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
-                        Some(t) if t.hir_owner == parent_id => t,
-                        _ => self.tcx.typeck(parent_id.def_id),
-                    };
-                    let expr = expr.peel_blocks();
-                    let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
-                    let span = expr.span;
-                    if Some(span) != err.span.primary_span() {
-                        err.span_label(
-                            span,
-                            if ty.references_error() {
-                                String::new()
-                            } else {
-                                format!("this tail expression is of type `{:?}`", ty)
-                            },
-                        );
-                    }
-                }
-                if let Some(Node::Expr(hir::Expr {
-                    kind:
-                        hir::ExprKind::Call(hir::Expr { span, .. }, _)
-                        | hir::ExprKind::MethodCall(
-                            hir::PathSegment { ident: Ident { span, .. }, .. },
-                            ..,
-                        ),
-                    ..
-                })) = hir.find(call_hir_id)
-                {
-                    if Some(*span) != err.span.primary_span() {
-                        err.span_label(*span, "required by a bound introduced by this call");
-                    }
-                }
+                self.function_argument_obligation(
+                    arg_hir_id,
+                    err,
+                    parent_code,
+                    param_env,
+                    predicate,
+                    call_hir_id,
+                );
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
@@ -2887,9 +2926,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => {
                 let item_name = self.tcx.item_name(trait_item_def_id);
                 let msg = format!(
-                    "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \
-                     corresponding trait's {kind}",
-                    predicate, item_name,
+                    "the requirement `{predicate}` appears on the `impl`'s {kind} \
+                     `{item_name}` but not on the corresponding trait's {kind}",
                 );
                 let sp = self
                     .tcx
@@ -2899,7 +2937,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 let mut assoc_span: MultiSpan = sp.into();
                 assoc_span.push_span_label(
                     sp,
-                    format!("this trait's {kind} doesn't have the requirement `{}`", predicate),
+                    format!("this trait's {kind} doesn't have the requirement `{predicate}`"),
                 );
                 if let Some(ident) = self
                     .tcx
@@ -2918,7 +2956,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
             ObligationCauseCode::OpaqueReturnType(expr_info) => {
                 if let Some((expr_ty, expr_span)) = expr_info {
-                    let expr_ty = self.resolve_vars_if_possible(expr_ty);
+                    let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty));
                     err.span_label(
                         expr_span,
                         format!("return type was inferred to be `{expr_ty}` here"),
@@ -2964,7 +3002,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     self.tcx.mk_projection(
                         item_def_id,
                         // Future::Output has no substs
-                        self.tcx.mk_substs_trait(trait_pred.self_ty(), []),
+                        [trait_pred.self_ty()],
                     )
                 });
                 let InferOk { value: projection_ty, .. } =
@@ -3098,6 +3136,392 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             );
         }
     }
+    fn function_argument_obligation(
+        &self,
+        arg_hir_id: HirId,
+        err: &mut Diagnostic,
+        parent_code: &ObligationCauseCode<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        predicate: ty::Predicate<'tcx>,
+        call_hir_id: HirId,
+    ) {
+        let tcx = self.tcx;
+        let hir = tcx.hir();
+        if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) {
+            let parent_id = hir.get_parent_item(arg_hir_id);
+            let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
+                Some(t) if t.hir_owner == parent_id => t,
+                _ => self.tcx.typeck(parent_id.def_id),
+            };
+            if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
+                let expr = expr.peel_blocks();
+                let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+                let span = expr.span;
+                if Some(span) != err.span.primary_span() {
+                    err.span_label(
+                        span,
+                        if ty.references_error() {
+                            String::new()
+                        } else {
+                            let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+                            format!("this tail expression is of type `{ty}`")
+                        },
+                    );
+                }
+            }
+
+            // FIXME: visit the ty to see if there's any closure involved, and if there is,
+            // check whether its evaluated return type is the same as the one corresponding
+            // to an associated type (as seen from `trait_pred`) in the predicate. Like in
+            // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
+            let mut type_diffs = vec![];
+
+            if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
+                && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
+                && let Some(pred) = predicates.predicates.get(*idx)
+            {
+                if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
+                    ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+                    _ => Err(()),
+                })
+                    && let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
+                        ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+                        _ => Err(()),
+                    })
+                {
+                    let mut c = CollectAllMismatches {
+                        infcx: self.infcx,
+                        param_env,
+                        errors: vec![],
+                    };
+                    if let Ok(_) = c.relate(trait_pred, trait_predicate) {
+                        type_diffs = c.errors;
+                    }
+                } else if let ty::PredicateKind::Clause(
+                    ty::Clause::Projection(proj)
+                ) = pred.kind().skip_binder()
+                    && let ty::PredicateKind::Clause(
+                        ty::Clause::Projection(projection)
+                    ) = predicate.kind().skip_binder()
+                {
+                    type_diffs = vec![
+                        Sorts(ty::error::ExpectedFound {
+                            expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)),
+                            found: projection.term.ty().unwrap(),
+                        }),
+                    ];
+                }
+            }
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+                && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
+                && let Some(binding_expr) = local.init
+            {
+                // If the expression we're calling on is a binding, we want to point at the
+                // `let` when talking about the type. Otherwise we'll point at every part
+                // of the method chain with the type.
+                self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
+            } else {
+                self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
+            }
+        }
+        let call_node = hir.find(call_hir_id);
+        if let Some(Node::Expr(hir::Expr {
+            kind: hir::ExprKind::MethodCall(path, rcvr, ..), ..
+        })) = call_node
+        {
+            if Some(rcvr.span) == err.span.primary_span() {
+                err.replace_span_with(path.ident.span);
+            }
+        }
+        if let Some(Node::Expr(hir::Expr {
+            kind:
+                hir::ExprKind::Call(hir::Expr { span, .. }, _)
+                | hir::ExprKind::MethodCall(hir::PathSegment { ident: Ident { span, .. }, .. }, ..),
+            ..
+        })) = hir.find(call_hir_id)
+        {
+            if Some(*span) != err.span.primary_span() {
+                err.span_label(*span, "required by a bound introduced by this call");
+            }
+        }
+    }
+
+    fn point_at_chain(
+        &self,
+        expr: &hir::Expr<'_>,
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: Vec<TypeError<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
+        err: &mut Diagnostic,
+    ) {
+        let mut primary_spans = vec![];
+        let mut span_labels = vec![];
+
+        let tcx = self.tcx;
+
+        let mut print_root_expr = true;
+        let mut assocs = vec![];
+        let mut expr = expr;
+        let mut prev_ty = self.resolve_vars_if_possible(
+            typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+        );
+        while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
+            // Point at every method call in the chain with the resulting type.
+            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+            //               ^^^^^^ ^^^^^^^^^^^
+            expr = rcvr_expr;
+            let assocs_in_this_method =
+                self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
+            assocs.push(assocs_in_this_method);
+            prev_ty = self.resolve_vars_if_possible(
+                typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+            );
+
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+                && let Some(parent) = self.tcx.hir().find(parent_hir_id)
+            {
+                // We've reached the root of the method call chain...
+                if let hir::Node::Local(local) = parent
+                    && let Some(binding_expr) = local.init
+                {
+                    // ...and it is a binding. Get the binding creation and continue the chain.
+                    expr = binding_expr;
+                }
+                if let hir::Node::Param(param) = parent {
+                    // ...and it is a an fn argument.
+                    let prev_ty = self.resolve_vars_if_possible(
+                        typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error()),
+                    );
+                    let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env);
+                    if assocs_in_this_method.iter().any(|a| a.is_some()) {
+                        assocs.push(assocs_in_this_method);
+                        print_root_expr = false;
+                    }
+                    break;
+                }
+            }
+        }
+        // We want the type before deref coercions, otherwise we talk about `&[_]`
+        // instead of `Vec<_>`.
+        if let Some(ty) = typeck_results.expr_ty_opt(expr) && print_root_expr {
+            let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+            // Point at the root expression
+            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+            // ^^^^^^^^^^^^^
+            span_labels.push((expr.span, format!("this expression has type `{ty}`")));
+        };
+        // Only show this if it is not a "trivial" expression (not a method
+        // chain) and there are associated types to talk about.
+        let mut assocs = assocs.into_iter().peekable();
+        while let Some(assocs_in_method) = assocs.next() {
+            let Some(prev_assoc_in_method) = assocs.peek() else {
+                for entry in assocs_in_method {
+                    let Some((span, (assoc, ty))) = entry else { continue; };
+                    if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
+                        let Sorts(expected_found) = diff else { return false; };
+                        self.can_eq(param_env, expected_found.found, ty).is_ok()
+                    }) {
+                        // FIXME: this doesn't quite work for `Iterator::collect`
+                        // because we have `Vec<i32>` and `()`, but we'd want `i32`
+                        // to point at the `.into_iter()` call, but as long as we
+                        // still point at the other method calls that might have
+                        // introduced the issue, this is fine for now.
+                        primary_spans.push(span);
+                    }
+                    span_labels.push((
+                        span,
+                        with_forced_trimmed_paths!(format!(
+                            "`{}` is `{ty}` here",
+                            self.tcx.def_path_str(assoc),
+                        )),
+                    ));
+                }
+                break;
+            };
+            for (entry, prev_entry) in
+                assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
+            {
+                match (entry, prev_entry) {
+                    (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
+                        let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
+
+                        let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
+                        if self.can_eq(param_env, ty, *prev_ty).is_err() {
+                            if type_diffs.iter().any(|diff| {
+                                let Sorts(expected_found) = diff else { return false; };
+                                self.can_eq(param_env, expected_found.found, ty).is_ok()
+                            }) {
+                                primary_spans.push(span);
+                            }
+                            span_labels
+                                .push((span, format!("`{assoc}` changed to `{ty_str}` here")));
+                        } else {
+                            span_labels.push((span, format!("`{assoc}` remains `{ty_str}` here")));
+                        }
+                    }
+                    (Some((span, (assoc, ty))), None) => {
+                        span_labels.push((
+                            span,
+                            with_forced_trimmed_paths!(format!(
+                                "`{}` is `{}` here",
+                                self.tcx.def_path_str(assoc),
+                                self.ty_to_string(ty),
+                            )),
+                        ));
+                    }
+                    (None, Some(_)) | (None, None) => {}
+                }
+            }
+        }
+        if !primary_spans.is_empty() {
+            let mut multi_span: MultiSpan = primary_spans.into();
+            for (span, label) in span_labels {
+                multi_span.push_span_label(span, label);
+            }
+            err.span_note(
+                multi_span,
+                format!("the method call chain might not have had the expected associated types"),
+            );
+        }
+    }
+
+    fn probe_assoc_types_at_expr(
+        &self,
+        type_diffs: &[TypeError<'tcx>],
+        span: Span,
+        prev_ty: Ty<'tcx>,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
+        let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
+        let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
+        for diff in type_diffs {
+            let Sorts(expected_found) = diff else { continue; };
+            let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else { continue; };
+
+            let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
+            let trait_def_id = proj.trait_def_id(self.tcx);
+            // Make `Self` be equivalent to the type of the call chain
+            // expression we're looking at now, so that we can tell what
+            // for example `Iterator::Item` is at this point in the chain.
+            let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
+                match param.kind {
+                    ty::GenericParamDefKind::Type { .. } => {
+                        if param.index == 0 {
+                            return prev_ty.into();
+                        }
+                    }
+                    ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Const { .. } => {}
+                }
+                self.var_for_def(span, param)
+            });
+            // This will hold the resolved type of the associated type, if the
+            // current expression implements the trait that associated type is
+            // in. For example, this would be what `Iterator::Item` is here.
+            let ty_var = self.infcx.next_ty_var(origin);
+            // This corresponds to `<ExprTy as Iterator>::Item = _`.
+            let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
+                ty::ProjectionPredicate {
+                    projection_ty: self.tcx.mk_alias_ty(proj.def_id, substs),
+                    term: ty_var.into(),
+                },
+            )));
+            // Add `<ExprTy as Iterator>::Item = _` obligation.
+            ocx.register_obligation(Obligation::misc(
+                self.tcx, span, body_id, param_env, projection,
+            ));
+            if ocx.select_where_possible().is_empty() {
+                // `ty_var` now holds the type that `Item` is for `ExprTy`.
+                let ty_var = self.resolve_vars_if_possible(ty_var);
+                assocs_in_this_method.push(Some((span, (proj.def_id, ty_var))));
+            } else {
+                // `<ExprTy as Iterator>` didn't select, so likely we've
+                // reached the end of the iterator chain, like the originating
+                // `Vec<_>`.
+                // Keep the space consistent for later zipping.
+                assocs_in_this_method.push(None);
+            }
+        }
+        assocs_in_this_method
+    }
+}
+
+/// Add a hint to add a missing borrow or remove an unnecessary one.
+fn hint_missing_borrow<'tcx>(
+    span: Span,
+    found_span: Span,
+    found: Ty<'tcx>,
+    expected: Ty<'tcx>,
+    found_node: Node<'_>,
+    err: &mut Diagnostic,
+) {
+    let found_args = match found.kind() {
+        ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+        kind => {
+            span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
+        }
+    };
+    let expected_args = match expected.kind() {
+        ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+        kind => {
+            span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
+        }
+    };
+
+    let fn_decl = found_node
+        .fn_decl()
+        .unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
+
+    let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
+
+    fn get_deref_type_and_refs<'tcx>(mut ty: Ty<'tcx>) -> (Ty<'tcx>, usize) {
+        let mut refs = 0;
+
+        while let ty::Ref(_, new_ty, _) = ty.kind() {
+            ty = *new_ty;
+            refs += 1;
+        }
+
+        (ty, refs)
+    }
+
+    let mut to_borrow = Vec::new();
+    let mut remove_borrow = Vec::new();
+
+    for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
+        let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
+        let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
+
+        if found_ty == expected_ty {
+            if found_refs < expected_refs {
+                to_borrow.push((arg_span, expected_arg.to_string()));
+            } else if found_refs > expected_refs {
+                remove_borrow.push((arg_span, expected_arg.to_string()));
+            }
+        }
+    }
+
+    if !to_borrow.is_empty() {
+        err.multipart_suggestion(
+            "consider borrowing the argument",
+            to_borrow,
+            Applicability::MaybeIncorrect,
+        );
+    }
+
+    if !remove_borrow.is_empty() {
+        err.multipart_suggestion(
+            "do not borrow the argument",
+            remove_borrow,
+            Applicability::MaybeIncorrect,
+        );
+    }
 }
 
 /// Collect all the returned expressions within the input expression.
@@ -3207,13 +3631,6 @@ fn suggest_trait_object_return_type_alternatives(
 ) {
     err.span_suggestion(
         ret_ty,
-        "use some type `T` that is `T: Sized` as the return type if all return paths have the \
-            same type",
-        "T",
-        Applicability::MaybeIncorrect,
-    );
-    err.span_suggestion(
-        ret_ty,
         &format!(
             "use `impl {}` as the return type if all return paths have the same type but you \
                 want to expose only the trait in the signature",
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index ea4bf42c515..2566d793d78 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -425,13 +425,8 @@ pub fn fully_solve_bound<'tcx>(
     bound: DefId,
 ) -> Vec<FulfillmentError<'tcx>> {
     let tcx = infcx.tcx;
-    let trait_ref = ty::TraitRef { def_id: bound, substs: tcx.mk_substs_trait(ty, []) };
-    let obligation = Obligation {
-        cause,
-        recursion_depth: 0,
-        param_env,
-        predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
-    };
+    let trait_ref = tcx.mk_trait_ref(bound, [ty]);
+    let obligation = Obligation::new(tcx, cause, param_env, ty::Binder::dummy(trait_ref));
 
     fully_solve_obligation(infcx, obligation)
 }
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index a45749fe48c..8b1ced78f4e 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -589,7 +589,7 @@ fn object_ty_for_trait<'tcx>(
             let pred = obligation.predicate.to_opt_poly_projection_pred()?;
             Some(pred.map_bound(|p| {
                 ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
-                    item_def_id: p.projection_ty.item_def_id,
+                    def_id: p.projection_ty.def_id,
                     substs: p.projection_ty.substs,
                     term: p.term,
                 })
@@ -694,18 +694,12 @@ fn receiver_is_dispatchable<'tcx>(
 
         // U: Trait<Arg1, ..., ArgN>
         let trait_predicate = {
-            let substs =
-                InternalSubsts::for_item(tcx, method.trait_container(tcx).unwrap(), |param, _| {
-                    if param.index == 0 {
-                        unsized_self_ty.into()
-                    } else {
-                        tcx.mk_param_from_def(param)
-                    }
-                });
+            let trait_def_id = method.trait_container(tcx).unwrap();
+            let substs = InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+                if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
+            });
 
-            ty::Binder::dummy(ty::TraitRef { def_id: unsize_did, substs })
-                .without_const()
-                .to_predicate(tcx)
+            ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, substs)).to_predicate(tcx)
         };
 
         let caller_bounds: Vec<Predicate<'tcx>> =
@@ -794,13 +788,13 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
                         ControlFlow::CONTINUE
                     }
                 }
-                ty::Projection(ref data)
-                    if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+                ty::Alias(ty::Projection, ref data)
+                    if self.tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder =>
                 {
                     // We'll deny these later in their own pass
                     ControlFlow::CONTINUE
                 }
-                ty::Projection(ref data) => {
+                ty::Alias(ty::Projection, ref data) => {
                     // This is a projected type `<Foo as SomeTrait>::X`.
 
                     // Compute supertraits of current trait lazily.
@@ -861,10 +855,10 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>(
     // FIXME(RPITIT): Perhaps we should use a visitor here?
     ty.skip_binder().walk().find_map(|arg| {
         if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Projection(proj) = ty.kind()
-            && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+            && let ty::Alias(ty::Projection, proj) = ty.kind()
+            && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
         {
-            Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.item_def_id)))
+            Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.def_id)))
         } else {
             None
         }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 5789754e4fc..84d7244c1db 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -45,7 +45,7 @@ pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPre
 
 pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
 
-pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
+pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>;
 
 pub(super) struct InProgress;
 
@@ -496,7 +496,9 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
             // This is really important. While we *can* handle this, this has
             // severe performance implications for large opaque types with
             // late-bound regions. See `issue-88862` benchmark.
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
+                if !substs.has_escaping_bound_vars() =>
+            {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.super_fold_with(self),
@@ -523,7 +525,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                 }
             }
 
-            ty::Projection(data) if !data.has_escaping_bound_vars() => {
+            ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
                 // This branch is *mostly* just an optimization: when we don't
                 // have escaping bound vars, we don't need to replace them with
                 // placeholders (see branch below). *Also*, we know that we can
@@ -562,7 +564,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                 normalized_ty.ty().unwrap()
             }
 
-            ty::Projection(data) => {
+            ty::Alias(ty::Projection, data) => {
                 // If there are escaping bound vars, we temporarily replace the
                 // bound vars with placeholders. Note though, that in the case
                 // that we still can't project for whatever reason (e.g. self
@@ -957,7 +959,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
 pub fn normalize_projection_type<'a, 'b, 'tcx>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
+    projection_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
@@ -995,7 +997,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
 fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
+    projection_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
@@ -1177,7 +1179,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
 fn normalize_to_error<'a, 'tcx>(
     selcx: &mut SelectionContext<'a, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
+    projection_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
 ) -> NormalizedTy<'tcx> {
@@ -1189,10 +1191,9 @@ fn normalize_to_error<'a, 'tcx>(
         predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
     };
     let tcx = selcx.infcx.tcx;
-    let def_id = projection_ty.item_def_id;
     let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
         kind: TypeVariableOriginKind::NormalizeProjectionType,
-        span: tcx.def_span(def_id),
+        span: tcx.def_span(projection_ty.def_id),
     });
     Normalized { value: new_value, obligations: vec![trait_obligation] }
 }
@@ -1270,7 +1271,7 @@ fn project<'cx, 'tcx>(
             // need to investigate whether or not this is fine.
             selcx
                 .tcx()
-                .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs)
+                .mk_projection(obligation.predicate.def_id, obligation.predicate.substs)
                 .into(),
         )),
         // Error occurred while trying to processing impls.
@@ -1290,13 +1291,12 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     let tcx = selcx.tcx();
-    if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
-        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+    if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
+        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
         // If we are trying to project an RPITIT with trait's default `Self` parameter,
         // then we must be within a default trait body.
         if obligation.predicate.self_ty()
-            == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
-                .type_at(0)
+            == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.def_id).type_at(0)
             && tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
         {
             candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
@@ -1309,8 +1309,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
         let trait_substs =
             obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
         // FIXME(named-returns): Binders
-        let trait_predicate =
-            ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs });
+        let trait_predicate = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, trait_substs));
 
         let _ = selcx.infcx.commit_if_ok(|_| {
             match selcx.select(&obligation.with(tcx, trait_predicate)) {
@@ -1377,8 +1376,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     // Check whether the self-type is itself a projection.
     // If so, extract what we know from the trait and try to come up with a good answer.
     let bounds = match *obligation.predicate.self_ty().kind() {
-        ty::Projection(ref data) => tcx.bound_item_bounds(data.item_def_id).subst(tcx, data.substs),
-        ty::Opaque(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs),
+        ty::Alias(_, ref data) => tcx.bound_item_bounds(data.def_id).subst(tcx, data.substs),
         ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -1430,7 +1428,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
     };
     let env_predicates = data
         .projection_bounds()
-        .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id)
+        .filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
         .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
 
     assemble_candidates_from_predicates(
@@ -1462,7 +1460,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
             predicate.kind().skip_binder()
         {
             let data = bound_predicate.rebind(data);
-            if data.projection_def_id() != obligation.predicate.item_def_id {
+            if data.projection_def_id() != obligation.predicate.def_id {
                 continue;
             }
 
@@ -1503,7 +1501,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     // Can't assemble candidate from impl for RPITIT
-    if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
+    if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
         return;
     }
 
@@ -1555,7 +1553,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // NOTE: This should be kept in sync with the similar code in
                 // `rustc_ty_utils::instance::resolve_associated_item()`.
                 let node_item =
-                    assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
+                    assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.def_id)
                         .map_err(|ErrorGuaranteed { .. }| ())?;
 
                 if node_item.is_final() {
@@ -1616,8 +1614,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                          // type parameters, opaques, and unnormalized projections have pointer
                         // metadata if they're known (e.g. by the param_env) to be sized
                         ty::Param(_)
-                        | ty::Projection(..)
-                        | ty::Opaque(..)
+                        | ty::Alias(..)
                         | ty::Bound(..)
                         | ty::Placeholder(..)
                         | ty::Infer(..)
@@ -1671,7 +1668,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 
                         // type parameters, opaques, and unnormalized projections have pointer
                         // metadata if they're known (e.g. by the param_env) to be sized
-                        ty::Param(_) | ty::Projection(..) | ty::Opaque(..)
+                        ty::Param(_) | ty::Alias(..)
                             if selcx.infcx.predicate_must_hold_modulo_regions(
                                 &obligation.with(
                                     selcx.tcx(),
@@ -1687,8 +1684,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 
                         // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
                         ty::Param(_)
-                        | ty::Projection(..)
-                        | ty::Opaque(..)
+                        | ty::Alias(..)
                         | ty::Bound(..)
                         | ty::Placeholder(..)
                         | ty::Infer(..)
@@ -1788,7 +1784,7 @@ fn confirm_candidate<'cx, 'tcx>(
         ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
             term: selcx
                 .tcx()
-                .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
+                .mk_opaque(obligation.predicate.def_id, obligation.predicate.substs)
                 .into(),
             obligations: vec![],
         },
@@ -1860,7 +1856,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         gen_sig,
     )
     .map_bound(|(trait_ref, yield_ty, return_ty)| {
-        let name = tcx.associated_item(obligation.predicate.item_def_id).name;
+        let name = tcx.associated_item(obligation.predicate.def_id).name;
         let ty = if name == sym::Return {
             return_ty
         } else if name == sym::Yield {
@@ -1870,10 +1866,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         };
 
         ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                substs: trait_ref.substs,
-                item_def_id: obligation.predicate.item_def_id,
-            },
+            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
             term: ty.into(),
         }
     });
@@ -1909,13 +1902,10 @@ fn confirm_future_candidate<'cx, 'tcx>(
         gen_sig,
     )
     .map_bound(|(trait_ref, return_ty)| {
-        debug_assert_eq!(tcx.associated_item(obligation.predicate.item_def_id).name, sym::Output);
+        debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
 
         ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                substs: trait_ref.substs,
-                item_def_id: obligation.predicate.item_def_id,
-            },
+            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
             term: return_ty.into(),
         }
     });
@@ -1934,7 +1924,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
     let self_ty = obligation.predicate.self_ty();
     let substs = tcx.mk_substs([self_ty.into()].iter());
     let lang_items = tcx.lang_items();
-    let item_def_id = obligation.predicate.item_def_id;
+    let item_def_id = obligation.predicate.def_id;
     let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
     let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
         let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
@@ -1969,7 +1959,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
     };
 
     let predicate =
-        ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id }, term };
+        ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, substs), term };
 
     confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
         .with_addl_obligations(obligations)
@@ -2038,10 +2028,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
         flag,
     )
     .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
-        projection_ty: ty::ProjectionTy {
-            substs: trait_ref.substs,
-            item_def_id: fn_once_output_def_id,
-        },
+        projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.substs),
         term: ret_type.into(),
     });
 
@@ -2122,7 +2109,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let tcx = selcx.tcx();
 
     let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
-    let assoc_item_id = obligation.predicate.item_def_id;
+    let assoc_item_id = obligation.predicate.def_id;
     let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
 
     let param_env = obligation.param_env;
@@ -2222,7 +2209,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     let tcx = selcx.tcx();
     let mut obligations = data.nested;
 
-    let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+    let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
     let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else {
         return Progress { term: tcx.ty_error().into(), obligations };
     };
@@ -2233,9 +2220,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     // Use the default `impl Trait` for the trait, e.g., for a default trait body
     if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
         return Progress {
-            term: tcx
-                .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
-                .into(),
+            term: tcx.mk_opaque(obligation.predicate.def_id, obligation.predicate.substs).into(),
             obligations,
         };
     }
@@ -2302,7 +2287,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
         obligation.recursion_depth + 1,
         tcx.bound_trait_impl_trait_tys(impl_fn_def_id)
             .map_bound(|tys| {
-                tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id])
+                tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
             })
             .subst(tcx, impl_fn_substs),
         &mut obligations,
@@ -2320,7 +2305,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
 ) {
     let tcx = selcx.tcx();
     let own = tcx
-        .predicates_of(obligation.predicate.item_def_id)
+        .predicates_of(obligation.predicate.def_id)
         .instantiate_own(tcx, obligation.predicate.substs);
     for (predicate, span) in std::iter::zip(own.predicates, own.spans) {
         let normalized = normalize_with_depth_to(
@@ -2343,13 +2328,13 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
             ObligationCause::new(
                 obligation.cause.span,
                 obligation.cause.body_id,
-                super::ItemObligation(obligation.predicate.item_def_id),
+                super::ItemObligation(obligation.predicate.def_id),
             )
         } else {
             ObligationCause::new(
                 obligation.cause.span,
                 obligation.cause.body_id,
-                super::BindingObligation(obligation.predicate.item_def_id, span),
+                super::BindingObligation(obligation.predicate.def_id, span),
             )
         };
         nested.push(Obligation::with_depth(
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index aad3c37f84e..0f21813bc40 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -62,9 +62,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
 
         // The following *might* require a destructor: needs deeper inspection.
         ty::Dynamic(..)
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Param(_)
-        | ty::Opaque(..)
         | ty::Placeholder(..)
         | ty::Infer(_)
         | ty::Bound(..)
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 7ad532d8a34..c6ef13e185b 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -205,7 +205,9 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
             // This is really important. While we *can* handle this, this has
             // severe performance implications for large opaque types with
             // late-bound regions. See `issue-88862` benchmark.
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
+                if !substs.has_escaping_bound_vars() =>
+            {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.try_super_fold_with(self),
@@ -242,7 +244,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                 }
             }
 
-            ty::Projection(data) if !data.has_escaping_bound_vars() => {
+            ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
                 // This branch is just an optimization: when we don't have escaping bound vars,
                 // we don't need to replace them with placeholders (see branch below).
 
@@ -291,7 +293,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                 }
             }
 
-            ty::Projection(data) => {
+            ty::Alias(ty::Projection, data) => {
                 // See note in `rustc_trait_selection::traits::project`
 
                 let tcx = self.infcx.tcx;
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
index bfa318787e5..34b5fc4891e 100644
--- a/compiler/rustc_trait_selection/src/traits/relationships.rs
+++ b/compiler/rustc_trait_selection/src/traits/relationships.rs
@@ -26,7 +26,7 @@ pub(crate) fn update<'tcx, T>(
                 .kind()
                 .rebind(
                     // (*) binder moved here
-                    ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_type(infcx.tcx, new_self_ty)))
+                    ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_ty(infcx.tcx, new_self_ty)))
                 ),
         );
         // Don't report overflow errors. Otherwise equivalent to may_hold.
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index e4b70f0d2ff..c54d901e9b1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -138,7 +138,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
-            ty::Projection(_) | ty::Opaque(..) => {}
+            ty::Alias(..) => {}
             ty::Infer(ty::TyVar(_)) => {
                 span_bug!(
                     obligation.cause.span,
@@ -394,7 +394,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // still be provided by a manual implementation for
                     // this trait and type.
                 }
-                ty::Param(..) | ty::Projection(..) => {
+                ty::Param(..) | ty::Alias(ty::Projection, ..) => {
                     // In these cases, we don't know what the actual
                     // type is.  Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -536,10 +536,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let ty = traits::normalize_projection_type(
                 self,
                 param_env,
-                ty::ProjectionTy {
-                    item_def_id: tcx.lang_items().deref_target()?,
-                    substs: trait_ref.substs,
-                },
+                tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.substs),
                 cause.clone(),
                 0,
                 // We're *intentionally* throwing these away,
@@ -737,13 +734,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
         match self_ty.skip_binder().kind() {
-            ty::Opaque(..)
+            ty::Alias(..)
             | ty::Dynamic(..)
             | ty::Error(_)
             | ty::Bound(..)
             | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Projection(_) => {
+            | ty::Placeholder(_) => {
                 // We don't know if these are `~const Destruct`, at least
                 // not structurally... so don't push a candidate.
             }
@@ -829,8 +825,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::Generator(_, _, _)
             | ty::GeneratorWitness(_)
             | ty::Never
-            | ty::Projection(_)
-            | ty::Opaque(_, _)
+            | ty::Alias(..)
             | ty::Param(_)
             | ty::Bound(_, _)
             | ty::Error(_)
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index fda415155c4..f6fe71fbd4f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -155,8 +155,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let placeholder_self_ty = placeholder_trait_predicate.self_ty();
         let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
         let (def_id, substs) = match *placeholder_self_ty.kind() {
-            ty::Projection(proj) => (proj.item_def_id, proj.substs),
-            ty::Opaque(def_id, substs) => (def_id, substs),
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
             _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
         };
 
@@ -184,7 +183,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 .map_err(|_| Unimplemented)
         })?);
 
-        if let ty::Projection(..) = placeholder_self_ty.kind() {
+        if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() {
             let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates;
             debug!(?predicates, "projection predicates");
             for predicate in predicates {
@@ -1279,7 +1278,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
                 // If we have a projection type, make sure to normalize it so we replace it
                 // with a fresh infer variable
-                ty::Projection(..) => {
+                ty::Alias(ty::Projection, ..) => {
                     let predicate = normalize_with_depth_to(
                         self,
                         obligation.param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 035deb61639..792933096b1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1595,8 +1595,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let tcx = self.infcx.tcx;
         let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
-            ty::Projection(ref data) => (data.item_def_id, data.substs),
-            ty::Opaque(def_id, substs) => (def_id, substs),
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
             _ => {
                 span_bug!(
                     obligation.cause.span,
@@ -1745,7 +1744,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             });
 
         if is_match {
-            let generics = self.tcx().generics_of(obligation.predicate.item_def_id);
+            let generics = self.tcx().generics_of(obligation.predicate.def_id);
             // FIXME(generic-associated-types): Addresses aggressive inference in #92917.
             // If this type is a GAT, and of the GAT substs resolve to something new,
             // that means that we must have newly inferred something about the GAT.
@@ -2067,7 +2066,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }))
             }
 
-            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
+            ty::Alias(..) | ty::Param(_) => None,
             ty::Infer(ty::TyVar(_)) => Ambiguous,
 
             ty::Placeholder(..)
@@ -2167,7 +2166,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
             }
 
-            ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
+            ty::Adt(..) | ty::Alias(..) | ty::Param(..) => {
                 // Fallback to whatever user-defined impls exist in this case.
                 None
             }
@@ -2220,7 +2219,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::Dynamic(..)
             | ty::Param(..)
             | ty::Foreign(..)
-            | ty::Projection(..)
+            | ty::Alias(ty::Projection, ..)
             | ty::Bound(..)
             | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("asked to assemble constituent types of unexpected type: {:?}", t);
@@ -2260,7 +2259,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect())
             }
 
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 // We can resolve the `impl Trait` to its concrete type,
                 // which enforces a DAG between the functions requiring
                 // the auto trait bounds in question.
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 4dc08e0f9da..892a7afd799 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -95,10 +95,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
             ty::Foreign(_) => {
                 return ControlFlow::Break(ty);
             }
-            ty::Opaque(..) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::Projection(..) => {
+            ty::Alias(..) => {
                 return ControlFlow::Break(ty);
             }
             ty::Closure(..) => {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index e47ba64245f..0e0a883d9f5 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -234,9 +234,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             // projection coming from another associated type. See
             // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
             // `traits-assoc-type-in-supertrait-bad.rs`.
-            if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind())
+            if let Some(ty::Alias(ty::Projection, projection_ty)) = proj.term.ty().map(|ty| ty.kind())
                 && let Some(&impl_item_id) =
-                    tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
+                    tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id)
                 && let Some(impl_item_span) = items
                     .iter()
                     .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
@@ -249,9 +249,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             // An associated item obligation born out of the `trait` failed to be met. An example
             // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
             debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
-            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind()
+            if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind()
                 && let Some(&impl_item_id) =
-                    tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
+                    tcx.impl_item_implementor_ids(impl_def_id).get(&def_id)
                 && let Some(impl_item_span) = items
                     .iter()
                     .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
@@ -369,7 +369,7 @@ impl<'tcx> WfPredicates<'tcx> {
 
     /// Pushes the obligations required for `trait_ref::Item` to be WF
     /// into `self.out`.
-    fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
+    fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) {
         // A projection is well-formed if
         //
         // (a) its predicates hold (*)
@@ -392,7 +392,7 @@ impl<'tcx> WfPredicates<'tcx> {
         //     `i32: Copy`
         // ]
         // Projection types do not require const predicates.
-        let obligations = self.nominal_obligations_without_const(data.item_def_id, data.substs);
+        let obligations = self.nominal_obligations_without_const(data.def_id, data.substs);
         self.out.extend(obligations);
 
         let tcx = self.tcx();
@@ -451,19 +451,21 @@ impl<'tcx> WfPredicates<'tcx> {
                 GenericArgKind::Const(ct) => {
                     match ct.kind() {
                         ty::ConstKind::Unevaluated(uv) => {
-                            let obligations = self.nominal_obligations(uv.def.did, uv.substs);
-                            self.out.extend(obligations);
-
-                            let predicate =
-                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
-                            let cause = self.cause(traits::WellFormed(None));
-                            self.out.push(traits::Obligation::with_depth(
-                                self.tcx(),
-                                cause,
-                                self.recursion_depth,
-                                self.param_env,
-                                predicate,
-                            ));
+                            if !ct.has_escaping_bound_vars() {
+                                let obligations = self.nominal_obligations(uv.def.did, uv.substs);
+                                self.out.extend(obligations);
+
+                                let predicate =
+                                    ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
+                                let cause = self.cause(traits::WellFormed(None));
+                                self.out.push(traits::Obligation::with_depth(
+                                    self.tcx(),
+                                    cause,
+                                    self.recursion_depth,
+                                    self.param_env,
+                                    predicate,
+                                ));
+                            }
                         }
                         ty::ConstKind::Infer(_) => {
                             let cause = self.cause(traits::WellFormed(None));
@@ -556,7 +558,7 @@ impl<'tcx> WfPredicates<'tcx> {
                     // Simple cases that are WF if their type args are WF.
                 }
 
-                ty::Projection(data) => {
+                ty::Alias(ty::Projection, data) => {
                     walker.skip_current_subtree(); // Subtree handled by compute_projection.
                     self.compute_projection(data);
                 }
@@ -648,12 +650,12 @@ impl<'tcx> WfPredicates<'tcx> {
                     // types appearing in the fn signature
                 }
 
-                ty::Opaque(did, substs) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     // All of the requirements on type parameters
                     // have already been checked for `impl Trait` in
                     // return position. We do need to check type-alias-impl-trait though.
-                    if ty::is_impl_trait_defn(self.tcx, did).is_none() {
-                        let obligations = self.nominal_obligations(did, substs);
+                    if ty::is_impl_trait_defn(self.tcx, def_id).is_none() {
+                        let obligations = self.nominal_obligations(def_id, substs);
                         self.out.extend(obligations);
                     }
                 }
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 344c8b93c17..bc4a52c5040 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -432,7 +432,10 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
                         (ast::Mutability::Not, chalk_ir::Mutability::Not) => true,
                     }
                 }
-                (&ty::Opaque(def_id, ..), OpaqueType(opaque_ty_id, ..)) => def_id == opaque_ty_id.0,
+                (
+                    &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
+                    OpaqueType(opaque_ty_id, ..),
+                ) => def_id == opaque_ty_id.0,
                 (&ty::FnDef(def_id, ..), FnDef(fn_def_id, ..)) => def_id == fn_def_id.0,
                 (&ty::Str, Str) => true,
                 (&ty::Never, Never) => true,
@@ -786,7 +789,7 @@ impl<'tcx> ty::TypeFolder<'tcx> for ReplaceOpaqueTyFolder<'tcx> {
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Opaque(def_id, substs) = *ty.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind() {
             if def_id == self.opaque_ty_id.0 && substs == self.identity_substs {
                 return self.tcx.mk_ty(ty::Bound(
                     self.binder_index,
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index c4ab86e9e9b..9712abb708f 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -66,15 +66,6 @@ impl<'tcx> LowerInto<'tcx, SubstsRef<'tcx>> for &chalk_ir::Substitution<RustInte
     }
 }
 
-impl<'tcx> LowerInto<'tcx, chalk_ir::AliasTy<RustInterner<'tcx>>> for ty::ProjectionTy<'tcx> {
-    fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasTy<RustInterner<'tcx>> {
-        chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
-            associated_ty_id: chalk_ir::AssocTypeId(self.item_def_id),
-            substitution: self.substs.lower_into(interner),
-        })
-    }
-}
-
 impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>>>
     for ChalkEnvironmentAndGoal<'tcx>
 {
@@ -255,7 +246,10 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq<RustInterner<'tcx>>>
         // FIXME(associated_const_equality): teach chalk about terms for alias eq.
         chalk_ir::AliasEq {
             ty: self.term.ty().unwrap().lower_into(interner),
-            alias: self.projection_ty.lower_into(interner),
+            alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
+                associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.def_id),
+                substitution: self.projection_ty.substs.lower_into(interner),
+            }),
         }
     }
 }
@@ -353,8 +347,13 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
             ty::Tuple(types) => {
                 chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner))
             }
-            ty::Projection(proj) => chalk_ir::TyKind::Alias(proj.lower_into(interner)),
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }) => {
+                chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
+                    associated_ty_id: chalk_ir::AssocTypeId(def_id),
+                    substitution: substs.lower_into(interner),
+                }))
+            }
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
                     opaque_ty_id: chalk_ir::OpaqueTyId(def_id),
                     substitution: substs.lower_into(interner),
@@ -442,13 +441,14 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
                 mutbl.lower_into(interner),
             ),
             TyKind::Str => ty::Str,
-            TyKind::OpaqueType(opaque_ty, substitution) => {
-                ty::Opaque(opaque_ty.0, substitution.lower_into(interner))
-            }
-            TyKind::AssociatedType(assoc_ty, substitution) => ty::Projection(ty::ProjectionTy {
-                substs: substitution.lower_into(interner),
-                item_def_id: assoc_ty.0,
-            }),
+            TyKind::OpaqueType(opaque_ty, substitution) => ty::Alias(
+                ty::Opaque,
+                interner.tcx.mk_alias_ty(opaque_ty.0, substitution.lower_into(interner)),
+            ),
+            TyKind::AssociatedType(assoc_ty, substitution) => ty::Alias(
+                ty::Projection,
+                interner.tcx.mk_alias_ty(assoc_ty.0, substitution.lower_into(interner)),
+            ),
             TyKind::Foreign(def_id) => ty::Foreign(def_id.0),
             TyKind::Error => return interner.tcx.ty_error(),
             TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
@@ -456,13 +456,20 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
                 name: ty::BoundVar::from_usize(placeholder.idx),
             }),
             TyKind::Alias(alias_ty) => match alias_ty {
-                chalk_ir::AliasTy::Projection(projection) => ty::Projection(ty::ProjectionTy {
-                    item_def_id: projection.associated_ty_id.0,
-                    substs: projection.substitution.lower_into(interner),
-                }),
-                chalk_ir::AliasTy::Opaque(opaque) => {
-                    ty::Opaque(opaque.opaque_ty_id.0, opaque.substitution.lower_into(interner))
-                }
+                chalk_ir::AliasTy::Projection(projection) => ty::Alias(
+                    ty::Projection,
+                    interner.tcx.mk_alias_ty(
+                        projection.associated_ty_id.0,
+                        projection.substitution.lower_into(interner),
+                    ),
+                ),
+                chalk_ir::AliasTy::Opaque(opaque) => ty::Alias(
+                    ty::Opaque,
+                    interner.tcx.mk_alias_ty(
+                        opaque.opaque_ty_id.0,
+                        opaque.substitution.lower_into(interner),
+                    ),
+                ),
             },
             TyKind::Function(_quantified_ty) => unimplemented!(),
             TyKind::BoundVar(_bound) => ty::Bound(
@@ -688,7 +695,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
                     binders.clone(),
                     chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
                         alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
-                            associated_ty_id: chalk_ir::AssocTypeId(predicate.item_def_id),
+                            associated_ty_id: chalk_ir::AssocTypeId(predicate.def_id),
                             substitution: interner
                                 .tcx
                                 .mk_substs_trait(self_ty, predicate.substs)
@@ -844,7 +851,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>
         let (trait_ref, own_substs) = self.projection_ty.trait_ref_and_own_substs(interner.tcx);
         chalk_solve::rust_ir::AliasEqBound {
             trait_bound: trait_ref.lower_into(interner),
-            associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
+            associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.def_id),
             parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(),
             value: self.term.ty().unwrap().lower_into(interner),
         }
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 66ab742f157..3f661ce6923 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -112,7 +112,7 @@ fn dropck_outlives<'tcx>(
 
                     // A projection that we couldn't resolve - it
                     // might have a destructor.
-                    ty::Projection(..) | ty::Opaque(..) => {
+                    ty::Alias(..) => {
                         result.kinds.push(ty.into());
                     }
 
@@ -268,7 +268,7 @@ fn dtorck_constraint_for_ty<'tcx>(
         }
 
         // Types that can't be resolved. Pass them forward.
-        ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => {
+        ty::Alias(..) | ty::Param(..) => {
             constraints.dtorck_types.push(ty);
         }
 
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index c6f2b16ca21..2da98d33429 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -44,7 +44,13 @@ fn inner_resolve_instance<'tcx>(
 
     let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
         debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
-        resolve_associated_item(tcx, def.did, param_env, trait_def_id, substs)
+        resolve_associated_item(
+            tcx,
+            def.did,
+            param_env,
+            trait_def_id,
+            tcx.normalize_erasing_regions(param_env, substs),
+        )
     } else {
         let ty = tcx.type_of(def.def_id_for_type_of());
         let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index f4672a70072..c761a4dbe45 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -444,7 +444,7 @@ fn layout_of_uncached<'tcx>(
         }
 
         // Types with no meaningful known layout.
-        ty::Projection(_) | ty::Opaque(..) => {
+        ty::Alias(..) => {
             // NOTE(eddyb) `layout_of` query should've normalized these away,
             // if that was possible, so there's no reason to try again here.
             return Err(LayoutError::Unknown(ty));
@@ -919,7 +919,7 @@ fn variant_info_for_generator<'tcx>(
     def_id: DefId,
     substs: ty::SubstsRef<'tcx>,
 ) -> (Vec<VariantInfo>, Option<Size>) {
-    let Variants::Multiple { tag, ref tag_encoding, .. } = layout.variants else {
+    let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
         return (vec![], None);
     };
 
@@ -975,12 +975,28 @@ fn variant_info_for_generator<'tcx>(
             if variant_size == Size::ZERO {
                 variant_size = upvars_size;
             }
-            // We need to add the discriminant size back into min_size, since it is subtracted
-            // later during printing.
-            variant_size += match tag_encoding {
-                TagEncoding::Direct => tag.size(cx),
-                _ => Size::ZERO,
-            };
+
+            // This `if` deserves some explanation.
+            //
+            // The layout code has a choice of where to place the discriminant of this generator.
+            // If the discriminant of the generator is placed early in the layout (before the
+            // variant's own fields), then it'll implicitly be counted towards the size of the
+            // variant, since we use the maximum offset to calculate size.
+            //    (side-note: I know this is a bit problematic given upvars placement, etc).
+            //
+            // This is important, since the layout printing code always subtracts this discriminant
+            // size from the variant size if the struct is "enum"-like, so failing to account for it
+            // will either lead to numerical underflow, or an underreported variant size...
+            //
+            // However, if the discriminant is placed past the end of the variant, then we need
+            // to factor in the size of the discriminant manually. This really should be refactored
+            // better, but this "works" for now.
+            if layout.fields.offset(tag_field) >= variant_size {
+                variant_size += match tag_encoding {
+                    TagEncoding::Direct => tag.size(cx),
+                    _ => Size::ZERO,
+                };
+            }
 
             VariantInfo {
                 name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))),
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 024dcd591bd..0df060fc5fb 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -152,7 +152,7 @@ where
                             queue_type(self, required);
                         }
                     }
-                    ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
+                    ty::Array(..) | ty::Alias(..) | ty::Param(_) => {
                         if ty == component {
                             // Return the type to the caller: they may be able
                             // to normalize further than we can.
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 5fc9bcac1b1..5279fc69a31 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -37,7 +37,7 @@ fn sized_constraint_for_ty<'tcx>(
                 .collect()
         }
 
-        Projection(..) | Opaque(..) => {
+        Alias(..) => {
             // must calculate explicitly.
             // FIXME: consider special-casing always-Sized projections
             vec![ty]
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index e3f7a1bd033..c992dbccd62 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -42,7 +42,7 @@ pub trait Interner {
     type ListBinderExistentialPredicate: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type BinderListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type ListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
-    type ProjectionTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+    type AliasTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type ParamTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type BoundTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type PlaceholderType: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 3ed616d709b..f30ae82d7cd 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -1,6 +1,6 @@
 #![allow(rustc::usage_of_ty_tykind)]
 
-use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use std::cmp::Ordering;
 use std::{fmt, hash};
 
 use crate::DebruijnIndex;
@@ -19,19 +19,8 @@ use rustc_data_structures::stable_hasher::HashStable;
 use rustc_serialize::{Decodable, Decoder, Encodable};
 
 /// Specifies how a trait object is represented.
-#[derive(
-    Clone,
-    Copy,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Hash,
-    Debug,
-    Encodable,
-    Decodable,
-    HashStable_Generic
-)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum DynKind {
     /// An unsized `dyn Trait` object
     Dyn,
@@ -46,6 +35,13 @@ pub enum DynKind {
     DynStar,
 }
 
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum AliasKind {
+    Projection,
+    Opaque,
+}
+
 /// Defines the kinds of types used by the type system.
 ///
 /// Types written by the user start out as `hir::TyKind` and get
@@ -170,21 +166,8 @@ pub enum TyKind<I: Interner> {
     /// A tuple type. For example, `(i32, bool)`.
     Tuple(I::ListTy),
 
-    /// The projection of an associated type. For example,
-    /// `<T as Trait<..>>::N`.
-    Projection(I::ProjectionTy),
-
-    /// Opaque (`impl Trait`) type found in a return type.
-    ///
-    /// The `DefId` comes either from
-    /// * the `impl Trait` ast::Ty node,
-    /// * or the `type Foo = impl Trait` declaration
-    ///
-    /// For RPIT the substitutions are for the generics of the function,
-    /// while for TAIT it is used for the generic parameters of the alias.
-    ///
-    /// During codegen, `tcx.type_of(def_id)` can be used to get the underlying type.
-    Opaque(I::DefId, I::SubstsRef),
+    /// A projection or opaque type. Both of these types
+    Alias(AliasKind, I::AliasTy),
 
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
     Param(I::ParamTy),
@@ -252,13 +235,12 @@ const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
         GeneratorWitness(_) => 17,
         Never => 18,
         Tuple(_) => 19,
-        Projection(_) => 20,
-        Opaque(_, _) => 21,
-        Param(_) => 22,
-        Bound(_, _) => 23,
-        Placeholder(_) => 24,
-        Infer(_) => 25,
-        Error(_) => 26,
+        Alias(_, _) => 20,
+        Param(_) => 21,
+        Bound(_, _) => 22,
+        Placeholder(_) => 23,
+        Infer(_) => 24,
+        Error(_) => 25,
     }
 }
 
@@ -268,9 +250,9 @@ impl<I: Interner> Clone for TyKind<I> {
         match self {
             Bool => Bool,
             Char => Char,
-            Int(i) => Int(i.clone()),
-            Uint(u) => Uint(u.clone()),
-            Float(f) => Float(f.clone()),
+            Int(i) => Int(*i),
+            Uint(u) => Uint(*u),
+            Float(f) => Float(*f),
             Adt(d, s) => Adt(d.clone(), s.clone()),
             Foreign(d) => Foreign(d.clone()),
             Str => Str,
@@ -280,16 +262,15 @@ impl<I: Interner> Clone for TyKind<I> {
             Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()),
             FnDef(d, s) => FnDef(d.clone(), s.clone()),
             FnPtr(s) => FnPtr(s.clone()),
-            Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), repr.clone()),
+            Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), *repr),
             Closure(d, s) => Closure(d.clone(), s.clone()),
             Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()),
             GeneratorWitness(g) => GeneratorWitness(g.clone()),
             Never => Never,
             Tuple(t) => Tuple(t.clone()),
-            Projection(p) => Projection(p.clone()),
-            Opaque(d, s) => Opaque(d.clone(), s.clone()),
+            Alias(k, p) => Alias(*k, p.clone()),
             Param(p) => Param(p.clone()),
-            Bound(d, b) => Bound(d.clone(), b.clone()),
+            Bound(d, b) => Bound(*d, b.clone()),
             Placeholder(p) => Placeholder(p.clone()),
             Infer(t) => Infer(t.clone()),
             Error(e) => Error(e.clone()),
@@ -323,8 +304,7 @@ impl<I: Interner> PartialEq for TyKind<I> {
                 }
                 (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
                 (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
-                (Projection(a_p), Projection(b_p)) => a_p == b_p,
-                (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d == b_d && a_s == b_s,
+                (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
                 (Param(a_p), Param(b_p)) => a_p == b_p,
                 (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
                 (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
@@ -381,8 +361,7 @@ impl<I: Interner> Ord for TyKind<I> {
                 }
                 (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g),
                 (Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t),
-                (Projection(a_p), Projection(b_p)) => a_p.cmp(b_p),
-                (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+                (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i.cmp(b_i).then_with(|| a_p.cmp(b_p)),
                 (Param(a_p), Param(b_p)) => a_p.cmp(b_p),
                 (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)),
                 (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p),
@@ -443,10 +422,9 @@ impl<I: Interner> hash::Hash for TyKind<I> {
             }
             GeneratorWitness(g) => g.hash(state),
             Tuple(t) => t.hash(state),
-            Projection(p) => p.hash(state),
-            Opaque(d, s) => {
-                d.hash(state);
-                s.hash(state)
+            Alias(i, p) => {
+                i.hash(state);
+                p.hash(state);
             }
             Param(p) => p.hash(state),
             Bound(d, b) => {
@@ -485,8 +463,7 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
             GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
             Never => f.write_str("Never"),
             Tuple(t) => f.debug_tuple_field1_finish("Tuple", t),
-            Projection(p) => f.debug_tuple_field1_finish("Projection", p),
-            Opaque(d, s) => f.debug_tuple_field2_finish("Opaque", d, s),
+            Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a),
             Param(p) => f.debug_tuple_field1_finish("Param", p),
             Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b),
             Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p),
@@ -513,7 +490,7 @@ where
     I::ListBinderExistentialPredicate: Encodable<E>,
     I::BinderListTy: Encodable<E>,
     I::ListTy: Encodable<E>,
-    I::ProjectionTy: Encodable<E>,
+    I::AliasTy: Encodable<E>,
     I::ParamTy: Encodable<E>,
     I::BoundTy: Encodable<E>,
     I::PlaceholderType: Encodable<E>,
@@ -586,13 +563,10 @@ where
             Tuple(substs) => e.emit_enum_variant(disc, |e| {
                 substs.encode(e);
             }),
-            Projection(p) => e.emit_enum_variant(disc, |e| {
+            Alias(k, p) => e.emit_enum_variant(disc, |e| {
+                k.encode(e);
                 p.encode(e);
             }),
-            Opaque(def_id, substs) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e);
-                substs.encode(e);
-            }),
             Param(p) => e.emit_enum_variant(disc, |e| {
                 p.encode(e);
             }),
@@ -630,8 +604,9 @@ where
     I::ListBinderExistentialPredicate: Decodable<D>,
     I::BinderListTy: Decodable<D>,
     I::ListTy: Decodable<D>,
-    I::ProjectionTy: Decodable<D>,
+    I::AliasTy: Decodable<D>,
     I::ParamTy: Decodable<D>,
+    I::AliasTy: Decodable<D>,
     I::BoundTy: Decodable<D>,
     I::PlaceholderType: Decodable<D>,
     I::InferTy: Decodable<D>,
@@ -660,13 +635,12 @@ where
             17 => GeneratorWitness(Decodable::decode(d)),
             18 => Never,
             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)),
+            20 => Alias(Decodable::decode(d), Decodable::decode(d)),
+            21 => Param(Decodable::decode(d)),
+            22 => Bound(Decodable::decode(d), Decodable::decode(d)),
+            23 => Placeholder(Decodable::decode(d)),
+            24 => Infer(Decodable::decode(d)),
+            25 => Error(Decodable::decode(d)),
             _ => panic!(
                 "{}",
                 format!(
@@ -695,7 +669,7 @@ where
     I::Mutability: HashStable<CTX>,
     I::BinderListTy: HashStable<CTX>,
     I::ListTy: HashStable<CTX>,
-    I::ProjectionTy: HashStable<CTX>,
+    I::AliasTy: HashStable<CTX>,
     I::BoundTy: HashStable<CTX>,
     I::ParamTy: HashStable<CTX>,
     I::PlaceholderType: HashStable<CTX>,
@@ -772,13 +746,10 @@ where
             Tuple(substs) => {
                 substs.hash_stable(__hcx, __hasher);
             }
-            Projection(p) => {
+            Alias(k, p) => {
+                k.hash_stable(__hcx, __hasher);
                 p.hash_stable(__hcx, __hasher);
             }
-            Opaque(def_id, substs) => {
-                def_id.hash_stable(__hcx, __hasher);
-                substs.hash_stable(__hcx, __hasher);
-            }
             Param(p) => {
                 p.hash_stable(__hcx, __hasher);
             }
@@ -965,7 +936,7 @@ impl<I: Interner> Clone for RegionKind<I> {
     fn clone(&self) -> Self {
         match self {
             ReEarlyBound(r) => ReEarlyBound(r.clone()),
-            ReLateBound(d, r) => ReLateBound(d.clone(), r.clone()),
+            ReLateBound(d, r) => ReLateBound(*d, r.clone()),
             ReFree(r) => ReFree(r.clone()),
             ReStatic => ReStatic,
             ReVar(r) => ReVar(r.clone()),
diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs
index fdd56cb4eaa..4a8302ee404 100644
--- a/library/core/src/borrow.rs
+++ b/library/core/src/borrow.rs
@@ -26,7 +26,7 @@
 /// to be modified, it can additionally implement [`BorrowMut<T>`].
 ///
 /// Further, when providing implementations for additional traits, it needs
-/// to be considered whether they should behave identical to those of the
+/// to be considered whether they should behave identically to those of the
 /// underlying type as a consequence of acting as a representation of that
 /// underlying type. Generic code typically uses `Borrow<T>` when it relies
 /// on the identical behavior of these additional trait implementations.
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index 8ba1c122884..0910ce599b7 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -21,15 +21,14 @@
 //! #[custom_mir(dialect = "built")]
 //! pub fn simple(x: i32) -> i32 {
 //!     mir!(
-//!         let temp1: i32;
-//!         let temp2: _;
+//!         let temp2: i32;
 //!
 //!         {
-//!             temp1 = x;
-//!             Goto(exit)
+//!             let temp1 = x;
+//!             Goto(my_second_block)
 //!         }
 //!
-//!         exit = {
+//!         my_second_block = {
 //!             temp2 = Move(temp1);
 //!             RET = temp2;
 //!             Return()
@@ -38,22 +37,168 @@
 //! }
 //! ```
 //!
-//! Hopefully most of this is fairly self-explanatory. Expanding on some notable details:
+//! The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
+//! attribute only works on functions - there is no way to insert custom MIR into the middle of
+//! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect
+//! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]`
+//! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
+//! "runtime", phase = "optimized")] if you don't.
 //!
-//!  - The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
-//!    attribute only works on functions - there is no way to insert custom MIR into the middle of
-//!    another function.
-//!  - The `dialect` and `phase` parameters indicate which version of MIR you are inserting here.
-//!    This will normally be the phase that corresponds to the thing you are trying to test. The
-//!    phase can be omitted for dialects that have just one.
-//!  - You should define your function signature like you normally would. Externally, this function
-//!    can be called like any other function.
-//!  - Type inference works - you don't have to spell out the type of all of your locals.
+//! [dialect docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
 //!
-//! For now, all statements and terminators are parsed from nested invocations of the special
-//! functions provided in this module. We additionally want to (but do not yet) support more
-//! "normal" Rust syntax in places where it makes sense. Also, most kinds of instructions are not
-//! supported yet.
+//! The input to the [`mir!`] macro is:
+//!
+//!  - A possibly empty list of local declarations. Locals can also be declared inline on
+//!    assignments via `let`. Type inference generally works. Shadowing does not.
+//!  - A list of basic blocks. The first of these is the start block and is where execution begins.
+//!    All blocks other than the start block need to be given a name, so that they can be referred
+//!    to later.
+//!     - Each block is a list of semicolon terminated statements, followed by a terminator. The
+//!       syntax for the various statements and terminators is designed to be as similar as possible
+//!       to the syntax for analogous concepts in native Rust. See below for a list.
+//!
+//! # Examples
+//!
+//! ```rust
+//! #![feature(core_intrinsics, custom_mir)]
+//!
+//! extern crate core;
+//! use core::intrinsics::mir::*;
+//!
+//! #[custom_mir(dialect = "built")]
+//! pub fn choose_load(a: &i32, b: &i32, c: bool) -> i32 {
+//!     mir!(
+//!         {
+//!             match c {
+//!                 true => t,
+//!                 _ => f,
+//!             }
+//!         }
+//!
+//!         t = {
+//!             let temp = a;
+//!             Goto(load_and_exit)
+//!         }
+//!
+//!         f = {
+//!             temp = b;
+//!             Goto(load_and_exit)
+//!         }
+//!
+//!         load_and_exit = {
+//!             RET = *temp;
+//!             Return()
+//!         }
+//!     )
+//! }
+//!
+//! #[custom_mir(dialect = "built")]
+//! fn unwrap_unchecked<T>(opt: Option<T>) -> T {
+//!     mir!({
+//!         RET = Move(Field(Variant(opt, 1), 0));
+//!         Return()
+//!     })
+//! }
+//! ```
+//!
+//! We can also set off compilation failures that happen in sufficiently late stages of the
+//! compiler:
+//!
+//! ```rust,compile_fail
+//! #![feature(core_intrinsics, custom_mir)]
+//!
+//! extern crate core;
+//! use core::intrinsics::mir::*;
+//!
+//! #[custom_mir(dialect = "built")]
+//! fn borrow_error(should_init: bool) -> i32 {
+//!     mir!(
+//!         let temp: i32;
+//!
+//!         {
+//!             match should_init {
+//!                 true => init,
+//!                 _ => use_temp,
+//!             }
+//!         }
+//!
+//!         init = {
+//!             temp = 0;
+//!             Goto(use_temp)
+//!         }
+//!
+//!         use_temp = {
+//!             RET = temp;
+//!             Return()
+//!         }
+//!     )
+//! }
+//! ```
+//!
+//! ```text
+//! error[E0381]: used binding is possibly-uninitialized
+//!   --> test.rs:24:13
+//!    |
+//! 8  | /     mir!(
+//! 9  | |         let temp: i32;
+//! 10 | |
+//! 11 | |         {
+//! ...  |
+//! 19 | |             temp = 0;
+//!    | |             -------- binding initialized here in some conditions
+//! ...  |
+//! 24 | |             RET = temp;
+//!    | |             ^^^^^^^^^^ value used here but it is possibly-uninitialized
+//! 25 | |             Return()
+//! 26 | |         }
+//! 27 | |     )
+//!    | |_____- binding declared here but left uninitialized
+//!
+//! error: aborting due to previous error
+//!
+//! For more information about this error, try `rustc --explain E0381`.
+//! ```
+//!
+//! # Syntax
+//!
+//! The lists below are an exhaustive description of how various MIR constructs can be created.
+//! Anything missing from the list should be assumed to not be supported, PRs welcome.
+//!
+//! #### Locals
+//!
+//!  - The `_0` return local can always be accessed via `RET`.
+//!  - Arguments can be accessed via their regular name.
+//!  - All other locals need to be declared with `let` somewhere and then can be accessed by name.
+//!
+//! #### Places
+//!  - Locals implicit convert to places.
+//!  - Field accesses, derefs, and indexing work normally.
+//!  - Fields in variants can be accessed via the [`Variant`] and [`Field`] associated functions,
+//!    see their documentation for details.
+//!
+//! #### Operands
+//!  - Places implicitly convert to `Copy` operands.
+//!  - `Move` operands can be created via [`Move`].
+//!  - Const blocks, literals, named constants, and const params all just work.
+//!  - [`Static`] and [`StaticMut`] can be used to create `&T` and `*mut T`s to statics. These are
+//!    constants in MIR and the only way to access statics.
+//!
+//! #### Statements
+//!  - Assign statements work via normal Rust assignment.
+//!  - [`Retag`] statements have an associated function.
+//!
+//! #### Rvalues
+//!
+//!  - Operands implicitly convert to `Use` rvalues.
+//!  - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
+//!  - [`Discriminant`] has an associated function.
+//!
+//! #### Terminators
+//!
+//!  - [`Goto`] and [`Return`] have associated functions.
+//!  - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
+//!     - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
+//!       otherwise branch.
 //!
 
 #![unstable(
@@ -69,9 +214,10 @@
 pub struct BasicBlock;
 
 macro_rules! define {
-    ($name:literal, $($sig:tt)*) => {
+    ($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => {
         #[rustc_diagnostic_item = $name]
-        pub $($sig)* { panic!() }
+        $( #[ $meta ] )*
+        pub fn $($sig)* { panic!() }
     }
 }
 
@@ -82,8 +228,73 @@ define!("mir_retag_raw", fn RetagRaw<T>(place: T));
 define!("mir_move", fn Move<T>(place: T) -> T);
 define!("mir_static", fn Static<T>(s: T) -> &'static T);
 define!("mir_static_mut", fn StaticMut<T>(s: T) -> *mut T);
+define!(
+    "mir_discriminant",
+    /// Gets the discriminant of a place.
+    fn Discriminant<T>(place: T) -> <T as ::core::marker::DiscriminantKind>::Discriminant
+);
+define!("mir_set_discriminant", fn SetDiscriminant<T>(place: T, index: u32));
+define!(
+    "mir_field",
+    /// Access the field with the given index of some place.
+    ///
+    /// This only makes sense to use in conjunction with [`Variant`]. If the type you are looking to
+    /// access the field of does not have variants, you can use normal field projection syntax.
+    ///
+    /// There is no proper way to do a place projection to a variant in Rust, and so these two
+    /// functions are a workaround. You can access a field of a variant via `Field(Variant(place,
+    /// var_idx), field_idx)`, where `var_idx` and `field_idx` are appropriate literals. Some
+    /// caveats:
+    ///
+    ///  - The return type of `Variant` is always `()`. Don't worry about that, the correct MIR will
+    ///    still be generated.
+    ///  - In some situations, the return type of `Field` cannot be inferred. You may need to
+    ///    annotate it on the function in these cases.
+    ///  - Since `Field` is a function call which is not a place expression, using this on the left
+    ///    hand side of an expression is rejected by the compiler. [`place!`] is a macro provided to
+    ///    work around that issue. Wrap the left hand side of an assignment in the macro to convince
+    ///    the compiler that it's ok.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(custom_mir, core_intrinsics)]
+    ///
+    /// extern crate core;
+    /// use core::intrinsics::mir::*;
+    ///
+    /// #[custom_mir(dialect = "built")]
+    /// fn unwrap_deref(opt: Option<&i32>) -> i32 {
+    ///     mir!({
+    ///         RET = *Field::<&i32>(Variant(opt, 1), 0);
+    ///         Return()
+    ///     })
+    /// }
+    ///
+    /// #[custom_mir(dialect = "built")]
+    /// fn set(opt: &mut Option<i32>) {
+    ///     mir!({
+    ///         place!(Field(Variant(*opt, 1), 0)) = 5;
+    ///         Return()
+    ///     })
+    /// }
+    /// ```
+    fn Field<F>(place: (), field: u32) -> F
+);
+define!(
+    "mir_variant",
+    /// Adds a variant projection with the given index to the place.
+    ///
+    /// See [`Field`] for documentation.
+    fn Variant<T>(place: T, index: u32) -> ()
+);
+define!(
+    "mir_make_place",
+    #[doc(hidden)]
+    fn __internal_make_place<T>(place: T) -> *mut T
+);
 
-/// Convenience macro for generating custom MIR.
+/// Macro for generating custom MIR.
 ///
 /// See the module documentation for syntax details. This macro is not magic - it only transforms
 /// your MIR into something that is easier to parse in the compiler.
@@ -139,6 +350,13 @@ pub macro mir {
     }}
 }
 
+/// Helper macro that allows you to treat a value expression like a place expression.
+///
+/// See the documentation on [`Variant`] for why this is necessary and how to use it.
+pub macro place($e:expr) {
+    (*::core::intrinsics::mir::__internal_make_place($e))
+}
+
 /// Helper macro that extracts the `let` declarations out of a bunch of statements.
 ///
 /// This macro is written using the "statement muncher" strategy. Each invocation parses the first
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 83c7e8977e9..1cdee992137 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1829,6 +1829,7 @@ pub trait Iterator {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")]
     fn collect<B: FromIterator<Self::Item>>(self) -> B
     where
         Self: Sized,
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 505d964e518..39462dca4ff 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -72,6 +72,50 @@
 //! }
 //! ```
 //!
+//! # The question mark operator, `?`
+//!
+//! Similar to the [`Result`] type, when writing code that calls many functions that return the
+//! [`Option`] type, handling `Some`/`None` can be tedious. The question mark
+//! operator, [`?`], hides some of the boilerplate of propagating values
+//! up the call stack.
+//!
+//! It replaces this:
+//!
+//! ```
+//! # #![allow(dead_code)]
+//! fn add_last_numbers(stack: &mut Vec<i32>) -> Option<i32> {
+//!     let a = stack.pop();
+//!     let b = stack.pop();
+//!
+//!     match (a, b) {
+//!         (Some(x), Some(y)) => Some(x + y),
+//!         _ => None,
+//!     }
+//! }
+//!
+//! ```
+//!
+//! With this:
+//!
+//! ```
+//! # #![allow(dead_code)]
+//! fn add_last_numbers(stack: &mut Vec<i32>) -> Option<i32> {
+//!     Some(stack.pop()? + stack.pop()?)
+//! }
+//! ```
+//!
+//! *It's much nicer!*
+//!
+//! Ending the expression with [`?`] will result in the [`Some`]'s unwrapped value, unless the
+//! result is [`None`], in which case [`None`] is returned early from the enclosing function.
+//!
+//! [`?`] can be used in functions that return [`Option`] because of the
+//! early return of [`None`] that it provides.
+//!
+//! [`?`]: crate::ops::Try
+//! [`Some`]: Some
+//! [`None`]: None
+//!
 //! # Representation
 //!
 //! Rust guarantees to optimize the following types `T` such that
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index d348135991a..b6373beac5f 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -1008,7 +1008,7 @@ impl<T: ?Sized> *const T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
-    #[inline]
+    #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub(self, count: usize) -> Self
     where
@@ -1173,7 +1173,7 @@ impl<T: ?Sized> *const T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
-    #[inline]
+    #[inline(always)]
     pub const fn wrapping_sub(self, count: usize) -> Self
     where
         T: Sized,
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index c924a90b1ff..7a5d9a70594 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1110,7 +1110,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
-    #[inline]
+    #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub(self, count: usize) -> Self
     where
@@ -1275,7 +1275,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
-    #[inline]
+    #[inline(always)]
     pub const fn wrapping_sub(self, count: usize) -> Self
     where
         T: Sized,
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 3f33c5fd6ca..f00c40f35d5 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -209,11 +209,10 @@
 //!
 //! *It's much nicer!*
 //!
-//! Ending the expression with [`?`] will result in the unwrapped
-//! success ([`Ok`]) value, unless the result is [`Err`], in which case
-//! [`Err`] is returned early from the enclosing function.
+//! Ending the expression with [`?`] will result in the [`Ok`]'s unwrapped value, unless the result
+//! is [`Err`], in which case [`Err`] is returned early from the enclosing function.
 //!
-//! [`?`] can only be used in functions that return [`Result`] because of the
+//! [`?`] can be used in functions that return [`Result`] because of the
 //! early return of [`Err`] that it provides.
 //!
 //! [`expect`]: Result::expect
diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs
index c65c275000c..301ad41c966 100644
--- a/library/core/src/sync/exclusive.rs
+++ b/library/core/src/sync/exclusive.rs
@@ -138,7 +138,7 @@ impl<T: ?Sized> Exclusive<T> {
         unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
     }
 
-    /// Build a _mutable_ references to an `Exclusive<T>` from
+    /// Build a _mutable_ reference to an `Exclusive<T>` from
     /// a _mutable_ reference to a `T`. This allows you to skip
     /// building an `Exclusive` with [`Exclusive::new`].
     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
@@ -149,7 +149,7 @@ impl<T: ?Sized> Exclusive<T> {
         unsafe { &mut *(r as *mut T as *mut Exclusive<T>) }
     }
 
-    /// Build a _pinned mutable_ references to an `Exclusive<T>` from
+    /// Build a _pinned mutable_ reference to an `Exclusive<T>` from
     /// a _pinned mutable_ reference to a `T`. This allows you to skip
     /// building an `Exclusive` with [`Exclusive::new`].
     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 0d3fc2c5244..f0e4f5d8a80 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -1493,7 +1493,7 @@ pub mod tracked_env {
     use std::ffi::OsStr;
 
     /// Retrieve an environment variable and add it to build dependency info.
-    /// Build system executing the compiler will know that the variable was accessed during
+    /// The build system executing the compiler will know that the variable was accessed during
     /// compilation, and will be able to rerun the build when the value of that variable changes.
     /// Besides the dependency tracking this function should be equivalent to `env::var` from the
     /// standard library, except that the argument must be UTF-8.
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index a7aefc26b97..29b5a468bf4 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
 libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.82" }
+compiler_builtins = { version = "0.1.85" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 6eb7cbea626..183f9ab3b08 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -570,6 +570,13 @@ impl Error for JoinPathsError {
 ///
 /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectorya
 ///
+/// # Deprecation
+///
+/// This function is deprecated because the behaviour on Windows is not correct.
+/// The 'HOME' environment variable is not standard on Windows, and may not produce
+/// desired results; for instance, under Cygwin or Mingw it will return `/home/you`
+/// when it should return `C:\Users\you`.
+///
 /// # Examples
 ///
 /// ```
@@ -582,7 +589,7 @@ impl Error for JoinPathsError {
 /// ```
 #[deprecated(
     since = "1.29.0",
-    note = "This function's behavior is unexpected and probably not what you want. \
+    note = "This function's behavior may be unexpected on Windows. \
             Consider using a crate from crates.io instead."
 )]
 #[must_use]
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index fb8d06c6682..818914a2df0 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1759,8 +1759,13 @@ mod remove_dir_impl {
     use crate::sys::common::small_c_string::run_path_with_cstr;
     use crate::sys::{cvt, cvt_r};
 
-    #[cfg(not(all(target_os = "macos", not(target_arch = "aarch64")),))]
+    #[cfg(not(any(
+        target_os = "linux",
+        all(target_os = "macos", not(target_arch = "aarch64"))
+    )))]
     use libc::{fdopendir, openat, unlinkat};
+    #[cfg(target_os = "linux")]
+    use libc::{fdopendir, openat64 as openat, unlinkat};
     #[cfg(all(target_os = "macos", not(target_arch = "aarch64")))]
     use macos_weak::{fdopendir, openat, unlinkat};
 
diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs
index 94546ca09d0..6fa85e859c0 100644
--- a/library/std/src/sys/unix/kernel_copy.rs
+++ b/library/std/src/sys/unix/kernel_copy.rs
@@ -61,6 +61,10 @@ use crate::ptr;
 use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
 use crate::sys::cvt;
 use crate::sys::weak::syscall;
+#[cfg(not(target_os = "linux"))]
+use libc::sendfile as sendfile64;
+#[cfg(target_os = "linux")]
+use libc::sendfile64;
 use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};
 
 #[cfg(test)]
@@ -647,7 +651,7 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) ->
 
         let result = match mode {
             SpliceMode::Sendfile => {
-                cvt(unsafe { libc::sendfile(writer, reader, ptr::null_mut(), chunk_size) })
+                cvt(unsafe { sendfile64(writer, reader, ptr::null_mut(), chunk_size) })
             }
             SpliceMode::Splice => cvt(unsafe {
                 splice(reader, ptr::null_mut(), writer, ptr::null_mut(), chunk_size, 0)
diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs
index 1ddb09905db..6be1abc2b08 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -2,6 +2,7 @@ use crate::cell::UnsafeCell;
 use crate::ptr;
 use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
 use crate::sys::locks::{pthread_mutex, Mutex};
+use crate::sys::time::TIMESPEC_MAX;
 use crate::sys_common::lazy_box::{LazyBox, LazyInit};
 use crate::time::Duration;
 
@@ -12,13 +13,6 @@ pub struct Condvar {
     mutex: AtomicPtr<libc::pthread_mutex_t>,
 }
 
-const TIMESPEC_MAX: libc::timespec =
-    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
-
-fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
-    if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t }
-}
-
 #[inline]
 fn raw(c: &Condvar) -> *mut libc::pthread_cond_t {
     c.inner.0.get()
@@ -133,26 +127,15 @@ impl Condvar {
         target_os = "horizon"
     )))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        use crate::mem;
+        use crate::sys::time::Timespec;
 
         let mutex = pthread_mutex::raw(mutex);
         self.verify(mutex);
 
-        let mut now: libc::timespec = mem::zeroed();
-        let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);
-        assert_eq!(r, 0);
-
-        // Nanosecond calculations can't overflow because both values are below 1e9.
-        let nsec = dur.subsec_nanos() + now.tv_nsec as u32;
-
-        let sec = saturating_cast_to_time_t(dur.as_secs())
-            .checked_add((nsec / 1_000_000_000) as libc::time_t)
-            .and_then(|s| s.checked_add(now.tv_sec));
-        let nsec = nsec % 1_000_000_000;
-
-        let timeout =
-            sec.map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec as _ }).unwrap_or(TIMESPEC_MAX);
-
+        let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
+            .checked_add_duration(&dur)
+            .and_then(|t| t.to_timespec())
+            .unwrap_or(TIMESPEC_MAX);
         let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
         assert!(r == libc::ETIMEDOUT || r == 0);
         r == 0
@@ -169,57 +152,41 @@ impl Condvar {
         target_os = "espidf",
         target_os = "horizon"
     ))]
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        use crate::sys::time::SystemTime;
         use crate::time::Instant;
 
         let mutex = pthread_mutex::raw(mutex);
         self.verify(mutex);
 
-        // 1000 years
-        let max_dur = Duration::from_secs(1000 * 365 * 86400);
-
-        if dur > max_dur {
-            // OSX implementation of `pthread_cond_timedwait` is buggy
-            // with super long durations. When duration is greater than
-            // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
-            // in macOS Sierra return error 316.
-            //
-            // This program demonstrates the issue:
-            // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
-            //
-            // To work around this issue, and possible bugs of other OSes, timeout
-            // is clamped to 1000 years, which is allowable per the API of `wait_timeout`
-            // because of spurious wakeups.
-
-            dur = max_dur;
-        }
-
-        // First, figure out what time it currently is, in both system and
-        // stable time.  pthread_cond_timedwait uses system time, but we want to
-        // report timeout based on stable time.
-        let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
-        let stable_now = Instant::now();
-        let r = libc::gettimeofday(&mut sys_now, ptr::null_mut());
-        assert_eq!(r, 0, "unexpected error: {:?}", crate::io::Error::last_os_error());
-
-        let nsec = dur.subsec_nanos() as libc::c_long + (sys_now.tv_usec * 1000) as libc::c_long;
-        let extra = (nsec / 1_000_000_000) as libc::time_t;
-        let nsec = nsec % 1_000_000_000;
-        let seconds = saturating_cast_to_time_t(dur.as_secs());
-
-        let timeout = sys_now
-            .tv_sec
-            .checked_add(extra)
-            .and_then(|s| s.checked_add(seconds))
-            .map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec })
+        // OSX implementation of `pthread_cond_timedwait` is buggy
+        // with super long durations. When duration is greater than
+        // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
+        // in macOS Sierra returns error 316.
+        //
+        // This program demonstrates the issue:
+        // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
+        //
+        // To work around this issue, and possible bugs of other OSes, timeout
+        // is clamped to 1000 years, which is allowable per the API of `wait_timeout`
+        // because of spurious wakeups.
+        let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400));
+
+        // pthread_cond_timedwait uses system time, but we want to report timeout
+        // based on stable time.
+        let now = Instant::now();
+
+        let timeout = SystemTime::now()
+            .t
+            .checked_add_duration(&dur)
+            .and_then(|t| t.to_timespec())
             .unwrap_or(TIMESPEC_MAX);
 
-        // And wait!
         let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
         debug_assert!(r == libc::ETIMEDOUT || r == 0);
 
         // ETIMEDOUT is not a totally reliable method of determining timeout due
         // to clock shifts, so do the check ourselves
-        stable_now.elapsed() < dur
+        now.elapsed() < dur
     }
 }
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 9055a011c51..3d60941e84e 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -95,6 +95,10 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
         )))]
         'poll: {
             use crate::sys::os::errno;
+            #[cfg(not(target_os = "linux"))]
+            use libc::open as open64;
+            #[cfg(target_os = "linux")]
+            use libc::open64;
             let pfds: &mut [_] = &mut [
                 libc::pollfd { fd: 0, events: 0, revents: 0 },
                 libc::pollfd { fd: 1, events: 0, revents: 0 },
@@ -116,7 +120,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
                 if pfd.revents & libc::POLLNVAL == 0 {
                     continue;
                 }
-                if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+                if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                     // If the stream is closed but we failed to reopen it, abort the
                     // process. Otherwise we wouldn't preserve the safety of
                     // operations on the corresponding Rust object Stdin, Stdout, or
@@ -139,9 +143,13 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
         )))]
         {
             use crate::sys::os::errno;
+            #[cfg(not(target_os = "linux"))]
+            use libc::open as open64;
+            #[cfg(target_os = "linux")]
+            use libc::open64;
             for fd in 0..3 {
                 if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
-                    if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+                    if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                         // If the stream is closed but we failed to reopen it, abort the
                         // process. Otherwise we wouldn't preserve the safety of
                         // operations on the corresponding Rust object Stdin, Stdout, or
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 56a805cef73..c0716a089bc 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -66,14 +66,15 @@ impl Command {
         //
         // Note that as soon as we're done with the fork there's no need to hold
         // a lock any more because the parent won't do anything and the child is
-        // in its own process. Thus the parent drops the lock guard while the child
-        // forgets it to avoid unlocking it on a new thread, which would be invalid.
+        // in its own process. Thus the parent drops the lock guard immediately.
+        // The child calls `mem::forget` to leak the lock, which is crucial because
+        // releasing a lock is not async-signal-safe.
         let env_lock = sys::os::env_read_lock();
         let (pid, pidfd) = unsafe { self.do_fork()? };
 
         if pid == 0 {
             crate::panic::always_abort();
-            mem::forget(env_lock);
+            mem::forget(env_lock); // avoid non-async-signal-safe unlocking
             drop(input);
             let Err(err) = unsafe { self.do_exec(theirs, envp.as_ref()) };
             let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;
diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs
index 75a5c0f9279..957e086798f 100644
--- a/library/std/src/sys/unix/stack_overflow.rs
+++ b/library/std/src/sys/unix/stack_overflow.rs
@@ -45,7 +45,10 @@ mod imp {
     use crate::thread;
 
     use libc::MAP_FAILED;
-    use libc::{mmap, munmap};
+    #[cfg(not(target_os = "linux"))]
+    use libc::{mmap as mmap64, munmap};
+    #[cfg(target_os = "linux")]
+    use libc::{mmap64, munmap};
     use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
     use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
     use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
@@ -135,7 +138,7 @@ mod imp {
         #[cfg(not(any(target_os = "openbsd", target_os = "netbsd", target_os = "linux",)))]
         let flags = MAP_PRIVATE | MAP_ANON;
         let stackp =
-            mmap(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
+            mmap64(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
         if stackp == MAP_FAILED {
             panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error());
         }
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 6ecf5bdcf86..d454a2a717c 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -653,7 +653,10 @@ pub mod guard {
 ))]
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    use libc::{mmap, mprotect};
+    #[cfg(not(target_os = "linux"))]
+    use libc::{mmap as mmap64, mprotect};
+    #[cfg(target_os = "linux")]
+    use libc::{mmap64, mprotect};
     use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
 
     use crate::io;
@@ -803,7 +806,7 @@ pub mod guard {
             // read/write permissions and only then mprotect() it to
             // no permissions at all. See issue #50313.
             let stackptr = get_stack_start_aligned()?;
-            let result = mmap(
+            let result = mmap64(
                 stackptr,
                 page_size,
                 PROT_READ | PROT_WRITE,
diff --git a/library/std/src/sys/unix/thread_parker/pthread.rs b/library/std/src/sys/unix/thread_parker/pthread.rs
index 3dfc0026ed1..c400c771567 100644
--- a/library/std/src/sys/unix/thread_parker/pthread.rs
+++ b/library/std/src/sys/unix/thread_parker/pthread.rs
@@ -6,6 +6,7 @@ use crate::pin::Pin;
 use crate::ptr::addr_of_mut;
 use crate::sync::atomic::AtomicUsize;
 use crate::sync::atomic::Ordering::SeqCst;
+use crate::sys::time::TIMESPEC_MAX;
 use crate::time::Duration;
 
 const EMPTY: usize = 0;
@@ -32,9 +33,6 @@ unsafe fn wait(cond: *mut libc::pthread_cond_t, lock: *mut libc::pthread_mutex_t
     debug_assert_eq!(r, 0);
 }
 
-const TIMESPEC_MAX: libc::timespec =
-    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
-
 unsafe fn wait_timeout(
     cond: *mut libc::pthread_cond_t,
     lock: *mut libc::pthread_mutex_t,
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index d5abd9b581c..2daad981b73 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -5,6 +5,9 @@ pub use self::inner::Instant;
 
 const NSEC_PER_SEC: u64 = 1_000_000_000;
 pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
+#[allow(dead_code)] // Used for pthread condvar timeouts
+pub const TIMESPEC_MAX: libc::timespec =
+    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[repr(transparent)]
diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs
index be5c9bb0788..05f25af68ea 100644
--- a/src/bootstrap/cache.rs
+++ b/src/bootstrap/cache.rs
@@ -89,16 +89,16 @@ impl<T: Internable + Hash> Hash for Interned<T> {
 
 impl<T: Internable + Deref> Deref for Interned<T> {
     type Target = T::Target;
-    fn deref(&self) -> &'static Self::Target {
+    fn deref(&self) -> &Self::Target {
         let l = T::intern_cache().lock().unwrap();
-        unsafe { mem::transmute::<&Self::Target, &'static Self::Target>(l.get(*self)) }
+        unsafe { mem::transmute::<&Self::Target, &Self::Target>(l.get(*self)) }
     }
 }
 
 impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Interned<T> {
-    fn as_ref(&self) -> &'static U {
+    fn as_ref(&self) -> &U {
         let l = T::intern_cache().lock().unwrap();
-        unsafe { mem::transmute::<&U, &'static U>(l.get(*self).as_ref()) }
+        unsafe { mem::transmute::<&U, &U>(l.get(*self).as_ref()) }
     }
 }
 
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 2fef7f65827..3cb0eccd324 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1470,7 +1470,7 @@ impl Step for Extended {
 
         let xform = |p: &Path| {
             let mut contents = t!(fs::read_to_string(p));
-            for tool in &["rust-demangler"] {
+            for tool in &["rust-demangler", "miri"] {
                 if !built_tools.contains(tool) {
                     contents = filter(&contents, tool);
                 }
@@ -1510,9 +1510,8 @@ impl Step for Extended {
             prepare("rust-std");
             prepare("rust-analysis");
             prepare("clippy");
-            prepare("miri");
             prepare("rust-analyzer");
-            for tool in &["rust-docs", "rust-demangler"] {
+            for tool in &["rust-docs", "rust-demangler", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1571,9 +1570,8 @@ impl Step for Extended {
             prepare("rust-docs");
             prepare("rust-std");
             prepare("clippy");
-            prepare("miri");
             prepare("rust-analyzer");
-            for tool in &["rust-demangler"] {
+            for tool in &["rust-demangler", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1710,23 +1708,25 @@ impl Step for Extended {
                         .arg(etc.join("msi/remove-duplicates.xsl")),
                 );
             }
-            builder.run(
-                Command::new(&heat)
-                    .current_dir(&exe)
-                    .arg("dir")
-                    .arg("miri")
-                    .args(&heat_flags)
-                    .arg("-cg")
-                    .arg("MiriGroup")
-                    .arg("-dr")
-                    .arg("Miri")
-                    .arg("-var")
-                    .arg("var.MiriDir")
-                    .arg("-out")
-                    .arg(exe.join("MiriGroup.wxs"))
-                    .arg("-t")
-                    .arg(etc.join("msi/remove-duplicates.xsl")),
-            );
+            if built_tools.contains("miri") {
+                builder.run(
+                    Command::new(&heat)
+                        .current_dir(&exe)
+                        .arg("dir")
+                        .arg("miri")
+                        .args(&heat_flags)
+                        .arg("-cg")
+                        .arg("MiriGroup")
+                        .arg("-dr")
+                        .arg("Miri")
+                        .arg("-var")
+                        .arg("var.MiriDir")
+                        .arg("-out")
+                        .arg(exe.join("MiriGroup.wxs"))
+                        .arg("-t")
+                        .arg(etc.join("msi/remove-duplicates.xsl")),
+                );
+            }
             builder.run(
                 Command::new(&heat)
                     .current_dir(&exe)
@@ -1774,7 +1774,6 @@ impl Step for Extended {
                     .arg("-dStdDir=rust-std")
                     .arg("-dAnalysisDir=rust-analysis")
                     .arg("-dClippyDir=clippy")
-                    .arg("-dMiriDir=miri")
                     .arg("-arch")
                     .arg(&arch)
                     .arg("-out")
@@ -1788,6 +1787,9 @@ impl Step for Extended {
                 if built_tools.contains("rust-analyzer") {
                     cmd.arg("-dRustAnalyzerDir=rust-analyzer");
                 }
+                if built_tools.contains("miri") {
+                    cmd.arg("-dMiriDir=miri");
+                }
                 if target.ends_with("windows-gnu") {
                     cmd.arg("-dGccDir=rust-mingw");
                 }
@@ -1801,7 +1803,9 @@ impl Step for Extended {
             candle("CargoGroup.wxs".as_ref());
             candle("StdGroup.wxs".as_ref());
             candle("ClippyGroup.wxs".as_ref());
-            candle("MiriGroup.wxs".as_ref());
+            if built_tools.contains("miri") {
+                candle("MiriGroup.wxs".as_ref());
+            }
             if built_tools.contains("rust-demangler") {
                 candle("RustDemanglerGroup.wxs".as_ref());
             }
@@ -1837,9 +1841,11 @@ impl Step for Extended {
                 .arg("StdGroup.wixobj")
                 .arg("AnalysisGroup.wixobj")
                 .arg("ClippyGroup.wixobj")
-                .arg("MiriGroup.wixobj")
                 .current_dir(&exe);
 
+            if built_tools.contains("miri") {
+                cmd.arg("MiriGroup.wixobj");
+            }
             if built_tools.contains("rust-analyzer") {
                 cmd.arg("RustAnalyzerGroup.wixobj");
             }
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index e0be4c432f1..24b033cc0dc 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -747,19 +747,9 @@ impl Step for RustAnalyzerProcMacroSrv {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        let builder = run.builder;
-
         // Allow building `rust-analyzer-proc-macro-srv` both as part of the `rust-analyzer` and as a stand-alone tool.
         run.path("src/tools/rust-analyzer")
             .path("src/tools/rust-analyzer/crates/proc-macro-srv-cli")
-            .default_condition(
-                builder.config.extended
-                    && builder.config.tools.as_ref().map_or(true, |tools| {
-                        tools.iter().any(|tool| {
-                            tool == "rust-analyzer" || tool == "rust-analyzer-proc-macro-srv"
-                        })
-                    }),
-            )
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index a2708d16947..3e86339859d 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -346,7 +346,7 @@ class TestEnvironment:
                 "-f",
                 self.ssh_keyfile_path(),
                 "-C",
-                "Generated by test_toolchain.py",
+                "Generated by fuchsia-test-runner.py",
             ],
             stdout=self.subprocess_output(),
             stderr=self.subprocess_output(),
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 75e44fe4987..5a0397a3d12 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -667,6 +667,7 @@ jobs:
                 --target=x86_64-pc-windows-msvc
                 --enable-full-tools
                 --enable-profiler
+                --set rust.lto=thin
               SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths
               DIST_REQUIRE_ALL_TOOLS: 1
             <<: *job-windows-xl
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index ef6eee75f1c..d4d26654ed1 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -434,6 +434,9 @@ replacement is purely textual, with no consideration of the current system's
 pathname syntax. For example `--remap-path-prefix foo=bar` will match
 `foo/lib.rs` but not `./foo/lib.rs`.
 
+When multiple remappings are given and several of them match, the **last**
+matching one is applied.
+
 <a id="option-json"></a>
 ## `--json`: configure json messages printed by the compiler
 
diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md
index fa38dd54d60..98b49e07171 100644
--- a/src/doc/rustc/src/exploit-mitigations.md
+++ b/src/doc/rustc/src/exploit-mitigations.md
@@ -217,7 +217,7 @@ It is recommended that explicit wrapping methods such as `wrapping_add` be
 used when wrapping semantics are intended, and that explicit checking and
 wrapping methods always be used when using Unsafe Rust.
 
-<small id="fn:2">2\. See <https://doc.rust-lang.org/std/primitive.u32.html>
+<small id="fn:2">2\. See [the `u32` docs](../std/primitive.u32.html)
 for more information on the checked, overflowing, saturating, and wrapping
 methods (using u32 as an example). <a href="#fnref:2"
 class="reversefootnote" role="doc-backlink">↩</a></small>
@@ -575,17 +575,17 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
    <https://hacks.mozilla.org/2019/02/fearless-security-thread-safety/>.
 
 3. S. Klabnik and C. Nichols. “What Is Ownership?.” The Rust Programming
-   Language. <https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html>.
+   Language. [https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html](../book/ch04-01-what-is-ownership.html).
 
 4. S. Klabnik and C. Nichols. “References and Borrowing.” The Rust
    Programming Language.
-   <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html>.
+   [https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html](../book/ch04-02-references-and-borrowing.html).
 
 5. S. Klabnik and C. Nichols. “The Slice Type.” The Rust Programming
-   Language. <https://doc.rust-lang.org/book/ch04-03-slices.html>.
+   Language. [https://doc.rust-lang.org/book/ch04-03-slices.html](../book/ch04-03-slices.html).
 
 6. S. Klabnik and C. Nichols. “Unsafe Rust.” The Rust Programming Language.
-   <https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html>.
+   [https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html](../book/ch19-01-unsafe-rust.html).
 
 7. S. Davidoff. “How Rust’s standard library was vulnerable for years and
    nobody noticed.” Medium.
@@ -696,4 +696,4 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
     for Rust #89653.” GitHub. <https://github.com/rust-lang/rust/issues/89653>.
 
 41. “ControlFlowIntegrity.” The Rust Unstable Book.
-    <https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity>.
+    [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity).
diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md
index 9272b9ac9b2..858b7bc79c4 100644
--- a/src/doc/rustc/src/linker-plugin-lto.md
+++ b/src/doc/rustc/src/linker-plugin-lto.md
@@ -112,7 +112,7 @@ targeting Windows-like targets
 This is fixed if you explicitly set the target, for example
 `cargo build --target x86_64-pc-windows-msvc`
 Without an explicit --target the flags will be passed to all compiler invocations (including build
-scripts and proc macros), see [cargo docs on rustflags](https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags)
+scripts and proc macros), see [cargo docs on rustflags](../cargo/reference/config.html#buildrustflags)
 
 If you have dependencies using the `cc` crate, you will need to set these
 environment variables:
diff --git a/src/doc/rustc/src/platform-support/android.md b/src/doc/rustc/src/platform-support/android.md
index b2c8e5d4df7..e351cfaf89c 100644
--- a/src/doc/rustc/src/platform-support/android.md
+++ b/src/doc/rustc/src/platform-support/android.md
@@ -42,4 +42,4 @@ edition of the [Android NDK].  Supported Android targets are:
 [Android NDK]: https://developer.android.com/ndk/downloads
 
 A list of all supported targets can be found
-[here](https://doc.rust-lang.org/rustc/platform-support.html)
+[here](../platform-support.html)
diff --git a/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md b/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md
index 215290e3898..2ce0ccb7876 100644
--- a/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md
+++ b/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md
@@ -111,7 +111,7 @@ 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)
+[custom test frameworks](../../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.
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index fbf999f9715..cc4ee2e67b1 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -90,7 +90,7 @@ rustup target add aarch64-fuchsia
 After installing our Fuchsia targets, we can now compile a Rust binary that targets
 Fuchsia.
 
-To create our Rust project, we can issue a standard `cargo` command as follows:
+To create our Rust project, we can use [`cargo`][cargo] as follows:
 
 **From base working directory**
 ```sh
@@ -867,7 +867,7 @@ ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
 [Fuchsia]: https://fuchsia.dev/
 [source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
 [rustup]: https://rustup.rs/
-[cargo]: https://doc.rust-lang.org/cargo/
+[cargo]: ../../cargo/index.html
 [Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
 [overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests
 [reference for the file format]: https://fuchsia.dev/reference/cml
diff --git a/src/doc/rustc/src/targets/custom.md b/src/doc/rustc/src/targets/custom.md
index 27ef2f49eee..a67cb10fc75 100644
--- a/src/doc/rustc/src/targets/custom.md
+++ b/src/doc/rustc/src/targets/custom.md
@@ -14,4 +14,4 @@ To see it for a different target, add the `--target` flag:
 rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json
 ```
 
-To use a custom target, see the (unstable) [`build-std` feature](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std) of `cargo`.
+To use a custom target, see the (unstable) [`build-std` feature](../../cargo/reference/unstable.html#build-std) of `cargo`.
diff --git a/src/doc/unstable-book/src/compiler-flags/branch-protection.md b/src/doc/unstable-book/src/compiler-flags/branch-protection.md
index 85403748e1d..33b1e223c22 100644
--- a/src/doc/unstable-book/src/compiler-flags/branch-protection.md
+++ b/src/doc/unstable-book/src/compiler-flags/branch-protection.md
@@ -15,4 +15,4 @@ For example, `-Z branch-protection=bti,pac-ret,leaf` is valid, but
 
 Rust's standard library does not ship with BTI or pointer authentication enabled by default.
 In Cargo projects the standard library can be recompiled with pointer authentication using the nightly
-[build-std](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std) feature.
+[build-std](../../cargo/reference/unstable.html#build-std) feature.
diff --git a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md
index 08c16d95f46..dbb741422a8 100644
--- a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md
+++ b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md
@@ -39,7 +39,7 @@ It is strongly recommended to also enable CFG checks for all linked libraries, i
 
 To enable CFG in the standard library, use the [cargo `-Z build-std` functionality][build-std] to recompile the standard library with the same configuration options as the main program.
 
-[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+[build-std]: ../../cargo/reference/unstable.html#build-std
 
 For example:
 ```cmd
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 9bbf9e28fff..a9616c34bff 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -420,8 +420,8 @@ flow using an indirect branch/call to a function with different return and
 parameter types than the return type expected and arguments intended/passed in
 the call/branch site, the execution is also terminated (see Fig. 9).
 
-[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
-[rust-book]: https://doc.rust-lang.org/book/title-page.html
+[rust-book-ch19-05]: ../../book/ch19-05-advanced-functions-and-closures.html
+[rust-book]: ../../book/title-page.html
 
 # HWAddressSanitizer
 
@@ -691,7 +691,7 @@ It is strongly recommended to combine sanitizers with recompiled and
 instrumented standard library, for example using [cargo `-Zbuild-std`
 functionality][build-std].
 
-[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+[build-std]: ../../cargo/reference/unstable.html#build-std
 
 # Build scripts and procedural macros
 
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
index c6516d838dd..5cb9758409a 100644
--- a/src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md
+++ b/src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md
@@ -36,4 +36,4 @@ optimized out, if unused. However, with `make_foo` you can produce a wrapped
 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
+[Clto]: ../../rustc/codegen-options/index.html#lto
diff --git a/src/doc/unstable-book/src/language-features/auto-traits.md b/src/doc/unstable-book/src/language-features/auto-traits.md
index f967c11fc4d..014e15d1ada 100644
--- a/src/doc/unstable-book/src/language-features/auto-traits.md
+++ b/src/doc/unstable-book/src/language-features/auto-traits.md
@@ -13,8 +13,8 @@ that are automatically implemented for every type, unless the type, or a type it
 has explicitly opted out via a negative impl. (Negative impls are separately controlled
 by the `negative_impls` feature.)
 
-[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
-[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+[`Send`]: ../../std/marker/trait.Send.html
+[`Sync`]: ../../std/marker/trait.Sync.html
 
 ```rust,ignore (partial-example)
 impl !Trait for Type {}
diff --git a/src/doc/unstable-book/src/language-features/unboxed-closures.md b/src/doc/unstable-book/src/language-features/unboxed-closures.md
index e4113d72d09..3609e7f52f8 100644
--- a/src/doc/unstable-book/src/language-features/unboxed-closures.md
+++ b/src/doc/unstable-book/src/language-features/unboxed-closures.md
@@ -12,7 +12,7 @@ The `unboxed_closures` feature allows you to write functions using the `"rust-ca
 required for implementing the [`Fn*`] family of traits. `"rust-call"` functions must have
 exactly one (non self) argument, a tuple representing the argument list.
 
-[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
+[`Fn*`]: ../../std/ops/trait.Fn.html
 
 ```rust
 #![feature(unboxed_closures)]
diff --git a/src/doc/unstable-book/src/library-features/default-free-fn.md b/src/doc/unstable-book/src/library-features/default-free-fn.md
index d40a27dddf3..bafc9ac4d0d 100644
--- a/src/doc/unstable-book/src/library-features/default-free-fn.md
+++ b/src/doc/unstable-book/src/library-features/default-free-fn.md
@@ -10,7 +10,7 @@ Adds a free `default()` function to the `std::default` module.  This function
 just forwards to [`Default::default()`], but may remove repetition of the word
 "default" from the call site.
 
-[`Default::default()`]: https://doc.rust-lang.org/nightly/std/default/trait.Default.html#tymethod.default
+[`Default::default()`]: ../../std/default/trait.Default.html#tymethod.default
 
 Here is an example:
 
diff --git a/src/doc/unstable-book/src/library-features/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md
index 29a8aecee6c..180184146d1 100644
--- a/src/doc/unstable-book/src/library-features/fn-traits.md
+++ b/src/doc/unstable-book/src/library-features/fn-traits.md
@@ -11,7 +11,7 @@ See Also: [`unboxed_closures`](../language-features/unboxed-closures.md)
 The `fn_traits` feature allows for implementation of the [`Fn*`] traits
 for creating custom closure-like types.
 
-[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
+[`Fn*`]: ../../std/ops/trait.Fn.html
 
 ```rust
 #![feature(unboxed_closures)]
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 953f4aa8a1b..4d6f1524732 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -44,7 +44,7 @@ where
         discard_positive_impl: bool,
     ) -> Option<Item> {
         let tcx = self.cx.tcx;
-        let trait_ref = tcx.mk_trait_ref(trait_def_id, [ty]);
+        let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, [ty]));
         if !self.cx.generated_synthetics.insert((ty, trait_def_id)) {
             debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref);
             return None;
@@ -124,7 +124,7 @@ where
                 unsafety: hir::Unsafety::Normal,
                 generics: new_generics,
                 trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, ThinVec::new())),
-                for_: clean_middle_ty(ty, self.cx, None),
+                for_: clean_middle_ty(ty::Binder::dummy(ty), self.cx, None),
                 items: Vec::new(),
                 polarity,
                 kind: ImplKind::Auto,
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index a1145b90d65..4ef5747596b 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -105,10 +105,10 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                         // the post-inference `trait_ref`, as it's more accurate.
                         trait_: Some(clean_trait_ref_with_bindings(
                             cx,
-                            trait_ref.0,
+                            ty::Binder::dummy(trait_ref.0),
                             ThinVec::new(),
                         )),
-                        for_: clean_middle_ty(ty.0, cx, None),
+                        for_: clean_middle_ty(ty::Binder::dummy(ty.0), cx, None),
                         items: cx
                             .tcx
                             .associated_items(impl_def_id)
@@ -117,7 +117,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             .collect::<Vec<_>>(),
                         polarity: ty::ImplPolarity::Positive,
                         kind: ImplKind::Blanket(Box::new(clean_middle_ty(
-                            trait_ref.0.self_ty(),
+                            ty::Binder::dummy(trait_ref.0.self_ty()),
                             cx,
                             None,
                         ))),
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 7f72d5d39a7..81f67672436 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -1,9 +1,8 @@
 use super::*;
 
-use rustc_ast::attr;
-use rustc_ast::Path;
+use rustc_ast::{LitKind, MetaItemLit, Path, StrStyle};
 use rustc_span::create_default_session_globals_then;
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::DUMMY_SP;
 
 fn word_cfg(s: &str) -> Cfg {
@@ -22,6 +21,15 @@ fn dummy_meta_item_word(name: &str) -> MetaItem {
     }
 }
 
+fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem {
+    let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
+    MetaItem {
+        path: Path::from_ident(Ident::from_str(name)),
+        kind: MetaItemKind::NameValue(lit),
+        span: DUMMY_SP,
+    }
+}
+
 macro_rules! dummy_meta_item_list {
     ($name:ident, [$($list:ident),* $(,)?]) => {
         MetaItem {
@@ -242,8 +250,8 @@ fn test_parse_ok() {
         let mi = dummy_meta_item_word("all");
         assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
 
-        let mi =
-            attr::mk_name_value_item_str(Ident::from_str("all"), Symbol::intern("done"), DUMMY_SP);
+        let done = Symbol::intern("done");
+        let mi = dummy_meta_item_name_value("all", done, LitKind::Str(done, StrStyle::Cooked));
         assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
 
         let mi = dummy_meta_item_list!(all, [a, b]);
@@ -272,7 +280,7 @@ fn test_parse_ok() {
 #[test]
 fn test_parse_err() {
     create_default_session_globals_then(|| {
-        let mi = attr::mk_name_value_item(Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP);
+        let mi = dummy_meta_item_name_value("foo", kw::False, LitKind::Bool(false));
         assert!(Cfg::parse(&mi).is_err());
 
         let mi = dummy_meta_item_list!(not, [a, b]);
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index e7c3e5a45e8..d1601272af7 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -293,7 +293,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
 
 fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::Typedef> {
     let predicates = cx.tcx.explicit_predicates_of(did);
-    let type_ = clean_middle_ty(cx.tcx.type_of(did), cx, Some(did));
+    let type_ = clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did));
 
     Box::new(clean::Typedef {
         type_,
@@ -325,7 +325,7 @@ pub(crate) fn build_impls(
     // * https://github.com/rust-lang/rust/pull/99917 — where the feature got used
     // * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error
     if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
-        use rustc_middle::ty::fast_reject::SimplifiedTypeGen::*;
+        use rustc_middle::ty::fast_reject::SimplifiedType::*;
         let type_ =
             if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) };
         for &did in tcx.incoherent_impls(type_) {
@@ -405,7 +405,7 @@ pub(crate) fn build_impl(
 
     let for_ = match &impl_item {
         Some(impl_) => clean_ty(impl_.self_ty, cx),
-        None => clean_middle_ty(tcx.type_of(did), cx, Some(did)),
+        None => clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)),
     };
 
     // Only inline impl if the implementing type is
@@ -496,7 +496,8 @@ pub(crate) fn build_impl(
         ),
     };
     let polarity = tcx.impl_polarity(did);
-    let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, ThinVec::new()));
+    let trait_ = associated_trait
+        .map(|t| clean_trait_ref_with_bindings(cx, ty::Binder::dummy(t), ThinVec::new()));
     if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
@@ -640,14 +641,14 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
 
 fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
     clean::Constant {
-        type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
         kind: clean::ConstantKind::Extern { def_id },
     }
 }
 
 fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
     clean::Static {
-        type_: clean_middle_ty(cx.tcx.type_of(did), cx, Some(did)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)),
         mutability: if mutable { Mutability::Mut } else { Mutability::Not },
         expr: None,
     }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2a2a9470d25..92886bbfe26 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -22,6 +22,7 @@ use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::TypeVisitable;
 use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{AstPass, MacroKind};
@@ -127,7 +128,7 @@ fn clean_generic_bound<'tcx>(
         hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
             let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
 
-            let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
+            let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
 
             let generic_args = clean_generic_args(generic_args, cx);
             let GenericArgs::AngleBracketed { bindings, .. } = generic_args
@@ -156,17 +157,18 @@ fn clean_generic_bound<'tcx>(
 
 pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
     cx: &mut DocContext<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
     bindings: ThinVec<TypeBinding>,
 ) -> Path {
-    let kind = cx.tcx.def_kind(trait_ref.def_id).into();
+    let kind = cx.tcx.def_kind(trait_ref.def_id()).into();
     if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
-        span_bug!(cx.tcx.def_span(trait_ref.def_id), "`TraitRef` had unexpected kind {:?}", kind);
+        span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {:?}", kind);
     }
-    inline::record_extern_fqn(cx, trait_ref.def_id, kind);
-    let path = external_path(cx, trait_ref.def_id, true, bindings, trait_ref.substs);
+    inline::record_extern_fqn(cx, trait_ref.def_id(), kind);
+    let path =
+        external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.substs));
 
-    debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
+    debug!(?trait_ref);
 
     path
 }
@@ -187,7 +189,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
         })
         .collect();
 
-    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref.skip_binder(), bindings);
+    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
     GenericBound::TraitBound(
         PolyTrait { trait_, generic_params: late_bound_regions },
         hir::TraitBoundModifier::None,
@@ -212,19 +214,19 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
 pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
     let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
     Constant {
-        type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
         kind: ConstantKind::Anonymous { body: constant.value.body },
     }
 }
 
 pub(crate) fn clean_middle_const<'tcx>(
-    constant: ty::Const<'tcx>,
+    constant: ty::Binder<'tcx, ty::Const<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> Constant {
     // FIXME: instead of storing the stringified expression, store `self` directly instead.
     Constant {
-        type_: clean_middle_ty(constant.ty(), cx, None),
-        kind: ConstantKind::TyConst { expr: constant.to_string().into() },
+        type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None),
+        kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
     }
 }
 
@@ -333,7 +335,7 @@ fn clean_poly_trait_predicate<'tcx>(
 
     let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
     Some(WherePredicate::BoundPredicate {
-        ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None),
+        ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None),
         bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())],
         bound_params: Vec::new(),
     })
@@ -359,7 +361,7 @@ fn clean_type_outlives_predicate<'tcx>(
     let ty::OutlivesPredicate(ty, lt) = pred;
 
     Some(WherePredicate::BoundPredicate {
-        ty: clean_middle_ty(ty, cx, None),
+        ty: clean_middle_ty(ty::Binder::dummy(ty), cx, None),
         bounds: vec![GenericBound::Outlives(
             clean_middle_region(lt).expect("failed to clean lifetimes"),
         )],
@@ -367,10 +369,13 @@ fn clean_type_outlives_predicate<'tcx>(
     })
 }
 
-fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
-    match term.unpack() {
-        ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)),
-        ty::TermKind::Const(c) => Term::Constant(clean_middle_const(c, cx)),
+fn clean_middle_term<'tcx>(
+    term: ty::Binder<'tcx, ty::Term<'tcx>>,
+    cx: &mut DocContext<'tcx>,
+) -> Term {
+    match term.skip_binder().unpack() {
+        ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None)),
+        ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)),
     }
 }
 
@@ -379,7 +384,10 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te
         hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
         hir::Term::Const(c) => {
             let def_id = cx.tcx.hir().local_def_id(c.hir_id);
-            Term::Constant(clean_middle_const(ty::Const::from_anon_const(cx.tcx, def_id), cx))
+            Term::Constant(clean_middle_const(
+                ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, def_id)),
+                cx,
+            ))
         }
     }
 }
@@ -398,32 +406,31 @@ fn clean_projection_predicate<'tcx>(
         })
         .collect();
 
-    let ty::ProjectionPredicate { projection_ty, term } = pred.skip_binder();
-
     WherePredicate::EqPredicate {
-        lhs: Box::new(clean_projection(projection_ty, cx, None)),
-        rhs: Box::new(clean_middle_term(term, cx)),
+        lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
+        rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
         bound_params: late_bound_regions,
     }
 }
 
 fn clean_projection<'tcx>(
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder {
+    if cx.tcx.def_kind(ty.skip_binder().def_id) == DefKind::ImplTraitPlaceholder {
         let bounds = cx
             .tcx
-            .explicit_item_bounds(ty.item_def_id)
+            .explicit_item_bounds(ty.skip_binder().def_id)
             .iter()
-            .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs))
+            .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs))
             .collect::<Vec<_>>();
         return clean_middle_opaque_bounds(cx, bounds);
     }
 
-    let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new());
-    let self_type = clean_middle_ty(ty.self_ty(), cx, None);
+    let trait_ =
+        clean_trait_ref_with_bindings(cx, ty.map_bound(|ty| ty.trait_ref(cx.tcx)), ThinVec::new());
+    let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None);
     let self_def_id = if let Some(def_id) = def_id {
         cx.tcx.opt_parent(def_id).or(Some(def_id))
     } else {
@@ -446,15 +453,16 @@ fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type
 }
 
 fn projection_to_path_segment<'tcx>(
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> PathSegment {
-    let item = cx.tcx.associated_item(ty.item_def_id);
-    let generics = cx.tcx.generics_of(ty.item_def_id);
+    let item = cx.tcx.associated_item(ty.skip_binder().def_id);
+    let generics = cx.tcx.generics_of(ty.skip_binder().def_id);
     PathSegment {
         name: item.name,
         args: GenericArgs::AngleBracketed {
-            args: substs_to_args(cx, &ty.substs[generics.parent_count..], false).into(),
+            args: substs_to_args(cx, ty.map_bound(|ty| &ty.substs[generics.parent_count..]), false)
+                .into(),
             bindings: Default::default(),
         },
     }
@@ -470,7 +478,11 @@ fn clean_generic_param_def<'tcx>(
         }
         ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
             let default = if has_default {
-                Some(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id)))
+                Some(clean_middle_ty(
+                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    cx,
+                    Some(def.def_id),
+                ))
             } else {
                 None
             };
@@ -488,7 +500,11 @@ fn clean_generic_param_def<'tcx>(
             def.name,
             GenericParamDefKind::Const {
                 did: def.def_id,
-                ty: Box::new(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id))),
+                ty: Box::new(clean_middle_ty(
+                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    cx,
+                    Some(def.def_id),
+                )),
                 default: match has_default {
                     true => Some(Box::new(cx.tcx.const_param_default(def.def_id).to_string())),
                     false => None,
@@ -733,8 +749,10 @@ fn clean_ty_generics<'tcx>(
         .collect::<ThinVec<GenericParamDef>>();
 
     // param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)]
-    let mut impl_trait_proj =
-        FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>, Vec<GenericParamDef>)>>::default();
+    let mut impl_trait_proj = FxHashMap::<
+        u32,
+        Vec<(DefId, PathSegment, ty::Binder<'_, Ty<'_>>, Vec<GenericParamDef>)>,
+    >::default();
 
     let where_predicates = preds
         .predicates
@@ -783,8 +801,8 @@ fn clean_ty_generics<'tcx>(
 
                     let proj = projection.map(|p| {
                         (
-                            clean_projection(p.skip_binder().projection_ty, cx, None),
-                            p.skip_binder().term,
+                            clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
+                            p.map_bound(|p| p.term),
                         )
                     });
                     if let Some(((_, trait_did, name), rhs)) = proj
@@ -795,7 +813,7 @@ fn clean_ty_generics<'tcx>(
                         impl_trait_proj.entry(param_idx).or_default().push((
                             trait_did,
                             name,
-                            rhs.ty().unwrap(),
+                            rhs.map_bound(|rhs| rhs.ty().unwrap()),
                             p.get_bound_params()
                                 .into_iter()
                                 .flatten()
@@ -1066,7 +1084,7 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
 
     // We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
     // but shouldn't change any code meaning.
-    let output = match clean_middle_ty(sig.skip_binder().output(), cx, None) {
+    let output = match clean_middle_ty(sig.output(), cx, None) {
         Type::Tuple(inner) if inner.is_empty() => DefaultReturn,
         ty => Return(ty),
     };
@@ -1076,11 +1094,10 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
         c_variadic: sig.skip_binder().c_variadic,
         inputs: Arguments {
             values: sig
-                .skip_binder()
                 .inputs()
                 .iter()
                 .map(|t| Argument {
-                    type_: clean_middle_ty(*t, cx, None),
+                    type_: clean_middle_ty(t.map_bound(|t| *t), cx, None),
                     name: names
                         .next()
                         .map(|i| i.name)
@@ -1134,7 +1151,8 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
             hir::TraitItemKind::Type(bounds, Some(default)) => {
                 let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
                 let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
-                let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
+                let item_type =
+                    clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, default)), cx, None);
                 AssocTypeItem(
                     Box::new(Typedef {
                         type_: clean_ty(default, cx),
@@ -1173,7 +1191,8 @@ pub(crate) fn clean_impl_item<'tcx>(
             hir::ImplItemKind::Type(hir_ty) => {
                 let type_ = clean_ty(hir_ty, cx);
                 let generics = clean_generics(impl_.generics, cx);
-                let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+                let item_type =
+                    clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
                 AssocTypeItem(
                     Box::new(Typedef { type_, generics, item_type: Some(item_type) }),
                     Vec::new(),
@@ -1192,7 +1211,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
     let tcx = cx.tcx;
     let kind = match assoc_item.kind {
         ty::AssocKind::Const => {
-            let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id));
+            let ty = clean_middle_ty(
+                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+                cx,
+                Some(assoc_item.def_id),
+            );
 
             let provided = match assoc_item.container {
                 ty::ImplContainer => true,
@@ -1375,7 +1398,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                     AssocTypeItem(
                         Box::new(Typedef {
                             type_: clean_middle_ty(
-                                tcx.type_of(assoc_item.def_id),
+                                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
                                 cx,
                                 Some(assoc_item.def_id),
                             ),
@@ -1393,7 +1416,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                 AssocTypeItem(
                     Box::new(Typedef {
                         type_: clean_middle_ty(
-                            tcx.type_of(assoc_item.def_id),
+                            ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
                             cx,
                             Some(assoc_item.def_id),
                         ),
@@ -1437,8 +1460,11 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
         hir::QPath::Resolved(Some(qself), p) => {
             // Try to normalize `<X as Y>::T` to a type
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
-            if let Some(normalized_value) = normalize(cx, ty) {
-                return clean_middle_ty(normalized_value, cx, None);
+            // `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>`
+            if !ty.has_escaping_bound_vars() {
+                if let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty)) {
+                    return clean_middle_ty(normalized_value, cx, None);
+                }
             }
 
             let trait_segments = &p.segments[..p.segments.len() - 1];
@@ -1461,11 +1487,13 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
         hir::QPath::TypeRelative(qself, segment) => {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
             let res = match ty.kind() {
-                ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
+                ty::Alias(ty::Projection, proj) => {
+                    Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
+                }
                 // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
                 ty::Error(_) => return Type::Infer,
                 // Otherwise, this is an inherent associated type.
-                _ => return clean_middle_ty(ty, cx, None),
+                _ => return clean_middle_ty(ty::Binder::dummy(ty), cx, None),
             };
             let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
             register_res(cx, trait_.res);
@@ -1632,7 +1660,10 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
 }
 
 /// Returns `None` if the type could not be normalized
-fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+fn normalize<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    ty: ty::Binder<'tcx, Ty<'tcx>>,
+) -> Option<ty::Binder<'tcx, Ty<'tcx>>> {
     // HACK: low-churn fix for #79459 while we wait for a trait normalization fix
     if !cx.tcx.sess.opts.unstable_opts.normalize_docs {
         return None;
@@ -1660,14 +1691,14 @@ fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>>
     }
 }
 
+#[instrument(level = "trace", skip(cx), ret)]
 pub(crate) fn clean_middle_ty<'tcx>(
-    ty: Ty<'tcx>,
+    bound_ty: ty::Binder<'tcx, Ty<'tcx>>,
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    trace!("cleaning type: {:?}", ty);
-    let ty = normalize(cx, ty).unwrap_or(ty);
-    match *ty.kind() {
+    let bound_ty = normalize(cx, bound_ty).unwrap_or(bound_ty);
+    match *bound_ty.skip_binder().kind() {
         ty::Never => Primitive(PrimitiveType::Never),
         ty::Bool => Primitive(PrimitiveType::Bool),
         ty::Char => Primitive(PrimitiveType::Char),
@@ -1675,20 +1706,23 @@ pub(crate) fn clean_middle_ty<'tcx>(
         ty::Uint(uint_ty) => Primitive(uint_ty.into()),
         ty::Float(float_ty) => Primitive(float_ty.into()),
         ty::Str => Primitive(PrimitiveType::Str),
-        ty::Slice(ty) => Slice(Box::new(clean_middle_ty(ty, cx, None))),
+        ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None))),
         ty::Array(ty, mut n) => {
             n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
             let n = print_const(cx, n);
-            Array(Box::new(clean_middle_ty(ty, cx, None)), n.into())
+            Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), n.into())
+        }
+        ty::RawPtr(mt) => {
+            RawPointer(mt.mutbl, Box::new(clean_middle_ty(bound_ty.rebind(mt.ty), cx, None)))
         }
-        ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))),
         ty::Ref(r, ty, mutbl) => BorrowedRef {
             lifetime: clean_middle_region(r),
             mutability: mutbl,
-            type_: Box::new(clean_middle_ty(ty, cx, None)),
+            type_: Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)),
         },
         ty::FnDef(..) | ty::FnPtr(_) => {
-            let sig = ty.fn_sig(cx.tcx);
+            // FIXME: should we merge the outer and inner binders somehow?
+            let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
             let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
             BareFunction(Box::new(BareFunctionDecl {
                 unsafety: sig.unsafety(),
@@ -1705,12 +1739,18 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 AdtKind::Enum => ItemType::Enum,
             };
             inline::record_extern_fqn(cx, did, kind);
-            let path = external_path(cx, did, false, ThinVec::new(), substs);
+            let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs));
             Type::Path { path }
         }
         ty::Foreign(did) => {
             inline::record_extern_fqn(cx, did, ItemType::ForeignType);
-            let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty());
+            let path = external_path(
+                cx,
+                did,
+                false,
+                ThinVec::new(),
+                ty::Binder::dummy(InternalSubsts::empty()),
+            );
             Type::Path { path }
         }
         ty::Dynamic(obj, ref reg, _) => {
@@ -1721,11 +1761,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
             let did = obj
                 .principal_def_id()
                 .or_else(|| dids.next())
-                .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", ty));
+                .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?"));
             let substs = match obj.principal() {
-                Some(principal) => principal.skip_binder().substs,
+                Some(principal) => principal.map_bound(|p| p.substs),
                 // marker traits have no substs.
-                _ => cx.tcx.intern_substs(&[]),
+                _ => ty::Binder::dummy(InternalSubsts::empty()),
             };
 
             inline::record_extern_fqn(cx, did, ItemType::Trait);
@@ -1736,7 +1776,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
             let lifetime = clean_middle_region(*reg);
             let mut bounds = dids
                 .map(|did| {
-                    let empty = cx.tcx.intern_substs(&[]);
+                    let empty = ty::Binder::dummy(InternalSubsts::empty());
                     let path = external_path(cx, did, false, ThinVec::new(), empty);
                     inline::record_extern_fqn(cx, did, ItemType::Trait);
                     PolyTrait { trait_: path, generic_params: Vec::new() }
@@ -1747,15 +1787,17 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 .projection_bounds()
                 .map(|pb| TypeBinding {
                     assoc: projection_to_path_segment(
-                        pb.skip_binder()
-                            // HACK(compiler-errors): Doesn't actually matter what self
-                            // type we put here, because we're only using the GAT's substs.
-                            .with_self_ty(cx.tcx, cx.tcx.types.self_param)
-                            .projection_ty,
+                        pb.map_bound(|pb| {
+                            pb
+                                // HACK(compiler-errors): Doesn't actually matter what self
+                                // type we put here, because we're only using the GAT's substs.
+                                .with_self_ty(cx.tcx, cx.tcx.types.self_param)
+                                .projection_ty
+                        }),
                         cx,
                     ),
                     kind: TypeBindingKind::Equality {
-                        term: clean_middle_term(pb.skip_binder().term, cx),
+                        term: clean_middle_term(pb.map_bound(|pb| pb.term), cx),
                     },
                 })
                 .collect();
@@ -1779,9 +1821,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
             DynTrait(bounds, lifetime)
         }
-        ty::Tuple(t) => Tuple(t.iter().map(|t| clean_middle_ty(t, cx, None)).collect()),
+        ty::Tuple(t) => {
+            Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None)).collect())
+        }
 
-        ty::Projection(ref data) => clean_projection(*data, cx, def_id),
+        ty::Alias(ty::Projection, ref data) => clean_projection(bound_ty.rebind(*data), cx, def_id),
 
         ty::Param(ref p) => {
             if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
@@ -1791,7 +1835,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
             }
         }
 
-        ty::Opaque(def_id, substs) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
             // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
             // by looking up the bounds associated with the def_id.
             let bounds = cx
@@ -1854,9 +1898,12 @@ fn clean_middle_opaque_bounds<'tcx>(
                     {
                         if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
                             Some(TypeBinding {
-                                assoc: projection_to_path_segment(proj.projection_ty, cx),
+                                assoc: projection_to_path_segment(
+                                    bound.kind().rebind(proj.projection_ty),
+                                    cx,
+                                ),
                                 kind: TypeBindingKind::Equality {
-                                    term: clean_middle_term(proj.term, cx),
+                                    term: clean_middle_term(bound.kind().rebind(proj.term), cx),
                                 },
                             })
                         } else {
@@ -1887,7 +1934,7 @@ pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext
     clean_field_with_def_id(
         field.did,
         field.name,
-        clean_middle_ty(cx.tcx.type_of(field.did), cx, Some(field.did)),
+        clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(field.did)), cx, Some(field.did)),
         cx,
     )
 }
@@ -2100,7 +2147,7 @@ fn clean_maybe_renamed_item<'tcx>(
             }),
             ItemKind::TyAlias(hir_ty, generics) => {
                 let rustdoc_ty = clean_ty(hir_ty, cx);
-                let ty = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+                let ty = clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
                 TypedefItem(Box::new(Typedef {
                     type_: rustdoc_ty,
                     generics: clean_generics(generics, cx),
@@ -2211,7 +2258,9 @@ fn clean_impl<'tcx>(
 
     let for_ = clean_ty(impl_.self_ty, cx);
     let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
-        DefKind::TyAlias => Some(clean_middle_ty(tcx.type_of(did), cx, Some(did))),
+        DefKind::TyAlias => {
+            Some(clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)))
+        }
         _ => None,
     });
     let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 2590bb0df3f..7a13e7e36d1 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -10,7 +10,6 @@ use std::{cmp, fmt, iter};
 use arrayvec::ArrayVec;
 use thin_vec::ThinVec;
 
-use rustc_ast::attr;
 use rustc_ast::util::comments::beautify_doc_string;
 use rustc_ast::{self as ast, AttrStyle};
 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
@@ -27,7 +26,6 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility};
 use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
-use rustc_span::source_map::DUMMY_SP;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{self, FileName, Loc};
 use rustc_target::abi::VariantIdx;
@@ -982,12 +980,12 @@ impl AttributesExt for [ast::Attribute] {
         // #[doc(cfg(target_feature = "feat"))] attributes as well
         for attr in self.lists(sym::target_feature) {
             if attr.has_name(sym::enable) {
-                if let Some(feat) = attr.value_str() {
-                    let meta = attr::mk_name_value_item_str(
-                        Ident::with_dummy_span(sym::target_feature),
-                        feat,
-                        DUMMY_SP,
-                    );
+                if attr.value_str().is_some() {
+                    // Clone `enable = "feat"`, change to `target_feature = "feat"`.
+                    // Unwrap is safe because `value_str` succeeded above.
+                    let mut meta = attr.meta_item().unwrap().clone();
+                    meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
+
                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
                         cfg &= feat_cfg;
                     }
@@ -1345,7 +1343,7 @@ pub(crate) enum GenericBound {
 impl GenericBound {
     pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
-        let empty = cx.tcx.intern_substs(&[]);
+        let empty = ty::Binder::dummy(ty::InternalSubsts::empty());
         let path = external_path(cx, did, false, ThinVec::new(), empty);
         inline::record_extern_fqn(cx, did, ItemType::Trait);
         GenericBound::TraitBound(
@@ -1872,7 +1870,7 @@ impl PrimitiveType {
     }
 
     pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
-        use ty::fast_reject::SimplifiedTypeGen::*;
+        use ty::fast_reject::SimplifiedType::*;
         use ty::{FloatTy, IntTy, UintTy};
         use PrimitiveType::*;
         static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 246560bad29..a12f764fa8e 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -78,12 +78,16 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
 
 pub(crate) fn substs_to_args<'tcx>(
     cx: &mut DocContext<'tcx>,
-    substs: &[ty::subst::GenericArg<'tcx>],
+    substs: ty::Binder<'tcx, &[ty::subst::GenericArg<'tcx>]>,
     mut skip_first: bool,
 ) -> Vec<GenericArg> {
     let mut ret_val =
-        Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 }));
-    ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() {
+        Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first {
+            1
+        } else {
+            0
+        }));
+    ret_val.extend(substs.iter().filter_map(|kind| match kind.skip_binder().unpack() {
         GenericArgKind::Lifetime(lt) => {
             Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
         }
@@ -91,8 +95,12 @@ pub(crate) fn substs_to_args<'tcx>(
             skip_first = false;
             None
         }
-        GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(ty, cx, None))),
-        GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(clean_middle_const(ct, cx)))),
+        GenericArgKind::Type(ty) => {
+            Some(GenericArg::Type(clean_middle_ty(kind.rebind(ty), cx, None)))
+        }
+        GenericArgKind::Const(ct) => {
+            Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx))))
+        }
     }));
     ret_val
 }
@@ -102,15 +110,20 @@ fn external_generic_args<'tcx>(
     did: DefId,
     has_self: bool,
     bindings: ThinVec<TypeBinding>,
-    substs: SubstsRef<'tcx>,
+    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> GenericArgs {
-    let args = substs_to_args(cx, substs, has_self);
+    let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self);
 
     if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
+        let ty = substs
+            .iter()
+            .nth(if has_self { 1 } else { 0 })
+            .unwrap()
+            .map_bound(|arg| arg.expect_ty());
         let inputs =
             // The trait's first substitution is the one after self, if there is one.
-            match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
-                ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::<Vec<_>>().into(),
+            match ty.skip_binder().kind() {
+                ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::<Vec<_>>().into(),
                 _ => return GenericArgs::AngleBracketed { args: args.into(), bindings },
             };
         let output = bindings.into_iter().next().and_then(|binding| match binding.kind {
@@ -130,7 +143,7 @@ pub(super) fn external_path<'tcx>(
     did: DefId,
     has_self: bool,
     bindings: ThinVec<TypeBinding>,
-    substs: SubstsRef<'tcx>,
+    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> Path {
     let def_kind = cx.tcx.def_kind(did);
     let name = cx.tcx.item_name(did);
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index f21e60a64e0..2f1f4cbf359 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -177,6 +177,9 @@ impl ItemType {
             ItemType::TraitAlias => "traitalias",
         }
     }
+    pub(crate) fn is_method(&self) -> bool {
+        matches!(*self, ItemType::Method | ItemType::TyMethod)
+    }
 }
 
 impl fmt::Display for ItemType {
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index cd8c8c463b1..8a9e6caf611 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -21,15 +21,15 @@ use rustc_span::{BytePos, Span, DUMMY_SP};
 use super::format::{self, Buffer};
 
 /// This type is needed in case we want to render links on items to allow to go to their definition.
-pub(crate) struct HrefContext<'a, 'b, 'c> {
-    pub(crate) context: &'a Context<'b>,
+pub(crate) struct HrefContext<'a, 'tcx> {
+    pub(crate) context: &'a Context<'tcx>,
     /// This span contains the current file we're going through.
     pub(crate) file_span: Span,
     /// This field is used to know "how far" from the top of the directory we are to link to either
     /// documentation pages or other source pages.
-    pub(crate) root_path: &'c str,
+    pub(crate) root_path: &'a str,
     /// This field is used to calculate precise local URLs.
-    pub(crate) current_href: &'c str,
+    pub(crate) current_href: String,
 }
 
 /// Decorations are represented as a map from CSS class to vector of character ranges.
@@ -70,7 +70,7 @@ pub(crate) fn render_source_with_highlighting(
     src: &str,
     out: &mut Buffer,
     line_numbers: Buffer,
-    href_context: HrefContext<'_, '_, '_>,
+    href_context: HrefContext<'_, '_>,
     decoration_info: DecorationInfo,
     extra: Option<&str>,
 ) {
@@ -137,7 +137,7 @@ fn can_merge(class1: Option<Class>, class2: Option<Class>, text: &str) -> bool {
 
 /// This type is used as a conveniency to prevent having to pass all its fields as arguments into
 /// the various functions (which became its methods).
-struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
+struct TokenHandler<'a, 'tcx> {
     out: &'a mut Buffer,
     /// It contains the closing tag and the associated `Class`.
     closing_tags: Vec<(&'static str, Class)>,
@@ -149,11 +149,11 @@ struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
     current_class: Option<Class>,
     /// We need to keep the `Class` for each element because it could contain a `Span` which is
     /// used to generate links.
-    pending_elems: Vec<(&'b str, Option<Class>)>,
-    href_context: Option<HrefContext<'c, 'd, 'e>>,
+    pending_elems: Vec<(&'a str, Option<Class>)>,
+    href_context: Option<HrefContext<'a, 'tcx>>,
 }
 
-impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
+impl<'a, 'tcx> TokenHandler<'a, 'tcx> {
     fn handle_exit_span(&mut self) {
         // We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
         // being used in `write_pending_elems`.
@@ -205,7 +205,7 @@ impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
     }
 }
 
-impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
+impl<'a, 'tcx> Drop for TokenHandler<'a, 'tcx> {
     /// When leaving, we need to flush all pending data to not have missing content.
     fn drop(&mut self) {
         if self.pending_exit_span.is_some() {
@@ -230,7 +230,7 @@ impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
 fn write_code(
     out: &mut Buffer,
     src: &str,
-    href_context: Option<HrefContext<'_, '_, '_>>,
+    href_context: Option<HrefContext<'_, '_>>,
     decoration_info: Option<DecorationInfo>,
 ) {
     // This replace allows to fix how the code source with DOS backline characters is displayed.
@@ -514,18 +514,18 @@ impl Decorations {
 
 /// Processes program tokens, classifying strings of text by highlighting
 /// category (`Class`).
-struct Classifier<'a> {
-    tokens: PeekIter<'a>,
+struct Classifier<'src> {
+    tokens: PeekIter<'src>,
     in_attribute: bool,
     in_macro: bool,
     in_macro_nonterminal: bool,
     byte_pos: u32,
     file_span: Span,
-    src: &'a str,
+    src: &'src str,
     decorations: Option<Decorations>,
 }
 
-impl<'a> Classifier<'a> {
+impl<'src> Classifier<'src> {
     /// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
     /// file span which will be used later on by the `span_correspondance_map`.
     fn new(src: &str, file_span: Span, decoration_info: Option<DecorationInfo>) -> Classifier<'_> {
@@ -603,7 +603,7 @@ impl<'a> Classifier<'a> {
     ///
     /// It returns the token's kind, the token as a string and its byte position in the source
     /// string.
-    fn next(&mut self) -> Option<(TokenKind, &'a str, u32)> {
+    fn next(&mut self) -> Option<(TokenKind, &'src str, u32)> {
         if let Some((kind, text)) = self.tokens.next() {
             let before = self.byte_pos;
             self.byte_pos += text.len() as u32;
@@ -618,7 +618,7 @@ impl<'a> Classifier<'a> {
     /// The general structure for this method is to iterate over each token,
     /// possibly giving it an HTML span with a class specifying what flavor of
     /// token is used.
-    fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'a>)) {
+    fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'src>)) {
         loop {
             if let Some(decs) = self.decorations.as_mut() {
                 let byte_pos = self.byte_pos;
@@ -666,8 +666,8 @@ impl<'a> Classifier<'a> {
     fn advance(
         &mut self,
         token: TokenKind,
-        text: &'a str,
-        sink: &mut dyn FnMut(Highlight<'a>),
+        text: &'src str,
+        sink: &mut dyn FnMut(Highlight<'src>),
         before: u32,
     ) {
         let lookahead = self.peek();
@@ -881,7 +881,7 @@ impl<'a> Classifier<'a> {
 fn enter_span(
     out: &mut Buffer,
     klass: Class,
-    href_context: &Option<HrefContext<'_, '_, '_>>,
+    href_context: &Option<HrefContext<'_, '_>>,
 ) -> &'static str {
     string_without_closing_tag(out, "", Some(klass), href_context, true).expect(
         "internal error: enter_span was called with Some(klass) but did not return a \
@@ -914,7 +914,7 @@ fn string<T: Display>(
     out: &mut Buffer,
     text: T,
     klass: Option<Class>,
-    href_context: &Option<HrefContext<'_, '_, '_>>,
+    href_context: &Option<HrefContext<'_, '_>>,
     open_tag: bool,
 ) {
     if let Some(closing_tag) = string_without_closing_tag(out, text, klass, href_context, open_tag)
@@ -936,7 +936,7 @@ fn string_without_closing_tag<T: Display>(
     out: &mut Buffer,
     text: T,
     klass: Option<Class>,
-    href_context: &Option<HrefContext<'_, '_, '_>>,
+    href_context: &Option<HrefContext<'_, '_>>,
     open_tag: bool,
 ) -> Option<&'static str> {
     let Some(klass) = klass
@@ -985,7 +985,7 @@ fn string_without_closing_tag<T: Display>(
                 // https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
                 match href {
                     LinkFromSrc::Local(span) => {
-                        context.href_from_span_relative(*span, href_context.current_href)
+                        context.href_from_span_relative(*span, &href_context.current_href)
                     }
                     LinkFromSrc::External(def_id) => {
                         format::href_with_root_path(*def_id, context, Some(href_context.root_path))
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 5ce62224d35..b141820fe42 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -236,18 +236,16 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
             return event;
         };
 
-        let mut origtext = String::new();
+        let mut original_text = String::new();
         for event in &mut self.inner {
             match event {
                 Event::End(Tag::CodeBlock(..)) => break,
                 Event::Text(ref s) => {
-                    origtext.push_str(s);
+                    original_text.push_str(s);
                 }
                 _ => {}
             }
         }
-        let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
-        let text = lines.intersperse("\n".into()).collect::<String>();
 
         let parse_result = match kind {
             CodeBlockKind::Fenced(ref lang) => {
@@ -260,7 +258,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
                                  <pre class=\"language-{}\"><code>{}</code></pre>\
                              </div>",
                             lang,
-                            Escape(&text),
+                            Escape(&original_text),
                         )
                         .into(),
                     ));
@@ -270,6 +268,9 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
             CodeBlockKind::Indented => Default::default(),
         };
 
+        let lines = original_text.lines().filter_map(|l| map_line(l).for_html());
+        let text = lines.intersperse("\n".into()).collect::<String>();
+
         compile_fail = parse_result.compile_fail;
         should_panic = parse_result.should_panic;
         ignore = parse_result.ignore;
@@ -284,7 +285,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
             if url.is_empty() {
                 return None;
             }
-            let test = origtext
+            let test = original_text
                 .lines()
                 .map(|l| map_line(l).for_code())
                 .intersperse("\n".into())
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index e4f72a05789..5878c58264e 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -309,3 +309,48 @@ fn test_find_testable_code_line() {
     t("```rust\n```\n```rust\n```", &[1, 3]);
     t("```rust\n```\n ```rust\n```", &[1, 3]);
 }
+
+#[test]
+fn test_ascii_with_prepending_hashtag() {
+    fn t(input: &str, expect: &str) {
+        let mut map = IdMap::new();
+        let output = Markdown {
+            content: input,
+            links: &[],
+            ids: &mut map,
+            error_codes: ErrorCodes::Yes,
+            edition: DEFAULT_EDITION,
+            playground: &None,
+            heading_offset: HeadingOffset::H2,
+        }
+        .into_string();
+        assert_eq!(output, expect, "original: {}", input);
+    }
+
+    t(
+        r#"```ascii
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+```"#,
+        "<div class=\"example-wrap\"><pre class=\"language-ascii\"><code>\
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+</code></pre></div>",
+    );
+    t(
+        r#"```markdown
+# hello
+```"#,
+        "<div class=\"example-wrap\"><pre class=\"language-markdown\"><code>\
+# hello
+</code></pre></div>",
+    );
+}
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 73690c86f4f..d4d3e4f6ea7 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -637,7 +637,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
                             You need to enable Javascript be able to update your settings.\
                         </section>\
                      </noscript>\
-                     <link rel=\"stylesheet\" type=\"text/css\" \
+                     <link rel=\"stylesheet\" \
                          href=\"{static_root_path}{settings_css}\">\
                      <script defer src=\"{static_root_path}{settings_js}\"></script>",
                     static_root_path = page.get_static_root_path(),
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 36d15ec3b86..80fbe9c1f06 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1512,8 +1512,7 @@ fn render_impl(
 
         let toggled = !doc_buffer.is_empty();
         if toggled {
-            let method_toggle_class =
-                if item_type == ItemType::Method { " method-toggle" } else { "" };
+            let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
             write!(w, "<details class=\"rustdoc-toggle{}\" open><summary>", method_toggle_class);
         }
         match &*item.kind {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index acbe3f22889..a7b57c373e3 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -732,7 +732,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
         document(&mut content, cx, m, Some(t), HeadingOffset::H5);
         let toggled = !content.is_empty();
         if toggled {
-            write!(w, "<details class=\"rustdoc-toggle method-toggle\" open><summary>");
+            let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
+            write!(w, "<details class=\"rustdoc-toggle{method_toggle_class}\" open><summary>");
         }
         write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id);
         render_rightside(w, cx, m, t, RenderMode::Normal);
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 54e296959b0..e639fadeb96 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -276,7 +276,7 @@ pub(crate) fn print_src(
     let mut line_numbers = Buffer::empty_from(buf);
     let extra;
     line_numbers.write_str("<pre class=\"src-line-numbers\">");
-    let current_href = &context
+    let current_href = context
         .href_from_span(clean::Span::new(file_span), false)
         .expect("only local crates should have sources emitted");
     match source_context {
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 91162ca4892..a527e9feaec 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -523,7 +523,6 @@ ul.block, .block li {
 }
 
 .source .content pre.rust {
-	overflow: auto;
 	padding-left: 0;
 }
 
@@ -586,8 +585,8 @@ ul.block, .block li {
 	text-overflow: ellipsis;
 }
 /* Wrap non-pre code blocks (`text`) but not (```text```). */
-.docblock > :not(pre) > code,
-.docblock-short > code {
+.docblock :not(pre) > code,
+.docblock-short code {
 	white-space: pre-wrap;
 }
 
@@ -903,10 +902,11 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	top: 100%;
 	right: 0;
 	z-index: 2;
-	display: block;
 	margin-top: 7px;
 	border-radius: 3px;
 	border: 1px solid var(--border-color);
+	background-color: var(--main-background-color);
+	color: var(--main-color);
 	--popover-arrow-offset: 11px;
 }
 
@@ -917,16 +917,12 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	right: var(--popover-arrow-offset);
 	border: solid var(--border-color);
 	border-width: 1px 1px 0 0;
+	background-color: var(--main-background-color);
 	padding: 4px;
 	transform: rotate(-45deg);
 	top: -5px;
 }
 
-.popover, .popover::before {
-	background-color: var(--main-background-color);
-	color: var(--main-color);
-}
-
 /* use larger max-width for help popover, but not for help.html */
 #help.popover {
 	max-width: 600px;
@@ -1075,6 +1071,10 @@ pre.rust .doccomment {
 	color: var(--code-highlight-doc-comment-color);
 }
 
+.rustdoc.source .example-wrap pre.rust a {
+	background: var(--codeblock-link-background);
+}
+
 .example-wrap.compile_fail,
 .example-wrap.should_panic {
 	border-left: 2px solid var(--codeblock-error-color);
@@ -1400,7 +1400,6 @@ kbd {
 	vertical-align: middle;
 	border: solid 1px var(--border-color);
 	border-radius: 3px;
-	cursor: default;
 	color: var(--kbd--color);
 	background-color: var(--kbd-background);
 	box-shadow: inset 0 -1px 0 var(--kbd-box-shadow-color);
@@ -1873,6 +1872,7 @@ in storage.js
 }
 
 .variants > .docblock,
+.implementors-toggle > .docblock,
 .impl-items > .rustdoc-toggle[open]:not(:last-child),
 .methods > .rustdoc-toggle[open]:not(:last-child),
 .implementors-toggle[open]:not(:last-child) {
@@ -1973,7 +1973,6 @@ in storage.js
 }
 
 .scraped-example .code-wrapper .src-line-numbers {
-	margin: 0;
 	padding: 14px 0;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index eba845bf5a9..de0dfcd4690 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -88,6 +88,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--source-sidebar-background-selected: #14191f;
 	--source-sidebar-background-hover: #14191f;
 	--table-alt-row-background-color: #191f26;
+	--codeblock-link-background: #333;
 }
 
 h1, h2, h3, h4 {
@@ -150,15 +151,10 @@ pre, .rustdoc.source .example-wrap {
 	color: #c5c5c5;
 }
 
-.content .item-info::before { color: #ccc; }
-
 .sidebar h2 a,
 .sidebar h3 a {
 	color: white;
 }
-body.source .example-wrap pre.rust a {
-	background: #333;
-}
 
 .result-name .primitive > i, .result-name .keyword > i {
 	color: #788797;
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index d945e956c53..dd7fc689253 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -83,12 +83,7 @@
 	--source-sidebar-background-selected: #333;
 	--source-sidebar-background-hover: #444;
 	--table-alt-row-background-color: #2A2A2A;
-}
-
-.content .item-info::before { color: #ccc; }
-
-body.source .example-wrap pre.rust a {
-	background: #333;
+	--codeblock-link-background: #333;
 }
 
 #titles > button:not(.selected) {
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 58955a79316..b69d8a1cff9 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -80,12 +80,7 @@
 	--source-sidebar-background-selected: #fff;
 	--source-sidebar-background-hover: #e0e0e0;
 	--table-alt-row-background-color: #F5F5F5;
-}
-
-.content .item-info::before { color: #ccc; }
-
-body.source .example-wrap pre.rust a {
-	background: #eee;
+	--codeblock-link-background: #eee;
 }
 
 #titles > button:not(.selected) {
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 152116089c7..3f97e4e2e39 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -184,7 +184,6 @@ function browserSupportsHistoryApi() {
 function loadCss(cssUrl) {
     const link = document.createElement("link");
     link.href = cssUrl;
-    link.type = "text/css";
     link.rel = "stylesheet";
     document.getElementsByTagName("head")[0].appendChild(link);
 }
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 044e051440c..5f4ad6d2aea 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -53,7 +53,7 @@ pub(crate) fn render<P: AsRef<Path>>(
 
     let mut css = String::new();
     for name in &options.markdown_css {
-        write!(css, r#"<link rel="stylesheet" type="text/css" href="{name}">"#)
+        write!(css, r#"<link rel="stylesheet" href="{name}">"#)
             .expect("Writing to a String can't fail");
     }
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 37a28b6b7bd..4f0eb8b8076 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -538,11 +538,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => {
                 Res::from_def_id(self.cx.tcx, did)
             }
-            ty::Projection(_)
+            ty::Alias(..)
             | ty::Closure(..)
             | ty::Generator(..)
             | ty::GeneratorWitness(_)
-            | ty::Opaque(..)
             | ty::Dynamic(..)
             | ty::Param(_)
             | ty::Bound(..)
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index d57f981d51a..79db3c6c3e7 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -19,6 +19,12 @@ pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass {
 };
 
 pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+    // We need to check if there are errors before running this pass because it would crash when
+    // we try to get auto and blanket implementations.
+    if cx.tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
+        return krate;
+    }
+
     let synth_impls = cx.sess().time("collect_synthetic_impls", || {
         let mut synth = SyntheticImplCollector { cx, impls: Vec::new() };
         synth.visit_crate(&krate);
diff --git a/src/test/codegen/avr/avr-func-addrspace.rs b/src/test/codegen/avr/avr-func-addrspace.rs
index cbbcfad3ef4..e9740e30da4 100644
--- a/src/test/codegen/avr/avr-func-addrspace.rs
+++ b/src/test/codegen/avr/avr-func-addrspace.rs
@@ -9,7 +9,7 @@
 // It also validates that functions can be called through function pointers
 // through traits.
 
-#![feature(no_core, lang_items, unboxed_closures, arbitrary_self_types)]
+#![feature(no_core, lang_items, intrinsics, unboxed_closures, arbitrary_self_types)]
 #![crate_type = "lib"]
 #![no_core]
 
@@ -49,6 +49,10 @@ pub trait Fn<Args: Tuple>: FnOnce<Args> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
 }
 
+extern "rust-intrinsic" {
+    pub fn transmute<Src, Dst>(src: Src) -> Dst;
+}
+
 pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
 pub static mut STORAGE_BAR: u32 = 12;
 
@@ -87,3 +91,21 @@ pub extern "C" fn test() {
         STORAGE_FOO(&1, &mut buf);
     }
 }
+
+// Validate that we can codegen transmutes between data ptrs and fn ptrs.
+
+// CHECK: define{{.+}}{{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}} @transmute_data_ptr_to_fn({{\{\}\*|ptr}}{{.*}} %x)
+#[no_mangle]
+pub unsafe fn transmute_data_ptr_to_fn(x: *const ()) -> fn() {
+    // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
+    // as long as it doesn't cause a verifier error by using `bitcast`.
+    transmute(x)
+}
+
+// CHECK: define{{.+}}{{\{\}\*|ptr}} @transmute_fn_ptr_to_data({{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}}{{.*}} %x)
+#[no_mangle]
+pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () {
+    // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
+    // as long as it doesn't cause a verifier error by using `bitcast`.
+    transmute(x)
+}
diff --git a/src/test/codegen/pgo-counter-bias.rs b/src/test/codegen/pgo-counter-bias.rs
new file mode 100644
index 00000000000..28caa7f4aa3
--- /dev/null
+++ b/src/test/codegen/pgo-counter-bias.rs
@@ -0,0 +1,10 @@
+// Test that __llvm_profile_counter_bias does not get internalized by lto.
+
+// ignore-macos -runtime-counter-relocation not honored on Mach-O
+// compile-flags: -Cprofile-generate -Cllvm-args=-runtime-counter-relocation -Clto=fat
+// needs-profiler-support
+// no-prefer-dynamic
+
+// CHECK: @__llvm_profile_counter_bias = {{.*}}global
+
+pub fn main() {}
diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs
index a12cd0d021e..ada541e644a 100644
--- a/src/test/incremental/hashes/loop_expressions.rs
+++ b/src/test/incremental/hashes/loop_expressions.rs
@@ -187,9 +187,9 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs
index f81855e42be..88fd4d89b28 100644
--- a/src/test/incremental/hashes/while_let_loops.rs
+++ b/src/test/incremental/hashes/while_let_loops.rs
@@ -158,9 +158,9 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -210,9 +210,9 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs
index e432cf8fe4c..9b4d23757b8 100644
--- a/src/test/incremental/hashes/while_loops.rs
+++ b/src/test/incremental/hashes/while_loops.rs
@@ -158,9 +158,9 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -212,9 +212,9 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
diff --git a/src/test/mir-opt/building/custom/enums.rs b/src/test/mir-opt/building/custom/enums.rs
new file mode 100644
index 00000000000..e5cd4563778
--- /dev/null
+++ b/src/test/mir-opt/building/custom/enums.rs
@@ -0,0 +1,120 @@
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+// EMIT_MIR enums.switch_bool.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn switch_bool(b: bool) -> u32 {
+    mir!(
+        {
+            match b {
+                true => t,
+                false => f,
+                _ => f,
+            }
+        }
+
+        t = {
+            RET = 5;
+            Return()
+        }
+
+        f = {
+            RET = 10;
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR enums.switch_option.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn switch_option(option: Option<()>) -> bool {
+    mir!(
+        {
+            let discr = Discriminant(option);
+            match discr {
+                0 => n,
+                1 => s,
+                _ => s,
+            }
+        }
+
+        n = {
+            RET = false;
+            Return()
+        }
+
+        s = {
+            RET = true;
+            Return()
+        }
+    )
+}
+
+#[repr(u8)]
+enum Bool {
+    False = 0,
+    True = 1,
+}
+
+// EMIT_MIR enums.switch_option_repr.built.after.mir
+#[custom_mir(dialect = "built")]
+fn switch_option_repr(option: Bool) -> bool {
+    mir!(
+        {
+            let discr = Discriminant(option);
+            match discr {
+                0 => f,
+                _ => t,
+            }
+        }
+
+        t = {
+            RET = true;
+            Return()
+        }
+
+        f = {
+            RET = false;
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR enums.set_discr.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "initial")]
+fn set_discr(option: &mut Option<()>) {
+    mir!({
+        SetDiscriminant(*option, 0);
+        Return()
+    })
+}
+
+// EMIT_MIR enums.set_discr_repr.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "initial")]
+fn set_discr_repr(b: &mut Bool) {
+    mir!({
+        SetDiscriminant(*b, 0);
+        Return()
+    })
+}
+
+fn main() {
+    assert_eq!(switch_bool(true), 5);
+    assert_eq!(switch_bool(false), 10);
+
+    assert_eq!(switch_option(Some(())), true);
+    assert_eq!(switch_option(None), false);
+
+    assert_eq!(switch_option_repr(Bool::True), true);
+    assert_eq!(switch_option_repr(Bool::False), false);
+
+    let mut opt = Some(());
+    set_discr(&mut opt);
+    assert_eq!(opt, None);
+
+    let mut b = Bool::True;
+    set_discr_repr(&mut b);
+    assert!(matches!(b, Bool::False));
+}
diff --git a/src/test/mir-opt/building/custom/enums.set_discr.built.after.mir b/src/test/mir-opt/building/custom/enums.set_discr.built.after.mir
new file mode 100644
index 00000000000..7de9ed0983f
--- /dev/null
+++ b/src/test/mir-opt/building/custom/enums.set_discr.built.after.mir
@@ -0,0 +1,10 @@
+// MIR for `set_discr` after built
+
+fn set_discr(_1: &mut Option<()>) -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/enums.rs:+0:39: +0:39
+
+    bb0: {
+        discriminant((*_1)) = 0;         // scope 0 at $DIR/enums.rs:+2:9: +2:36
+        return;                          // scope 0 at $DIR/enums.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/enums.set_discr_repr.built.after.mir b/src/test/mir-opt/building/custom/enums.set_discr_repr.built.after.mir
new file mode 100644
index 00000000000..6fdc3d0f4d4
--- /dev/null
+++ b/src/test/mir-opt/building/custom/enums.set_discr_repr.built.after.mir
@@ -0,0 +1,10 @@
+// MIR for `set_discr_repr` after built
+
+fn set_discr_repr(_1: &mut Bool) -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/enums.rs:+0:33: +0:33
+
+    bb0: {
+        discriminant((*_1)) = 0;         // scope 0 at $DIR/enums.rs:+2:9: +2:31
+        return;                          // scope 0 at $DIR/enums.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/enums.switch_bool.built.after.mir b/src/test/mir-opt/building/custom/enums.switch_bool.built.after.mir
new file mode 100644
index 00000000000..95c57d2dca3
--- /dev/null
+++ b/src/test/mir-opt/building/custom/enums.switch_bool.built.after.mir
@@ -0,0 +1,19 @@
+// MIR for `switch_bool` after built
+
+fn switch_bool(_1: bool) -> u32 {
+    let mut _0: u32;                     // return place in scope 0 at $DIR/enums.rs:+0:32: +0:35
+
+    bb0: {
+        switchInt(_1) -> [1: bb1, 0: bb2, otherwise: bb2]; // scope 0 at $DIR/enums.rs:+3:13: +7:14
+    }
+
+    bb1: {
+        _0 = const 5_u32;                // scope 0 at $DIR/enums.rs:+11:13: +11:20
+        return;                          // scope 0 at $DIR/enums.rs:+12:13: +12:21
+    }
+
+    bb2: {
+        _0 = const 10_u32;               // scope 0 at $DIR/enums.rs:+16:13: +16:21
+        return;                          // scope 0 at $DIR/enums.rs:+17:13: +17:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/enums.switch_option.built.after.mir b/src/test/mir-opt/building/custom/enums.switch_option.built.after.mir
new file mode 100644
index 00000000000..a659ba7c114
--- /dev/null
+++ b/src/test/mir-opt/building/custom/enums.switch_option.built.after.mir
@@ -0,0 +1,21 @@
+// MIR for `switch_option` after built
+
+fn switch_option(_1: Option<()>) -> bool {
+    let mut _0: bool;                    // return place in scope 0 at $DIR/enums.rs:+0:45: +0:49
+    let mut _2: isize;                   // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _2 = discriminant(_1);           // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+        switchInt(_2) -> [0: bb1, 1: bb2, otherwise: bb2]; // scope 0 at $DIR/enums.rs:+4:13: +8:14
+    }
+
+    bb1: {
+        _0 = const false;                // scope 0 at $DIR/enums.rs:+12:13: +12:24
+        return;                          // scope 0 at $DIR/enums.rs:+13:13: +13:21
+    }
+
+    bb2: {
+        _0 = const true;                 // scope 0 at $DIR/enums.rs:+17:13: +17:23
+        return;                          // scope 0 at $DIR/enums.rs:+18:13: +18:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/enums.switch_option_repr.built.after.mir b/src/test/mir-opt/building/custom/enums.switch_option_repr.built.after.mir
new file mode 100644
index 00000000000..d60e4b1b712
--- /dev/null
+++ b/src/test/mir-opt/building/custom/enums.switch_option_repr.built.after.mir
@@ -0,0 +1,21 @@
+// MIR for `switch_option_repr` after built
+
+fn switch_option_repr(_1: Bool) -> bool {
+    let mut _0: bool;                    // return place in scope 0 at $DIR/enums.rs:+0:40: +0:44
+    let mut _2: u8;                      // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _2 = discriminant(_1);           // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+        switchInt(_2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/enums.rs:+4:13: +7:14
+    }
+
+    bb1: {
+        _0 = const true;                 // scope 0 at $DIR/enums.rs:+11:13: +11:23
+        return;                          // scope 0 at $DIR/enums.rs:+12:13: +12:21
+    }
+
+    bb2: {
+        _0 = const false;                // scope 0 at $DIR/enums.rs:+16:13: +16:24
+        return;                          // scope 0 at $DIR/enums.rs:+17:13: +17:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.rs b/src/test/mir-opt/building/custom/projections.rs
new file mode 100644
index 00000000000..5e472e531c7
--- /dev/null
+++ b/src/test/mir-opt/building/custom/projections.rs
@@ -0,0 +1,85 @@
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+union U {
+    a: i32,
+    b: u32,
+}
+
+// EMIT_MIR projections.unions.built.after.mir
+#[custom_mir(dialect = "built")]
+fn unions(u: U) -> i32 {
+    mir!({
+        RET = u.a;
+        Return()
+    })
+}
+
+// EMIT_MIR projections.tuples.built.after.mir
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn tuples(i: (u32, i32)) -> (u32, i32) {
+    mir!(
+        // FIXME(JakobDegen): This is necessary because we can't give type hints for `RET`
+        let temp: (u32, i32);
+        {
+            temp.0 = i.0;
+            temp.1 = i.1;
+
+            RET = temp;
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR projections.unwrap.built.after.mir
+#[custom_mir(dialect = "built")]
+fn unwrap(opt: Option<i32>) -> i32 {
+    mir!({
+        RET = Field(Variant(opt, 1), 0);
+        Return()
+    })
+}
+
+// EMIT_MIR projections.unwrap_deref.built.after.mir
+#[custom_mir(dialect = "built")]
+fn unwrap_deref(opt: Option<&i32>) -> i32 {
+    mir!({
+        RET = *Field::<&i32>(Variant(opt, 1), 0);
+        Return()
+    })
+}
+
+// EMIT_MIR projections.set.built.after.mir
+#[custom_mir(dialect = "built")]
+fn set(opt: &mut Option<i32>) {
+    mir!({
+        place!(Field(Variant(*opt, 1), 0)) = 10;
+        Return()
+    })
+}
+
+// EMIT_MIR projections.simple_index.built.after.mir
+#[custom_mir(dialect = "built")]
+fn simple_index(a: [i32; 10], b: &[i32]) -> i32 {
+    mir!({
+        let temp = 3;
+        RET = a[temp];
+        RET = (*b)[temp];
+        Return()
+    })
+}
+
+fn main() {
+    assert_eq!(unions(U { a: 5 }), 5);
+    assert_eq!(tuples((5, 6)), (5, 6));
+
+    assert_eq!(unwrap(Some(5)), 5);
+    assert_eq!(unwrap_deref(Some(&5)), 5);
+    let mut o = Some(5);
+    set(&mut o);
+    assert_eq!(o, Some(10));
+
+    assert_eq!(simple_index([0; 10], &[0; 10]), 0);
+}
diff --git a/src/test/mir-opt/building/custom/projections.set.built.after.mir b/src/test/mir-opt/building/custom/projections.set.built.after.mir
new file mode 100644
index 00000000000..2f15176a61f
--- /dev/null
+++ b/src/test/mir-opt/building/custom/projections.set.built.after.mir
@@ -0,0 +1,10 @@
+// MIR for `set` after built
+
+fn set(_1: &mut Option<i32>) -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/projections.rs:+0:31: +0:31
+
+    bb0: {
+        (((*_1) as variant#1).0: i32) = const 10_i32; // scope 0 at $DIR/projections.rs:+2:9: +2:48
+        return;                          // scope 0 at $DIR/projections.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.simple_index.built.after.mir b/src/test/mir-opt/building/custom/projections.simple_index.built.after.mir
new file mode 100644
index 00000000000..fc422e4b3f0
--- /dev/null
+++ b/src/test/mir-opt/building/custom/projections.simple_index.built.after.mir
@@ -0,0 +1,13 @@
+// MIR for `simple_index` after built
+
+fn simple_index(_1: [i32; 10], _2: &[i32]) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:45: +0:48
+    let mut _3: usize;                   // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _3 = const 3_usize;              // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+        _0 = _1[_3];                     // scope 0 at $DIR/projections.rs:+3:9: +3:22
+        _0 = (*_2)[_3];                  // scope 0 at $DIR/projections.rs:+4:9: +4:25
+        return;                          // scope 0 at $DIR/projections.rs:+5:9: +5:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.tuples.built.after.mir b/src/test/mir-opt/building/custom/projections.tuples.built.after.mir
new file mode 100644
index 00000000000..65487d3c9ed
--- /dev/null
+++ b/src/test/mir-opt/building/custom/projections.tuples.built.after.mir
@@ -0,0 +1,13 @@
+// MIR for `tuples` after built
+
+fn tuples(_1: (u32, i32)) -> (u32, i32) {
+    let mut _0: (u32, i32);              // return place in scope 0 at $DIR/projections.rs:+0:29: +0:39
+    let mut _2: (u32, i32);              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        (_2.0: u32) = (_1.0: u32);       // scope 0 at $DIR/projections.rs:+5:13: +5:25
+        (_2.1: i32) = (_1.1: i32);       // scope 0 at $DIR/projections.rs:+6:13: +6:25
+        _0 = _2;                         // scope 0 at $DIR/projections.rs:+8:13: +8:23
+        return;                          // scope 0 at $DIR/projections.rs:+9:13: +9:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.unions.built.after.mir b/src/test/mir-opt/building/custom/projections.unions.built.after.mir
new file mode 100644
index 00000000000..922538a5f17
--- /dev/null
+++ b/src/test/mir-opt/building/custom/projections.unions.built.after.mir
@@ -0,0 +1,10 @@
+// MIR for `unions` after built
+
+fn unions(_1: U) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:20: +0:23
+
+    bb0: {
+        _0 = (_1.0: i32);                // scope 0 at $DIR/projections.rs:+2:9: +2:18
+        return;                          // scope 0 at $DIR/projections.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.unwrap.built.after.mir b/src/test/mir-opt/building/custom/projections.unwrap.built.after.mir
new file mode 100644
index 00000000000..75b03a3c393
--- /dev/null
+++ b/src/test/mir-opt/building/custom/projections.unwrap.built.after.mir
@@ -0,0 +1,10 @@
+// MIR for `unwrap` after built
+
+fn unwrap(_1: Option<i32>) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:32: +0:35
+
+    bb0: {
+        _0 = ((_1 as variant#1).0: i32); // scope 0 at $DIR/projections.rs:+2:9: +2:40
+        return;                          // scope 0 at $DIR/projections.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.unwrap_deref.built.after.mir b/src/test/mir-opt/building/custom/projections.unwrap_deref.built.after.mir
new file mode 100644
index 00000000000..c6b0f7efa9b
--- /dev/null
+++ b/src/test/mir-opt/building/custom/projections.unwrap_deref.built.after.mir
@@ -0,0 +1,10 @@
+// MIR for `unwrap_deref` after built
+
+fn unwrap_deref(_1: Option<&i32>) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:39: +0:42
+
+    bb0: {
+        _0 = (*((_1 as variant#1).0: &i32)); // scope 0 at $DIR/projections.rs:+2:9: +2:49
+        return;                          // scope 0 at $DIR/projections.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/references.raw_pointer.built.after.mir b/src/test/mir-opt/building/custom/references.raw_pointer.built.after.mir
new file mode 100644
index 00000000000..775e5e3ad9b
--- /dev/null
+++ b/src/test/mir-opt/building/custom/references.raw_pointer.built.after.mir
@@ -0,0 +1,10 @@
+// MIR for `raw_pointer` after built
+
+fn raw_pointer(_1: *const i32) -> *const i32 {
+    let mut _0: *const i32;              // return place in scope 0 at $DIR/references.rs:+0:38: +0:48
+
+    bb0: {
+        _0 = &raw const (*_1);           // scope 0 at $DIR/references.rs:+4:9: +4:27
+        return;                          // scope 0 at $DIR/references.rs:+5:9: +5:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/references.rs b/src/test/mir-opt/building/custom/references.rs
index dee85722e86..c93f6ec624b 100644
--- a/src/test/mir-opt/building/custom/references.rs
+++ b/src/test/mir-opt/building/custom/references.rs
@@ -36,8 +36,22 @@ pub fn immut_ref(x: &i32) -> &i32 {
     )
 }
 
+// EMIT_MIR references.raw_pointer.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn raw_pointer(x: *const i32) -> *const i32 {
+    // Regression test for a bug in which unsafetyck was not correctly turned off for
+    // `dialect = "built"`
+    mir!({
+        RET = addr_of!(*x);
+        Return()
+    })
+}
+
 fn main() {
     let mut x = 5;
     assert_eq!(*mut_ref(&mut x), 5);
     assert_eq!(*immut_ref(&x), 5);
+    unsafe {
+        assert_eq!(*raw_pointer(addr_of!(x)), 5);
+    }
 }
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
index 624376769b7..44445731e72 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
@@ -12,7 +12,6 @@
       let mut _7: usize;                   // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33
       let mut _8: bool;                    // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33
       let mut _9: &[u32; 3];               // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19
-      let mut _10: &[u32; 3];              // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
@@ -25,16 +24,14 @@
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
-          StorageLive(_10);                // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
-          _10 = _3;                        // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           StorageDead(_3);                 // scope 0 at $DIR/slice_len.rs:+1:18: +1:19
           StorageLive(_6);                 // scope 0 at $DIR/slice_len.rs:+1:31: +1:32
           _6 = const 1_usize;              // scope 0 at $DIR/slice_len.rs:+1:31: +1:32
-          _7 = const 3_usize;              // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
-          StorageDead(_10);                // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
+-         _7 = Len((*_2));                 // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
 -         _8 = Lt(_6, _7);                 // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
++         _7 = const 3_usize;              // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
 +         _8 = const true;                 // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
       }
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
index 624376769b7..44445731e72 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
@@ -12,7 +12,6 @@
       let mut _7: usize;                   // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33
       let mut _8: bool;                    // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33
       let mut _9: &[u32; 3];               // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19
-      let mut _10: &[u32; 3];              // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
@@ -25,16 +24,14 @@
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
-          StorageLive(_10);                // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
-          _10 = _3;                        // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           StorageDead(_3);                 // scope 0 at $DIR/slice_len.rs:+1:18: +1:19
           StorageLive(_6);                 // scope 0 at $DIR/slice_len.rs:+1:31: +1:32
           _6 = const 1_usize;              // scope 0 at $DIR/slice_len.rs:+1:31: +1:32
-          _7 = const 3_usize;              // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
-          StorageDead(_10);                // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
+-         _7 = Len((*_2));                 // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
 -         _8 = Lt(_6, _7);                 // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
++         _7 = const 3_usize;              // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
 +         _8 = const true;                 // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
       }
diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
index 2368c021eda..e97b46f6ecc 100644
--- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
@@ -22,7 +22,6 @@
       let mut _20: *const T;               // in scope 0 at $DIR/issue_76432.rs:+3:70: +3:84
       let mut _21: *const T;               // in scope 0 at $DIR/issue_76432.rs:+3:70: +3:84
       let mut _22: !;                      // in scope 0 at $SRC_DIR/core/src/panic.rs:LL:COL
-      let mut _23: &[T; 3];                // in scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
       scope 1 {
           debug v => _2;                   // in scope 1 at $DIR/issue_76432.rs:+1:9: +1:10
           let _13: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
@@ -52,17 +51,16 @@
           StorageDead(_6);                 // scope 0 at $DIR/issue_76432.rs:+1:28: +1:29
           _4 = &_5;                        // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
           _3 = _4;                         // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
-          StorageLive(_23);                // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
-          _23 = _3;                        // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
           _2 = move _3 as &[T] (Pointer(Unsize)); // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
           StorageDead(_3);                 // scope 0 at $DIR/issue_76432.rs:+1:28: +1:29
           StorageDead(_4);                 // scope 0 at $DIR/issue_76432.rs:+1:29: +1:30
           StorageLive(_9);                 // scope 1 at $DIR/issue_76432.rs:+2:5: +5:6
-          _10 = const 3_usize;             // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
-          StorageDead(_23);                // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
+          _10 = Len((*_2));                // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
           _11 = const 3_usize;             // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
-          _12 = const true;                // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
-          goto -> bb2;                     // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
+-         _12 = Eq(move _10, const 3_usize); // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
+-         switchInt(move _12) -> [0: bb1, otherwise: bb2]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
++         nop;                             // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
++         switchInt(move _10) -> [3: bb2, otherwise: bb1]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
       }
   
       bb1: {
diff --git a/src/test/mir-opt/lower_array_len_e2e.rs b/src/test/mir-opt/lower_array_len_e2e.rs
index 49b35d509f0..d8e4e521ee6 100644
--- a/src/test/mir-opt/lower_array_len_e2e.rs
+++ b/src/test/mir-opt/lower_array_len_e2e.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z mir-opt-level=4
+// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
 
 // EMIT_MIR lower_array_len_e2e.array_bound.PreCodegen.after.mir
 pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
diff --git a/src/test/rustdoc-gui/docblock-big-code-mobile.goml b/src/test/rustdoc-gui/docblock-big-code-mobile.goml
index 9f8df44d762..3ce921c2c91 100644
--- a/src/test/rustdoc-gui/docblock-big-code-mobile.goml
+++ b/src/test/rustdoc-gui/docblock-big-code-mobile.goml
@@ -7,3 +7,7 @@ show-text: true // We need to enable text draw to be able to have the "real" siz
 // Little explanations for this test: if the text wasn't displayed on two lines, it would take
 // around 20px (which is the font size).
 assert-property: (".docblock p > code", {"offsetHeight": "44"})
+
+// Same check, but where the long code block is also a link
+goto: "file://" + |DOC_PATH| + "/test_docs/long_code_block_link/index.html"
+assert-property: (".docblock p > a > code", {"offsetHeight": "44"})
diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
index fec21ad35c3..b094c483876 100644
--- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
@@ -33,7 +33,9 @@ assert-css: ("#settings", {"display": "block"})
 click: "input#line-numbers"
 wait-for: 100 // wait-for-false does not exist
 assert-false: "pre.example-line-numbers"
+assert-local-storage: {"rustdoc-line-numbers": "false" }
 
 // Finally, turn it on again.
 click: "input#line-numbers"
 wait-for: "pre.example-line-numbers"
+assert-local-storage: {"rustdoc-line-numbers": "true" }
diff --git a/src/test/rustdoc-gui/help-page.goml b/src/test/rustdoc-gui/help-page.goml
index 799ba851c92..80203901ed3 100644
--- a/src/test/rustdoc-gui/help-page.goml
+++ b/src/test/rustdoc-gui/help-page.goml
@@ -27,7 +27,6 @@ define-function: (
             "color": |color|,
             "background-color": |background|,
             "box-shadow": |box_shadow| + " 0px -1px 0px 0px inset",
-            "cursor": "default",
         }, ALL)),
     ],
 )
diff --git a/src/test/rustdoc-gui/impl-doc.goml b/src/test/rustdoc-gui/impl-doc.goml
new file mode 100644
index 00000000000..7322032b3f5
--- /dev/null
+++ b/src/test/rustdoc-gui/impl-doc.goml
@@ -0,0 +1,9 @@
+// A docblock on an impl must have a margin to separate it from the contents.
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html"
+
+// The text is about 24px tall, so if there's a margin, then their position will be >24px apart
+compare-elements-position-near-false: (
+	"#implementations-list > .implementors-toggle > .docblock > p",
+	"#implementations-list > .implementors-toggle > .impl-items",
+	{"y": 24}
+)
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index d6eeab803df..f1b69d4dc1d 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -154,6 +154,11 @@ pub mod huge_amount_of_consts {
 /// Very long code text `hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`.
 pub mod long_code_block {}
 
+/// Very long code text [`hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`][lnk].
+///
+/// [lnk]: crate::long_code_block_link
+pub mod long_code_block_link {}
+
 #[macro_export]
 macro_rules! repro {
     () => {};
@@ -442,3 +447,11 @@ pub mod trait_members {
         fn function2() {}
     }
 }
+
+pub struct TypeWithImplDoc;
+
+/// impl doc
+impl TypeWithImplDoc {
+    /// fn doc
+    pub fn test_fn() {}
+}
diff --git a/src/test/rustdoc-ui/unable-fulfill-trait.rs b/src/test/rustdoc-ui/unable-fulfill-trait.rs
new file mode 100644
index 00000000000..70357082248
--- /dev/null
+++ b/src/test/rustdoc-ui/unable-fulfill-trait.rs
@@ -0,0 +1,13 @@
+// This test ensures that it's not crashing rustdoc.
+
+pub struct Foo<'a, 'b, T> {
+    field1: dyn Bar<'a, 'b,>,
+    //~^ ERROR
+    //~^^ ERROR
+}
+
+pub trait Bar<'x, 's, U>
+    where U: 'x,
+    Self:'x,
+    Self:'s
+{}
diff --git a/src/test/rustdoc-ui/unable-fulfill-trait.stderr b/src/test/rustdoc-ui/unable-fulfill-trait.stderr
new file mode 100644
index 00000000000..a16b5b6eb2f
--- /dev/null
+++ b/src/test/rustdoc-ui/unable-fulfill-trait.stderr
@@ -0,0 +1,26 @@
+error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+  --> $DIR/unable-fulfill-trait.rs:4:17
+   |
+LL |     field1: dyn Bar<'a, 'b,>,
+   |                 ^^^ expected 1 generic argument
+   |
+note: trait defined here, with 1 generic parameter: `U`
+  --> $DIR/unable-fulfill-trait.rs:9:11
+   |
+LL | pub trait Bar<'x, 's, U>
+   |           ^^^         -
+help: add missing generic argument
+   |
+LL |     field1: dyn Bar<'a, 'b, U,>,
+   |                           +++
+
+error[E0227]: ambiguous lifetime bound, explicit lifetime bound required
+  --> $DIR/unable-fulfill-trait.rs:4:13
+   |
+LL |     field1: dyn Bar<'a, 'b,>,
+   |             ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0107, E0227.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index 94cf7b94241..3537e669608 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -35,6 +35,7 @@
     -Z            dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
     -Z                       dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
     -Z                       dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
+    -Z                         dump-mono-stats=val -- output statistics about monomorphization collection (format: markdown)
     -Z                           dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
     -Z                               dylib-lto=val -- enables LTO for dylib crate type
     -Z                        emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
diff --git a/src/test/rustdoc/toggle-trait-fn.rs b/src/test/rustdoc/toggle-trait-fn.rs
index e41422ce7c5..0a1f088b9ab 100644
--- a/src/test/rustdoc/toggle-trait-fn.rs
+++ b/src/test/rustdoc/toggle-trait-fn.rs
@@ -4,6 +4,8 @@
 // summary. Trait methods with no documentation should not be wrapped.
 //
 // @has foo/trait.Foo.html
+// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item'
+// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item2'
 // @has -  '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
 // @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
 // @has -  '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
@@ -11,6 +13,11 @@
 // @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
 // @has -  '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
 pub trait Foo {
+    /// is documented
+    type Item;
+
+    type Item2;
+
     fn not_documented();
 
     /// is_documented is documented
diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
index 2cb1ed6fcb7..3f7429a5fcc 100644
--- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
+++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
@@ -33,8 +33,7 @@ fn main() {
         TyKind::GeneratorWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Never => (),                //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Tuple(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
-        TyKind::Projection(..) => (),       //~ ERROR usage of `ty::TyKind::<kind>`
-        TyKind::Opaque(..) => (),           //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Alias(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Param(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Bound(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Placeholder(..) => (),      //~ ERROR usage of `ty::TyKind::<kind>`
diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
index 171f49087d6..1f49d6b6464 100644
--- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
+++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
@@ -133,53 +133,47 @@ LL |         TyKind::Tuple(..) => (),
 error: usage of `ty::TyKind::<kind>`
   --> $DIR/ty_tykind_usage.rs:36:9
    |
-LL |         TyKind::Projection(..) => (),
+LL |         TyKind::Alias(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
   --> $DIR/ty_tykind_usage.rs:37:9
    |
-LL |         TyKind::Opaque(..) => (),
-   |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
-
-error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:38:9
-   |
 LL |         TyKind::Param(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:39:9
+  --> $DIR/ty_tykind_usage.rs:38:9
    |
 LL |         TyKind::Bound(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:40:9
+  --> $DIR/ty_tykind_usage.rs:39:9
    |
 LL |         TyKind::Placeholder(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:41:9
+  --> $DIR/ty_tykind_usage.rs:40:9
    |
 LL |         TyKind::Infer(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:42:9
+  --> $DIR/ty_tykind_usage.rs:41:9
    |
 LL |         TyKind::Error(_) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:47:12
+  --> $DIR/ty_tykind_usage.rs:46:12
    |
 LL |     if let TyKind::Int(int_ty) = kind {}
    |            ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind`
-  --> $DIR/ty_tykind_usage.rs:49:24
+  --> $DIR/ty_tykind_usage.rs:48:24
    |
 LL |     fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
    |                        ^^^^^^^^^^
@@ -187,7 +181,7 @@ LL |     fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
    = help: try using `Ty` instead
 
 error: usage of `ty::TyKind`
-  --> $DIR/ty_tykind_usage.rs:51:37
+  --> $DIR/ty_tykind_usage.rs:50:37
    |
 LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    |                                     ^^^^^^^^^^^
@@ -195,7 +189,7 @@ LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    = help: try using `Ty` instead
 
 error: usage of `ty::TyKind`
-  --> $DIR/ty_tykind_usage.rs:51:53
+  --> $DIR/ty_tykind_usage.rs:50:53
    |
 LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    |                                                     ^^^^^^^^^^^
@@ -203,12 +197,12 @@ LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    = help: try using `Ty` instead
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:54:9
+  --> $DIR/ty_tykind_usage.rs:53:9
    |
 LL |         IrTyKind::Bool
    |         --------^^^^^^
    |         |
    |         help: try using `ty::<kind>` directly: `ty`
 
-error: aborting due to 33 previous errors
+error: aborting due to 32 previous errors
 
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index cb4cd466590..c19b639a8d5 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -683,7 +683,7 @@ struct RawIdentDiagnosticArg {
 #[diag(compiletest_example)]
 struct SubdiagnosticBad {
     #[subdiagnostic(bad)]
-    //~^ ERROR `#[subdiagnostic(bad)]` is not a valid attribute
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -707,7 +707,7 @@ struct SubdiagnosticBadTwice {
 #[diag(compiletest_example)]
 struct SubdiagnosticBadLitStr {
     #[subdiagnostic("bad")]
-    //~^ ERROR `#[subdiagnostic("...")]` is not a valid attribute
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -723,6 +723,7 @@ struct SubdiagnosticEagerLint {
 #[diag(compiletest_example)]
 struct SubdiagnosticEagerCorrect {
     #[subdiagnostic(eager)]
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -743,6 +744,7 @@ pub(crate) struct SubdiagnosticWithSuggestion {
 #[diag(compiletest_example)]
 struct SubdiagnosticEagerSuggestion {
     #[subdiagnostic(eager)]
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     sub: SubdiagnosticWithSuggestion,
 }
 
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index b4c211db47c..f39d32a221c 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -533,21 +533,19 @@ LL | #[label]
    |
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
-error: `#[subdiagnostic(bad)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:685:21
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:685:5
    |
 LL |     #[subdiagnostic(bad)]
-   |                     ^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   = help: `subdiagnostic` does not support nested attributes
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:693:5
    |
 LL |     #[subdiagnostic = "bad"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:701:5
@@ -555,15 +553,15 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic(bad, bad)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   = help: `subdiagnostic` does not support nested attributes
 
-error: `#[subdiagnostic("...")]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:709:21
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:709:5
    |
 LL |     #[subdiagnostic("bad")]
-   |                     ^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   = help: `subdiagnostic` does not support nested attributes
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:717:5
@@ -571,22 +569,38 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic(eager)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: eager subdiagnostics are not supported on lints
+   = help: `subdiagnostic` does not support nested attributes
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:725:5
+   |
+LL |     #[subdiagnostic(eager)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `subdiagnostic` does not support nested attributes
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:746:5
+   |
+LL |     #[subdiagnostic(eager)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `subdiagnostic` does not support nested attributes
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:775:18
+  --> $DIR/diagnostic-derive.rs:777:18
    |
 LL |     #[suggestion(code())]
    |                  ^^^^^^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:783:23
+  --> $DIR/diagnostic-derive.rs:785:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
 error: `code = "..."`/`code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:791:18
+  --> $DIR/diagnostic-derive.rs:793:18
    |
 LL |     #[suggestion(code = 3)]
    |                  ^^^^^^^^
@@ -660,12 +674,9 @@ LL | #[derive(Diagnostic)]
    = help: normalized in stderr
 note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
   --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
-   |
-LL |         arg: impl IntoDiagnosticArg,
-   |                   ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
-   = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 83 previous errors
+error: aborting due to 85 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
index adb652fe616..2673ee9f937 100644
--- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
+++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
@@ -17,9 +17,6 @@ LL | |  }
    = note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types
 note: struct `core::alloc::Layout` is defined in crate `core`
   --> $SRC_DIR/core/src/alloc/layout.rs:LL:COL
-   |
-LL | pub struct Layout {
-   | ^^^^^^^^^^^^^^^^^
 note: struct `Layout` is defined in the current crate
   --> $DIR/alloc-error-handler-bad-signature-2.rs:7:1
    |
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
index bf5f642ca82..afb7f8fea92 100644
--- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
@@ -13,6 +13,10 @@ note: required by a bound in `f1`
    |
 LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
    |                         ^^^^^^^^^^^^ required by this bound in `f1`
+help: consider borrowing the argument
+   |
+LL |     f1(|_: &(), _: &()| {});
+   |            ~~~     ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
@@ -29,6 +33,10 @@ note: required by a bound in `f2`
    |
 LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
+help: consider borrowing the argument
+   |
+LL |     f2(|_: &'a (), _: &()| {});
+   |            ~~~~~~     ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -45,6 +53,10 @@ note: required by a bound in `f3`
    |
 LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
    |                             ^^^^^^^^^^^^^^^ required by this bound in `f3`
+help: consider borrowing the argument
+   |
+LL |     f3(|_: &(), _: &()| {});
+   |            ~~~     ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
@@ -61,6 +73,10 @@ note: required by a bound in `f4`
    |
 LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
+help: consider borrowing the argument
+   |
+LL |     f4(|_: &(), _: &'r ()| {});
+   |            ~~~     ~~~~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -77,13 +93,19 @@ note: required by a bound in `f5`
    |
 LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
+help: consider borrowing the argument
+   |
+LL |     f5(|_: &'r (), _: &'r ()| {});
+   |            ~~~~~~     ~~~~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
    |
 LL |     g1(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -98,8 +120,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
    |
 LL |     g2(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
@@ -114,8 +138,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
    |
 LL |     g3(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&'s ()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -130,8 +156,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
    |
 LL |     g4(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
@@ -157,6 +185,10 @@ note: required by a bound in `h1`
    |
 LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1`
+help: consider borrowing the argument
+   |
+LL |     h1(|_: &(), _: (), _: &(), _: ()| {});
+   |            ~~~            ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -173,6 +205,10 @@ note: required by a bound in `h2`
    |
 LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
+help: consider borrowing the argument
+   |
+LL |     h2(|_: &(), _: (), _: &'t0 (), _: ()| {});
+   |            ~~~            ~~~~~~~
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/argument-suggestions/display-is-suggestable.rs b/src/test/ui/argument-suggestions/display-is-suggestable.rs
new file mode 100644
index 00000000000..d765bc4f74d
--- /dev/null
+++ b/src/test/ui/argument-suggestions/display-is-suggestable.rs
@@ -0,0 +1,8 @@
+use std::fmt::Display;
+
+fn foo(x: &(dyn Display + Send)) {}
+
+fn main() {
+    foo();
+    //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+}
diff --git a/src/test/ui/argument-suggestions/display-is-suggestable.stderr b/src/test/ui/argument-suggestions/display-is-suggestable.stderr
new file mode 100644
index 00000000000..edd72b53eb3
--- /dev/null
+++ b/src/test/ui/argument-suggestions/display-is-suggestable.stderr
@@ -0,0 +1,19 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/display-is-suggestable.rs:6:5
+   |
+LL |     foo();
+   |     ^^^-- an argument of type `&dyn std::fmt::Display + Send` is missing
+   |
+note: function defined here
+  --> $DIR/display-is-suggestable.rs:3:4
+   |
+LL | fn foo(x: &(dyn Display + Send)) {}
+   |    ^^^ ------------------------
+help: provide the argument
+   |
+LL |     foo(/* &dyn std::fmt::Display + Send */);
+   |        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/array-slice-vec/infer_array_len.stderr b/src/test/ui/array-slice-vec/infer_array_len.stderr
index 919550cac30..c2a509a1963 100644
--- a/src/test/ui/array-slice-vec/infer_array_len.stderr
+++ b/src/test/ui/array-slice-vec/infer_array_len.stderr
@@ -6,8 +6,8 @@ LL |     let [_, _] = a.into();
    |
 help: consider giving this pattern a type
    |
-LL |     let [_, _]: _ = a.into();
-   |               +++
+LL |     let [_, _]: /* Type */ = a.into();
+   |               ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-item/issue-105449.rs b/src/test/ui/associated-item/issue-105449.rs
new file mode 100644
index 00000000000..dd14e05fd49
--- /dev/null
+++ b/src/test/ui/associated-item/issue-105449.rs
@@ -0,0 +1,59 @@
+// check-pass
+// compile-flags: -C debug_assertions=yes -Zunstable-options
+
+#[allow(dead_code)]
+fn problematic_function<Space>()
+where
+    DefaultAlloc: FinAllok<R1, Space>,
+{
+    let e = Edge2dElement;
+    let _ = Into::<Point>::into(e.map_reference_coords());
+}
+impl<N> Allocator<N, R0> for DefaultAlloc {
+    type Buffer = MStorage;
+}
+impl<N> Allocator<N, R1> for DefaultAlloc {
+    type Buffer = MStorage;
+}
+impl<N, D> From<VectorN<N, D>> for Point
+where
+    DefaultAlloc: Allocator<N, D>,
+{
+    fn from(_: VectorN<N, D>) -> Self {
+        unimplemented!()
+    }
+}
+impl<GeometryDim, NodalDim> FinAllok<GeometryDim, NodalDim> for DefaultAlloc
+where
+    DefaultAlloc: Allocator<Ure, GeometryDim>,
+    DefaultAlloc: Allocator<Ure, NodalDim>
+{
+}
+impl FiniteElement<R1> for Edge2dElement {
+    fn map_reference_coords(&self) -> VectorN<Ure, R1> {
+        unimplemented!()
+    }
+}
+type VectorN<N, R> = (N, R, <DefaultAlloc as Allocator<N, R>>::Buffer);
+struct DefaultAlloc;
+struct R0;
+struct R1;
+struct MStorage;
+struct Point;
+struct Edge2dElement;
+struct Ure;
+trait Allocator<N, R> {
+    type Buffer;
+}
+trait FinAllok<GeometryDim, NodalDim>:
+    Allocator<Ure, GeometryDim> +
+    Allocator<Ure, NodalDim> +
+{
+}
+trait FiniteElement<Rau>
+where
+    DefaultAlloc: FinAllok<Rau, Rau>,
+{
+    fn map_reference_coords(&self) -> VectorN<Ure, Rau>;
+}
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr b/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr
new file mode 100644
index 00000000000..0f1ec9ad052
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr
@@ -0,0 +1,24 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const-projection-err.rs:4:26
+   |
+LL | #![cfg_attr(gce, feature(generic_const_exprs))]
+   |                          ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+  --> $DIR/const-projection-err.rs:14:11
+   |
+LL |     foo::<T>();
+   |           ^ expected `0`, found `1`
+   |
+note: required by a bound in `foo`
+  --> $DIR/const-projection-err.rs:11:28
+   |
+LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
+   |                            ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-type-bounds/const-projection-err.rs b/src/test/ui/associated-type-bounds/const-projection-err.rs
new file mode 100644
index 00000000000..bead8563001
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/const-projection-err.rs
@@ -0,0 +1,18 @@
+// revisions: stock gce
+
+#![feature(associated_const_equality)]
+#![cfg_attr(gce, feature(generic_const_exprs))]
+//[gce]~^ WARN the feature `generic_const_exprs` is incomplete
+
+trait TraitWAssocConst {
+    const A: usize;
+}
+
+fn foo<T: TraitWAssocConst<A = 1>>() {}
+
+fn bar<T: TraitWAssocConst<A = 0>>() {
+    foo::<T>();
+    //~^ ERROR type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr b/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr
new file mode 100644
index 00000000000..bf0824259a5
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr
@@ -0,0 +1,17 @@
+error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+  --> $DIR/const-projection-err.rs:14:11
+   |
+LL |     foo::<T>();
+   |           ^ expected `1`, found `<T as TraitWAssocConst>::A`
+   |
+   = note: expected constant `1`
+              found constant `<T as TraitWAssocConst>::A`
+note: required by a bound in `foo`
+  --> $DIR/const-projection-err.rs:11:28
+   |
+LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
+   |                            ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-type-bounds/issue-99828.stderr b/src/test/ui/associated-type-bounds/issue-99828.stderr
index 1c20ead0556..dc93c47dace 100644
--- a/src/test/ui/associated-type-bounds/issue-99828.stderr
+++ b/src/test/ui/associated-type-bounds/issue-99828.stderr
@@ -15,9 +15,6 @@ LL | fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ {
    |
 note: associated type defined here
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     type Item;
-   |     ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.rs b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs
index 26b9f4b3a92..fed60ccf089 100644
--- a/src/test/ui/associated-types/associated-types-overridden-binding-2.rs
+++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs
@@ -4,5 +4,5 @@ trait I32Iterator = Iterator<Item = i32>;
 
 fn main() {
     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
-    //~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
+    //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
 }
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
index 2d25f68de44..a28a0b74e4a 100644
--- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
+++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
@@ -1,4 +1,4 @@
-error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
+error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
   --> $DIR/associated-types-overridden-binding-2.rs:6:43
    |
 LL |     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr
index e51a8f3bd1a..ef9b7cae01b 100644
--- a/src/test/ui/associated-types/associated-types-unconstrained.stderr
+++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr
@@ -6,6 +6,11 @@ LL |     fn bar() -> isize;
 ...
 LL |     let x: isize = Foo::bar();
    |                    ^^^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     let x: isize = <isize as Foo>::bar();
+   |                    +++++++++    +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/defaults-wf.stderr b/src/test/ui/associated-types/defaults-wf.stderr
index 8455f88f18e..fc830b8d676 100644
--- a/src/test/ui/associated-types/defaults-wf.stderr
+++ b/src/test/ui/associated-types/defaults-wf.stderr
@@ -7,9 +7,6 @@ LL |     type Ty = Vec<[u8]>;
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr
index 0edc9a556b7..8e7cf86c406 100644
--- a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr
+++ b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr
@@ -6,9 +6,6 @@ LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self>
    |
 note: required by a bound in `Add`
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   |               ^^^^^^^^^^ required by this bound in `Add`
 help: consider further restricting `Self`
    |
 LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> + Sized {}
diff --git a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
index 616623ee077..f0f5245a3b4 100644
--- a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
+++ b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
@@ -68,14 +68,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/async-await-let-else.rs:33:28
    |
 LL |         (Rc::new(()), bar().await);
-   |          -----------       ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
-   |          |
+   |          -----------       ^^^^^^ - `Rc::new(())` is later dropped here
+   |          |                 |
+   |          |                 await occurs here, with `Rc::new(())` maybe used later
    |          has type `Rc<()>` which is not `Send`
-note: `Rc::new(())` is later dropped here
-  --> $DIR/async-await-let-else.rs:33:35
-   |
-LL |         (Rc::new(()), bar().await);
-   |                                   ^
 note: required by a bound in `is_send`
   --> $DIR/async-await-let-else.rs:19:15
    |
diff --git a/src/test/ui/async-await/async-await-let-else.no-drop-tracking.stderr b/src/test/ui/async-await/async-await-let-else.no-drop-tracking.stderr
index 7f93563e288..d3c5e80a30d 100644
--- a/src/test/ui/async-await/async-await-let-else.no-drop-tracking.stderr
+++ b/src/test/ui/async-await/async-await-let-else.no-drop-tracking.stderr
@@ -53,14 +53,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/async-await-let-else.rs:33:28
    |
 LL |         (Rc::new(()), bar().await);
-   |          -----------       ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
-   |          |
+   |          -----------       ^^^^^^ - `Rc::new(())` is later dropped here
+   |          |                 |
+   |          |                 await occurs here, with `Rc::new(())` maybe used later
    |          has type `Rc<()>` which is not `Send`
-note: `Rc::new(())` is later dropped here
-  --> $DIR/async-await-let-else.rs:33:35
-   |
-LL |         (Rc::new(()), bar().await);
-   |                                   ^
 note: required by a bound in `is_send`
   --> $DIR/async-await-let-else.rs:19:15
    |
diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr
index 1686153acf9..963c6ba57ad 100644
--- a/src/test/ui/async-await/generator-desc.stderr
+++ b/src/test/ui/async-await/generator-desc.stderr
@@ -12,9 +12,6 @@ LL |     fun(async {}, async {});
               found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |              ^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:12:16
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
index 61d7e2520ea..1b1b3cffd58 100644
--- a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
@@ -1,4 +1,3 @@
-// check-pass
 // edition: 2021
 
 #![feature(async_fn_in_trait)]
@@ -13,11 +12,9 @@ trait MyTrait {
 }
 
 impl MyTrait for i32 {
-    // This will break once a PR that implements #102745 is merged
     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
-        Box::pin(async {
-            *self
-        })
+        //~^ ERROR method `foo` should be async
+        Box::pin(async { *self })
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr
new file mode 100644
index 00000000000..60fa534a64f
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-boxed.rs:15:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs b/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs
new file mode 100644
index 00000000000..81e1e59a362
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs
@@ -0,0 +1,37 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::Poll;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+#[derive(Clone)]
+struct MyFuture(i32);
+
+impl Future for MyFuture {
+    type Output = i32;
+    fn poll(
+        self: Pin<&mut Self>,
+        _: &mut std::task::Context<'_>,
+    ) -> Poll<<Self as Future>::Output> {
+        Poll::Ready(self.0)
+    }
+}
+
+impl MyTrait for i32 {
+    // FIXME: this should eventually require `#[refine]` to compile, because it also provides
+    // `Clone`.
+    fn foo(&self) -> impl Future<Output = i32> + Clone {
+        MyFuture(*self)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs b/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs
new file mode 100644
index 00000000000..71473e7455f
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs
@@ -0,0 +1,29 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::task::Poll;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+struct MyFuture;
+impl Future for MyFuture {
+    type Output = i32;
+    fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
+        Poll::Ready(0)
+    }
+}
+
+impl MyTrait for u32 {
+    fn foo(&self) -> MyFuture {
+        //~^ ERROR method `foo` should be async
+        MyFuture
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr
new file mode 100644
index 00000000000..567a36a86d1
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-manual.rs:23:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> MyFuture {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared.rs b/src/test/ui/async-await/in-trait/async-example-desugared.rs
index 1313c9edd86..fb92ec78674 100644
--- a/src/test/ui/async-await/in-trait/async-example-desugared.rs
+++ b/src/test/ui/async-await/in-trait/async-example-desugared.rs
@@ -12,11 +12,8 @@ trait MyTrait {
 }
 
 impl MyTrait for i32 {
-    // This will break once a PR that implements #102745 is merged
     fn foo(&self) -> impl Future<Output = i32> + '_ {
-        async {
-            *self
-        }
+        async { *self }
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err.rs b/src/test/ui/async-await/in-trait/fn-not-async-err.rs
index f94d32145a2..9598d53bce8 100644
--- a/src/test/ui/async-await/in-trait/fn-not-async-err.rs
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err.rs
@@ -9,7 +9,7 @@ trait MyTrait {
 
 impl MyTrait for i32 {
     fn foo(&self) -> i32 {
-        //~^ ERROR: `i32` is not a future [E0277]
+        //~^ ERROR: method `foo` should be async
         *self
     }
 }
diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err.stderr b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr
index 03321dc5b5a..579801d0f39 100644
--- a/src/test/ui/async-await/in-trait/fn-not-async-err.stderr
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr
@@ -1,17 +1,11 @@
-error[E0277]: `i32` is not a future
-  --> $DIR/fn-not-async-err.rs:11:22
-   |
-LL |     fn foo(&self) -> i32 {
-   |                      ^^^ `i32` is not a future
-   |
-   = help: the trait `Future` is not implemented for `i32`
-   = note: i32 must be a future or must implement `IntoFuture` to be awaited
-note: required by a bound in `MyTrait::foo::{opaque#0}`
-  --> $DIR/fn-not-async-err.rs:7:28
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/fn-not-async-err.rs:11:5
    |
 LL |     async fn foo(&self) -> i32;
-   |                            ^^^ required by this bound in `MyTrait::foo::{opaque#0}`
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> i32 {
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs
index 594baa91ad8..2c4ed553580 100644
--- a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs
@@ -12,9 +12,7 @@ trait MyTrait {
 impl MyTrait for i32 {
     fn foo(&self) -> impl Future<Output = i32> {
         //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562]
-        async {
-            *self
-        }
+        async { *self }
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/issue-104678.rs b/src/test/ui/async-await/in-trait/issue-104678.rs
new file mode 100644
index 00000000000..e396df4e5d1
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/issue-104678.rs
@@ -0,0 +1,31 @@
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+pub trait Pool {
+    type Conn;
+
+    async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+        &'a self,
+        callback: F,
+    ) -> ();
+}
+
+pub struct PoolImpl;
+pub struct ConnImpl;
+
+impl Pool for PoolImpl {
+    type Conn = ConnImpl;
+
+    async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+        &'a self,
+        _callback: F,
+    ) -> () {
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
index 34b31198e4f..8036d82daa4 100644
--- a/src/test/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
@@ -12,14 +12,10 @@ LL |           baz(|| async{
    |  _____________-
 LL | |             foo(tx.clone());
 LL | |         }).await;
-   | |         - ^^^^^^ await occurs here, with the value maybe used later
-   | |_________|
+   | |         - ^^^^^^- the value is later dropped here
+   | |         | |
+   | |_________| await occurs here, with the value maybe used later
    |           has type `[closure@$DIR/issue-70935-complex-spans.rs:17:13: 17:15]` which is not `Send`
-note: the value is later dropped here
-  --> $DIR/issue-70935-complex-spans.rs:19:17
-   |
-LL |         }).await;
-   |                 ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/issue-72442.stderr b/src/test/ui/async-await/issue-72442.stderr
index 919abf64603..4a1705715ca 100644
--- a/src/test/ui/async-await/issue-72442.stderr
+++ b/src/test/ui/async-await/issue-72442.stderr
@@ -8,9 +8,6 @@ LL |             let mut f = File::open(path.to_str())?;
    |
 note: required by a bound in `File::open`
   --> $SRC_DIR/std/src/fs.rs:LL:COL
-   |
-LL |     pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
-   |                    ^^^^^^^^^^^ required by this bound in `File::open`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr
index 45f5ec40cd7..40c0e72b203 100644
--- a/src/test/ui/async-await/issues/issue-65159.stderr
+++ b/src/test/ui/async-await/issues/issue-65159.stderr
@@ -6,11 +6,6 @@ LL | async fn copy() -> Result<()>
    |                    |
    |                    expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL | async fn copy() -> Result<(), E>
diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
index ab196dca20c..1033fa6cc8b 100644
--- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
+++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
@@ -13,14 +13,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/issue-65436-raw-ptr-not-send.rs:18:35
    |
 LL |         bar(Foo(std::ptr::null())).await;
-   |                 ----------------  ^^^^^^ await occurs here, with `std::ptr::null()` maybe used later
-   |                 |
+   |                 ----------------  ^^^^^^- `std::ptr::null()` is later dropped here
+   |                 |                 |
+   |                 |                 await occurs here, with `std::ptr::null()` maybe used later
    |                 has type `*const u8` which is not `Send`
-note: `std::ptr::null()` is later dropped here
-  --> $DIR/issue-65436-raw-ptr-not-send.rs:18:41
-   |
-LL |         bar(Foo(std::ptr::null())).await;
-   |                                         ^
 help: consider moving this into a `let` binding to create a shorter lived borrow
   --> $DIR/issue-65436-raw-ptr-not-send.rs:18:13
    |
diff --git a/src/test/ui/async-await/issues/issue-67893.stderr b/src/test/ui/async-await/issues/issue-67893.stderr
index 316b6d06f93..2ce68a78291 100644
--- a/src/test/ui/async-await/issues/issue-67893.stderr
+++ b/src/test/ui/async-await/issues/issue-67893.stderr
@@ -9,14 +9,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/auxiliary/issue_67893.rs:9:26
    |
 LL |     f(*x.lock().unwrap()).await;
-   |        ----------------- ^^^^^^ await occurs here, with `x.lock().unwrap()` maybe used later
-   |        |
+   |        ----------------- ^^^^^^- `x.lock().unwrap()` is later dropped here
+   |        |                 |
+   |        |                 await occurs here, with `x.lock().unwrap()` maybe used later
    |        has type `MutexGuard<'_, ()>` which is not `Send`
-note: `x.lock().unwrap()` is later dropped here
-  --> $DIR/auxiliary/issue_67893.rs:9:32
-   |
-LL |     f(*x.lock().unwrap()).await;
-   |                                ^
 note: required by a bound in `g`
   --> $DIR/issue-67893.rs:6:14
    |
diff --git a/src/test/ui/async-await/pin-needed-to-poll-2.stderr b/src/test/ui/async-await/pin-needed-to-poll-2.stderr
index 83d1a02c876..0a6f705e255 100644
--- a/src/test/ui/async-await/pin-needed-to-poll-2.stderr
+++ b/src/test/ui/async-await/pin-needed-to-poll-2.stderr
@@ -14,9 +14,6 @@ LL | struct Sleep(std::marker::PhantomPinned);
    |        ^^^^^
 note: required by a bound in `Pin::<P>::new`
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
-   |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/pin-needed-to-poll.stderr b/src/test/ui/async-await/pin-needed-to-poll.stderr
index 2e8723b2743..b1f4a73aafe 100644
--- a/src/test/ui/async-await/pin-needed-to-poll.stderr
+++ b/src/test/ui/async-await/pin-needed-to-poll.stderr
@@ -6,11 +6,9 @@ LL | struct Sleep;
 ...
 LL |         self.sleep.poll(cx)
    |                    ^^^^ method not found in `Sleep`
+  --> $SRC_DIR/core/src/future/future.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/future/future.rs:LL:COL
-   |
-LL |     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
-   |        ---- the method is available for `Pin<&mut Sleep>` here
+   = note: the method is available for `Pin<&mut Sleep>` here
    |
 help: consider wrapping the receiver expression with the appropriate type
    |
diff --git a/src/test/ui/async-await/track-caller/async-block.rs b/src/test/ui/async-await/track-caller/async-block.rs
new file mode 100644
index 00000000000..8e81387c34b
--- /dev/null
+++ b/src/test/ui/async-await/track-caller/async-block.rs
@@ -0,0 +1,9 @@
+// edition:2021
+
+#![feature(closure_track_caller, stmt_expr_attributes)]
+
+fn main() {
+    let _ = #[track_caller] async {
+        //~^ ERROR attribute should be applied to a function definition [E0739]
+    };
+}
diff --git a/src/test/ui/async-await/track-caller/async-block.stderr b/src/test/ui/async-await/track-caller/async-block.stderr
new file mode 100644
index 00000000000..407439921c0
--- /dev/null
+++ b/src/test/ui/async-await/track-caller/async-block.stderr
@@ -0,0 +1,12 @@
+error[E0739]: attribute should be applied to a function definition
+  --> $DIR/async-block.rs:6:13
+   |
+LL |       let _ = #[track_caller] async {
+   |  _____________^^^^^^^^^^^^^^^_-
+LL | |
+LL | |     };
+   | |_____- not a function definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0739`.
diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.rs b/src/test/ui/async-await/track-caller/async-closure-gate.rs
new file mode 100644
index 00000000000..9593fdb1908
--- /dev/null
+++ b/src/test/ui/async-await/track-caller/async-closure-gate.rs
@@ -0,0 +1,10 @@
+// edition:2021
+
+#![feature(async_closure, stmt_expr_attributes)]
+
+fn main() {
+    let _ = #[track_caller] async || {
+        //~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
+        //~| ERROR `#[track_caller]` on closures is currently unstable [E0658]
+    };
+}
diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.stderr b/src/test/ui/async-await/track-caller/async-closure-gate.stderr
new file mode 100644
index 00000000000..be3d110eccd
--- /dev/null
+++ b/src/test/ui/async-await/track-caller/async-closure-gate.stderr
@@ -0,0 +1,25 @@
+error[E0658]: `#[track_caller]` on closures is currently unstable
+  --> $DIR/async-closure-gate.rs:6:13
+   |
+LL |     let _ = #[track_caller] async || {
+   |             ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+   = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error[E0658]: `#[track_caller]` on closures is currently unstable
+  --> $DIR/async-closure-gate.rs:6:38
+   |
+LL |       let _ = #[track_caller] async || {
+   |  ______________________________________^
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+   = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+   = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.rs b/src/test/ui/async-await/track-caller/panic-track-caller.rs
index 5ebfeb3f36a..066cf97628f 100644
--- a/src/test/ui/async-await/track-caller/panic-track-caller.rs
+++ b/src/test/ui/async-await/track-caller/panic-track-caller.rs
@@ -1,7 +1,7 @@
 // run-pass
 // edition:2021
 // needs-unwind
-#![feature(closure_track_caller)]
+#![feature(closure_track_caller, async_closure, stmt_expr_attributes)]
 
 use std::future::Future;
 use std::panic;
@@ -67,6 +67,13 @@ async fn foo_assoc() {
     Foo::bar_assoc().await
 }
 
+async fn foo_closure() {
+    let c = #[track_caller] async || {
+        panic!();
+    };
+    c().await
+}
+
 fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
     let loc = Arc::new(Mutex::new(None));
 
@@ -87,4 +94,5 @@ fn main() {
     assert_eq!(panicked_at(|| block_on(foo())), 41);
     assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
     assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
+    assert_eq!(panicked_at(|| block_on(foo_closure())), 74);
 }
diff --git a/src/test/ui/binop/binop-consume-args.stderr b/src/test/ui/binop/binop-consume-args.stderr
index c734f8c1e17..6fbbb55437e 100644
--- a/src/test/ui/binop/binop-consume-args.stderr
+++ b/src/test/ui/binop/binop-consume-args.stderr
@@ -10,9 +10,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn add<A: Add<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -46,9 +43,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn sub(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn sub<A: Sub<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -82,9 +76,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn mul(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn mul<A: Mul<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -118,9 +109,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn div(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn div<A: Div<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -154,9 +142,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn rem(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn rem<A: Rem<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -190,9 +175,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn bitand(self, rhs: Rhs) -> Self::Output;
-   |               ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitand<A: BitAnd<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -226,9 +208,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn bitor(self, rhs: Rhs) -> Self::Output;
-   |              ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitor<A: BitOr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -262,9 +241,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn bitxor(self, rhs: Rhs) -> Self::Output;
-   |               ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitxor<A: BitXor<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -298,9 +274,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn shl(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn shl<A: Shl<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -334,9 +307,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn shr(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
diff --git a/src/test/ui/binop/binop-move-semantics.stderr b/src/test/ui/binop/binop-move-semantics.stderr
index 994eaf9d8c7..dae267da05d 100644
--- a/src/test/ui/binop/binop-move-semantics.stderr
+++ b/src/test/ui/binop/binop-move-semantics.stderr
@@ -13,9 +13,6 @@ LL | |     x;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn double_move<T: Add<Output=()> + Copy>(x: T) {
@@ -78,9 +75,6 @@ LL | |     *n;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 
 error[E0507]: cannot move out of `*n` which is behind a shared reference
   --> $DIR/binop-move-semantics.rs:32:5
diff --git a/src/test/ui/binop/issue-28837.stderr b/src/test/ui/binop/issue-28837.stderr
index b9c7e1bea70..6e236ca5296 100644
--- a/src/test/ui/binop/issue-28837.stderr
+++ b/src/test/ui/binop/issue-28837.stderr
@@ -11,11 +11,8 @@ note: an implementation of `Add<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot subtract `A` from `A`
   --> $DIR/issue-28837.rs:8:7
@@ -30,11 +27,8 @@ note: an implementation of `Sub<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Sub<_>`
-note: the following trait must be implemented
+note: the trait `Sub` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Sub<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot multiply `A` by `A`
   --> $DIR/issue-28837.rs:10:7
@@ -49,11 +43,8 @@ note: an implementation of `Mul<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Mul<_>`
-note: the following trait must be implemented
+note: the trait `Mul` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Mul<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot divide `A` by `A`
   --> $DIR/issue-28837.rs:12:7
@@ -68,11 +59,8 @@ note: an implementation of `Div<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Div<_>`
-note: the following trait must be implemented
+note: the trait `Div` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Div<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot mod `A` by `A`
   --> $DIR/issue-28837.rs:14:7
@@ -87,11 +75,8 @@ note: an implementation of `Rem<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Rem<_>`
-note: the following trait must be implemented
+note: the trait `Rem` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Rem<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A & A`
   --> $DIR/issue-28837.rs:16:7
@@ -106,11 +91,8 @@ note: an implementation of `BitAnd<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `BitAnd<_>`
-note: the following trait must be implemented
+note: the trait `BitAnd` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait BitAnd<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A | A`
   --> $DIR/issue-28837.rs:18:7
@@ -125,11 +107,8 @@ note: an implementation of `BitOr<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `BitOr<_>`
-note: the following trait must be implemented
+note: the trait `BitOr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait BitOr<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A << A`
   --> $DIR/issue-28837.rs:20:7
@@ -144,11 +123,8 @@ note: an implementation of `Shl<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Shl<_>`
-note: the following trait must be implemented
+note: the trait `Shl` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Shl<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A >> A`
   --> $DIR/issue-28837.rs:22:7
@@ -163,11 +139,8 @@ note: an implementation of `Shr<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Shr<_>`
-note: the following trait must be implemented
+note: the trait `Shr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Shr<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: binary operation `==` cannot be applied to type `A`
   --> $DIR/issue-28837.rs:24:7
diff --git a/src/test/ui/binop/issue-3820.stderr b/src/test/ui/binop/issue-3820.stderr
index f21f8906911..c313ed6037f 100644
--- a/src/test/ui/binop/issue-3820.stderr
+++ b/src/test/ui/binop/issue-3820.stderr
@@ -11,11 +11,8 @@ note: an implementation of `Mul<_>` might be missing for `Thing`
    |
 LL | struct Thing {
    | ^^^^^^^^^^^^ must implement `Mul<_>`
-note: the following trait must be implemented
+note: the trait `Mul` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Mul<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/access-mode-in-closures.stderr b/src/test/ui/borrowck/access-mode-in-closures.stderr
index 13a6277da14..abee72ba8cf 100644
--- a/src/test/ui/borrowck/access-mode-in-closures.stderr
+++ b/src/test/ui/borrowck/access-mode-in-closures.stderr
@@ -3,10 +3,15 @@ error[E0507]: cannot move out of `s` which is behind a shared reference
    |
 LL |         match *s { S(v) => v }
    |               ^^     -
-   |               |      |
-   |               |      data moved here
-   |               |      move occurs because `v` has type `Vec<isize>`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&*s`
+   |                      |
+   |                      data moved here
+   |                      move occurs because `v` has type `Vec<isize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -         match *s { S(v) => v }
+LL +         match s { S(v) => v }
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr
index 2eabc1f1d9d..f9ced03e0f0 100644
--- a/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr
+++ b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr
@@ -2,31 +2,46 @@ error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:15
    |
 LL |     for &a in x.iter() {
-   |         --    ^^^^^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `a`
+   |          -    ^^^^^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     for &a in x.iter() {
+LL +     for a in x.iter() {
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:18:15
    |
 LL |     for &a in &f.a {
-   |         --    ^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `a` has type `Box<isize>`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `a`
+   |          -    ^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     for &a in &f.a {
+LL +     for a in &f.a {
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:15
    |
 LL |     for &a in x.iter() {
-   |         --    ^^^^^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `a` has type `Box<i32>`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `a`
+   |          -    ^^^^^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     for &a in x.iter() {
+LL +     for a in x.iter() {
+   |
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.fixed b/src/test/ui/borrowck/borrowck-issue-2657-2.fixed
new file mode 100644
index 00000000000..625e7c3cad5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-issue-2657-2.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+fn main() {
+
+    let x: Option<Box<_>> = Some(Box::new(1));
+
+    match x {
+      Some(ref y) => {
+        let _b = y; //~ ERROR cannot move out
+      }
+      _ => {}
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.rs b/src/test/ui/borrowck/borrowck-issue-2657-2.rs
index 7dbac02154a..f79a846e70e 100644
--- a/src/test/ui/borrowck/borrowck-issue-2657-2.rs
+++ b/src/test/ui/borrowck/borrowck-issue-2657-2.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 fn main() {
 
     let x: Option<Box<_>> = Some(Box::new(1));
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.stderr b/src/test/ui/borrowck/borrowck-issue-2657-2.stderr
index f9ba2ca416b..850bb9ae393 100644
--- a/src/test/ui/borrowck/borrowck-issue-2657-2.stderr
+++ b/src/test/ui/borrowck/borrowck-issue-2657-2.stderr
@@ -1,11 +1,14 @@
 error[E0507]: cannot move out of `*y` which is behind a shared reference
-  --> $DIR/borrowck-issue-2657-2.rs:7:18
+  --> $DIR/borrowck-issue-2657-2.rs:8:18
    |
 LL |         let _b = *y;
-   |                  ^^
-   |                  |
-   |                  move occurs because `*y` has type `Box<i32>`, which does not implement the `Copy` trait
-   |                  help: consider borrowing here: `&*y`
+   |                  ^^ move occurs because `*y` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -         let _b = *y;
+LL +         let _b = y;
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.fixed b/src/test/ui/borrowck/borrowck-move-error-with-note.fixed
new file mode 100644
index 00000000000..cf6c382a692
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-error-with-note.fixed
@@ -0,0 +1,56 @@
+// run-rustfix
+#![allow(unused)]
+enum Foo {
+    Foo1(Box<u32>, Box<u32>),
+    Foo2(Box<u32>),
+    Foo3,
+}
+
+
+
+fn blah() {
+    let f = &Foo::Foo1(Box::new(1), Box::new(2));
+    match f { //~ ERROR cannot move out of
+        Foo::Foo1(num1,
+                  num2) => (),
+        Foo::Foo2(num) => (),
+        Foo::Foo3 => ()
+    }
+}
+
+struct S {
+    f: String,
+    g: String
+}
+impl Drop for S {
+    fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+    match (S {f: "foo".to_string(), g: "bar".to_string()}) {
+        //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+        S {
+            f: ref _s,
+            g: ref _t
+        } => {}
+    }
+}
+
+// from issue-8064
+struct A {
+    a: Box<isize>,
+}
+
+fn free<T>(_: T) {}
+
+fn blah2() {
+    let a = &A { a: Box::new(1) };
+    match &a.a { //~ ERROR cannot move out of
+        n => {
+            free(n)
+        }
+    }
+    free(a)
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.rs b/src/test/ui/borrowck/borrowck-move-error-with-note.rs
index ef38cbb63a5..f336ac4f994 100644
--- a/src/test/ui/borrowck/borrowck-move-error-with-note.rs
+++ b/src/test/ui/borrowck/borrowck-move-error-with-note.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused)]
 enum Foo {
     Foo1(Box<u32>, Box<u32>),
     Foo2(Box<u32>),
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
index 96246d9ae1a..722c2c1443a 100644
--- a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
+++ b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr
@@ -1,8 +1,8 @@
 error[E0507]: cannot move out of `f` as enum variant `Foo1` which is behind a shared reference
-  --> $DIR/borrowck-move-error-with-note.rs:11:11
+  --> $DIR/borrowck-move-error-with-note.rs:13:11
    |
 LL |     match *f {
-   |           ^^ help: consider borrowing here: `&*f`
+   |           ^^
 LL |         Foo::Foo1(num1,
    |                   ---- data moved here
 LL |                   num2) => (),
@@ -11,9 +11,14 @@ LL |         Foo::Foo2(num) => (),
    |                   --- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the dereference here
+   |
+LL -     match *f {
+LL +     match f {
+   |
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-error-with-note.rs:28:11
+  --> $DIR/borrowck-move-error-with-note.rs:30:11
    |
 LL |     match (S {f: "foo".to_string(), g: "bar".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
@@ -24,17 +29,30 @@ LL |             g: _t
    |                -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |             f: ref _s,
+   |                +++
+help: consider borrowing the pattern binding
+   |
+LL |             g: ref _t
+   |                +++
 
 error[E0507]: cannot move out of `a.a` which is behind a shared reference
-  --> $DIR/borrowck-move-error-with-note.rs:46:11
+  --> $DIR/borrowck-move-error-with-note.rs:48:11
    |
 LL |     match a.a {
-   |           ^^^ help: consider borrowing here: `&a.a`
+   |           ^^^
 LL |         n => {
    |         -
    |         |
    |         data moved here
    |         move occurs because `n` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &a.a {
+   |           +
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
index 7ac095e808a..43fc102bd62 100644
--- a/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
+++ b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of `*x` which is behind a raw pointer
   --> $DIR/borrowck-move-from-unsafe-ptr.rs:2:13
    |
 LL |     let y = *x;
-   |             ^^
-   |             |
-   |             move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*x`
+   |             ^^ move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let y = *x;
+LL +     let y = x;
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.stderr b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.stderr
index 6b19f9d977e..21bd073321b 100644
--- a/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.stderr
+++ b/src/test/ui/borrowck/borrowck-move-in-irrefut-pat.stderr
@@ -3,30 +3,45 @@ error[E0507]: cannot move out of a shared reference
    |
 LL | fn arg_item(&_x: &String) {}
    |             ^--
-   |             ||
-   |             |data moved here
-   |             |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
-   |             help: consider removing the `&`: `_x`
+   |              |
+   |              data moved here
+   |              move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL - fn arg_item(&_x: &String) {}
+LL + fn arg_item(_x: &String) {}
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-move-in-irrefut-pat.rs:7:11
    |
 LL |     with(|&_x| ())
    |           ^--
-   |           ||
-   |           |data moved here
-   |           |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
-   |           help: consider removing the `&`: `_x`
+   |            |
+   |            data moved here
+   |            move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     with(|&_x| ())
+LL +     with(|_x| ())
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-move-in-irrefut-pat.rs:12:15
    |
 LL |     let &_x = &"hi".to_string();
-   |         ---   ^^^^^^^^^^^^^^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `_x`
+   |          --   ^^^^^^^^^^^^^^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &_x = &"hi".to_string();
+LL +     let _x = &"hi".to_string();
+   |
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
index 800f30b34e5..ecf5382e863 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
@@ -7,11 +7,8 @@ LL |     let _x = Rc::new(vec![1, 2]).into_iter();
    |              |                   value moved due to this method call
    |              move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves value
+note: `into_iter` takes ownership of the receiver `self`, which moves value
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
index 68994c2071b..599fa1e88df 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of an `Rc`
   --> $DIR/borrowck-move-out-of-overloaded-deref.rs:4:14
    |
 LL |     let _x = *Rc::new("hi".to_string());
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |              |
-   |              move occurs because value has type `String`, which does not implement the `Copy` trait
-   |              help: consider borrowing here: `&*Rc::new("hi".to_string())`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let _x = *Rc::new("hi".to_string());
+LL +     let _x = Rc::new("hi".to_string());
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed
new file mode 100644
index 00000000000..c463c655938
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed
@@ -0,0 +1,24 @@
+// run-rustfix
+#![allow(unused)]
+struct S {f:String}
+impl Drop for S {
+    fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+    match (S {f:"foo".to_string()}) {
+        //~^ ERROR [E0509]
+        S {f:ref _s} => {}
+    }
+}
+
+fn move_in_let() {
+    let S {f:ref _s} = S {f:"foo".to_string()};
+    //~^ ERROR [E0509]
+}
+
+fn move_in_fn_arg(S {f:ref _s}: S) {
+    //~^ ERROR [E0509]
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs
index a429f4bc33b..93183062d61 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused)]
 struct S {f:String}
 impl Drop for S {
     fn drop(&mut self) { println!("{}", self.f); }
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr
index 7b00ac9f1c3..58f706c65ff 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr
@@ -1,5 +1,5 @@
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:7:11
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:9:11
    |
 LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
@@ -9,18 +9,28 @@ LL |         S {f:_s} => {}
    |              |
    |              data moved here
    |              move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         S {f:ref _s} => {}
+   |              +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:14:20
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:16:20
    |
 LL |     let S {f:_s} = S {f:"foo".to_string()};
    |              --    ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |              |
    |              data moved here
    |              move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let S {f:ref _s} = S {f:"foo".to_string()};
+   |              +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:19
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:20:19
    |
 LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   ^^^^^--^
@@ -28,6 +38,11 @@ LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   |    data moved here
    |                   |    move occurs because `_s` has type `String`, which does not implement the `Copy` trait
    |                   cannot move out of here
+   |
+help: consider borrowing the pattern binding
+   |
+LL | fn move_in_fn_arg(S {f:ref _s}: S) {
+   |                        +++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed
new file mode 100644
index 00000000000..bc2ddf85fb4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed
@@ -0,0 +1,24 @@
+// run-rustfix
+#![allow(unused)]
+struct S(String);
+impl Drop for S {
+    fn drop(&mut self) { }
+}
+
+fn move_in_match() {
+    match S("foo".to_string()) {
+        //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+        S(ref _s) => {}
+    }
+}
+
+fn move_in_let() {
+    let S(ref _s) = S("foo".to_string());
+    //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn move_in_fn_arg(S(ref _s): S) {
+    //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs
index 5bd32f82ebc..f050bce8740 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused)]
 struct S(String);
 impl Drop for S {
     fn drop(&mut self) { }
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr
index f00181b7468..160a1f99f63 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr
@@ -1,5 +1,5 @@
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:7:11
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:9:11
    |
 LL |     match S("foo".to_string()) {
    |           ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
@@ -9,18 +9,28 @@ LL |         S(_s) => {}
    |           |
    |           data moved here
    |           move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         S(ref _s) => {}
+   |           +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:14:17
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:16:17
    |
 LL |     let S(_s) = S("foo".to_string());
    |           --    ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |           |
    |           data moved here
    |           move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let S(ref _s) = S("foo".to_string());
+   |           +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:19
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:20:19
    |
 LL | fn move_in_fn_arg(S(_s): S) {
    |                   ^^--^
@@ -28,6 +38,11 @@ LL | fn move_in_fn_arg(S(_s): S) {
    |                   | data moved here
    |                   | move occurs because `_s` has type `String`, which does not implement the `Copy` trait
    |                   cannot move out of here
+   |
+help: consider borrowing the pattern binding
+   |
+LL | fn move_in_fn_arg(S(ref _s): S) {
+   |                     +++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
index a865812cb4a..9ff20a1f46a 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
@@ -10,10 +10,10 @@ LL |                   Foo { string: b }] => {
    |                                 - ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~                 [Foo { string: a },
-LL ~                   Foo { string: b }] => {
+LL -                 &[Foo { string: a },
+LL +                 [Foo { string: a },
    |
 
 error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr
index 2b4293b433e..f5f4817e9bf 100644
--- a/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of index of `MyVec<Box<i32>>`
   --> $DIR/borrowck-overloaded-index-move-from-vec.rs:20:15
    |
 LL |     let bad = v[0];
-   |               ^^^^
-   |               |
-   |               move occurs because value has type `Box<i32>`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&v[0]`
+   |               ^^^^ move occurs because value has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let bad = &v[0];
+   |               +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
index 8a9296c5978..0e9284a2cad 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
@@ -37,7 +37,7 @@ fn c() {
         &mut [_a,
         //~^ NOTE data moved here
         //~| NOTE move occurs because `_a` has type
-        //~| HELP consider removing the `&mut`
+        //~| HELP consider removing the mutable borrow
             ..
         ] => {
         }
@@ -56,7 +56,7 @@ fn d() {
         //~^ ERROR cannot move out
         //~| NOTE cannot move out
         &mut [
-        //~^ HELP consider removing the `&mut`
+        //~^ HELP consider removing the mutable borrow
          _b] => {}
         //~^ NOTE data moved here
         //~| NOTE move occurs because `_b` has type
@@ -79,7 +79,7 @@ fn e() {
         //~^ NOTE data moved here
         //~| NOTE and here
         //~| NOTE and here
-        //~| HELP consider removing the `&mut`
+        //~| HELP consider removing the mutable borrow
         _ => {}
     }
     let a = vec[0]; //~ ERROR cannot move out
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
index c3bcb7de65d..0dc5e64e4ff 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
@@ -34,14 +34,10 @@ LL |         &mut [_a,
    |               data moved here
    |               move occurs because `_a` has type `Box<isize>`, which does not implement the `Copy` trait
    |
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         [_a,
-LL +
-LL +
-LL +
-LL +             ..
-LL ~         ] => {
+LL -         &mut [_a,
+LL +         [_a,
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
@@ -52,7 +48,11 @@ LL |     let a = vec[0];
    |             |
    |             cannot move out of here
    |             move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&vec[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &vec[0];
+   |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:55:11
@@ -66,11 +66,10 @@ LL |          _b] => {}
    |          data moved here
    |          move occurs because `_b` has type `Box<isize>`, which does not implement the `Copy` trait
    |
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         [
-LL +
-LL ~          _b] => {}
+LL -         &mut [
+LL +         [
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
@@ -81,7 +80,11 @@ LL |     let a = vec[0];
    |             |
    |             cannot move out of here
    |             move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&vec[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &vec[0];
+   |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:74:11
@@ -90,14 +93,17 @@ LL |     match vec {
    |           ^^^ cannot move out of here
 ...
 LL |         &mut [_a, _b, _c] => {}
-   |         -----------------
-   |         |     |   |   |
-   |         |     |   |   ...and here
-   |         |     |   ...and here
-   |         |     data moved here
-   |         help: consider removing the `&mut`: `[_a, _b, _c]`
+   |               --  --  -- ...and here
+   |               |   |
+   |               |   ...and here
+   |               data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut [_a, _b, _c] => {}
+LL +         [_a, _b, _c] => {}
+   |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:85:13
@@ -107,7 +113,11 @@ LL |     let a = vec[0];
    |             |
    |             cannot move out of here
    |             move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&vec[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &vec[0];
+   |             +
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/borrowck/issue-104639-lifetime-order.rs b/src/test/ui/borrowck/issue-104639-lifetime-order.rs
new file mode 100644
index 00000000000..db1f8f8d588
--- /dev/null
+++ b/src/test/ui/borrowck/issue-104639-lifetime-order.rs
@@ -0,0 +1,10 @@
+// edition:2018
+// check-pass
+
+#![allow(dead_code)]
+async fn fail<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, {}
+async fn pass<'a, 'c, 'b>(_: &'static str) where 'a: 'c, 'b: 'c, {}
+async fn pass2<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, 'c: 'a, {}
+async fn pass3<'a, 'b, 'c>(_: &'static str) where 'a: 'b, 'b: 'c, 'c: 'a, {}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/issue-17718-static-move.stderr b/src/test/ui/borrowck/issue-17718-static-move.stderr
index 984534bfb8b..65aea5b1834 100644
--- a/src/test/ui/borrowck/issue-17718-static-move.stderr
+++ b/src/test/ui/borrowck/issue-17718-static-move.stderr
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of static item `FOO`
   --> $DIR/issue-17718-static-move.rs:6:14
    |
 LL |     let _a = FOO;
-   |              ^^^
-   |              |
-   |              move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
-   |              help: consider borrowing here: `&FOO`
+   |              ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let _a = &FOO;
+   |              +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/issue-20801.stderr b/src/test/ui/borrowck/issue-20801.stderr
index d276231dc0c..215bf010063 100644
--- a/src/test/ui/borrowck/issue-20801.stderr
+++ b/src/test/ui/borrowck/issue-20801.stderr
@@ -2,37 +2,49 @@ error[E0507]: cannot move out of a mutable reference
   --> $DIR/issue-20801.rs:26:22
    |
 LL |     let a = unsafe { *mut_ref() };
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*mut_ref()`
+   |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let a = unsafe { *mut_ref() };
+LL +     let a = unsafe { mut_ref() };
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/issue-20801.rs:29:22
    |
 LL |     let b = unsafe { *imm_ref() };
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*imm_ref()`
+   |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let b = unsafe { *imm_ref() };
+LL +     let b = unsafe { imm_ref() };
+   |
 
 error[E0507]: cannot move out of a raw pointer
   --> $DIR/issue-20801.rs:32:22
    |
 LL |     let c = unsafe { *mut_ptr() };
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*mut_ptr()`
+   |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let c = unsafe { *mut_ptr() };
+LL +     let c = unsafe { mut_ptr() };
+   |
 
 error[E0507]: cannot move out of a raw pointer
   --> $DIR/issue-20801.rs:35:22
    |
 LL |     let d = unsafe { *const_ptr() };
-   |                      ^^^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*const_ptr()`
+   |                      ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let d = unsafe { *const_ptr() };
+LL +     let d = unsafe { const_ptr() };
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-29166.rs b/src/test/ui/borrowck/issue-29166.rs
index ca819ba39a2..ca819ba39a2 100644
--- a/src/test/ui/issues/issue-29166.rs
+++ b/src/test/ui/borrowck/issue-29166.rs
diff --git a/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr
index eb41af1cea8..8d4918867f7 100644
--- a/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr
+++ b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of static item `X`
   --> $DIR/issue-47215-ice-from-drop-elab.rs:17:21
    |
 LL |         let mut x = X;
-   |                     ^
-   |                     |
-   |                     move occurs because `X` has type `AtomicUsize`, which does not implement the `Copy` trait
-   |                     help: consider borrowing here: `&X`
+   |                     ^ move occurs because `X` has type `AtomicUsize`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let mut x = &X;
+   |                     +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-51301.rs b/src/test/ui/borrowck/issue-51301.rs
index 7e0a5190fcd..7e0a5190fcd 100644
--- a/src/test/ui/issues/issue-51301.rs
+++ b/src/test/ui/borrowck/issue-51301.rs
diff --git a/src/test/ui/issues/issue-51301.stderr b/src/test/ui/borrowck/issue-51301.stderr
index f3decf7a991..6ec920cb81f 100644
--- a/src/test/ui/issues/issue-51301.stderr
+++ b/src/test/ui/borrowck/issue-51301.stderr
@@ -6,6 +6,11 @@ LL |             .find(|(&event_type, _)| event == event_type)
    |                      |
    |                      data moved here
    |                      move occurs because `event_type` has type `EventType`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |             .find(|(&ref event_type, _)| event == event_type)
+   |                      +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/issue-51415.fixed b/src/test/ui/borrowck/issue-51415.fixed
new file mode 100644
index 00000000000..92943f6c9ec
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51415.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+// Regression test for #51415: match default bindings were failing to
+// see the "move out" implied by `&s` below.
+
+fn main() {
+    let a = vec![String::from("a")];
+    let opt = a.iter().enumerate().find(|(_, &ref s)| {
+        //~^ ERROR cannot move out
+        *s == String::from("d")
+    }).map(|(i, _)| i);
+    println!("{:?}", opt);
+}
diff --git a/src/test/ui/borrowck/issue-51415.rs b/src/test/ui/borrowck/issue-51415.rs
index f031308fb78..56ed57a61a0 100644
--- a/src/test/ui/borrowck/issue-51415.rs
+++ b/src/test/ui/borrowck/issue-51415.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 // Regression test for #51415: match default bindings were failing to
 // see the "move out" implied by `&s` below.
 
diff --git a/src/test/ui/borrowck/issue-51415.stderr b/src/test/ui/borrowck/issue-51415.stderr
index a88819efcf7..0d486b45592 100644
--- a/src/test/ui/borrowck/issue-51415.stderr
+++ b/src/test/ui/borrowck/issue-51415.stderr
@@ -1,11 +1,16 @@
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/issue-51415.rs:6:42
+  --> $DIR/issue-51415.rs:7:42
    |
 LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
    |                                          ^^^^^-^
    |                                               |
    |                                               data moved here
    |                                               move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &ref s)| {
+   |                                               +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
index 1f9cbdb7342..99c63e4db50 100644
--- a/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
+++ b/src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of `*array` which is behind a shared reference
   --> $DIR/issue-54597-reject-move-out-of-borrow-via-pat.rs:14:13
    |
 LL |             *array
-   |             ^^^^^^
-   |             |
-   |             move occurs because `*array` has type `Vec<Value>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*array`
+   |             ^^^^^^ move occurs because `*array` has type `Vec<Value>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -             *array
+LL +             array
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/issue-83760.stderr b/src/test/ui/borrowck/issue-83760.stderr
index 2552fff860c..a585bff0c65 100644
--- a/src/test/ui/borrowck/issue-83760.stderr
+++ b/src/test/ui/borrowck/issue-83760.stderr
@@ -27,11 +27,8 @@ LL |         foo = Some(Struct);
 LL |     let _y = foo;
    |              ^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `foo`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap(self) -> T {
-   |                         ^^^^
 
 error[E0382]: use of moved value: `foo`
   --> $DIR/issue-83760.rs:37:14
@@ -55,11 +52,8 @@ LL |         foo = Some(Struct);
 LL |     } else if true {
 LL |         foo = Some(Struct);
    |         ^^^^^^^^^^^^^^^^^^
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `foo`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap(self) -> T {
-   |                         ^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/issue-87456-point-to-closure.stderr b/src/test/ui/borrowck/issue-87456-point-to-closure.stderr
index 039575a8d79..afd141125ac 100644
--- a/src/test/ui/borrowck/issue-87456-point-to-closure.stderr
+++ b/src/test/ui/borrowck/issue-87456-point-to-closure.stderr
@@ -8,10 +8,12 @@ LL |     take_mut(|| {
    |              -- captured by this `FnMut` closure
 LL |
 LL |         let _foo: String = val;
-   |                            ^^^
-   |                            |
-   |                            move occurs because `val` has type `String`, which does not implement the `Copy` trait
-   |                            help: consider borrowing here: `&val`
+   |                            ^^^ move occurs because `val` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let _foo: String = &val;
+   |                            +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/move-error-snippets.stderr b/src/test/ui/borrowck/move-error-snippets.stderr
index 984981ce2ea..8ac711e9e59 100644
--- a/src/test/ui/borrowck/move-error-snippets.stderr
+++ b/src/test/ui/borrowck/move-error-snippets.stderr
@@ -2,10 +2,7 @@ error[E0507]: cannot move out of static item `D`
   --> $DIR/move-error-snippets-ext.rs:5:17
    |
 LL |         let a = $c;
-   |                 ^^
-   |                 |
-   |                 move occurs because `D` has type `A`, which does not implement the `Copy` trait
-   |                 help: consider borrowing here: `&$c`
+   |                 ^^ move occurs because `D` has type `A`, which does not implement the `Copy` trait
    |
   ::: $DIR/move-error-snippets.rs:21:1
    |
@@ -13,6 +10,10 @@ LL | sss!();
    | ------ in this macro invocation
    |
    = note: this error originates in the macro `aaa` which comes from the expansion of the macro `sss` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider borrowing here
+   |
+LL |         let a = &$c;
+   |                 +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr
index 13a2005e2ef..ecd916a59fc 100644
--- a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr
+++ b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr
@@ -9,11 +9,8 @@ LL |
 LL |     fill_segment(state);
    |                  ^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `state`
+note: `into_iter` takes ownership of the receiver `self`, which moves `state`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider creating a fresh reborrow of `state` here
    |
 LL |     for _ in &mut *state {}
diff --git a/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr b/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
index b1af090aec2..4621d879351 100644
--- a/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
+++ b/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
@@ -8,11 +8,8 @@ LL |     cb.map(|cb| cb());
    |     help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |     move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `*cb`
+note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `*cb`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn map<U, F>(self, f: F) -> Option<U>
-   |                            ^^^^
 
 error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
   --> $DIR/suggest-as-ref-on-mut-closure.rs:12:26
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
index 0c151b09707..b1367c65218 100644
--- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
@@ -10,11 +10,8 @@ LL |         y.into_iter();
    |         |
    |         move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `into_iter` takes ownership of the receiver `self`, which moves `y`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/box/into-boxed-slice-fail.stderr b/src/test/ui/box/into-boxed-slice-fail.stderr
index de654fdc1a4..f102f666dc2 100644
--- a/src/test/ui/box/into-boxed-slice-fail.stderr
+++ b/src/test/ui/box/into-boxed-slice-fail.stderr
@@ -9,9 +9,6 @@ LL |     let _ = Box::into_boxed_slice(boxed_slice);
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Box::<T, A>::into_boxed_slice`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T, A: Allocator> Box<T, A> {
-   |      ^ required by this bound in `Box::<T, A>::into_boxed_slice`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/into-boxed-slice-fail.rs:7:13
@@ -33,9 +30,6 @@ LL |     let _ = Box::into_boxed_slice(boxed_trait);
    = help: the trait `Sized` is not implemented for `dyn Debug`
 note: required by a bound in `Box::<T, A>::into_boxed_slice`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T, A: Allocator> Box<T, A> {
-   |      ^ required by this bound in `Box::<T, A>::into_boxed_slice`
 
 error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
   --> $DIR/into-boxed-slice-fail.rs:11:13
diff --git a/src/test/ui/by-move-pattern-binding.rs b/src/test/ui/by-move-pattern-binding.rs
index d4c9f23164f..f68d181291d 100644
--- a/src/test/ui/by-move-pattern-binding.rs
+++ b/src/test/ui/by-move-pattern-binding.rs
@@ -19,4 +19,11 @@ fn main() {
         &E::Foo => {}
         &E::Bar(ref identifier) => println!("{}", *identifier)
     };
+    if let &E::Bar(identifier) = &s.x { //~ ERROR cannot move
+        f(identifier.clone());
+    };
+    let &E::Bar(identifier) = &s.x else { //~ ERROR cannot move
+        return;
+    };
+    f(identifier.clone());
 }
diff --git a/src/test/ui/by-move-pattern-binding.stderr b/src/test/ui/by-move-pattern-binding.stderr
index 0012f67cfa1..203e37dc387 100644
--- a/src/test/ui/by-move-pattern-binding.stderr
+++ b/src/test/ui/by-move-pattern-binding.stderr
@@ -5,12 +5,47 @@ LL |     match &s.x {
    |           ^^^^
 LL |         &E::Foo => {}
 LL |         &E::Bar(identifier) => f(identifier.clone())
-   |         -------------------
-   |         |       |
-   |         |       data moved here
-   |         |       move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `E::Bar(identifier)`
+   |                 ----------
+   |                 |
+   |                 data moved here
+   |                 move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &E::Bar(identifier) => f(identifier.clone())
+LL +         E::Bar(identifier) => f(identifier.clone())
+   |
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/by-move-pattern-binding.rs:22:34
+   |
+LL |     if let &E::Bar(identifier) = &s.x {
+   |                    ----------    ^^^^
+   |                    |
+   |                    data moved here
+   |                    move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let &E::Bar(identifier) = &s.x {
+LL +     if let E::Bar(identifier) = &s.x {
+   |
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/by-move-pattern-binding.rs:25:31
+   |
+LL |     let &E::Bar(identifier) = &s.x else {
+   |                 ----------    ^^^^
+   |                 |
+   |                 data moved here
+   |                 move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &E::Bar(identifier) = &s.x else {
+LL +     let E::Bar(identifier) = &s.x else {
+   |
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/c-variadic/issue-86053-1.stderr b/src/test/ui/c-variadic/issue-86053-1.stderr
index 075bd1fc488..d1f13d52362 100644
--- a/src/test/ui/c-variadic/issue-86053-1.stderr
+++ b/src/test/ui/c-variadic/issue-86053-1.stderr
@@ -63,11 +63,9 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
    |                                                ^
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
    |
 help: a trait with a similar name exists
    |
diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr
index 4804df13340..eda867f4159 100644
--- a/src/test/ui/chalkify/bugs/async.stderr
+++ b/src/test/ui/chalkify/bugs/async.stderr
@@ -14,9 +14,6 @@ LL | | }
    = note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |                                      ^^^^^^^^^^^^^^^^^^ required by this bound in `identity_future`
 
 error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output` cannot be known at compilation time
   --> $DIR/async.rs:7:29
@@ -30,9 +27,6 @@ LL | | }
    = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output`
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |                              ^ required by this bound in `identity_future`
 
 error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
   --> $DIR/async.rs:7:25
diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr
index 31939f7f6db..b13700a4ea5 100644
--- a/src/test/ui/check-static-values-constraints.stderr
+++ b/src/test/ui/check-static-values-constraints.stderr
@@ -58,10 +58,12 @@ error[E0507]: cannot move out of static item `x`
   --> $DIR/check-static-values-constraints.rs:110:45
    |
 LL |     let y = { static x: Box<isize> = box 3; x };
-   |                                             ^
-   |                                             |
-   |                                             move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
-   |                                             help: consider borrowing here: `&x`
+   |                                             ^ move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let y = { static x: Box<isize> = box 3; &x };
+   |                                             +
 
 error[E0010]: allocations are not allowed in statics
   --> $DIR/check-static-values-constraints.rs:110:38
diff --git a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
index d5432755cfe..7a04ed7381e 100644
--- a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
+++ b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
@@ -6,8 +6,8 @@ LL |     with_closure(|x: u32, y| {});
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     with_closure(|x: u32, y: _| {});
-   |                            +++
+LL |     with_closure(|x: u32, y: /* Type */| {});
+   |                            ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-expected.stderr b/src/test/ui/closures/closure-expected.stderr
index 7ffe3c1ef95..87a5d67a420 100644
--- a/src/test/ui/closures/closure-expected.stderr
+++ b/src/test/ui/closures/closure-expected.stderr
@@ -10,9 +10,6 @@ LL |     let y = x.or_else(4);
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `Option::<T>::or_else`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce() -> Option<T>,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::or_else`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-move-sync.stderr b/src/test/ui/closures/closure-move-sync.stderr
index a2ca06b4e6e..64e3b51ea71 100644
--- a/src/test/ui/closures/closure-move-sync.stderr
+++ b/src/test/ui/closures/closure-move-sync.stderr
@@ -19,9 +19,6 @@ LL |     let t = thread::spawn(|| {
    |                           ^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL |     F: Send + 'static,
-   |        ^^^^ required by this bound in `spawn`
 
 error[E0277]: `Sender<()>` cannot be shared between threads safely
   --> $DIR/closure-move-sync.rs:18:19
@@ -40,9 +37,6 @@ LL |     thread::spawn(|| tx.send(()).unwrap());
    |                   ^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL |     F: Send + 'static,
-   |        ^^^^ required by this bound in `spawn`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/closures/closure-return-type-must-be-sized.stderr b/src/test/ui/closures/closure-return-type-must-be-sized.stderr
index b07425bd825..d4fc723fa81 100644
--- a/src/test/ui/closures/closure-return-type-must-be-sized.stderr
+++ b/src/test/ui/closures/closure-return-type-must-be-sized.stderr
@@ -19,7 +19,7 @@ note: required by a bound in `a::bar`
   --> $DIR/closure-return-type-must-be-sized.rs:14:19
    |
 LL |     pub fn bar<F: FnOnce() -> R, R: ?Sized>() {}
-   |                   ^^^^^^^^^^^^^ required by this bound in `a::bar`
+   |                   ^^^^^^^^^^^^^ required by this bound in `bar`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
   --> $DIR/closure-return-type-must-be-sized.rs:56:5
@@ -51,7 +51,7 @@ note: required by a bound in `b::bar`
   --> $DIR/closure-return-type-must-be-sized.rs:28:19
    |
 LL |     pub fn bar<F: Fn() -> R, R: ?Sized>() {}
-   |                   ^^^^^^^^^ required by this bound in `b::bar`
+   |                   ^^^^^^^^^ required by this bound in `bar`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
   --> $DIR/closure-return-type-must-be-sized.rs:63:5
@@ -83,7 +83,7 @@ note: required by a bound in `c::bar`
   --> $DIR/closure-return-type-must-be-sized.rs:42:19
    |
 LL |     pub fn bar<F: FnMut() -> R, R: ?Sized>() {}
-   |                   ^^^^^^^^^^^^ required by this bound in `c::bar`
+   |                   ^^^^^^^^^^^^ required by this bound in `bar`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
   --> $DIR/closure-return-type-must-be-sized.rs:70:5
diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.stderr b/src/test/ui/closures/coerce-unsafe-to-closure.stderr
index 6ce63e829b3..449cd0b3177 100644
--- a/src/test/ui/closures/coerce-unsafe-to-closure.stderr
+++ b/src/test/ui/closures/coerce-unsafe-to-closure.stderr
@@ -10,9 +10,6 @@ LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> U,
-   |            ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr
index 4c24a54bbbe..9ba24c7a886 100644
--- a/src/test/ui/closures/issue-52437.stderr
+++ b/src/test/ui/closures/issue-52437.stderr
@@ -12,8 +12,8 @@ LL |     [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
-   |                               +++
+LL |     [(); &(&'static: loop { |x: /* Type */| {}; }) as *const _ as usize]
+   |                               ++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/closures/issue-78720.stderr b/src/test/ui/closures/issue-78720.stderr
index da3f539a007..1e860d32b2a 100644
--- a/src/test/ui/closures/issue-78720.stderr
+++ b/src/test/ui/closures/issue-78720.stderr
@@ -9,11 +9,9 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL |     _func: F,
    |            ^
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
    |
 help: a trait with a similar name exists
    |
diff --git a/src/test/ui/closures/issue-87461.stderr b/src/test/ui/closures/issue-87461.stderr
index 0e788a16eb0..72337892734 100644
--- a/src/test/ui/closures/issue-87461.stderr
+++ b/src/test/ui/closures/issue-87461.stderr
@@ -8,9 +8,6 @@ LL |     Ok(())
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-87461.rs:17:8
@@ -22,9 +19,6 @@ LL |     Ok(())
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-87461.rs:26:12
@@ -36,9 +30,6 @@ LL |         Ok(())
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/closures/issue-90871.stderr b/src/test/ui/closures/issue-90871.stderr
index a482750fbd0..4a578b4d7f5 100644
--- a/src/test/ui/closures/issue-90871.stderr
+++ b/src/test/ui/closures/issue-90871.stderr
@@ -3,11 +3,9 @@ error[E0412]: cannot find type `n` in this scope
    |
 LL |     type_ascribe!(2, n([u8; || 1]))
    |                      ^ help: a trait with a similar name exists: `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0308]: mismatched types
   --> $DIR/issue-90871.rs:4:29
diff --git a/src/test/ui/closures/multiple-fn-bounds.stderr b/src/test/ui/closures/multiple-fn-bounds.stderr
index eefc123fed7..da26302c9d8 100644
--- a/src/test/ui/closures/multiple-fn-bounds.stderr
+++ b/src/test/ui/closures/multiple-fn-bounds.stderr
@@ -2,8 +2,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/multiple-fn-bounds.rs:10:5
    |
 LL |     foo(move |x| v);
-   |     ^^^ -------- found signature defined here
-   |     |
+   |     ^^^ --------
+   |     |   |     |
+   |     |   |     help: do not borrow the argument: `char`
+   |     |   found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `fn(char) -> _`
diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr
index 080f6c39449..e0e369124a4 100644
--- a/src/test/ui/codemap_tests/tab_3.stderr
+++ b/src/test/ui/codemap_tests/tab_3.stderr
@@ -9,11 +9,8 @@ LL |     {
 LL |         println!("{:?}", some_vec);
    |                          ^^^^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `some_vec`
+note: `into_iter` takes ownership of the receiver `self`, which moves `some_vec`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider cloning the value if the performance cost is acceptable
    |
diff --git a/src/test/ui/confuse-field-and-method/issue-33784.stderr b/src/test/ui/confuse-field-and-method/issue-33784.stderr
index 34debb68317..3906d64c946 100644
--- a/src/test/ui/confuse-field-and-method/issue-33784.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-33784.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
+error[E0599]: no method named `closure` found for reference `&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
   --> $DIR/issue-33784.rs:27:7
    |
 LL |     p.closure();
@@ -9,7 +9,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (p.closure)();
    |     +         +
 
-error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
+error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
   --> $DIR/issue-33784.rs:29:7
    |
 LL |     q.fn_ptr();
diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
index 688db695fa8..13ea4a295af 100644
--- a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
+++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
@@ -5,11 +5,14 @@ LL |     let y = Mask::<_, _>::splat(false);
    |         ^   ------------------- type must be known at this point
    |
    = note: cannot satisfy `_: MaskElement`
+   = help: the following types implement trait `MaskElement`:
+             i16
+             i32
+             i64
+             i8
+             isize
 note: required by a bound in `Mask::<T, LANES>::splat`
   --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
-   |
-LL |     T: MaskElement,
-   |        ^^^^^^^^^^^ required by this bound in `Mask::<T, LANES>::splat`
 help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
    |
 LL |     let y: Mask<_, LANES> = Mask::<_, _>::splat(false);
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr
index ada1050d35f..cdf97bd88fd 100644
--- a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr
@@ -14,7 +14,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:17:5
@@ -28,7 +28,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error: unconstrained generic constant
   --> $DIR/abstract-const-as-cast-3.rs:20:19
@@ -46,7 +46,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:20:5
@@ -60,7 +60,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:23:5
@@ -74,7 +74,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:25:5
@@ -88,7 +88,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error: unconstrained generic constant
   --> $DIR/abstract-const-as-cast-3.rs:35:19
@@ -106,7 +106,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:35:5
@@ -120,7 +120,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error: unconstrained generic constant
   --> $DIR/abstract-const-as-cast-3.rs:38:19
@@ -138,7 +138,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:38:5
@@ -152,7 +152,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:41:5
@@ -166,7 +166,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:43:5
@@ -180,7 +180,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs b/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs
new file mode 100644
index 00000000000..e28ba3b1ada
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs
@@ -0,0 +1,15 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Combination<const STRATEGIES: usize>;
+
+impl<const STRATEGIES: usize> Combination<STRATEGIES> {
+    fn and<M>(self) -> Combination<{ STRATEGIES + 1 }> {
+        Combination
+    }
+}
+
+pub fn main() {
+    Combination::<0>.and::<_>().and::<_>();
+    //~^ ERROR: type annotations needed
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr
new file mode 100644
index 00000000000..0be4c43daac
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-105608.rs:13:22
+   |
+LL |     Combination::<0>.and::<_>().and::<_>();
+   |                      ^^^ cannot infer type of the type parameter `M` declared on the associated function `and`
+   |
+help: consider specifying the generic argument
+   |
+LL |     Combination::<0>.and::<_>().and::<_>();
+   |                         ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
index 4d0d0253f1b..0af5493f816 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
@@ -40,7 +40,17 @@ error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True
 LL |     IsLessOrEqual<I, 8>: True,
    |                          ^^^^
    |
-   = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
+note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
+  --> $DIR/issue-72787.rs:10:1
+   |
+LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     IsLessOrEqual<I, 8>: True,
+   |                          ^^^^
+...
+LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+   |                                          ^^^^
 
 error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True`
   --> $DIR/issue-72787.rs:21:26
@@ -48,7 +58,17 @@ error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True
 LL |     IsLessOrEqual<I, 8>: True,
    |                          ^^^^
    |
-   = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
+note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
+  --> $DIR/issue-72787.rs:10:1
+   |
+LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     IsLessOrEqual<I, 8>: True,
+   |                          ^^^^
+...
+LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+   |                                          ^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr
index bf1b411ee7c..a08c9912527 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ size_of called on unsized type `dyn Debug`
+   = note: size_of called on unsized type `dyn Debug`
    |
 note: inside `std::mem::size_of::<dyn Debug>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `Inline::<dyn Debug>::{constant#0}`
   --> $DIR/issue-80742.rs:22:10
    |
@@ -23,11 +19,9 @@ LL | struct Inline<T>
 ...
 LL |     let dst = Inline::<dyn Debug>::new(0);
    |                                    ^^^ function or associated item cannot be called on `Inline<dyn Debug>` due to unsatisfied trait bounds
+  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL | pub trait Debug {
-   | --------------- doesn't satisfy `dyn Debug: Sized`
+   = note: doesn't satisfy `dyn Debug: Sized`
    |
    = note: the following trait bounds were not satisfied:
            `dyn Debug: Sized`
@@ -35,14 +29,10 @@ LL | pub trait Debug {
 error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ size_of called on unsized type `dyn Debug`
+   = note: size_of called on unsized type `dyn Debug`
    |
 note: inside `std::mem::size_of::<dyn Debug>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `Inline::<dyn Debug>::{constant#0}`
   --> $DIR/issue-80742.rs:14:10
    |
diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
index d955b4f9651..8c76ca69029 100644
--- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
+++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
@@ -4,11 +4,6 @@ error[E0107]: this associated function takes 0 generic arguments but 1 generic a
 LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
    |                       ^^^^^^^^ expected 0 generic arguments
    |
-note: associated function defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn try_into(self) -> Result<T, Self::Error>;
-   |        ^^^^^^^^
 help: consider moving this generic argument to the `TryInto` trait, which takes up to 1 argument
    |
 LL |     let _: u32 = TryInto::<32>::try_into(5i32).unwrap();
diff --git a/src/test/ui/const-generics/invalid-constant-in-args.stderr b/src/test/ui/const-generics/invalid-constant-in-args.stderr
index 1400d2bf5a7..993b63518e4 100644
--- a/src/test/ui/const-generics/invalid-constant-in-args.stderr
+++ b/src/test/ui/const-generics/invalid-constant-in-args.stderr
@@ -5,12 +5,6 @@ LL |     let _: Cell<&str, "a"> = Cell::new("");
    |            ^^^^       --- help: remove this generic argument
    |            |
    |            expected 1 generic argument
-   |
-note: struct defined here, with 1 generic parameter: `T`
-  --> $SRC_DIR/core/src/cell.rs:LL:COL
-   |
-LL | pub struct Cell<T: ?Sized> {
-   |            ^^^^ -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issue-105689.rs b/src/test/ui/const-generics/issue-105689.rs
new file mode 100644
index 00000000000..4237b3cad8e
--- /dev/null
+++ b/src/test/ui/const-generics/issue-105689.rs
@@ -0,0 +1,14 @@
+// check-pass
+// edition:2021
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+#[allow(unused)]
+async fn foo<'a>() {
+    let _data = &mut [0u8; { 1 + 4 }];
+    bar().await
+}
+
+async fn bar() {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-83249.stderr b/src/test/ui/const-generics/issues/issue-83249.stderr
index 362b8554b2f..7491fdc8a69 100644
--- a/src/test/ui/const-generics/issues/issue-83249.stderr
+++ b/src/test/ui/const-generics/issues/issue-83249.stderr
@@ -6,8 +6,8 @@ LL |     let _ = foo([0; 1]);
    |
 help: consider giving this pattern a type
    |
-LL |     let _: _ = foo([0; 1]);
-   |          +++
+LL |     let _: /* Type */ = foo([0; 1]);
+   |          ++++++++++++
 
 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 563f3ffd674..0079bb3aad6 100644
--- a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
+++ b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
@@ -1,14 +1,10 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `std::slice::from_raw_parts::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S0`
   --> $DIR/forbidden_slices.rs:18:34
    |
@@ -18,14 +14,10 @@ LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `std::slice::from_raw_parts::<'_, ()>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S1`
   --> $DIR/forbidden_slices.rs:19:33
    |
@@ -35,14 +27,10 @@ LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   = note: dereferencing pointer failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `std::slice::from_raw_parts::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S2`
   --> $DIR/forbidden_slices.rs:22:34
    |
@@ -57,7 +45,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
    |
    = 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: 4) {
-               ╾─ALLOC_ID─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -69,7 +57,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -80,31 +68,27 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
    |
    = 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: 4) {
-               ╾─ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:32:1
    |
 LL | pub static S7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
    |
    = 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: 4) {
-               ╾─A_ID+0x1─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID+0x2╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   = note: dereferencing pointer failed: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
 note: inside `std::slice::from_raw_parts::<'_, u64>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S8`
   --> $DIR/forbidden_slices.rs:43:5
    |
@@ -114,19 +98,12 @@ LL |     from_raw_parts(ptr, 1)
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R0`
   --> $DIR/forbidden_slices.rs:46:34
    |
@@ -136,19 +113,12 @@ LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, ()>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R1`
   --> $DIR/forbidden_slices.rs:47:33
    |
@@ -159,19 +129,12 @@ LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u32>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u32>::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { self.offset(count as isize) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R2`
   --> $DIR/forbidden_slices.rs:50:25
    |
@@ -186,7 +149,7 @@ LL | pub static R4: &[u8] = unsafe {
    |
    = 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: 4) {
-               ╾ALLOC_ID─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -198,7 +161,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -209,38 +172,35 @@ LL | pub static R6: &[bool] = unsafe {
    |
    = 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: 4) {
-               ╾ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/forbidden_slices.rs:67:1
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL | pub static R7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   = note: accessing memory with alignment 1, but alignment 2 is required
    |
-   = 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: 4) {
-               ╾A_ID+0x1─╼ 04 00 00 00                         │ ╾──╼....
-           }
+note: inside `std::slice::from_raw_parts::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `from_ptr_range::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R7`
+  --> $DIR/forbidden_slices.rs:69:5
+   |
+LL |     from_ptr_range(ptr..ptr.add(4))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u64>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u64>::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { self.offset(count as isize) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R8`
-  --> $DIR/forbidden_slices.rs:74:25
+  --> $DIR/forbidden_slices.rs:73:25
    |
 LL |     from_ptr_range(ptr..ptr.add(1))
    |                         ^^^^^^^^^^
@@ -248,21 +208,14 @@ LL |     from_ptr_range(ptr..ptr.add(1))
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R9`
-  --> $DIR/forbidden_slices.rs:79:34
+  --> $DIR/forbidden_slices.rs:78:34
    |
 LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -270,21 +223,14 @@ LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).ad
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R10`
-  --> $DIR/forbidden_slices.rs:80:35
+  --> $DIR/forbidden_slices.rs:79:35
    |
 LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
index 43529d57f40..f4f9fe69516 100644
--- a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
+++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
@@ -1,14 +1,10 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `std::slice::from_raw_parts::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S0`
   --> $DIR/forbidden_slices.rs:18:34
    |
@@ -18,14 +14,10 @@ LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `std::slice::from_raw_parts::<'_, ()>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S1`
   --> $DIR/forbidden_slices.rs:19:33
    |
@@ -35,14 +27,10 @@ LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   = note: dereferencing pointer failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `std::slice::from_raw_parts::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S2`
   --> $DIR/forbidden_slices.rs:22:34
    |
@@ -57,7 +45,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
    |
    = 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: 16, align: 8) {
-               ╾───────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -69,7 +57,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -80,31 +68,27 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
    |
    = 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: 16, align: 8) {
-               ╾───────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:32:1
    |
 LL | pub static S7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
    |
    = 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: 16, align: 8) {
-               ╾─────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID+0x2╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   = note: dereferencing pointer failed: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
 note: inside `std::slice::from_raw_parts::<'_, u64>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `S8`
   --> $DIR/forbidden_slices.rs:43:5
    |
@@ -114,19 +98,12 @@ LL |     from_raw_parts(ptr, 1)
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R0`
   --> $DIR/forbidden_slices.rs:46:34
    |
@@ -136,19 +113,12 @@ LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, ()>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R1`
   --> $DIR/forbidden_slices.rs:47:33
    |
@@ -159,19 +129,12 @@ LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u32>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u32>::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { self.offset(count as isize) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R2`
   --> $DIR/forbidden_slices.rs:50:25
    |
@@ -186,7 +149,7 @@ LL | pub static R4: &[u8] = unsafe {
    |
    = 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: 16, align: 8) {
-               ╾──────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -198,7 +161,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -209,38 +172,35 @@ LL | pub static R6: &[bool] = unsafe {
    |
    = 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: 16, align: 8) {
-               ╾──────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/forbidden_slices.rs:67:1
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL | pub static R7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   = note: accessing memory with alignment 1, but alignment 2 is required
    |
-   = 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: 16, align: 8) {
-               ╾────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
-           }
+note: inside `std::slice::from_raw_parts::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `from_ptr_range::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R7`
+  --> $DIR/forbidden_slices.rs:69:5
+   |
+LL |     from_ptr_range(ptr..ptr.add(4))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u64>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u64>::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { self.offset(count as isize) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R8`
-  --> $DIR/forbidden_slices.rs:74:25
+  --> $DIR/forbidden_slices.rs:73:25
    |
 LL |     from_ptr_range(ptr..ptr.add(1))
    |                         ^^^^^^^^^^
@@ -248,21 +208,14 @@ LL |     from_ptr_range(ptr..ptr.add(1))
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R9`
-  --> $DIR/forbidden_slices.rs:79:34
+  --> $DIR/forbidden_slices.rs:78:34
    |
 LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -270,21 +223,14 @@ LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).ad
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `from_ptr_range::<'_, u32>`
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `R10`
-  --> $DIR/forbidden_slices.rs:80:35
+  --> $DIR/forbidden_slices.rs:79:35
    |
 LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/const-ptr/forbidden_slices.rs b/src/test/ui/const-ptr/forbidden_slices.rs
index e2184911f42..cc6100226dc 100644
--- a/src/test/ui/const-ptr/forbidden_slices.rs
+++ b/src/test/ui/const-ptr/forbidden_slices.rs
@@ -1,6 +1,6 @@
 // stderr-per-bitwidth
-// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
-// normalize-stderr-test "a[0-9]+\+0x" -> "A_ID+0x"
+// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼"
+// normalize-stderr-test "alloc\d+" -> "allocN"
 // error-pattern: could not evaluate static initializer
 #![feature(
     slice_from_ptr_range,
@@ -31,7 +31,7 @@ pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; /
 // Reading padding is not ok
 pub static S7: &[u16] = unsafe {
     //~^ ERROR: it is undefined behavior to use this value
-    let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+    let ptr = (&D2 as *const Struct as *const u16).add(1);
 
     from_raw_parts(ptr, 4)
 };
@@ -65,13 +65,12 @@ pub static R6: &[bool] = unsafe {
     from_ptr_range(ptr..ptr.add(4))
 };
 pub static R7: &[u16] = unsafe {
-    //~^ ERROR: it is undefined behavior to use this value
     let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
-    from_ptr_range(ptr..ptr.add(4))
+    from_ptr_range(ptr..ptr.add(4)) //~ inside `R7`
 };
 pub static R8: &[u64] = unsafe {
     let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::<u64>();
-    from_ptr_range(ptr..ptr.add(1))
+    from_ptr_range(ptr..ptr.add(1)) //~ inside `R8`
 };
 
 // This is sneaky: &D0 and &D0 point to different objects
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 bca29b46881..3e7b09a5982 100644
--- a/src/test/ui/const-ptr/out_of_bounds_read.stderr
+++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `_READ`
   --> $DIR/out_of_bounds_read.rs:12:33
    |
@@ -18,19 +14,12 @@ LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u32>::read`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ^^^^^^^^^^
 note: inside `_CONST_READ`
   --> $DIR/out_of_bounds_read.rs:13:39
    |
@@ -40,19 +29,12 @@ LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::mut_ptr::<impl *mut u32>::read`
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ^^^^^^^^^^
 note: inside `_MUT_READ`
   --> $DIR/out_of_bounds_read.rs:14:37
    |
diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
index e5b5c7a846c..a0a8d76d10d 100644
--- a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:13:1
+  --> $DIR/ub-ref-ptr.rs:14:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
@@ -10,7 +10,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:17:1
+  --> $DIR/ub-ref-ptr.rs:18:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
@@ -21,7 +21,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:21:1
+  --> $DIR/ub-ref-ptr.rs:22:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
@@ -32,7 +32,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:24:1
+  --> $DIR/ub-ref-ptr.rs:25:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
@@ -43,7 +43,7 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:31:1
+  --> $DIR/ub-ref-ptr.rs:32:1
    |
 LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -52,7 +52,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:34:39
+  --> $DIR/ub-ref-ptr.rs:35:39
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -61,13 +61,13 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:34:38
+  --> $DIR/ub-ref-ptr.rs:35:38
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:37:86
+  --> $DIR/ub-ref-ptr.rs:38:86
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                      ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -76,13 +76,13 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:37:85
+  --> $DIR/ub-ref-ptr.rs:38:85
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:40:1
+  --> $DIR/ub-ref-ptr.rs:41:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
@@ -93,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:43:1
+  --> $DIR/ub-ref-ptr.rs:44:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
@@ -104,13 +104,13 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:46:41
+  --> $DIR/ub-ref-ptr.rs:47:41
    |
 LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:50:1
+  --> $DIR/ub-ref-ptr.rs:51:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -121,13 +121,13 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:52:38
+  --> $DIR/ub-ref-ptr.rs:53:38
    |
 LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:55:1
+  --> $DIR/ub-ref-ptr.rs:56:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -138,7 +138,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:57:1
+  --> $DIR/ub-ref-ptr.rs:58:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
@@ -148,6 +148,39 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
                ╾─alloc41─╼                                     │ ╾──╼
            }
 
-error: aborting due to 14 previous errors
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
+error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
index 607366cabc4..d53b44671e3 100644
--- a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:13:1
+  --> $DIR/ub-ref-ptr.rs:14:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
@@ -10,7 +10,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:17:1
+  --> $DIR/ub-ref-ptr.rs:18:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
@@ -21,7 +21,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:21:1
+  --> $DIR/ub-ref-ptr.rs:22:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
@@ -32,7 +32,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:24:1
+  --> $DIR/ub-ref-ptr.rs:25:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
@@ -43,7 +43,7 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:31:1
+  --> $DIR/ub-ref-ptr.rs:32:1
    |
 LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -52,7 +52,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:34:39
+  --> $DIR/ub-ref-ptr.rs:35:39
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -61,13 +61,13 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:34:38
+  --> $DIR/ub-ref-ptr.rs:35:38
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:37:86
+  --> $DIR/ub-ref-ptr.rs:38:86
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                      ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -76,13 +76,13 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:37:85
+  --> $DIR/ub-ref-ptr.rs:38:85
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:40:1
+  --> $DIR/ub-ref-ptr.rs:41:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
@@ -93,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:43:1
+  --> $DIR/ub-ref-ptr.rs:44:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
@@ -104,13 +104,13 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:46:41
+  --> $DIR/ub-ref-ptr.rs:47:41
    |
 LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:50:1
+  --> $DIR/ub-ref-ptr.rs:51:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -121,13 +121,13 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:52:38
+  --> $DIR/ub-ref-ptr.rs:53:38
    |
 LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:55:1
+  --> $DIR/ub-ref-ptr.rs:56:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -138,7 +138,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:57:1
+  --> $DIR/ub-ref-ptr.rs:58:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
@@ -148,6 +148,39 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
                ╾───────alloc41───────╼                         │ ╾──────╼
            }
 
-error: aborting due to 14 previous errors
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
+error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.rs b/src/test/ui/consts/const-eval/ub-ref-ptr.rs
index a1c81239009..b0fc3c196a4 100644
--- a/src/test/ui/consts/const-eval/ub-ref-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-ref-ptr.rs
@@ -1,6 +1,7 @@
 // ignore-tidy-linelength
 // stderr-per-bitwidth
 #![allow(invalid_value)]
+#![feature(const_ptr_read)]
 
 use std::mem;
 
@@ -57,4 +58,12 @@ const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
 const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
 //~^ ERROR it is undefined behavior to use this value
 
+
+const UNALIGNED_READ: () = unsafe {
+    let x = &[0u8; 4];
+    let ptr = x.as_ptr().cast::<u32>();
+    ptr.read(); //~ inside `UNALIGNED_READ`
+};
+
+
 fn main() {}
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 9994c2e5a83..90a3dcada05 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
@@ -1,27 +1,27 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:36:1
+  --> $DIR/ub-wide-ptr.rs:37:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = 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: 4) {
-               ╾─allocN──╼ e7 03 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:38:1
+  --> $DIR/ub-wide-ptr.rs:39:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = 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: 4) {
-               ╾─allocN─╼ ff ff ff ff                         │ ╾──╼....
+               ╾ALLOC_ID╼ ff ff ff ff                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:41:1
+  --> $DIR/ub-wide-ptr.rs:42:1
    |
 LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -30,7 +30,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:44:1
+  --> $DIR/ub-wide-ptr.rs:45:1
    |
 LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -39,68 +39,68 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:46:1
+  --> $DIR/ub-wide-ptr.rs:47:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = 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: 4) {
-               ╾─allocN─╼ ff ff ff ff                         │ ╾──╼....
+               ╾ALLOC_ID╼ ff ff ff ff                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:50:1
+  --> $DIR/ub-wide-ptr.rs:51:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
    |
    = 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: 4) {
-               ╾─allocN─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:53:1
+  --> $DIR/ub-wide-ptr.rs:54:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
    |
    = 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: 4) {
-               ╾─allocN─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:60:1
+  --> $DIR/ub-wide-ptr.rs:61:1
    |
 LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:67:1
+  --> $DIR/ub-wide-ptr.rs:68:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = 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: 4) {
-               ╾─allocN─╼ e7 03 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:70:1
+  --> $DIR/ub-wide-ptr.rs:71:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = 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: 4) {
-               ╾─allocN─╼ ff ff ff 7f                         │ ╾──╼....
+               ╾ALLOC_ID╼ ff ff ff 7f                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:73:1
+  --> $DIR/ub-wide-ptr.rs:74:1
    |
 LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -109,18 +109,18 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:76:1
+  --> $DIR/ub-wide-ptr.rs:77:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
    |
    = 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: 4) {
-               ╾─allocN─╼ e7 03 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:79:1
+  --> $DIR/ub-wide-ptr.rs:80:1
    |
 LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -129,165 +129,165 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:83:1
+  --> $DIR/ub-wide-ptr.rs:84:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
    |
    = 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) {
-               ╾─allocN─╼                                     │ ╾──╼
+               ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:83:40
+  --> $DIR/ub-wide-ptr.rs:84:40
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:90:1
+  --> $DIR/ub-wide-ptr.rs:91:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
    |
    = 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) {
-               ╾allocN─╼                                     │ ╾──╼
+               ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:90:42
+  --> $DIR/ub-wide-ptr.rs:91:42
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:94:1
+  --> $DIR/ub-wide-ptr.rs:95:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
    |
    = 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) {
-               ╾allocN─╼                                     │ ╾──╼
+               ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:94:42
+  --> $DIR/ub-wide-ptr.rs:95:42
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:102:1
+  --> $DIR/ub-wide-ptr.rs:103:1
    |
 LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:111:1
+  --> $DIR/ub-wide-ptr.rs:112:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = 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: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:115:1
+  --> $DIR/ub-wide-ptr.rs:116:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = 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: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:119:1
+  --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
    |
    = 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: 4) {
-               ╾allocN─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:122:57
+  --> $DIR/ub-wide-ptr.rs:123:57
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:125:57
+  --> $DIR/ub-wide-ptr.rs:126:57
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:128:56
+  --> $DIR/ub-wide-ptr.rs:129:56
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:131:1
+  --> $DIR/ub-wide-ptr.rs:132:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = 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: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:136:1
+  --> $DIR/ub-wide-ptr.rs:137:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
    |
    = 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: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:141:1
+  --> $DIR/ub-wide-ptr.rs:142:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
    |
    = 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: 4) {
-               ╾allocN─╼ 00 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 00 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:143:1
+  --> $DIR/ub-wide-ptr.rs:144:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
    |
    = 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: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:149:5
+  --> $DIR/ub-wide-ptr.rs:150:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:153:5
+  --> $DIR/ub-wide-ptr.rs:154:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
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 06a377d9f7c..ab25303ddc0 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
@@ -1,27 +1,27 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:36:1
+  --> $DIR/ub-wide-ptr.rs:37:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = 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: 16, align: 8) {
-               ╾───────allocN────────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:38:1
+  --> $DIR/ub-wide-ptr.rs:39:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = 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: 16, align: 8) {
-               ╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
+               ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:41:1
+  --> $DIR/ub-wide-ptr.rs:42:1
    |
 LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -30,7 +30,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:44:1
+  --> $DIR/ub-wide-ptr.rs:45:1
    |
 LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -39,68 +39,68 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:46:1
+  --> $DIR/ub-wide-ptr.rs:47:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = 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: 16, align: 8) {
-               ╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
+               ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:50:1
+  --> $DIR/ub-wide-ptr.rs:51:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
    |
    = 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: 16, align: 8) {
-               ╾───────allocN───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:53:1
+  --> $DIR/ub-wide-ptr.rs:54:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
    |
    = 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: 16, align: 8) {
-               ╾───────allocN───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:60:1
+  --> $DIR/ub-wide-ptr.rs:61:1
    |
 LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:67:1
+  --> $DIR/ub-wide-ptr.rs:68:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = 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: 16, align: 8) {
-               ╾───────allocN───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:70:1
+  --> $DIR/ub-wide-ptr.rs:71:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = 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: 16, align: 8) {
-               ╾───────allocN───────╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
+               ╾ALLOC_ID╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:73:1
+  --> $DIR/ub-wide-ptr.rs:74:1
    |
 LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -109,18 +109,18 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:76:1
+  --> $DIR/ub-wide-ptr.rs:77:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
    |
    = 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: 16, align: 8) {
-               ╾───────allocN───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:79:1
+  --> $DIR/ub-wide-ptr.rs:80:1
    |
 LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -129,165 +129,165 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:83:1
+  --> $DIR/ub-wide-ptr.rs:84:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
    |
    = 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) {
-               ╾───────allocN───────╼                         │ ╾──────╼
+               ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:83:40
+  --> $DIR/ub-wide-ptr.rs:84:40
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:90:1
+  --> $DIR/ub-wide-ptr.rs:91:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
    |
    = 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) {
-               ╾──────allocN───────╼                         │ ╾──────╼
+               ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:90:42
+  --> $DIR/ub-wide-ptr.rs:91:42
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:94:1
+  --> $DIR/ub-wide-ptr.rs:95:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
    |
    = 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) {
-               ╾──────allocN───────╼                         │ ╾──────╼
+               ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:94:42
+  --> $DIR/ub-wide-ptr.rs:95:42
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:102:1
+  --> $DIR/ub-wide-ptr.rs:103:1
    |
 LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:111:1
+  --> $DIR/ub-wide-ptr.rs:112:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = 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: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:115:1
+  --> $DIR/ub-wide-ptr.rs:116:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = 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: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:119:1
+  --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
    |
    = 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: 16, align: 8) {
-               ╾──────allocN───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:122:57
+  --> $DIR/ub-wide-ptr.rs:123:57
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:125:57
+  --> $DIR/ub-wide-ptr.rs:126:57
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:128:56
+  --> $DIR/ub-wide-ptr.rs:129:56
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:131:1
+  --> $DIR/ub-wide-ptr.rs:132:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = 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: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:136:1
+  --> $DIR/ub-wide-ptr.rs:137:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
    |
    = 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: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:141:1
+  --> $DIR/ub-wide-ptr.rs:142:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
    |
    = 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: 16, align: 8) {
-               ╾──────allocN───────╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:143:1
+  --> $DIR/ub-wide-ptr.rs:144:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
    |
    = 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: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:149:5
+  --> $DIR/ub-wide-ptr.rs:150:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:153:5
+  --> $DIR/ub-wide-ptr.rs:154:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
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 2894ef83188..d12e5e2bed9 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
@@ -4,6 +4,7 @@
 
 use std::mem;
 
+// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼"
 // normalize-stderr-test "offset \d+" -> "offset N"
 // normalize-stderr-test "alloc\d+" -> "allocN"
 // normalize-stderr-test "size \d+" -> "size N"
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 195a087ffa5..7ad02252094 100644
--- a/src/test/ui/consts/const-float-bits-reject-conv.stderr
+++ b/src/test/ui/consts/const-float-bits-reject-conv.stderr
@@ -1,19 +1,12 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
+   = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
 note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `core::f32::<impl f32>::to_bits`
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `f32::MASKED_NAN1`
   --> $DIR/const-float-bits-reject-conv.rs:28:30
    |
@@ -24,19 +17,12 @@ LL |     const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
+   = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
 note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `core::f32::<impl f32>::to_bits`
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `f32::MASKED_NAN2`
   --> $DIR/const-float-bits-reject-conv.rs:30:30
    |
@@ -71,19 +57,12 @@ LL |     const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
+   = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
 note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `core::f64::<impl f64>::to_bits`
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `f64::MASKED_NAN1`
   --> $DIR/const-float-bits-reject-conv.rs:50:30
    |
@@ -94,19 +73,12 @@ LL |     const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
+   = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
 note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `core::f64::<impl f64>::to_bits`
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `f64::MASKED_NAN2`
   --> $DIR/const-float-bits-reject-conv.rs:52:30
    |
diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr
index 02960b363e7..f6b532fb658 100644
--- a/src/test/ui/consts/const-fn-error.stderr
+++ b/src/test/ui/consts/const-fn-error.stderr
@@ -21,9 +21,6 @@ LL |     for i in 0..x {
    |
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL | impl<I: Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constant functions
diff --git a/src/test/ui/consts/const-for.stderr b/src/test/ui/consts/const-for.stderr
index 11e4ae309c0..294ea627d85 100644
--- a/src/test/ui/consts/const-for.stderr
+++ b/src/test/ui/consts/const-for.stderr
@@ -6,9 +6,6 @@ LL |     for _ in 0..5 {}
    |
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL | impl<I: Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
index cbc7cac937a..593a51bfe8f 100644
--- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
+++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/hint.rs:LL:COL
    |
-LL |         intrinsics::unreachable()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ entering unreachable code
+   = note: entering unreachable code
    |
 note: inside `unreachable_unchecked`
   --> $SRC_DIR/core/src/hint.rs:LL:COL
-   |
-LL |         intrinsics::unreachable()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `foo`
   --> $DIR/const_unsafe_unreachable_ub.rs:6:18
    |
diff --git a/src/test/ui/consts/copy-intrinsic.rs b/src/test/ui/consts/copy-intrinsic.rs
index 249bbb5991c..94d7bdc6bae 100644
--- a/src/test/ui/consts/copy-intrinsic.rs
+++ b/src/test/ui/consts/copy-intrinsic.rs
@@ -17,7 +17,7 @@ const COPY_ZERO: () = unsafe {
     // Since we are not copying anything, this should be allowed.
     let src = ();
     let mut dst = ();
-    copy_nonoverlapping(&src as *const _ as *const i32, &mut dst as *mut _ as *mut i32, 0);
+    copy_nonoverlapping(&src as *const _ as *const u8, &mut dst as *mut _ as *mut u8, 0);
 };
 
 const COPY_OOB_1: () = unsafe {
diff --git a/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs b/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
index 9c239c8a100..e2f8149883b 100644
--- a/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
+++ b/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
@@ -28,15 +28,4 @@ const UNALIGNED_PTR: () = unsafe {
     //[with_flag]~| invalid value
 };
 
-const UNALIGNED_READ: () = {
-    INNER; //[with_flag]~ constant
-    // There is an error here but its span is in the standard library so we cannot match it...
-    // so we have this in a *nested* const, such that the *outer* const fails to use it.
-    const INNER: () = unsafe {
-        let x = &[0u8; 4];
-        let ptr = x.as_ptr().cast::<u32>();
-        ptr.read();
-    };
-};
-
 fn main() {}
diff --git a/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr b/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
index 2603a73583e..b2a5fd90149 100644
--- a/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
+++ b/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
@@ -28,34 +28,6 @@ error[E0080]: evaluation of constant value failed
 LL |     let _x: &u32 = transmute(&[0u8; 4]);
    |                    ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
 
-error[E0080]: evaluation of constant value failed
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required
-   |
-note: inside `std::ptr::read::<u32>`
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: inside `ptr::const_ptr::<impl *const u32>::read`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ^^^^^^^^^^
-note: inside `INNER`
-  --> $DIR/detect-extra-ub.rs:38:9
-   |
-LL |         ptr.read();
-   |         ^^^^^^^^^^
-
-note: erroneous constant used
-  --> $DIR/detect-extra-ub.rs:32:5
-   |
-LL |     INNER;
-   |     ^^^^^
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr
index 1f82e1777af..61865b1dad7 100644
--- a/src/test/ui/consts/issue-miri-1910.stderr
+++ b/src/test/ui/consts/issue-miri-1910.stderr
@@ -1,21 +1,14 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to copy parts of a pointer from memory at ALLOC
+   = note: unable to copy parts of a pointer from memory at ALLOC
    |
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 note: inside `std::ptr::read::<u8>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ptr::const_ptr::<impl *const u8>::read`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ^^^^^^^^^^
 note: inside `C`
   --> $DIR/issue-miri-1910.rs:8:5
    |
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.stderr b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
index b26f121dba0..e1da43c3aea 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
@@ -1,19 +1,12 @@
 error[E0080]: evaluation of `<std::string::String as Bar<std::vec::Vec<u32>, std::string::String>>::F` failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `<Vec<u32> as Drop>::drop`
+   = note: calling non-const function `<Vec<u32> as Drop>::drop`
    |
 note: inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `<String as Bar<Vec<u32>, String>>::F`
   --> $DIR/assoc_const.rs:12:31
    |
diff --git a/src/test/ui/consts/miri_unleashed/drop.stderr b/src/test/ui/consts/miri_unleashed/drop.stderr
index e2e2f16d5a0..4f60b882069 100644
--- a/src/test/ui/consts/miri_unleashed/drop.stderr
+++ b/src/test/ui/consts/miri_unleashed/drop.stderr
@@ -1,14 +1,10 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `<Vec<i32> as Drop>::drop`
+   = note: calling non-const function `<Vec<i32> as Drop>::drop`
    |
 note: inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `TEST_BAD`
   --> $DIR/drop.rs:17:1
    |
diff --git a/src/test/ui/consts/missing_span_in_backtrace.rs b/src/test/ui/consts/missing_span_in_backtrace.rs
index c4930b73aaa..dd2b81c5af2 100644
--- a/src/test/ui/consts/missing_span_in_backtrace.rs
+++ b/src/test/ui/consts/missing_span_in_backtrace.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ui-testing=no
+// compile-flags: -Z ui-testing=no
 // normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
 
 #![feature(const_swap)]
diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr
index 9578d90ea9d..fff4729689f 100644
--- a/src/test/ui/consts/offset_from_ub.stderr
+++ b/src/test/ui/consts/offset_from_ub.stderr
@@ -7,14 +7,10 @@ LL |     let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on pointers into different allocations
+   = note: `ptr_offset_from` called on pointers into different allocations
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `NOT_PTR`
   --> $DIR/offset_from_ub.rs:24:14
    |
@@ -90,14 +86,10 @@ LL |     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `OFFSET_VERY_FAR1`
   --> $DIR/offset_from_ub.rs:115:14
    |
@@ -107,14 +99,10 @@ LL |     unsafe { ptr2.offset_from(ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `OFFSET_VERY_FAR2`
   --> $DIR/offset_from_ub.rs:121:14
    |
diff --git a/src/test/ui/consts/offset_ub.stderr b/src/test/ui/consts/offset_ub.stderr
index 7938f70a269..c0c851df507 100644
--- a/src/test/ui/consts/offset_ub.stderr
+++ b/src/test/ui/consts/offset_ub.stderr
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `BEFORE_START`
   --> $DIR/offset_ub.rs:7:46
    |
@@ -18,14 +14,10 @@ LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1)
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `AFTER_END`
   --> $DIR/offset_ub.rs:8:43
    |
@@ -35,14 +27,10 @@ LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `AFTER_ARRAY`
   --> $DIR/offset_ub.rs:9:45
    |
@@ -52,14 +40,10 @@ LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101)
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u16>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `OVERFLOW`
   --> $DIR/offset_ub.rs:11:43
    |
@@ -69,14 +53,10 @@ LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u16>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `UNDERFLOW`
   --> $DIR/offset_ub.rs:12:44
    |
@@ -86,14 +66,10 @@ LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize:
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `OVERFLOW_ADDRESS_SPACE`
   --> $DIR/offset_ub.rs:13:56
    |
@@ -103,14 +79,10 @@ LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *cons
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   = note: overflowing in-bounds pointer arithmetic
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `UNDERFLOW_ADDRESS_SPACE`
   --> $DIR/offset_ub.rs:14:57
    |
@@ -120,14 +92,10 @@ LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).of
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `NEGATIVE_OFFSET`
   --> $DIR/offset_ub.rs:15:49
    |
@@ -137,14 +105,10 @@ LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `ZERO_SIZED_ALLOC`
   --> $DIR/offset_ub.rs:17:50
    |
@@ -154,14 +118,10 @@ LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) as *mut T }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+   = note: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::mut_ptr::<impl *mut u8>::offset`
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) as *mut T }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `DANGLING`
   --> $DIR/offset_ub.rs:18:42
    |
@@ -171,14 +131,10 @@ LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `NULL_OFFSET_ZERO`
   --> $DIR/offset_ub.rs:21:50
    |
@@ -188,14 +144,10 @@ LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
+   = note: out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `UNDERFLOW_ABS`
   --> $DIR/offset_ub.rs:24:47
    |
diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr
index 274753ef1bc..fea924d12e5 100644
--- a/src/test/ui/consts/ptr_comparisons.stderr
+++ b/src/test/ui/consts/ptr_comparisons.stderr
@@ -1,14 +1,10 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
    |
 note: inside `ptr::const_ptr::<impl *const usize>::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `_`
   --> $DIR/ptr_comparisons.rs:50:34
    |
diff --git a/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr
index e3fb234b96e..2be69a30b1c 100644
--- a/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr
+++ b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr
@@ -9,9 +9,6 @@ LL |      x: Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
diff --git a/src/test/ui/derives/derives-span-Eq-enum.stderr b/src/test/ui/derives/derives-span-Eq-enum.stderr
index 4e10c3f69e7..4f4f821cca3 100644
--- a/src/test/ui/derives/derives-span-Eq-enum.stderr
+++ b/src/test/ui/derives/derives-span-Eq-enum.stderr
@@ -9,9 +9,6 @@ LL |      Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
diff --git a/src/test/ui/derives/derives-span-Eq-struct.stderr b/src/test/ui/derives/derives-span-Eq-struct.stderr
index bfdab052a2e..f15659c3e16 100644
--- a/src/test/ui/derives/derives-span-Eq-struct.stderr
+++ b/src/test/ui/derives/derives-span-Eq-struct.stderr
@@ -9,9 +9,6 @@ LL |     x: Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
diff --git a/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr b/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr
index 26b8be34333..4e5659b35f4 100644
--- a/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr
+++ b/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr
@@ -9,9 +9,6 @@ LL |     Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
diff --git a/src/test/ui/derives/deriving-meta-unknown-trait.stderr b/src/test/ui/derives/deriving-meta-unknown-trait.stderr
index f3ff95a85da..053d34f6825 100644
--- a/src/test/ui/derives/deriving-meta-unknown-trait.stderr
+++ b/src/test/ui/derives/deriving-meta-unknown-trait.stderr
@@ -3,22 +3,18 @@ error: cannot find derive macro `Eqr` in this scope
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub macro Eq($item:item) {
-   | ------------ similarly named derive macro `Eq` defined here
+   = note: similarly named derive macro `Eq` defined here
 
 error: cannot find derive macro `Eqr` in this scope
   --> $DIR/deriving-meta-unknown-trait.rs:1:10
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub macro Eq($item:item) {
-   | ------------ similarly named derive macro `Eq` defined here
+   = note: similarly named derive macro `Eq` defined here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/deriving/issue-103157.stderr b/src/test/ui/deriving/issue-103157.stderr
index ee3528fe106..b18e1e5098b 100644
--- a/src/test/ui/deriving/issue-103157.stderr
+++ b/src/test/ui/deriving/issue-103157.stderr
@@ -20,9 +20,6 @@ LL |     Float(Option<f64>),
    = note: required for `Option<f64>` to implement `Eq`
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/destructuring-assignment/note-unsupported.stderr b/src/test/ui/destructuring-assignment/note-unsupported.stderr
index e45344aa51f..8a88332b73e 100644
--- a/src/test/ui/destructuring-assignment/note-unsupported.stderr
+++ b/src/test/ui/destructuring-assignment/note-unsupported.stderr
@@ -49,11 +49,8 @@ note: an implementation of `AddAssign<_>` might be missing for `S`
    |
 LL | struct S { x: u8, y: u8 }
    | ^^^^^^^^ must implement `AddAssign<_>`
-note: the following trait must be implemented
+note: the trait `AddAssign` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait AddAssign<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0067]: invalid left-hand side of assignment
   --> $DIR/note-unsupported.rs:17:22
diff --git a/src/test/ui/diagnostic-width/long-E0308.rs b/src/test/ui/diagnostic-width/long-E0308.rs
index 3fd7a7110fd..f021f102933 100644
--- a/src/test/ui/diagnostic-width/long-E0308.rs
+++ b/src/test/ui/diagnostic-width/long-E0308.rs
@@ -1,9 +1,20 @@
 // compile-flags: --diagnostic-width=60
 // normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
 
-struct Atype<T, K>(T, K);
-struct Btype<T, K>(T, K);
-struct Ctype<T, K>(T, K);
+mod a {
+    // Force the "short path for unique types" machinery to trip up
+    pub struct Atype;
+    pub struct Btype;
+    pub struct Ctype;
+}
+
+mod b {
+    pub struct Atype<T, K>(T, K);
+    pub struct Btype<T, K>(T, K);
+    pub struct Ctype<T, K>(T, K);
+}
+
+use b::*;
 
 fn main() {
     let x: Atype<
diff --git a/src/test/ui/diagnostic-width/long-E0308.stderr b/src/test/ui/diagnostic-width/long-E0308.stderr
index 487ab23a1c1..1c99898bc83 100644
--- a/src/test/ui/diagnostic-width/long-E0308.stderr
+++ b/src/test/ui/diagnostic-width/long-E0308.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:33:9
+  --> $DIR/long-E0308.rs:44:9
    |
 LL |        let x: Atype<
    |  _____________-
@@ -24,7 +24,7 @@ LL |  |     ))))))))))))))))))))))))))))));
            the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
 
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:46:26
+  --> $DIR/long-E0308.rs:57:26
    |
 LL |       ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
    |  __________________________^
@@ -40,7 +40,7 @@ LL | |     ))))))))))))))))))))))));
            the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
 
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:77:9
+  --> $DIR/long-E0308.rs:88:9
    |
 LL |       let x: Atype<
    |  ____________-
@@ -59,7 +59,7 @@ LL | |     > = ();
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/long-E0308.rs:80:17
+  --> $DIR/long-E0308.rs:91:17
    |
 LL |       let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
    |  ____________--___^
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed
new file mode 100644
index 00000000000..ae0a84eea4d
--- /dev/null
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed
@@ -0,0 +1,21 @@
+// run-rustfix
+struct X {
+    x: String,
+}
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("value: {}", self.x);
+    }
+}
+
+fn unwrap(x: X) -> String {
+    let X { x: ref y } = x; //~ ERROR cannot move out of type
+    y.to_string()
+}
+
+fn main() {
+    let x = X { x: "hello".to_string() };
+    let y = unwrap(x);
+    println!("contents: {}", y);
+}
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs
index 8e394498a23..c8db7861068 100644
--- a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 struct X {
     x: String,
 }
@@ -10,7 +11,7 @@ impl Drop for X {
 
 fn unwrap(x: X) -> String {
     let X { x: y } = x; //~ ERROR cannot move out of type
-    y
+    y.to_string()
 }
 
 fn main() {
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr
index cda81d13669..596ad4bf784 100644
--- a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr
@@ -1,11 +1,16 @@
 error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
-  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:12:22
+  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:13:22
    |
 LL |     let X { x: y } = x;
    |                -     ^ cannot move out of here
    |                |
    |                data moved here
    |                move occurs because `y` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let X { x: ref y } = x;
+   |                +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed
new file mode 100644
index 00000000000..c8a451efeb2
--- /dev/null
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+struct X {
+    x: String,
+}
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("value: {}", self.x);
+    }
+}
+
+fn main() {
+    let x = X { x: "hello".to_string() };
+
+    match x {
+    //~^ ERROR cannot move out of type `X`, which implements the `Drop` trait
+        X { x: ref y } => println!("contents: {}", y)
+    }
+}
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs
index 9c996a93b95..815567ffec3 100644
--- a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 struct X {
     x: String,
 }
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr
index 70cdd6446c8..e32a4dd4411 100644
--- a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr
+++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr
@@ -1,5 +1,5 @@
 error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
-  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:14:11
+  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:15:11
    |
 LL |     match x {
    |           ^ cannot move out of here
@@ -9,6 +9,11 @@ LL |         X { x: y } => println!("contents: {}", y)
    |                |
    |                data moved here
    |                move occurs because `y` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         X { x: ref y } => println!("contents: {}", y)
+   |                +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/disambiguate-identical-names.stderr b/src/test/ui/disambiguate-identical-names.stderr
index 42925cfed55..87560c4c797 100644
--- a/src/test/ui/disambiguate-identical-names.stderr
+++ b/src/test/ui/disambiguate-identical-names.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/disambiguate-identical-names.rs:13:10
    |
 LL |     test(&v);
-   |     ---- ^^ expected struct `std::vec::Vec`, found struct `HashMap`
+   |     ---- ^^ expected struct `Vec`, found struct `HashMap`
    |     |
    |     arguments to this function are incorrect
    |
diff --git a/src/test/ui/issues/issue-21486.rs b/src/test/ui/drop/issue-21486.rs
index 46d6ccd56bd..46d6ccd56bd 100644
--- a/src/test/ui/issues/issue-21486.rs
+++ b/src/test/ui/drop/issue-21486.rs
diff --git a/src/test/ui/dst/dst-rvalue.stderr b/src/test/ui/dst/dst-rvalue.stderr
index 727f4d84303..8d0a82b707d 100644
--- a/src/test/ui/dst/dst-rvalue.stderr
+++ b/src/test/ui/dst/dst-rvalue.stderr
@@ -9,9 +9,6 @@ LL |     let _x: Box<str> = Box::new(*"hello world");
    = help: the trait `Sized` is not implemented for `str`
 note: required by a bound in `Box::<T>::new`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T> Box<T> {
-   |      ^ required by this bound in `Box::<T>::new`
 
 error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
   --> $DIR/dst-rvalue.rs:8:37
@@ -24,9 +21,6 @@ LL |     let _x: Box<[isize]> = Box::new(*array);
    = help: the trait `Sized` is not implemented for `[isize]`
 note: required by a bound in `Box::<T>::new`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T> Box<T> {
-   |      ^ required by this bound in `Box::<T>::new`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/dyn-star/no-implicit-dyn-star.stderr b/src/test/ui/dyn-star/no-implicit-dyn-star.stderr
index e7c5918629b..a3f4d21ca94 100644
--- a/src/test/ui/dyn-star/no-implicit-dyn-star.stderr
+++ b/src/test/ui/dyn-star/no-implicit-dyn-star.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/no-implicit-dyn-star.rs:6:48
    |
 LL |     dyn_star_foreign::require_dyn_star_display(1usize);
-   |     ------------------------------------------ ^^^^^^ expected trait object `dyn std::fmt::Display`, found `usize`
+   |     ------------------------------------------ ^^^^^^ expected trait object `dyn Display`, found `usize`
    |     |
    |     arguments to this function are incorrect
    |
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index e1a7a02a568..0e580aedeaa 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -100,22 +100,22 @@ help: a unit struct with a similar name exists
 LL |     let xe1 = XEmpty2();
    |               ~~~~~~~
 
-error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:25:19
    |
 LL |     let xe3 = XE::Empty3;
    |                   ^^^^^^
    |                   |
-   |                   variant or associated item not found in `empty_struct::XE`
+   |                   variant or associated item not found in `XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
-error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:26:19
    |
 LL |     let xe3 = XE::Empty3();
    |                   ^^^^^^
    |                   |
-   |                   variant or associated item not found in `empty_struct::XE`
+   |                   variant or associated item not found in `XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
 error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE`
diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr
index 6f5bb4309c3..e829bac196f 100644
--- a/src/test/ui/error-codes/E0004-2.stderr
+++ b/src/test/ui/error-codes/E0004-2.stderr
@@ -6,15 +6,12 @@ LL |     match x { }
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr
index de8e6bac486..0f179259356 100644
--- a/src/test/ui/error-codes/E0005.stderr
+++ b/src/test/ui/error-codes/E0005.stderr
@@ -8,12 +8,9 @@ LL |     let Some(y) = x;
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
diff --git a/src/test/ui/error-codes/E0059.stderr b/src/test/ui/error-codes/E0059.stderr
index f331d014226..4f6abb22ab2 100644
--- a/src/test/ui/error-codes/E0059.stderr
+++ b/src/test/ui/error-codes/E0059.stderr
@@ -6,9 +6,6 @@ LL | fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
    |
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   |                    ^^^^^ required by this bound in `Fn`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr
index d01aa3617c7..892d3a81f27 100644
--- a/src/test/ui/error-codes/E0282.stderr
+++ b/src/test/ui/error-codes/E0282.stderr
@@ -6,8 +6,8 @@ LL |     let x = "hello".chars().rev().collect();
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = "hello".chars().rev().collect();
-   |          +++
+LL |     let x: Vec<_> = "hello".chars().rev().collect();
+   |          ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0297.stderr b/src/test/ui/error-codes/E0297.stderr
index 693b079238d..903422f3b9b 100644
--- a/src/test/ui/error-codes/E0297.stderr
+++ b/src/test/ui/error-codes/E0297.stderr
@@ -6,12 +6,9 @@ LL |     for Some(x) in xs {}
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr
index 9687eca61fa..fa4b91cacef 100644
--- a/src/test/ui/error-codes/E0401.stderr
+++ b/src/test/ui/error-codes/E0401.stderr
@@ -59,7 +59,7 @@ note: required by a bound in `bfnr`
    |
 LL |     fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
    |                              ^^^^ required by this bound in `bfnr`
-help: consider specifying the type arguments in the function call
+help: consider specifying the generic arguments
    |
 LL |     bfnr::<U, V, W>(x);
    |         +++++++++++
diff --git a/src/test/ui/error-codes/E0507.stderr b/src/test/ui/error-codes/E0507.stderr
index ce8d1ef0349..03630f38987 100644
--- a/src/test/ui/error-codes/E0507.stderr
+++ b/src/test/ui/error-codes/E0507.stderr
@@ -7,7 +7,7 @@ LL |     x.borrow().nothing_is_true();
    |     |          value moved due to this method call
    |     move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves value
+note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, which moves value
   --> $DIR/E0507.rs:6:24
    |
 LL |     fn nothing_is_true(self) {}
diff --git a/src/test/ui/error-codes/E0508-fail.stderr b/src/test/ui/error-codes/E0508-fail.stderr
index b69d7743b6c..208ba30729f 100644
--- a/src/test/ui/error-codes/E0508-fail.stderr
+++ b/src/test/ui/error-codes/E0508-fail.stderr
@@ -6,7 +6,11 @@ LL |     let _value = array[0];
    |                  |
    |                  cannot move out of here
    |                  move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
-   |                  help: consider borrowing here: `&array[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let _value = &array[0];
+   |                  +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0508.stderr b/src/test/ui/error-codes/E0508.stderr
index 5e7b56dcd37..df2d3b0d311 100644
--- a/src/test/ui/error-codes/E0508.stderr
+++ b/src/test/ui/error-codes/E0508.stderr
@@ -6,7 +6,11 @@ LL |     let _value = array[0];
    |                  |
    |                  cannot move out of here
    |                  move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
-   |                  help: consider borrowing here: `&array[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let _value = &array[0];
+   |                  +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0509.stderr b/src/test/ui/error-codes/E0509.stderr
index cbfbc3ccf6a..c00d9142e75 100644
--- a/src/test/ui/error-codes/E0509.stderr
+++ b/src/test/ui/error-codes/E0509.stderr
@@ -6,7 +6,11 @@ LL |     let fancy_field = drop_struct.fancy;
    |                       |
    |                       cannot move out of here
    |                       move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait
-   |                       help: consider borrowing here: `&drop_struct.fancy`
+   |
+help: consider borrowing here
+   |
+LL |     let fancy_field = &drop_struct.fancy;
+   |                       +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0790.stderr b/src/test/ui/error-codes/E0790.stderr
index f68c0e7d220..fc025a3fca2 100644
--- a/src/test/ui/error-codes/E0790.stderr
+++ b/src/test/ui/error-codes/E0790.stderr
@@ -37,8 +37,8 @@ LL |     inner::MyTrait::my_fn();
    |
 help: use the fully-qualified path to the only available implementation
    |
-LL |     inner::<MyStruct as MyTrait>::my_fn();
-   |            ++++++++++++        +
+LL |     <MyStruct as inner::MyTrait>::my_fn();
+   |     ++++++++++++               +
 
 error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/E0790.rs:30:13
@@ -51,8 +51,8 @@ LL |     let _ = inner::MyTrait::MY_ASSOC_CONST;
    |
 help: use the fully-qualified path to the only available implementation
    |
-LL |     let _ = inner::<MyStruct as MyTrait>::MY_ASSOC_CONST;
-   |                    ++++++++++++        +
+LL |     let _ = <MyStruct as inner::MyTrait>::MY_ASSOC_CONST;
+   |             ++++++++++++               +
 
 error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/E0790.rs:50:5
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index 43122c13efb..fe9956b70bd 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -41,11 +41,8 @@ note: an implementation of `Not` might be missing for `Question`
    |
 LL | enum Question {
    | ^^^^^^^^^^^^^ must implement `Not`
-note: the following trait must be implemented
+note: the trait `Not` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Not {
-   | ^^^^^^^^^^^^^
 
 error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/error-festival.rs:25:5
diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
index 759d79493a9..2f9d10d70a2 100644
--- a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
+++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
@@ -14,7 +14,7 @@ LL |       let p = Some(45).and_then({
 LL | |
 LL | |         |x| println!("doubling {}", x);
 LL | |         Some(x * 2)
-   | |         ----------- this tail expression is of type `std::option::Option<_>`
+   | |         ----------- this tail expression is of type `Option<_>`
 LL | |
 LL | |     });
    | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
@@ -22,9 +22,6 @@ LL | |     });
    = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>`
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> Option<U>,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::and_then`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
index 5ced344f13f..e253e4791e8 100644
--- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
+++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
@@ -8,12 +8,9 @@ LL |     let Ok(_x) = foo();
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Result<u32, !>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, !>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
index 9b868ed7a9e..c04e57843d4 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
@@ -1,5 +1,5 @@
+#![allow(unused, bare_trait_objects)]
 #[repr(align(256))]
-#[allow(dead_code)]
 struct A {
     v: u8,
 }
@@ -14,13 +14,17 @@ impl Foo for A {
     }
 }
 
-fn foo(x: dyn Foo) {
-    //~^ ERROR [E0277]
+fn foo(x: dyn Foo) { //~ ERROR [E0277]
     x.foo()
 }
 
+fn bar(x: Foo) { //~ ERROR [E0277]
+    x.foo()
+}
+
+fn qux(_: [()]) {} //~ ERROR [E0277]
+
 fn main() {
     let x: Box<dyn Foo> = Box::new(A { v: 22 });
-    foo(*x);
-    //~^ ERROR [E0277]
+    foo(*x); //~ ERROR [E0277]
 }
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
index 0f7520ef7f8..92c71392672 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
@@ -6,13 +6,47 @@ LL | fn foo(x: dyn Foo) {
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn foo(x: impl Foo) {
+   |           ~~~~
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | fn foo(x: &dyn Foo) {
    |           +
 
 error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
-  --> $DIR/feature-gate-unsized_fn_params.rs:24:9
+  --> $DIR/feature-gate-unsized_fn_params.rs:21:8
+   |
+LL | fn bar(x: Foo) {
+   |        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
+   = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn bar(x: impl Foo) {
+   |           ++++
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn bar(x: &Foo) {
+   |           +
+
+error[E0277]: the size for values of type `[()]` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_fn_params.rs:25:8
+   |
+LL | fn qux(_: [()]) {}
+   |        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[()]`
+   = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn qux(_: &[()]) {}
+   |           +
+
+error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_fn_params.rs:29:9
    |
 LL |     foo(*x);
    |         ^^ doesn't have a size known at compile-time
@@ -21,6 +55,6 @@ LL |     foo(*x);
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
index c4507843e36..9aeeb88cf04 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
@@ -6,6 +6,10 @@ LL | fn f(f: dyn FnOnce()) {}
    |
    = help: the trait `Sized` is not implemented for `(dyn FnOnce() + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn f(f: impl FnOnce()) {}
+   |         ~~~~
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | fn f(f: &dyn FnOnce()) {}
diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr
index 1b595a50e99..a8a2a47fe46 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.stderr
+++ b/src/test/ui/fmt/ifmt-bad-arg.stderr
@@ -309,9 +309,6 @@ LL |     println!("{} {:.*} {}", 1, 3.2, 4);
               found reference `&{float}`
 note: associated function defined here
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |     pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
-   |            ^^^^^^^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
@@ -327,9 +324,6 @@ LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
               found reference `&{float}`
 note: associated function defined here
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |     pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
-   |            ^^^^^^^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 38 previous errors
diff --git a/src/test/ui/fmt/ifmt-unimpl.stderr b/src/test/ui/fmt/ifmt-unimpl.stderr
index 0e34f913511..be321c3c5c0 100644
--- a/src/test/ui/fmt/ifmt-unimpl.stderr
+++ b/src/test/ui/fmt/ifmt-unimpl.stderr
@@ -17,9 +17,6 @@ LL |     format!("{:X}", "3");
    = note: required for `&str` to implement `UpperHex`
 note: required by a bound in `ArgumentV1::<'a>::new_upper_hex`
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |     arg_new!(new_upper_hex, UpperHex);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ArgumentV1::<'a>::new_upper_hex`
    = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `arg_new` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/functions-closures/fn-help-with-err.stderr b/src/test/ui/functions-closures/fn-help-with-err.stderr
index 2296666219e..463ac7684ec 100644
--- a/src/test/ui/functions-closures/fn-help-with-err.stderr
+++ b/src/test/ui/functions-closures/fn-help-with-err.stderr
@@ -17,11 +17,11 @@ note: `Bar` defines an item `bar`, perhaps you need to implement it
 LL | trait Bar {
    | ^^^^^^^^^
 
-error[E0599]: no method named `bar` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>` in the current scope
+error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:22:36]>` in the current scope
   --> $DIR/fn-help-with-err.rs:23:10
    |
 LL |     arc2.bar();
-   |          ^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>`
+   |          ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:22:36]>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Bar` defines an item `bar`, perhaps you need to implement it
diff --git a/src/test/ui/generator/issue-102645.stderr b/src/test/ui/generator/issue-102645.stderr
index 7b4d5021325..afb39c9e594 100644
--- a/src/test/ui/generator/issue-102645.stderr
+++ b/src/test/ui/generator/issue-102645.stderr
@@ -6,9 +6,6 @@ LL |     Pin::new(&mut b).resume();
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/generator.rs:LL:COL
-   |
-LL |     fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
-   |        ^^^^^^
 help: provide the argument
    |
 LL |     Pin::new(&mut b).resume(());
diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr
index ea2a48d13ce..fb34540d969 100644
--- a/src/test/ui/generator/sized-yield.stderr
+++ b/src/test/ui/generator/sized-yield.stderr
@@ -20,9 +20,6 @@ LL |    Pin::new(&mut gen).resume(());
    = help: the trait `Sized` is not implemented for `str`
 note: required by a bound in `GeneratorState`
   --> $SRC_DIR/core/src/ops/generator.rs:LL:COL
-   |
-LL | pub enum GeneratorState<Y, R> {
-   |                         ^ required by this bound in `GeneratorState`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/cross-crate-bounds.stderr b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr
index c81cd7e7718..83ee04d5a6c 100644
--- a/src/test/ui/generic-associated-types/cross-crate-bounds.stderr
+++ b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr
@@ -8,7 +8,7 @@ note: required by a bound in `foo_defn::Foo::Bar`
   --> $DIR/auxiliary/foo_defn.rs:4:15
    |
 LL |     type Bar: AsRef<()>;
-   |               ^^^^^^^^^ required by this bound in `foo_defn::Foo::Bar`
+   |               ^^^^^^^^^ required by this bound in `Foo::Bar`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-101020.stderr b/src/test/ui/generic-associated-types/issue-101020.stderr
index b4e94cb83f7..422ac548427 100644
--- a/src/test/ui/generic-associated-types/issue-101020.stderr
+++ b/src/test/ui/generic-associated-types/issue-101020.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied
-  --> $DIR/issue-101020.rs:31:5
+  --> $DIR/issue-101020.rs:31:22
    |
 LL |     (&mut EmptyIter).consume(());
-   |     ^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |     |
-   |     the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
+   |                      ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
    |
 note: required for `&'a mut ()` to implement `for<'a> FuncInput<'a, &'a mut ()>`
   --> $DIR/issue-101020.rs:27:20
diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr
index 0475eb908a7..b48966a1a1e 100644
--- a/src/test/ui/generics/wrong-number-of-args.stderr
+++ b/src/test/ui/generics/wrong-number-of-args.stderr
@@ -889,11 +889,6 @@ error[E0107]: missing generics for struct `HashMap`
 LL |         type A = HashMap;
    |                  ^^^^^^^ expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type A = HashMap<K, V>;
@@ -907,11 +902,6 @@ LL |         type B = HashMap<String>;
    |                  |
    |                  expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic argument
    |
 LL |         type B = HashMap<String, V>;
@@ -924,12 +914,6 @@ LL |         type C = HashMap<'static>;
    |                  ^^^^^^^--------- help: remove these generics
    |                  |
    |                  expected 0 lifetime arguments
-   |
-note: struct defined here, with 0 lifetime parameters
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^
 
 error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:318:18
@@ -937,11 +921,6 @@ error[E0107]: this struct takes at least 2 generic arguments but 0 generic argum
 LL |         type C = HashMap<'static>;
    |                  ^^^^^^^ expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type C = HashMap<'static, K, V>;
@@ -954,12 +933,6 @@ LL |         type D = HashMap<usize, String, char, f64>;
    |                  ^^^^^^^                      --- help: remove this generic argument
    |                  |
    |                  expected at most 3 generic arguments
-   |
-note: struct defined here, with at most 3 generic parameters: `K`, `V`, `S`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -  ---------------
 
 error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:328:18
@@ -967,11 +940,6 @@ error[E0107]: this struct takes at least 2 generic arguments but 0 generic argum
 LL |         type E = HashMap<>;
    |                  ^^^^^^^ expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type E = HashMap<K, V>;
@@ -983,11 +951,6 @@ error[E0107]: missing generics for enum `Result`
 LL |         type A = Result;
    |                  ^^^^^^ expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type A = Result<T, E>;
@@ -1001,11 +964,6 @@ LL |         type B = Result<String>;
    |                  |
    |                  expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL |         type B = Result<String, E>;
@@ -1018,12 +976,6 @@ LL |         type C = Result<'static>;
    |                  ^^^^^^--------- help: remove these generics
    |                  |
    |                  expected 0 lifetime arguments
-   |
-note: enum defined here, with 0 lifetime parameters
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^
 
 error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:342:18
@@ -1031,11 +983,6 @@ error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were s
 LL |         type C = Result<'static>;
    |                  ^^^^^^ expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type C = Result<'static, T, E>;
@@ -1048,12 +995,6 @@ LL |         type D = Result<usize, String, char>;
    |                  ^^^^^^                ---- help: remove this generic argument
    |                  |
    |                  expected 2 generic arguments
-   |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 
 error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:352:18
@@ -1061,11 +1002,6 @@ error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were s
 LL |         type E = Result<>;
    |                  ^^^^^^ expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type E = Result<T, E>;
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
index a6f8563a047..095a1c6af37 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [_, 99.., _] => {},
-   |             ^^ expected struct `std::ops::Range`, found integer
+   |             ^^ expected struct `Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
index 4e0102c930d..2ea3205dcd4 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [_, 99..] => {},
-   |             ^^ expected struct `std::ops::Range`, found integer
+   |             ^^ expected struct `Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
index 790a1337228..bbdf0c83f62 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [..9, 99..100, _] => {},
-   |            ^ expected struct `std::ops::Range`, found integer
+   |            ^ expected struct `Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
@@ -17,7 +17,7 @@ LL |     match [5..4, 99..105, 43..44] {
 LL |         [..9, 99..100, _] => {},
    |               ^^  --- this is of type `{integer}`
    |               |
-   |               expected struct `std::ops::Range`, found integer
+   |               expected struct `Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
@@ -28,7 +28,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [..9, 99..100, _] => {},
-   |               --  ^^^ expected struct `std::ops::Range`, found integer
+   |               --  ^^^ expected struct `Range`, found integer
    |               |
    |               this is of type `{integer}`
    |
diff --git a/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs
new file mode 100644
index 00000000000..d34b7a29623
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs
@@ -0,0 +1,16 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+fn id(
+    f: &dyn Fn(u32),
+) -> &dyn Fn(
+    &dyn Fn(
+        &dyn Fn(
+            &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+        ),
+    ),
+) {
+    f
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
new file mode 100644
index 00000000000..71e196c3227
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/hang-on-deeply-nested-dyn.rs:12:5
+   |
+LL |   ) -> &dyn Fn(
+   |  ______-
+LL | |     &dyn Fn(
+LL | |         &dyn Fn(
+LL | |             &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+LL | |         ),
+LL | |     ),
+LL | | ) {
+   | |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
+LL |       f
+   |       ^ expected reference, found `u32`
+   |
+   = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a ...) + 'a)) + 'a)) + 'a))`
+           the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
+              found reference `&dyn Fn(u32)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr
index c1e235441d6..0458d2535f2 100644
--- a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr
@@ -1,4 +1,4 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>`, but its trait bounds were not satisfied
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@issue-30786.rs:117:27]>`, but its trait bounds were not satisfied
   --> $DIR/issue-30786.rs:118:22
    |
 LL | pub struct Map<S, F> {
@@ -8,7 +8,7 @@ LL | pub struct Map<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let filter = map.filterx(|x: &_| true);
-   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>` due to unsatisfied trait bounds
+   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@issue-30786.rs:117:27]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
       `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
@@ -19,7 +19,7 @@ note: the following trait bounds were not satisfied:
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
 
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied
   --> $DIR/issue-30786.rs:130:24
    |
 LL | pub struct Filter<S, F> {
@@ -29,7 +29,7 @@ LL | pub struct Filter<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let count = filter.countx();
-   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds
+   |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
       `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
index ab5598e364f..fdd192f4313 100644
--- a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
@@ -30,7 +30,7 @@ LL |     where
 LL |         F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
    |                                                   ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
 
-error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]` to be a closure that returns `Unit3`, but it returns `Unit4`
+error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4`
   --> $DIR/issue-62203-hrtb-ice.rs:39:9
    |
 LL |       let v = Unit2.m(
diff --git a/src/test/ui/issues/issue-15221.rs b/src/test/ui/hygiene/issue-15221.rs
index 4b8319a8304..4b8319a8304 100644
--- a/src/test/ui/issues/issue-15221.rs
+++ b/src/test/ui/hygiene/issue-15221.rs
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.rs b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs
new file mode 100644
index 00000000000..deb84f6fe97
--- /dev/null
+++ b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs
@@ -0,0 +1,34 @@
+struct MutType;
+
+pub trait MutTrait {
+    fn function(&mut self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl MutTrait for MutType {
+    fn function(&mut self) {}
+}
+
+struct Type;
+
+pub trait Trait {
+    fn function(&self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl Trait for Type {
+    fn function(&self) {}
+}
+
+fn main() {
+    (&MutType as &dyn MutTrait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+    //~| NOTE you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+    (&mut Type as &mut dyn Trait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+    //~| NOTE you need `&dyn Trait` instead of `&mut dyn Trait`
+}
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr
new file mode 100644
index 00000000000..dbbf79a4f1a
--- /dev/null
+++ b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr
@@ -0,0 +1,24 @@
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/mutability-mismatch.rs:28:33
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&MutType as &dyn MutTrait).function();
+   |                                 ^^^^^^^^
+   |
+   = note: you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/mutability-mismatch.rs:31:35
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&mut Type as &mut dyn Trait).function();
+   |                                   ^^^^^^^^
+   |
+   = note: you need `&dyn Trait` instead of `&mut dyn Trait`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/illegal-sized-bound/regular.rs b/src/test/ui/illegal-sized-bound/regular.rs
new file mode 100644
index 00000000000..7abd27ef983
--- /dev/null
+++ b/src/test/ui/illegal-sized-bound/regular.rs
@@ -0,0 +1,32 @@
+struct MutType;
+
+pub trait MutTrait {
+    fn function(&mut self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl MutTrait for MutType {
+    fn function(&mut self) {}
+}
+
+struct Type;
+
+pub trait Trait {
+    fn function(&self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl Trait for Type {
+    fn function(&self) {}
+}
+
+fn main() {
+    (&mut MutType as &mut dyn MutTrait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+    (&Type as &dyn Trait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+}
diff --git a/src/test/ui/illegal-sized-bound/regular.stderr b/src/test/ui/illegal-sized-bound/regular.stderr
new file mode 100644
index 00000000000..7f3744145d9
--- /dev/null
+++ b/src/test/ui/illegal-sized-bound/regular.stderr
@@ -0,0 +1,20 @@
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/regular.rs:28:41
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&mut MutType as &mut dyn MutTrait).function();
+   |                                         ^^^^^^^^
+
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/regular.rs:30:27
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&Type as &dyn Trait).function();
+   |                           ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
index f90399b6b94..7f73d5e12d1 100644
--- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
+++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -70,10 +70,6 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bak() -> dyn Trait { unimplemented!() }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
-   |
-LL | fn bak() -> T { unimplemented!() }
-   |             ~
 help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature
    |
 LL | fn bak() -> impl Trait { unimplemented!() }
diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.stderr b/src/test/ui/impl-trait/impl-generic-mismatch.stderr
index 542f02d7ec5..973b65bfd62 100644
--- a/src/test/ui/impl-trait/impl-generic-mismatch.stderr
+++ b/src/test/ui/impl-trait/impl-generic-mismatch.stderr
@@ -46,11 +46,9 @@ error[E0643]: method `hash` has incompatible signature for trait
    |
 LL |     fn hash(&self, hasher: &mut impl Hasher) {}
    |                                 ^^^^^^^^^^^ expected generic parameter, found `impl Trait`
+  --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
-   |
-LL |     fn hash<H: Hasher>(&self, state: &mut H);
-   |             - declaration in trait here
+   = note: declaration in trait here
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/impl-trait/in-trait/wf-bounds.stderr b/src/test/ui/impl-trait/in-trait/wf-bounds.stderr
index 92e36841b70..03cc4c2b93b 100644
--- a/src/test/ui/impl-trait/in-trait/wf-bounds.stderr
+++ b/src/test/ui/impl-trait/in-trait/wf-bounds.stderr
@@ -7,9 +7,6 @@ LL |     fn nya() -> impl Wf<Vec<[u8]>>;
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/wf-bounds.rs:12:23
diff --git a/src/test/ui/impl-trait/issues/issue-62742.stderr b/src/test/ui/impl-trait/issues/issue-62742.stderr
index 34f4dc2cef3..bc342dc4689 100644
--- a/src/test/ui/impl-trait/issues/issue-62742.stderr
+++ b/src/test/ui/impl-trait/issues/issue-62742.stderr
@@ -25,7 +25,7 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
    |
    = note: the following trait bounds were not satisfied:
            `RawImpl<()>: Raw<()>`
-note: the following trait must be implemented
+note: the trait `Raw` must be implemented
   --> $DIR/issue-62742.rs:12:1
    |
 LL | pub trait Raw<T: ?Sized> {
diff --git a/src/test/ui/impl-trait/issues/issue-86719.stderr b/src/test/ui/impl-trait/issues/issue-86719.stderr
index 09047cdcbe1..7592418fdfd 100644
--- a/src/test/ui/impl-trait/issues/issue-86719.stderr
+++ b/src/test/ui/impl-trait/issues/issue-86719.stderr
@@ -20,8 +20,8 @@ LL |         |_| true
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |_: _| true
-   |           +++
+LL |         |_: /* Type */| true
+   |           ++++++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/impl-trait/issues/issue-92305.stderr b/src/test/ui/impl-trait/issues/issue-92305.stderr
index 34d5c2d61dc..f09c14d3df1 100644
--- a/src/test/ui/impl-trait/issues/issue-92305.stderr
+++ b/src/test/ui/impl-trait/issues/issue-92305.stderr
@@ -4,11 +4,6 @@ error[E0107]: missing generics for struct `Vec`
 LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> {
    |                                             ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |            ^^^ -
 help: add missing generic argument
    |
 LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> {
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
index 3d4ae11e576..548c89d0a38 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -145,11 +145,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method2` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:50:37
    |
 LL |     no_method_suggested_traits::Foo.method2();
-   |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+   |                                     ^^^^^^^ method not found in `Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -158,11 +158,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:52:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
-   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -171,11 +171,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method2` found for enum `Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:54:40
    |
 LL |     no_method_suggested_traits::Bar::X.method2();
-   |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+   |                                        ^^^^^^^ method not found in `Bar`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -184,11 +184,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:56:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
-   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -255,29 +255,29 @@ error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&usize>>`
 LL |     std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
    |                                               ^^^^^^^ method not found in `Rc<&mut Box<&usize>>`
 
-error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:71:37
    |
 LL |     no_method_suggested_traits::Foo.method3();
-   |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+   |                                     ^^^^^^^ method not found in `Foo`
 
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:72:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
-   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
 
-error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:74:40
    |
 LL |     no_method_suggested_traits::Bar::X.method3();
-   |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+   |                                        ^^^^^^^ method not found in `Bar`
 
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:75:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
-   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
 
 error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index 3dda5761ada..3ee26f74a78 100644
--- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -15,7 +15,7 @@ LL |     type Foo = impl PartialEq<(Foo, i32)>;
 LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
    |                              ^^^^^^^^^^^
    |                              |
-   |                              expected struct `a::Bar`, found opaque type
+   |                              expected struct `Bar`, found opaque type
    |                              help: change the parameter type to match the trait: `&(a::Bar, i32)`
    |
    = note: expected fn pointer `fn(&a::Bar, &(a::Bar, i32)) -> _`
@@ -38,7 +38,7 @@ LL |     type Foo = impl PartialEq<(Foo, i32)>;
 LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    |                              ^^^^^^^^^^^
    |                              |
-   |                              expected opaque type, found struct `b::Bar`
+   |                              expected opaque type, found struct `Bar`
    |                              help: change the parameter type to match the trait: `&(b::Foo, i32)`
    |
    = note: expected fn pointer `fn(&b::Bar, &(b::Foo, i32)) -> _`
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr
index c31c8840381..ade479ed102 100644
--- a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr
+++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr
@@ -24,11 +24,8 @@ LL |         extern crate std as Vec;
 ...
 LL | define_vec!();
    | ------------- in this macro invocation
-note: `Vec` could also refer to the struct defined here
+note: `Vec` could also refer to a struct from prelude
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
-   |
-LL |     pub use super::v1::*;
-   |             ^^^^^^^^^^^^
    = note: this error originates in the macro `define_vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-26930.rs b/src/test/ui/imports/issue-26930.rs
index 707e71b1124..707e71b1124 100644
--- a/src/test/ui/issues/issue-26930.rs
+++ b/src/test/ui/imports/issue-26930.rs
diff --git a/src/test/ui/inference/erase-type-params-in-label.stderr b/src/test/ui/inference/erase-type-params-in-label.stderr
index 5c52e7bcfab..9be18286480 100644
--- a/src/test/ui/inference/erase-type-params-in-label.stderr
+++ b/src/test/ui/inference/erase-type-params-in-label.stderr
@@ -10,10 +10,10 @@ note: required by a bound in `foo`
    |
 LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
    |                 ^^^^^^^ required by this bound in `foo`
-help: consider specifying the type arguments in the function call
+help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified
    |
-LL |     let foo = foo::<T, K, W, Z>(1, "");
-   |                  ++++++++++++++
+LL |     let foo: Foo<i32, &str, W, Z> = foo(1, "");
+   |            ++++++++++++++++++++++
 
 error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
   --> $DIR/erase-type-params-in-label.rs:5:9
@@ -27,10 +27,10 @@ note: required by a bound in `bar`
    |
 LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
    |                 ^^^^^^^ required by this bound in `bar`
-help: consider specifying the type arguments in the function call
+help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified
    |
-LL |     let bar = bar::<T, K, Z>(1, "");
-   |                  +++++++++++
+LL |     let bar: Bar<i32, &str, Z> = bar(1, "");
+   |            +++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/inference/issue-71732.stderr b/src/test/ui/inference/issue-71732.stderr
index 79bee33280d..01b37f2acaa 100644
--- a/src/test/ui/inference/issue-71732.stderr
+++ b/src/test/ui/inference/issue-71732.stderr
@@ -12,9 +12,6 @@ LL |         .get(&"key".into())
              where T: ?Sized;
 note: required by a bound in `HashMap::<K, V, S>::get`
   --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL |         K: Borrow<Q>,
-   |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
 help: consider specifying the generic argument
    |
 LL |         .get::<Q>(&"key".into())
diff --git a/src/test/ui/inference/issue-72690.stderr b/src/test/ui/inference/issue-72690.stderr
index d4eeda07366..8eda71ec09b 100644
--- a/src/test/ui/inference/issue-72690.stderr
+++ b/src/test/ui/inference/issue-72690.stderr
@@ -32,8 +32,8 @@ LL |     |x| String::from("x".as_ref());
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     |x: _| String::from("x".as_ref());
-   |       +++
+LL |     |x: /* Type */| String::from("x".as_ref());
+   |       ++++++++++++
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:12:26
diff --git a/src/test/ui/inline-const/expr-unsafe-err.mir.stderr b/src/test/ui/inline-const/expr-unsafe-err.mir.stderr
new file mode 100644
index 00000000000..1bec41e2efa
--- /dev/null
+++ b/src/test/ui/inline-const/expr-unsafe-err.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/expr-unsafe-err.rs:8:9
+   |
+LL |         require_unsafe();
+   |         ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/inline-const/expr-unsafe-err.rs b/src/test/ui/inline-const/expr-unsafe-err.rs
new file mode 100644
index 00000000000..adf05d352ea
--- /dev/null
+++ b/src/test/ui/inline-const/expr-unsafe-err.rs
@@ -0,0 +1,11 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+#![feature(inline_const)]
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    const {
+        require_unsafe();
+        //~^ ERROR [E0133]
+    }
+}
diff --git a/src/test/ui/inline-const/expr-unsafe-err.thir.stderr b/src/test/ui/inline-const/expr-unsafe-err.thir.stderr
new file mode 100644
index 00000000000..c971e8afb35
--- /dev/null
+++ b/src/test/ui/inline-const/expr-unsafe-err.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
+  --> $DIR/expr-unsafe-err.rs:8:9
+   |
+LL |         require_unsafe();
+   |         ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/inline-const/expr-unsafe.mir.stderr b/src/test/ui/inline-const/expr-unsafe.mir.stderr
new file mode 100644
index 00000000000..1ab6e42fba0
--- /dev/null
+++ b/src/test/ui/inline-const/expr-unsafe.mir.stderr
@@ -0,0 +1,14 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/expr-unsafe.rs:12:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/expr-unsafe.rs:4:9
+   |
+LL | #![warn(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/inline-const/expr-unsafe.rs b/src/test/ui/inline-const/expr-unsafe.rs
new file mode 100644
index 00000000000..d71efd33db1
--- /dev/null
+++ b/src/test/ui/inline-const/expr-unsafe.rs
@@ -0,0 +1,16 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+#![warn(unused_unsafe)]
+#![feature(inline_const)]
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    unsafe {
+        const {
+            require_unsafe();
+            unsafe {}
+            //~^ WARNING unnecessary `unsafe` block
+        }
+    }
+}
diff --git a/src/test/ui/inline-const/expr-unsafe.thir.stderr b/src/test/ui/inline-const/expr-unsafe.thir.stderr
new file mode 100644
index 00000000000..4737444fb61
--- /dev/null
+++ b/src/test/ui/inline-const/expr-unsafe.thir.stderr
@@ -0,0 +1,17 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/expr-unsafe.rs:12:13
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+...
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/expr-unsafe.rs:4:9
+   |
+LL | #![warn(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/inline-const/pat-unsafe-err.rs b/src/test/ui/inline-const/pat-unsafe-err.rs
new file mode 100644
index 00000000000..e290b438c51
--- /dev/null
+++ b/src/test/ui/inline-const/pat-unsafe-err.rs
@@ -0,0 +1,17 @@
+// ignore-test This is currently broken
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(incomplete_features)]
+#![feature(inline_const_pat)]
+
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    match () {
+        const {
+            require_unsafe();
+            //~^ ERROR [E0133]
+        } => (),
+    }
+}
diff --git a/src/test/ui/inline-const/pat-unsafe.rs b/src/test/ui/inline-const/pat-unsafe.rs
new file mode 100644
index 00000000000..bcf7f6e0180
--- /dev/null
+++ b/src/test/ui/inline-const/pat-unsafe.rs
@@ -0,0 +1,22 @@
+// ignore-test This is currently broken
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(incomplete_features)]
+#![warn(unused_unsafe)]
+#![feature(inline_const_pat)]
+
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    unsafe {
+        match () {
+            const {
+                require_unsafe();
+                unsafe {}
+                //~^ WARNING unnecessary `unsafe` block
+            } => (),
+        }
+    }
+}
diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr
index 94f41c92598..034d22591b3 100644
--- a/src/test/ui/interior-mutability/interior-mutability.stderr
+++ b/src/test/ui/interior-mutability/interior-mutability.stderr
@@ -16,9 +16,6 @@ LL |     catch_unwind(|| { x.set(23); });
    |                  ^^
 note: required by a bound in `catch_unwind`
   --> $SRC_DIR/std/src/panic.rs:LL:COL
-   |
-LL | pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
-   |                                        ^^^^^^^^^^ required by this bound in `catch_unwind`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr
index 3720528ad4e..fd7d061b6b2 100644
--- a/src/test/ui/intrinsics/const-eval-select-bad.stderr
+++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr
@@ -37,9 +37,6 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         F: FnOnce<ARG, Output = RET>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error: this argument must be a function item
   --> $DIR/const-eval-select-bad.rs:10:31
@@ -62,9 +59,6 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         G: FnOnce<ARG, Output = RET>,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error[E0271]: expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
   --> $DIR/const-eval-select-bad.rs:32:34
@@ -76,9 +70,6 @@ LL |     const_eval_select((1,), foo, bar);
    |
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         G: FnOnce<ARG, Output = RET>,
-   |                        ^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/const-eval-select-bad.rs:37:32
@@ -95,9 +86,6 @@ LL |     const_eval_select((true,), foo, baz);
               found function signature `fn(i32) -> _`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         F: FnOnce<ARG, Output = RET>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error: this argument must be a `const fn`
   --> $DIR/const-eval-select-bad.rs:42:29
diff --git a/src/test/ui/issues/issue-105330.stderr b/src/test/ui/issues/issue-105330.stderr
index 92f2ccb6544..30c380152a5 100644
--- a/src/test/ui/issues/issue-105330.stderr
+++ b/src/test/ui/issues/issue-105330.stderr
@@ -55,8 +55,10 @@ error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
   --> $DIR/issue-105330.rs:12:11
    |
 LL |     foo::<Demo>()();
-   |           ^^^^ types differ
+   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
    |
+   = note: expected constant `32`
+              found constant `<Demo as TraitWAssocConst>::A`
 note: required by a bound in `foo`
   --> $DIR/issue-105330.rs:11:28
    |
@@ -89,8 +91,10 @@ error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
   --> $DIR/issue-105330.rs:19:11
    |
 LL |     foo::<Demo>();
-   |           ^^^^ types differ
+   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
    |
+   = note: expected constant `32`
+              found constant `<Demo as TraitWAssocConst>::A`
 note: required by a bound in `foo`
   --> $DIR/issue-105330.rs:11:28
    |
diff --git a/src/test/ui/issues/issue-12567.stderr b/src/test/ui/issues/issue-12567.stderr
index 3ce659ccd14..7fa06825f0f 100644
--- a/src/test/ui/issues/issue-12567.stderr
+++ b/src/test/ui/issues/issue-12567.stderr
@@ -11,6 +11,14 @@ LL |         (&[hd1, ..], &[hd2, ..])
    |            --- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
+   |                 +++
+help: consider borrowing the pattern binding
+   |
+LL |         (&[ref hd1, ..], &[hd2, ..])
+   |            +++
 
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
   --> $DIR/issue-12567.rs:2:11
@@ -25,6 +33,14 @@ LL |         (&[hd1, ..], &[hd2, ..])
    |                        --- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
+   |                 +++
+help: consider borrowing the pattern binding
+   |
+LL |         (&[hd1, ..], &[ref hd2, ..])
+   |                        +++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-14091-2.stderr b/src/test/ui/issues/issue-14091-2.stderr
index a191afd7980..f8375d4ef90 100644
--- a/src/test/ui/issues/issue-14091-2.stderr
+++ b/src/test/ui/issues/issue-14091-2.stderr
@@ -9,11 +9,8 @@ note: an implementation of `Not` might be missing for `BytePos`
    |
 LL | pub struct BytePos(pub u32);
    | ^^^^^^^^^^^^^^^^^^ must implement `Not`
-note: the following trait must be implemented
+note: the trait `Not` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Not {
-   | ^^^^^^^^^^^^^
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-14092.stderr b/src/test/ui/issues/issue-14092.stderr
index 7928b3fba27..132e2b101a5 100644
--- a/src/test/ui/issues/issue-14092.stderr
+++ b/src/test/ui/issues/issue-14092.stderr
@@ -4,13 +4,6 @@ error[E0107]: missing generics for struct `Box`
 LL | fn fn1(0: Box) {}
    |           ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | pub struct Box<
-   |            ^^^
-LL |     T: ?Sized,
-   |     -
 help: add missing generic argument
    |
 LL | fn fn1(0: Box<T>) {}
diff --git a/src/test/ui/issues/issue-16966.stderr b/src/test/ui/issues/issue-16966.stderr
index 8524a62a0a4..60f5190dbd0 100644
--- a/src/test/ui/issues/issue-16966.stderr
+++ b/src/test/ui/issues/issue-16966.stderr
@@ -5,11 +5,6 @@ LL |     panic!(std::default::Default::default());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `M` declared on the function `begin_panic`
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider specifying the generic argument
-  --> $SRC_DIR/std/src/panic.rs:LL:COL
-   |
-LL |         $crate::rt::begin_panic::<M>($msg)
-   |                                +++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index 16678c8c8a9..81592320a27 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -3,11 +3,9 @@ error[E0573]: expected type, found variant `NoResult`
    |
 LL |     fn new() -> NoResult<MyEnum, String> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | --------------------- similarly named enum `Result` defined here
+   = note: similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
@@ -57,11 +55,9 @@ error[E0573]: expected type, found variant `NoResult`
    |
 LL | fn newer() -> NoResult<foo::MyEnum, String> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | --------------------- similarly named enum `Result` defined here
+   = note: similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr
index efaaeeda2fa..b37811e1955 100644
--- a/src/test/ui/issues/issue-17651.stderr
+++ b/src/test/ui/issues/issue-17651.stderr
@@ -9,9 +9,6 @@ LL |     (|| Box::new(*(&[0][..])))();
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by a bound in `Box::<T>::new`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T> Box<T> {
-   |      ^ required by this bound in `Box::<T>::new`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18107.stderr b/src/test/ui/issues/issue-18107.stderr
index 28478457b29..1669b550a9b 100644
--- a/src/test/ui/issues/issue-18107.stderr
+++ b/src/test/ui/issues/issue-18107.stderr
@@ -4,10 +4,6 @@ error[E0746]: return type cannot have an unboxed trait object
 LL |     dyn AbstractRenderer
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
-   |
-LL |     T
-   |
 help: use `impl AbstractRenderer` as the return type if all return paths have the same type but you want to expose only the trait in the signature
    |
 LL |     impl AbstractRenderer
diff --git a/src/test/ui/issues/issue-18159.stderr b/src/test/ui/issues/issue-18159.stderr
index 605ff3829d1..5e0589eed43 100644
--- a/src/test/ui/issues/issue-18159.stderr
+++ b/src/test/ui/issues/issue-18159.stderr
@@ -6,8 +6,8 @@ LL |     let x;
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _;
-   |          +++
+LL |     let x: /* Type */;
+   |          ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18423.stderr b/src/test/ui/issues/issue-18423.stderr
index 4711a3f3ce0..bbf79366244 100644
--- a/src/test/ui/issues/issue-18423.stderr
+++ b/src/test/ui/issues/issue-18423.stderr
@@ -5,12 +5,6 @@ LL |     x: Box<'a, isize>
    |        ^^^ -- help: remove this lifetime argument
    |        |
    |        expected 0 lifetime arguments
-   |
-note: struct defined here, with 0 lifetime parameters
-  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | pub struct Box<
-   |            ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20162.stderr b/src/test/ui/issues/issue-20162.stderr
index 3f9b3be9851..1c5b76fbfc1 100644
--- a/src/test/ui/issues/issue-20162.stderr
+++ b/src/test/ui/issues/issue-20162.stderr
@@ -1,16 +1,11 @@
 error[E0277]: the trait bound `X: Ord` is not satisfied
-  --> $DIR/issue-20162.rs:5:5
+  --> $DIR/issue-20162.rs:5:7
    |
 LL |     b.sort();
-   |     ^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `Ord` is not implemented for `X`
+   |       ^^^^ the trait `Ord` is not implemented for `X`
    |
 note: required by a bound in `slice::<impl [T]>::sort`
   --> $SRC_DIR/alloc/src/slice.rs:LL:COL
-   |
-LL |         T: Ord,
-   |            ^^^ required by this bound in `slice::<impl [T]>::sort`
 help: consider annotating `X` with `#[derive(Ord)]`
    |
 LL | #[derive(Ord)]
diff --git a/src/test/ui/issues/issue-20433.stderr b/src/test/ui/issues/issue-20433.stderr
index 9d3bb8b924d..3ae952546a6 100644
--- a/src/test/ui/issues/issue-20433.stderr
+++ b/src/test/ui/issues/issue-20433.stderr
@@ -7,9 +7,6 @@ LL |     fn iceman(c: Vec<[i32]>) {}
    = help: the trait `Sized` is not implemented for `[i32]`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-2151.stderr b/src/test/ui/issues/issue-2151.stderr
index 31a8ca5fbfa..c75038b6169 100644
--- a/src/test/ui/issues/issue-2151.stderr
+++ b/src/test/ui/issues/issue-2151.stderr
@@ -8,8 +8,8 @@ LL |     x.clone();
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = panic!();
-   |          +++
+LL |     let x: /* Type */ = panic!();
+   |          ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr
index 4e010a13653..2d60b18b1f2 100644
--- a/src/test/ui/issues/issue-21974.stderr
+++ b/src/test/ui/issues/issue-21974.stderr
@@ -4,7 +4,13 @@ error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo`
 LL |     where &'a T : Foo,
    |                   ^^^
    |
-   = note: cannot satisfy `&'a T: Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found
+  --> $DIR/issue-21974.rs:11:19
+   |
+LL |     where &'a T : Foo,
+   |                   ^^^
+LL |           &'b T : Foo
+   |                   ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr
index dc8b34a70c3..014eb2897b4 100644
--- a/src/test/ui/issues/issue-23024.stderr
+++ b/src/test/ui/issues/issue-23024.stderr
@@ -13,11 +13,6 @@ error[E0107]: missing generics for trait `Fn`
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
    |                                       ^^ expected 1 generic argument
    |
-note: trait defined here, with 1 generic parameter: `Args`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   |           ^^ ----
 help: add missing generic argument
    |
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn<Args>)(3));
diff --git a/src/test/ui/issues/issue-23966.stderr b/src/test/ui/issues/issue-23966.stderr
index ae8233d5c76..8f934481d85 100644
--- a/src/test/ui/issues/issue-23966.stderr
+++ b/src/test/ui/issues/issue-23966.stderr
@@ -9,9 +9,6 @@ LL |     "".chars().fold(|_, _| (), ());
    = help: the trait `FnMut<(_, char)>` is not implemented for `()`
 note: required by a bound in `fold`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(B, Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fold`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-24036.stderr b/src/test/ui/issues/issue-24036.stderr
index a42e35c4cad..0e73a51faed 100644
--- a/src/test/ui/issues/issue-24036.stderr
+++ b/src/test/ui/issues/issue-24036.stderr
@@ -19,8 +19,8 @@ LL |         1 => |c| c + 1,
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         1 => |c: _| c + 1,
-   |                +++
+LL |         1 => |c: /* Type */| c + 1,
+   |                ++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr
index 8f3b2ac7319..50d7f988e19 100644
--- a/src/test/ui/issues/issue-24424.stderr
+++ b/src/test/ui/issues/issue-24424.stderr
@@ -4,7 +4,11 @@ error[E0283]: type annotations needed: cannot satisfy `T0: Trait0<'l0>`
 LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
    |                                                         ^^^^^^^^^^^
    |
-   = note: cannot satisfy `T0: Trait0<'l0>`
+note: multiple `impl`s or `where` clauses satisfying `T0: Trait0<'l0>` found
+  --> $DIR/issue-24424.rs:4:57
+   |
+LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
+   |                                                         ^^^^^^^^^^^       ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-27033.stderr b/src/test/ui/issues/issue-27033.stderr
index 9a38d49cd0c..7a0ca888d74 100644
--- a/src/test/ui/issues/issue-27033.stderr
+++ b/src/test/ui/issues/issue-27033.stderr
@@ -3,11 +3,9 @@ error[E0530]: match bindings cannot shadow unit variants
    |
 LL |         None @ _ => {}
    |         ^^^^ cannot be named the same as a unit variant
+  --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/prelude/mod.rs:LL:COL
-   |
-LL |     pub use super::v1::*;
-   |             ------------ the unit variant `None` is defined here
+   = note: the unit variant `None` is defined here
 
 error[E0530]: match bindings cannot shadow constants
   --> $DIR/issue-27033.rs:7:9
diff --git a/src/test/ui/issues/issue-30123.stderr b/src/test/ui/issues/issue-30123.stderr
index e9d934332f1..7808cbf8aa1 100644
--- a/src/test/ui/issues/issue-30123.stderr
+++ b/src/test/ui/issues/issue-30123.stderr
@@ -1,8 +1,8 @@
-error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
+error[E0599]: no function or associated item named `new_undirected` found for struct `Graph<i32, i32>` in the current scope
   --> $DIR/issue-30123.rs:7:33
    |
 LL |     let ug = Graph::<i32, i32>::new_undirected();
-   |                                 ^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph<i32, i32>`
+   |                                 ^^^^^^^^^^^^^^ function or associated item not found in `Graph<i32, i32>`
    |
    = note: the function or associated item was found for
            - `issue_30123_aux::Graph<N, E, Undirected>`
diff --git a/src/test/ui/issues/issue-3044.stderr b/src/test/ui/issues/issue-3044.stderr
index a4c455ca192..2b142f688ec 100644
--- a/src/test/ui/issues/issue-3044.stderr
+++ b/src/test/ui/issues/issue-3044.stderr
@@ -9,9 +9,6 @@ LL | |     });
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn fold<B, F>(mut self, init: B, mut f: F) -> B
-   |        ^^^^
 help: provide the argument
    |
 LL ~     needlesArr.iter().fold(|x, y| {
diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/issues/issue-31173.rs
index 04efa27189b..f678df5b42b 100644
--- a/src/test/ui/issues/issue-31173.rs
+++ b/src/test/ui/issues/issue-31173.rs
@@ -4,12 +4,11 @@ pub fn get_tok(it: &mut IntoIter<u8>) {
     let mut found_e = false;
 
     let temp: Vec<u8> = it
-        //~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .take_while(|&x| {
             found_e = true;
             false
         })
-        .cloned()
+        .cloned() //~ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .collect(); //~ ERROR the method
 }
 
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr
index e3334eef3ad..f3be99f9bcb 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -1,46 +1,43 @@
-error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>` to be an iterator that yields `&_`, but it yields `u8`
-  --> $DIR/issue-31173.rs:6:25
+error[E0271]: expected `TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>` to be an iterator that yields `&_`, but it yields `u8`
+  --> $DIR/issue-31173.rs:11:10
    |
-LL |       let temp: Vec<u8> = it
-   |  _________________________^
-LL | |
-LL | |         .take_while(|&x| {
-LL | |             found_e = true;
-LL | |             false
-LL | |         })
-   | |__________^ expected reference, found `u8`
-LL |           .cloned()
-   |            ------ required by a bound introduced by this call
+LL |         .cloned()
+   |          ^^^^^^ expected reference, found `u8`
    |
    = note: expected reference `&_`
                    found type `u8`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-31173.rs:3:20
+   |
+LL |   pub fn get_tok(it: &mut IntoIter<u8>) {
+   |                      ^^^^^^^^^^^^^^^^^ `Iterator::Item` is `u8` here
+...
+LL |           .take_while(|&x| {
+   |  __________-
+LL | |             found_e = true;
+LL | |             false
+LL | |         })
+   | |__________- `Iterator::Item` remains `u8` here
 note: required by a bound in `cloned`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         Self: Sized + Iterator<Item = &'a T>,
-   |                                ^^^^^^^^^^^^ required by this bound in `cloned`
 
-error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>`, but its trait bounds were not satisfied
-  --> $DIR/issue-31173.rs:13:10
+error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied
+  --> $DIR/issue-31173.rs:12:10
    |
 LL |         .collect();
-   |          ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>` due to unsatisfied trait bounds
-   |
-  ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
-   |
-LL | pub struct TakeWhile<I, P> {
-   | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_`
+   |          ^^^^^^^ method cannot be called due to unsatisfied trait bounds
+  --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
+   = note: doesn't satisfy `<_ as Iterator>::Item = &_`
+  --> $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
    |
-LL | pub struct Cloned<I> {
-   | -------------------- doesn't satisfy `_: Iterator`
+   = note: doesn't satisfy `_: Iterator`
    |
    = note: the following trait bounds were not satisfied:
-           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]> as Iterator>::Item = &_`
-           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
-           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
-           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
+           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_`
+           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr
index 5a758c7002b..b8362499b2d 100644
--- a/src/test/ui/issues/issue-32655.stderr
+++ b/src/test/ui/issues/issue-32655.stderr
@@ -6,11 +6,9 @@ LL |         #[derive_Clone]
 ...
 LL | foo!();
    | ------ in this macro invocation
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     pub macro derive_const($item:item) {
-   |     ---------------------- similarly named attribute macro `derive_const` defined here
+   = note: similarly named attribute macro `derive_const` defined here
    |
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -19,11 +17,9 @@ error: cannot find attribute `derive_Clone` in this scope
    |
 LL |     #[derive_Clone]
    |       ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     pub macro derive_const($item:item) {
-   |     ---------------------- similarly named attribute macro `derive_const` defined here
+   = note: similarly named attribute macro `derive_const` defined here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs
index 8430e85df87..e3b6dcf55a7 100644
--- a/src/test/ui/issues/issue-33941.rs
+++ b/src/test/ui/issues/issue-33941.rs
@@ -3,7 +3,7 @@
 use std::collections::HashMap;
 
 fn main() {
-    for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-    //~^ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-    //~| ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+    for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+    //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+    //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
 }
diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr
index 691b8f88f4e..668eaabca4c 100644
--- a/src/test/ui/issues/issue-33941.stderr
+++ b/src/test/ui/issues/issue-33941.stderr
@@ -1,20 +1,22 @@
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-  --> $DIR/issue-33941.rs:6:14
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+  --> $DIR/issue-33941.rs:6:36
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^ ------ required by a bound introduced by this call
-   |              |
-   |              expected reference, found tuple
+   |                                    ^^^^^^ expected reference, found tuple
    |
    = note: expected reference `&_`
                   found tuple `(&_, &_)`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-33941.rs:6:29
+   |
+LL |     for _ in HashMap::new().iter().cloned() {}
+   |              -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here
+   |              |
+   |              this expression has type `HashMap<_, _>`
 note: required by a bound in `cloned`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         Self: Sized + Iterator<Item = &'a T>,
-   |                                ^^^^^^^^^^^^ required by this bound in `cloned`
 
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
   --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
@@ -25,7 +27,7 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator`
 
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
   --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index 72082f0cd17..9d2c315e4db 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -13,20 +13,25 @@ LL |     let sr: Vec<(u32, _, _)> = vec![];
    |                            +
 
 error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
-  --> $DIR/issue-34334.rs:5:33
+  --> $DIR/issue-34334.rs:5:87
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |                                 |
-   |                                 value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
+   |                                                                                       ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-34334.rs:5:43
+   |
+LL |     let sr: Vec<(u32, _, _) = vec![];
+   |                               ------ this expression has type `Vec<(_, _, _)>`
+...
+LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
+   |                                    ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+   |                                    |
+   |                                    `Iterator::Item` is `&(_, _, _)` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr
index 045819061c1..f2bf22227db 100644
--- a/src/test/ui/issues/issue-34721.stderr
+++ b/src/test/ui/issues/issue-34721.stderr
@@ -13,7 +13,7 @@ LL |         };
 LL |         x.zero()
    |         ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `Foo::zero` takes ownership of the receiver `self`, which moves `x`
   --> $DIR/issue-34721.rs:4:13
    |
 LL |     fn zero(self) -> Self;
diff --git a/src/test/ui/issues/issue-38857.stderr b/src/test/ui/issues/issue-38857.stderr
index 23090c1ed78..4d505784b86 100644
--- a/src/test/ui/issues/issue-38857.stderr
+++ b/src/test/ui/issues/issue-38857.stderr
@@ -12,9 +12,6 @@ LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!()
    |
 note: the module `sys` is defined here
   --> $SRC_DIR/std/src/lib.rs:LL:COL
-   |
-LL | mod sys;
-   | ^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr
index 0a5a6b80e9b..e15eed65612 100644
--- a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr
+++ b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of index of `Vec<String>`
   --> $DIR/issue-40402-1.rs:9:13
    |
 LL |     let e = f.v[0];
-   |             ^^^^^^
-   |             |
-   |             move occurs because value has type `String`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&f.v[0]`
+   |             ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let e = &f.v[0];
+   |             +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr
index b6049f967ff..1bc554efb5c 100644
--- a/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr
+++ b/src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr
@@ -2,12 +2,16 @@ error[E0507]: cannot move out of index of `Vec<(String, String)>`
   --> $DIR/issue-40402-2.rs:5:18
    |
 LL |     let (a, b) = x[0];
-   |          -  -    ^^^^ help: consider borrowing here: `&x[0]`
+   |          -  -    ^^^^
    |          |  |
    |          |  ...and here
    |          data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing here
+   |
+LL |     let (a, b) = &x[0];
+   |                  +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr
index fd694df3045..00c375f8d2a 100644
--- a/src/test/ui/issues/issue-41880.stderr
+++ b/src/test/ui/issues/issue-41880.stderr
@@ -5,7 +5,7 @@ LL | pub struct Iterate<T, F> {
    | ------------------------ method `iter` not found for this struct
 ...
 LL |     println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
-   |                        ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:27]>`
+   |                        ^^^^ method not found in `Iterate<{integer}, [closure@issue-41880.rs:26:24]>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-42312.stderr b/src/test/ui/issues/issue-42312.stderr
index 6fe15162243..3ca6a2957e1 100644
--- a/src/test/ui/issues/issue-42312.stderr
+++ b/src/test/ui/issues/issue-42312.stderr
@@ -23,6 +23,10 @@ LL | pub fn f(_: dyn ToString) {}
    |
    = help: the trait `Sized` is not implemented for `(dyn ToString + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | pub fn f(_: impl ToString) {}
+   |             ~~~~
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | pub fn f(_: &dyn ToString) {}
diff --git a/src/test/ui/issues/issue-48364.stderr b/src/test/ui/issues/issue-48364.stderr
index 7fd36676df8..da3e62e35dc 100644
--- a/src/test/ui/issues/issue-48364.stderr
+++ b/src/test/ui/issues/issue-48364.stderr
@@ -10,9 +10,6 @@ LL |     b"".starts_with(stringify!(foo))
               found reference `&'static str`
 note: associated function defined here
   --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
-   |
-LL |     pub fn starts_with(&self, needle: &[T]) -> bool
-   |            ^^^^^^^^^^^
    = note: this error originates in the macro `stringify` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-51154.stderr b/src/test/ui/issues/issue-51154.stderr
index 44ec626dea5..d8a833a86f5 100644
--- a/src/test/ui/issues/issue-51154.stderr
+++ b/src/test/ui/issues/issue-51154.stderr
@@ -13,9 +13,6 @@ LL |     let _: Box<F> = Box::new(|| ());
    = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F`
 note: associated function defined here
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL |     pub fn new(x: T) -> Self {
-   |            ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-5353.rs b/src/test/ui/issues/issue-5353.rs
deleted file mode 100644
index 1d6813d5a39..00000000000
--- a/src/test/ui/issues/issue-5353.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// check-pass
-#![allow(dead_code)]
-// pretty-expanded FIXME #23616
-
-const INVALID_ENUM : u32 = 0;
-const INVALID_VALUE : u32 = 1;
-
-fn gl_err_str(err: u32) -> String
-{
-  match err
-  {
-    INVALID_ENUM => { "Invalid enum".to_string() },
-    INVALID_VALUE => { "Invalid value".to_string() },
-    _ => { "Unknown error".to_string() }
-  }
-}
-
-pub fn main() {}
diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr
index 8a20a60853a..ffff403e0d4 100644
--- a/src/test/ui/issues/issue-5883.stderr
+++ b/src/test/ui/issues/issue-5883.stderr
@@ -6,6 +6,10 @@ LL |     r: dyn A + 'static
    |
    = help: the trait `Sized` is not implemented for `(dyn A + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL |     r: impl A + 'static
+   |        ~~~~
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL |     r: &dyn A + 'static
diff --git a/src/test/ui/issues/issue-61108.stderr b/src/test/ui/issues/issue-61108.stderr
index e5b671d7b7a..3aaf5fb3f3e 100644
--- a/src/test/ui/issues/issue-61108.stderr
+++ b/src/test/ui/issues/issue-61108.stderr
@@ -9,11 +9,8 @@ LL |     for l in bad_letters {
 LL |     bad_letters.push('s');
    |     ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `bad_letters`
+note: `into_iter` takes ownership of the receiver `self`, which moves `bad_letters`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<char>`'s content to avoid moving into the `for` loop
    |
 LL |     for l in &bad_letters {
diff --git a/src/test/ui/issues/issue-64559.stderr b/src/test/ui/issues/issue-64559.stderr
index ef178bbd155..386ac794d7d 100644
--- a/src/test/ui/issues/issue-64559.stderr
+++ b/src/test/ui/issues/issue-64559.stderr
@@ -10,11 +10,8 @@ LL |     let _closure = || orig;
    |                    |
    |                    value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `orig`
+note: `into_iter` takes ownership of the receiver `self`, which moves `orig`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<bool>`'s content to avoid moving into the `for` loop
    |
 LL |     for _val in &orig {}
diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
index 2de15037650..cec482a53ba 100644
--- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
+++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
@@ -1,34 +1,39 @@
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:24
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39
    |
 LL |     let x2: Vec<f64> = x1.into_iter().collect();
-   |                        ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |                        |
-   |                        value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                                       ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
+   |
+LL |     let x1: &[f64] = &v;
+   |                      -- this expression has type `&Vec<f64>`
+LL |     let x2: Vec<f64> = x1.into_iter().collect();
+   |                           ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:14
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
    |
 LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
-   |              ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |              |
-   |              value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                             ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
+   |
+LL |     let x1: &[f64] = &v;
+   |                      -- this expression has type `&Vec<f64>`
+...
+LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
+   |                 ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-7607-1.stderr b/src/test/ui/issues/issue-7607-1.stderr
index f1ab0ad26d7..c983026995b 100644
--- a/src/test/ui/issues/issue-7607-1.stderr
+++ b/src/test/ui/issues/issue-7607-1.stderr
@@ -3,11 +3,9 @@ error[E0412]: cannot find type `Fo` in this scope
    |
 LL | impl Fo {
    |      ^^ help: a trait with a similar name exists: `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-83924.stderr b/src/test/ui/issues/issue-83924.stderr
index 767571cddbe..572414df2bf 100644
--- a/src/test/ui/issues/issue-83924.stderr
+++ b/src/test/ui/issues/issue-83924.stderr
@@ -10,11 +10,8 @@ LL |     for n in v {
 LL |     for n in v {
    |              ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `v`
+note: `into_iter` takes ownership of the receiver `self`, which moves `v`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider creating a fresh reborrow of `v` here
    |
 LL |     for n in &mut *v {
diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs
index 4c424999b75..99d0d9bd735 100644
--- a/src/test/ui/iterators/collect-into-array.rs
+++ b/src/test/ui/iterators/collect-into-array.rs
@@ -3,5 +3,4 @@ fn main() {
     //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
     //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
     //~| NOTE required by a bound in `collect`
-    //~| NOTE required by a bound introduced by this call
 }
diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr
index a23a36a88ab..e38745cc10e 100644
--- a/src/test/ui/iterators/collect-into-array.stderr
+++ b/src/test/ui/iterators/collect-into-array.stderr
@@ -1,17 +1,12 @@
 error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
-  --> $DIR/collect-into-array.rs:2:31
+  --> $DIR/collect-into-array.rs:2:39
    |
 LL |     let whatever: [u32; 10] = (0..10).collect();
-   |                               ^^^^^^^ ------- required by a bound introduced by this call
-   |                               |
-   |                               try collecting into a `Vec<{integer}>`, then using `.try_into()`
+   |                                       ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs
index 09832c260d0..5a8aacb1a6d 100644
--- a/src/test/ui/iterators/collect-into-slice.rs
+++ b/src/test/ui/iterators/collect-into-slice.rs
@@ -13,6 +13,5 @@ fn main() {
     //~| NOTE all local variables must have a statically known size
     //~| NOTE doesn't have a size known at compile-time
     //~| NOTE doesn't have a size known at compile-time
-    //~| NOTE required by a bound introduced by this call
     process_slice(&some_generated_vec);
 }
diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr
index bc152467ce3..29fff8c51c6 100644
--- a/src/test/ui/iterators/collect-into-slice.stderr
+++ b/src/test/ui/iterators/collect-into-slice.stderr
@@ -17,24 +17,16 @@ LL |     let some_generated_vec = (0..10).collect();
    = help: the trait `Sized` is not implemented for `[i32]`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                ^ required by this bound in `collect`
 
 error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
-  --> $DIR/collect-into-slice.rs:6:30
+  --> $DIR/collect-into-slice.rs:6:38
    |
 LL |     let some_generated_vec = (0..10).collect();
-   |                              ^^^^^^^ ------- required by a bound introduced by this call
-   |                              |
-   |                              try explicitly collecting into a `Vec<{integer}>`
+   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs
new file mode 100644
index 00000000000..ebdf33303c9
--- /dev/null
+++ b/src/test/ui/iterators/invalid-iterator-chain.rs
@@ -0,0 +1,53 @@
+use std::collections::hash_set::Iter;
+use std::collections::HashSet;
+
+fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
+    let i = i.map(|x| x.clone());
+    i.collect() //~ ERROR E0277
+}
+
+fn main() {
+    let scores = vec![(0, 0)]
+        .iter()
+        .map(|(a, b)| {
+            a + b;
+        });
+    println!("{}", scores.sum::<i32>()); //~ ERROR E0277
+    println!(
+        "{}",
+        vec![0, 1]
+            .iter()
+            .map(|x| x * 2)
+            .map(|x| x as f64)
+            .map(|x| x as i64)
+            .filter(|x| *x > 0)
+            .map(|x| { x + 1 })
+            .map(|x| { x; })
+            .sum::<i32>(), //~ ERROR E0277
+    );
+    println!(
+        "{}",
+        vec![0, 1]
+            .iter()
+            .map(|x| x * 2)
+            .map(|x| x as f64)
+            .filter(|x| *x > 0.0)
+            .map(|x| { x + 1.0 })
+            .sum::<i32>(), //~ ERROR E0277
+    );
+    println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); //~ ERROR E0277
+    println!("{}", vec![(), ()].iter().sum::<i32>()); //~ ERROR E0277
+    let a = vec![0];
+    let b = a.into_iter();
+    let c = b.map(|x| x + 1);
+    let d = c.filter(|x| *x > 10 );
+    let e = d.map(|x| {
+        x + 1;
+    });
+    let f = e.filter(|_| false);
+    let g: Vec<i32> = f.collect(); //~ ERROR E0277
+
+    let mut s = HashSet::new();
+    s.insert(1u8);
+    println!("{:?}", iter_to_vec(s.iter()));
+}
diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr
new file mode 100644
index 00000000000..d76a4bfb7b3
--- /dev/null
+++ b/src/test/ui/iterators/invalid-iterator-chain.stderr
@@ -0,0 +1,176 @@
+error[E0277]: a value of type `Vec<X>` cannot be built from an iterator over elements of type `&X`
+  --> $DIR/invalid-iterator-chain.rs:6:7
+   |
+LL |     i.collect()
+   |       ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
+   |
+   = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
+   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:4:26
+   |
+LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
+   |                          ^^^^^^^^^^^ `Iterator::Item` is `&X` here
+LL |     let i = i.map(|x| x.clone());
+   |               ------------------ `Iterator::Item` remains `&X` here
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:15:27
+   |
+LL |     println!("{}", scores.sum::<i32>());
+   |                           ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:12:10
+   |
+LL |       let scores = vec![(0, 0)]
+   |                    ------------ this expression has type `Vec<({integer}, {integer})>`
+LL |           .iter()
+   |            ------ `Iterator::Item` is `&({integer}, {integer})` here
+LL |           .map(|(a, b)| {
+   |  __________^
+LL | |             a + b;
+LL | |         });
+   | |__________^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:26:14
+   |
+LL |             .sum::<i32>(),
+   |              ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:20:14
+   |
+LL |         vec![0, 1]
+   |         ---------- this expression has type `Vec<{integer}>`
+LL |             .iter()
+   |              ------ `Iterator::Item` is `&{integer}` here
+LL |             .map(|x| x * 2)
+   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL |             .map(|x| x as f64)
+   |              ----------------- `Iterator::Item` changed to `f64` here
+LL |             .map(|x| x as i64)
+   |              ----------------- `Iterator::Item` changed to `i64` here
+LL |             .filter(|x| *x > 0)
+   |              ------------------ `Iterator::Item` remains `i64` here
+LL |             .map(|x| { x + 1 })
+   |              ------------------ `Iterator::Item` remains `i64` here
+LL |             .map(|x| { x; })
+   |              ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64`
+  --> $DIR/invalid-iterator-chain.rs:36:14
+   |
+LL |             .sum::<i32>(),
+   |              ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=f64>`
+   |
+   = help: the trait `Sum<f64>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:32:14
+   |
+LL |         vec![0, 1]
+   |         ---------- this expression has type `Vec<{integer}>`
+LL |             .iter()
+   |              ------ `Iterator::Item` is `&{integer}` here
+LL |             .map(|x| x * 2)
+   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL |             .map(|x| x as f64)
+   |              ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here
+LL |             .filter(|x| *x > 0.0)
+   |              -------------------- `Iterator::Item` remains `f64` here
+LL |             .map(|x| { x + 1.0 })
+   |              -------------------- `Iterator::Item` remains `f64` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:38:54
+   |
+LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+   |                                                      ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:38:38
+   |
+LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+   |                    ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+   |                    |          |
+   |                    |          `Iterator::Item` is `&{integer}` here
+   |                    this expression has type `Vec<{integer}>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
+  --> $DIR/invalid-iterator-chain.rs:39:40
+   |
+LL |     println!("{}", vec![(), ()].iter().sum::<i32>());
+   |                                        ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Sum<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:39:33
+   |
+LL |     println!("{}", vec![(), ()].iter().sum::<i32>());
+   |                    ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |                    |
+   |                    this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:48:25
+   |
+LL |     let g: Vec<i32> = f.collect();
+   |                         ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
+   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:44:15
+   |
+LL |       let a = vec![0];
+   |               ------- this expression has type `Vec<{integer}>`
+LL |       let b = a.into_iter();
+   |                 ----------- `Iterator::Item` is `{integer}` here
+LL |       let c = b.map(|x| x + 1);
+   |                 -------------- `Iterator::Item` remains `{integer}` here
+LL |       let d = c.filter(|x| *x > 10 );
+   |                 -------------------- `Iterator::Item` remains `{integer}` here
+LL |       let e = d.map(|x| {
+   |  _______________^
+LL | |         x + 1;
+LL | |     });
+   | |______^ `Iterator::Item` changed to `()` here
+LL |       let f = e.filter(|_| false);
+   |                 ----------------- `Iterator::Item` remains `()` here
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/iterators/vec-on-unimplemented.stderr b/src/test/ui/iterators/vec-on-unimplemented.stderr
index afcce5c30ca..a7d9c481a1a 100644
--- a/src/test/ui/iterators/vec-on-unimplemented.stderr
+++ b/src/test/ui/iterators/vec-on-unimplemented.stderr
@@ -3,11 +3,9 @@ error[E0599]: `Vec<bool>` is not an iterator
    |
 LL |     vec![true, false].map(|v| !v).collect::<Vec<_>>();
    |                       ^^^ `Vec<bool>` is not an iterator; try calling `.into_iter()` or `.iter()`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<bool>: Iterator`
+   = note: doesn't satisfy `Vec<bool>: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `Vec<bool>: Iterator`
diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
index 33f82448dd2..0b206f31e7b 100644
--- a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
+++ b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
@@ -1,17 +1,12 @@
 error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_`
-  --> $DIR/branches.rs:19:9
+  --> $DIR/branches.rs:19:28
    |
 LL |         std::iter::empty().collect()
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Bar`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr
index 420104e526d..fe2631f9474 100644
--- a/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr
+++ b/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr
@@ -6,8 +6,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/branches3.rs:15:10
@@ -17,8 +17,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/branches3.rs:23:10
@@ -28,8 +28,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/branches3.rs:30:10
@@ -39,8 +39,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
index 57978edf2bf..d8ac39a4f27 100644
--- a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
@@ -1,32 +1,22 @@
 error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:10:9
+  --> $DIR/recursion4.rs:10:28
    |
 LL |     x = std::iter::empty().collect();
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Foo`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:19:9
+  --> $DIR/recursion4.rs:19:28
    |
 LL |     x = std::iter::empty().collect();
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `impl Debug`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/let-else/let-else-deref-coercion.stderr b/src/test/ui/let-else/let-else-deref-coercion.stderr
index addcd798f4f..bf78a079cdf 100644
--- a/src/test/ui/let-else/let-else-deref-coercion.stderr
+++ b/src/test/ui/let-else/let-else-deref-coercion.stderr
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
 LL |         let Bar(z) = x;
    |             ^^^^^^   - this expression has type `&mut irrefutable::Foo`
    |             |
-   |             expected struct `irrefutable::Foo`, found struct `irrefutable::Bar`
+   |             expected struct `Foo`, found struct `Bar`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetimes/conflicting-bounds.rs b/src/test/ui/lifetimes/conflicting-bounds.rs
new file mode 100644
index 00000000000..f37f163dbb6
--- /dev/null
+++ b/src/test/ui/lifetimes/conflicting-bounds.rs
@@ -0,0 +1,11 @@
+//~ type annotations needed: cannot satisfy `Self: Gen<'source>`
+
+pub trait Gen<'source> {
+    type Output;
+
+    fn gen<T>(&self) -> T
+    where
+        Self: for<'s> Gen<'s, Output = T>;
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/conflicting-bounds.stderr b/src/test/ui/lifetimes/conflicting-bounds.stderr
new file mode 100644
index 00000000000..42aa393667d
--- /dev/null
+++ b/src/test/ui/lifetimes/conflicting-bounds.stderr
@@ -0,0 +1,14 @@
+error[E0283]: type annotations needed: cannot satisfy `Self: Gen<'source>`
+   |
+note: multiple `impl`s or `where` clauses satisfying `Self: Gen<'source>` found
+  --> $DIR/conflicting-bounds.rs:3:1
+   |
+LL | pub trait Gen<'source> {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |         Self: for<'s> Gen<'s, Output = T>;
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/lifetimes/issue-34979.stderr b/src/test/ui/lifetimes/issue-34979.stderr
index 5832c4d173c..3d4208031cd 100644
--- a/src/test/ui/lifetimes/issue-34979.stderr
+++ b/src/test/ui/lifetimes/issue-34979.stderr
@@ -4,7 +4,16 @@ error[E0283]: type annotations needed: cannot satisfy `&'a (): Foo`
 LL |     &'a (): Foo,
    |             ^^^
    |
-   = note: cannot satisfy `&'a (): Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a (): Foo` found
+  --> $DIR/issue-34979.rs:2:1
+   |
+LL | impl<'a, T> Foo for &'a T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     &'a (): Foo,
+   |             ^^^
+LL |     &'static (): Foo;
+   |                  ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/limits/issue-55878.stderr b/src/test/ui/limits/issue-55878.stderr
index f17f8141b90..f455dcb06f7 100644
--- a/src/test/ui/limits/issue-55878.stderr
+++ b/src/test/ui/limits/issue-55878.stderr
@@ -1,14 +1,8 @@
 error[E0080]: values of the type `[u8; SIZE]` are too big for the current architecture
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
 note: inside `std::mem::size_of::<[u8; SIZE]>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `main`
   --> $DIR/issue-55878.rs:7:26
    |
diff --git a/src/test/ui/lint/invalid_value.stderr b/src/test/ui/lint/invalid_value.stderr
index 5370660d6c1..48fd4169da7 100644
--- a/src/test/ui/lint/invalid_value.stderr
+++ b/src/test/ui/lint/invalid_value.stderr
@@ -604,9 +604,6 @@ LL |         let _val: Result<i32, i32> = mem::uninitialized();
    |
 note: enums with multiple inhabited variants have to be initialized to a variant
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: the type `&i32` does not permit zero-initialization
   --> $DIR/invalid_value.rs:152:34
diff --git a/src/test/ui/lint/lint-const-item-mutation.stderr b/src/test/ui/lint/lint-const-item-mutation.stderr
index 9f4360e6763..747c38b8007 100644
--- a/src/test/ui/lint/lint-const-item-mutation.stderr
+++ b/src/test/ui/lint/lint-const-item-mutation.stderr
@@ -108,9 +108,6 @@ LL |     VEC.push(0);
    = note: the mutable reference will refer to this temporary, not the original `const` item
 note: mutable reference created due to call to this method
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL |     pub fn push(&mut self, value: T) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `const` item defined here
   --> $DIR/lint-const-item-mutation.rs:31:1
    |
diff --git a/src/test/ui/loops/issue-82916.stderr b/src/test/ui/loops/issue-82916.stderr
index 57d76016c45..e6a60d7bc40 100644
--- a/src/test/ui/loops/issue-82916.stderr
+++ b/src/test/ui/loops/issue-82916.stderr
@@ -9,11 +9,8 @@ LL |     for y in x {
 LL |     let z = x;
    |             ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<S>`'s content to avoid moving into the `for` loop
    |
 LL |     for y in &x {
diff --git a/src/test/ui/macros/format-args-temporaries-in-write.stderr b/src/test/ui/macros/format-args-temporaries-in-write.stderr
index 03ecc4b4418..287cd7d6704 100644
--- a/src/test/ui/macros/format-args-temporaries-in-write.stderr
+++ b/src/test/ui/macros/format-args-temporaries-in-write.stderr
@@ -12,11 +12,6 @@ LL |     };
    |     |
    |     `mutex` dropped here while still borrowed
    |
-help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
-  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |         $dst.write_fmt($crate::format_args!($($arg)*));
-   |                                                       +
 
 error[E0597]: `mutex` does not live long enough
   --> $DIR/format-args-temporaries-in-write.rs:47:29
@@ -32,11 +27,6 @@ LL |     };
    |     |
    |     `mutex` dropped here while still borrowed
    |
-help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
-  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |         $dst.write_fmt($crate::format_args_nl!($($arg)*));
-   |                                                          +
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-42954.fixed b/src/test/ui/macros/issue-42954.fixed
index a73054c9257..a73054c9257 100644
--- a/src/test/ui/issues/issue-42954.fixed
+++ b/src/test/ui/macros/issue-42954.fixed
diff --git a/src/test/ui/issues/issue-42954.rs b/src/test/ui/macros/issue-42954.rs
index 5f9b0e31da5..5f9b0e31da5 100644
--- a/src/test/ui/issues/issue-42954.rs
+++ b/src/test/ui/macros/issue-42954.rs
diff --git a/src/test/ui/issues/issue-42954.stderr b/src/test/ui/macros/issue-42954.stderr
index 396a91994eb..396a91994eb 100644
--- a/src/test/ui/issues/issue-42954.stderr
+++ b/src/test/ui/macros/issue-42954.stderr
diff --git a/src/test/ui/issues/issue-51848.rs b/src/test/ui/macros/issue-51848.rs
index 4792bdd64f0..4792bdd64f0 100644
--- a/src/test/ui/issues/issue-51848.rs
+++ b/src/test/ui/macros/issue-51848.rs
diff --git a/src/test/ui/issues/issue-51848.stderr b/src/test/ui/macros/issue-51848.stderr
index c25bedf37b7..c25bedf37b7 100644
--- a/src/test/ui/issues/issue-51848.stderr
+++ b/src/test/ui/macros/issue-51848.stderr
diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr
index 3e8cfb3f0e9..d7c8aaae22e 100644
--- a/src/test/ui/macros/macro-name-typo.stderr
+++ b/src/test/ui/macros/macro-name-typo.stderr
@@ -3,11 +3,9 @@ error: cannot find macro `printlx` in this scope
    |
 LL |     printlx!("oh noes!");
    |     ^^^^^^^ help: a macro with a similar name exists: `println`
+  --> $SRC_DIR/std/src/macros.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/macros.rs:LL:COL
-   |
-LL | macro_rules! println {
-   | -------------------- similarly named macro `println` defined here
+   = note: similarly named macro `println` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
index 70900a6bc81..f1c3512bc9b 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -3,11 +3,9 @@ error: cannot find macro `inline` in this scope
    |
 LL |     inline!();
    |     ^^^^^^ help: a macro with a similar name exists: `line`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     macro_rules! line {
-   |     ----------------- similarly named macro `line` defined here
+   = note: similarly named macro `line` defined here
    |
    = note: `inline` is in scope, but it is an attribute: `#[inline]`
 
diff --git a/src/test/ui/macros/unknown-builtin.stderr b/src/test/ui/macros/unknown-builtin.stderr
index 8f9dba16578..22f54e04e54 100644
--- a/src/test/ui/macros/unknown-builtin.stderr
+++ b/src/test/ui/macros/unknown-builtin.stderr
@@ -7,9 +7,6 @@ LL | macro_rules! unknown { () => () }
 error[E0773]: attempted to define built-in macro more than once
   --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-LL |     macro_rules! line {
-   |     ^^^^^^^^^^^^^^^^^
-   |
 note: previously defined here
   --> $DIR/unknown-builtin.rs:9:1
    |
diff --git a/src/test/ui/malformed/malformed-derive-entry.stderr b/src/test/ui/malformed/malformed-derive-entry.stderr
index 803883460f0..6ff6fbabb4a 100644
--- a/src/test/ui/malformed/malformed-derive-entry.stderr
+++ b/src/test/ui/malformed/malformed-derive-entry.stderr
@@ -24,9 +24,6 @@ LL | #[derive(Copy(Bad))]
    |
 note: required by a bound in `Copy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |                 ^^^^^ required by this bound in `Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Test1` with `#[derive(Clone)]`
    |
@@ -41,9 +38,6 @@ LL | #[derive(Copy="bad")]
    |
 note: required by a bound in `Copy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |                 ^^^^^ required by this bound in `Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Test2` with `#[derive(Clone)]`
    |
diff --git a/src/test/ui/match/match-unresolved-one-arm.stderr b/src/test/ui/match/match-unresolved-one-arm.stderr
index 9eadb88a8ba..e3b501b2fd5 100644
--- a/src/test/ui/match/match-unresolved-one-arm.stderr
+++ b/src/test/ui/match/match-unresolved-one-arm.stderr
@@ -6,8 +6,8 @@ LL |     let x = match () {
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = match () {
-   |          +++
+LL |     let x: /* Type */ = match () {
+   |          ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/issues/issue-90315.stderr b/src/test/ui/methods/issues/issue-90315.stderr
index 070cd305436..8d7b32e025a 100644
--- a/src/test/ui/methods/issues/issue-90315.stderr
+++ b/src/test/ui/methods/issues/issue-90315.stderr
@@ -57,7 +57,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:28:8
    |
 LL |     if 1..(end + 1).is_empty() {
-   |        ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<{integer}>`
@@ -77,7 +77,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:34:8
    |
 LL |     if 1..(end + 1).is_sorted() {
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<{integer}>`
@@ -97,7 +97,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:40:21
    |
 LL |     let _res: i32 = 3..6.take(2).sum();
-   |               ---   ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
+   |               ---   ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Range`
    |               |
    |               expected due to this
    |
@@ -119,7 +119,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:45:21
    |
 LL |     let _sum: i32 = 3..6.sum();
-   |               ---   ^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
+   |               ---   ^^^^^^^^^^ expected `i32`, found struct `Range`
    |               |
    |               expected due to this
    |
@@ -158,7 +158,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:62:8
    |
 LL |     if 1..end.error_method() {
-   |        ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<{integer}>`
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index a4ffb864dad..3f4e647491e 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -61,11 +61,8 @@ LL |      .take()
    = note: the following trait bounds were not satisfied:
            `Foo: Iterator`
            which is required by `&mut Foo: Iterator`
-note: the following trait must be implemented
+note: the trait `Iterator` must be implemented
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL | pub trait Iterator {
-   | ^^^^^^^^^^^^^^^^^^
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `take`, perhaps you need to implement it:
            candidate #1: `Iterator`
diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
index 62f20d6d50c..25ad360b329 100644
--- a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
@@ -11,11 +11,9 @@ warning: cannot specify lifetime arguments explicitly if late bound lifetime par
    |
 LL |     0.clone::<'a>();
    |               ^^
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |              - the late bound lifetime parameter is introduced here
+   = note: the late bound lifetime parameter is introduced here
    |
    = 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 #42868 <https://github.com/rust-lang/rust/issues/42868>
diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr
index fc42d1a4dcd..8846efba871 100644
--- a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr
+++ b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr
@@ -23,7 +23,7 @@ error[E0599]: no method named `extend` found for struct `Map` in the current sco
   --> $DIR/method-not-found-generic-arg-elision.rs:87:29
    |
 LL |     v.iter().map(|x| x * x).extend(std::iter::once(100));
-   |                             ^^^^^^ method not found in `Map<std::slice::Iter<'_, i32>, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:21]>`
+   |                             ^^^^^^ method not found in `Map<Iter<'_, i32>, [closure@method-not-found-generic-arg-elision.rs:87:18]>`
 
 error[E0599]: no method named `method` found for struct `Wrapper<bool>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:90:13
diff --git a/src/test/ui/issues/issue-29227.rs b/src/test/ui/mir/issue-29227.rs
index e9dfc2840e5..e9dfc2840e5 100644
--- a/src/test/ui/issues/issue-29227.rs
+++ b/src/test/ui/mir/issue-29227.rs
diff --git a/src/test/ui/issues/issue-46845.rs b/src/test/ui/mir/issue-46845.rs
index fc85b25519a..fc85b25519a 100644
--- a/src/test/ui/issues/issue-46845.rs
+++ b/src/test/ui/mir/issue-46845.rs
diff --git a/src/test/ui/issues/issue-77002.rs b/src/test/ui/mir/issue-77002.rs
index 0c37346eaf8..0c37346eaf8 100644
--- a/src/test/ui/issues/issue-77002.rs
+++ b/src/test/ui/mir/issue-77002.rs
diff --git a/src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr b/src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr
index ffd95b48ac2..2393791a9b2 100644
--- a/src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr
+++ b/src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr
@@ -11,11 +11,8 @@ note: an implementation of `AddAssign<_>` might be missing for `Foo`
    |
 LL | struct Foo;
    | ^^^^^^^^^^ must implement `AddAssign<_>`
-note: the following trait must be implemented
+note: the trait `AddAssign` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait AddAssign<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index a02ec819838..2ecab9f024a 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -128,9 +128,6 @@ LL | fn foo() {}
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
   --> $DIR/closure-arg-count.rs:27:57
@@ -144,9 +141,6 @@ LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
   --> $DIR/closure-arg-count.rs:29:57
@@ -161,9 +155,6 @@ LL | fn qux(x: usize, y: usize) {}
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
   --> $DIR/closure-arg-count.rs:32:45
@@ -175,9 +166,6 @@ LL |     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/closure-arg-count.rs:35:10
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
index 92d545b7366..fab9b7edc0c 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -2,17 +2,16 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:3:14
    |
 LL |     a.iter().map(|_: (u32, u32)| 45);
-   |              ^^^ --------------- found signature defined here
-   |              |
+   |              ^^^ ---------------
+   |              |   |   |
+   |              |   |   help: consider borrowing the argument: `&(u32, u32)`
+   |              |   found signature defined here
    |              expected due to this
    |
    = note: expected closure signature `fn(&(u32, u32)) -> _`
               found closure signature `fn((u32, u32)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:4:14
@@ -26,9 +25,6 @@ LL |     a.iter().map(|_: &(u16, u16)| 45);
               found closure signature `for<'a> fn(&'a (u16, u16)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:5:14
@@ -42,9 +38,6 @@ LL |     a.iter().map(|_: (u16, u16)| 45);
               found closure signature `fn((u16, u16)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr
index 5ea9bcfc122..680aff1726f 100644
--- a/src/test/ui/mismatched_types/issue-35030.stderr
+++ b/src/test/ui/mismatched_types/issue-35030.stderr
@@ -13,9 +13,6 @@ LL |         Some(true)
                         found type `bool` (`bool`)
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index 906001ca1e0..72fb0e4d774 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -2,31 +2,28 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/issue-36053-2.rs:7:32
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
-   |                                ^^^^^^ --------- found signature defined here
-   |                                |
+   |                                ^^^^^^ ---------
+   |                                |      |   |
+   |                                |      |   help: consider borrowing the argument: `&&str`
+   |                                |      found signature defined here
    |                                expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a &str) -> _`
               found closure signature `for<'a> fn(&'a str) -> _`
 note: required by a bound in `filter`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         P: FnMut(&Self::Item) -> bool,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter`
 
-error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>`, but its trait bounds were not satisfied
+error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied
   --> $DIR/issue-36053-2.rs:7:55
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
-   |                                       ---------       ^^^^^ method cannot be called on `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>` due to unsatisfied trait bounds
+   |                                       ---------       ^^^^^ method cannot be called due to unsatisfied trait bounds
    |                                       |
    |                                       doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
    |                                       doesn't satisfy `_: FnMut<(&&str,)>`
+  --> $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
-   |
-LL | pub struct Filter<I, P> {
-   | ----------------------- doesn't satisfy `_: Iterator`
+   = note: doesn't satisfy `_: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `<[closure@$DIR/issue-36053-2.rs:7:39: 7:48] as FnOnce<(&&str,)>>::Output = bool`
diff --git a/src/test/ui/mismatched_types/issue-47706-trait.stderr b/src/test/ui/mismatched_types/issue-47706-trait.stderr
index d596b4a69f3..a5f38dd5366 100644
--- a/src/test/ui/mismatched_types/issue-47706-trait.stderr
+++ b/src/test/ui/mismatched_types/issue-47706-trait.stderr
@@ -10,9 +10,6 @@ LL |         None::<()>.map(Self::f);
    |
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> U,
-   |            ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/issue-47706.stderr b/src/test/ui/mismatched_types/issue-47706.stderr
index 8b856368401..d9d408844d0 100644
--- a/src/test/ui/mismatched_types/issue-47706.stderr
+++ b/src/test/ui/mismatched_types/issue-47706.stderr
@@ -11,9 +11,6 @@ LL |         self.foo.map(Foo::new)
    |
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> U,
-   |            ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/issue-47706.rs:27:9
diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
index 94a9c97576f..b75c7a99fdd 100644
--- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
+++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
@@ -14,11 +14,9 @@ error: `impl` item signature doesn't match `trait` item signature
    |
 LL |     fn next(&mut self) -> Option<IteratorChunk<T, S>> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn next(&mut self) -> Option<Self::Item>;
-   |     ----------------------------------------- expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
+   = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
    |
    = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
               found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
index 36748fae13c..d3b7525072f 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -1,18 +1,13 @@
 error[E0277]: `Foo` doesn't implement `Debug`
-  --> $DIR/method-help-unsatisfied-bound.rs:5:5
+  --> $DIR/method-help-unsatisfied-bound.rs:5:7
    |
 LL |     a.unwrap();
-   |     ^ ------ required by a bound introduced by this call
-   |     |
-   |     `Foo` cannot be formatted using `{:?}`
+   |       ^^^^^^ `Foo` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Foo`
    = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
 note: required by a bound in `Result::<T, E>::unwrap`
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |         E: fmt::Debug,
-   |            ^^^^^^^^^^ required by this bound in `Result::<T, E>::unwrap`
 help: consider annotating `Foo` with `#[derive(Debug)]`
    |
 LL | #[derive(Debug)]
diff --git a/src/test/ui/mismatched_types/similar_paths.stderr b/src/test/ui/mismatched_types/similar_paths.stderr
index e65ae58d4ce..46a38332552 100644
--- a/src/test/ui/mismatched_types/similar_paths.stderr
+++ b/src/test/ui/mismatched_types/similar_paths.stderr
@@ -9,9 +9,6 @@ LL |     Some(42_u8)
    = note: enum `std::option::Option` and enum `Option` have similar names, but are actually distinct types
 note: enum `std::option::Option` is defined in crate `core`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   | ^^^^^^^^^^^^^^^^^^
 note: enum `Option` is defined in the current crate
   --> $DIR/similar_paths.rs:1:1
    |
diff --git a/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
index e8eb8d263ec..fdd92cbfc44 100644
--- a/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
+++ b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
@@ -42,7 +42,7 @@ error[E0308]: mismatched types
   --> $DIR/wrap-suggestion-privacy.rs:22:17
    |
 LL |     needs_ready(Some(0));
-   |     ----------- ^^^^^^^ expected struct `std::future::Ready`, found enum `Option`
+   |     ----------- ^^^^^^^ expected struct `Ready`, found enum `Option`
    |     |
    |     arguments to this function are incorrect
    |
diff --git a/src/test/ui/moves/issue-99470-move-out-of-some.stderr b/src/test/ui/moves/issue-99470-move-out-of-some.stderr
index 6e4a4e5ba22..c5159471fe3 100644
--- a/src/test/ui/moves/issue-99470-move-out-of-some.stderr
+++ b/src/test/ui/moves/issue-99470-move-out-of-some.stderr
@@ -5,11 +5,16 @@ LL |     match x {
    |           ^
 LL |
 LL |         &Some(_y) => (),
-   |         ---------
-   |         |     |
-   |         |     data moved here
-   |         |     move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Some(_y)`
+   |               --
+   |               |
+   |               data moved here
+   |               move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Some(_y) => (),
+LL +         Some(_y) => (),
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/move-fn-self-receiver.stderr b/src/test/ui/moves/move-fn-self-receiver.stderr
index c13dc58826e..b3f95ee192a 100644
--- a/src/test/ui/moves/move-fn-self-receiver.stderr
+++ b/src/test/ui/moves/move-fn-self-receiver.stderr
@@ -6,11 +6,8 @@ LL |     val.0.into_iter().next();
 LL |     val.0;
    |     ^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `val.0`
+note: `into_iter` takes ownership of the receiver `self`, which moves `val.0`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
    = note: move occurs because `val.0` has type `Vec<bool>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `foo`
@@ -23,7 +20,7 @@ LL |     foo.use_self();
 LL |     foo;
    |     ^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Foo::use_self` takes ownership of the receiver `self`, which moves `foo`
   --> $DIR/move-fn-self-receiver.rs:13:17
    |
 LL |     fn use_self(self) {}
@@ -49,7 +46,7 @@ LL |     boxed_foo.use_box_self();
 LL |     boxed_foo;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `boxed_foo`
+note: `Foo::use_box_self` takes ownership of the receiver `self`, which moves `boxed_foo`
   --> $DIR/move-fn-self-receiver.rs:14:21
    |
 LL |     fn use_box_self(self: Box<Self>) {}
@@ -65,7 +62,7 @@ LL |     pin_box_foo.use_pin_box_self();
 LL |     pin_box_foo;
    |     ^^^^^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `pin_box_foo`
+note: `Foo::use_pin_box_self` takes ownership of the receiver `self`, which moves `pin_box_foo`
   --> $DIR/move-fn-self-receiver.rs:15:25
    |
 LL |     fn use_pin_box_self(self: Pin<Box<Self>>) {}
@@ -91,7 +88,7 @@ LL |     rc_foo.use_rc_self();
 LL |     rc_foo;
    |     ^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `rc_foo`
+note: `Foo::use_rc_self` takes ownership of the receiver `self`, which moves `rc_foo`
   --> $DIR/move-fn-self-receiver.rs:16:20
    |
 LL |     fn use_rc_self(self: Rc<Self>) {}
@@ -113,9 +110,6 @@ LL |     foo_add;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 
 error[E0382]: use of moved value: `implicit_into_iter`
   --> $DIR/move-fn-self-receiver.rs:63:5
@@ -157,7 +151,7 @@ LL |     for _val in container.custom_into_iter() {}
 LL |     container;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `container`
+note: `Container::custom_into_iter` takes ownership of the receiver `self`, which moves `container`
   --> $DIR/move-fn-self-receiver.rs:23:25
    |
 LL |     fn custom_into_iter(self) -> impl Iterator<Item = bool> {
diff --git a/src/test/ui/moves/move-out-of-array-ref.stderr b/src/test/ui/moves/move-out-of-array-ref.stderr
index 0caa0b83a4c..26d4996d6cb 100644
--- a/src/test/ui/moves/move-out-of-array-ref.stderr
+++ b/src/test/ui/moves/move-out-of-array-ref.stderr
@@ -2,45 +2,61 @@ error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:8:24
    |
 LL |     let [_, e, _, _] = *a;
-   |             -          ^^
-   |             |          |
-   |             |          cannot move out of here
-   |             |          help: consider borrowing here: `&*a`
+   |             -          ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, e, _, _] = *a;
+LL +     let [_, e, _, _] = a;
+   |
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:13:27
    |
 LL |     let [_, s @ .. , _] = *a;
-   |             -             ^^
-   |             |             |
-   |             |             cannot move out of here
-   |             |             help: consider borrowing here: `&*a`
+   |             -             ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, s @ .. , _] = *a;
+LL +     let [_, s @ .. , _] = a;
+   |
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:18:24
    |
 LL |     let [_, e, _, _] = *a;
-   |             -          ^^
-   |             |          |
-   |             |          cannot move out of here
-   |             |          help: consider borrowing here: `&*a`
+   |             -          ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, e, _, _] = *a;
+LL +     let [_, e, _, _] = a;
+   |
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:23:27
    |
 LL |     let [_, s @ .. , _] = *a;
-   |             -             ^^
-   |             |             |
-   |             |             cannot move out of here
-   |             |             help: consider borrowing here: `&*a`
+   |             -             ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, s @ .. , _] = *a;
+LL +     let [_, s @ .. , _] = a;
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/moves/move-out-of-slice-1.stderr b/src/test/ui/moves/move-out-of-slice-1.stderr
index ce5ddb3e183..5a0357cf567 100644
--- a/src/test/ui/moves/move-out-of-slice-1.stderr
+++ b/src/test/ui/moves/move-out-of-slice-1.stderr
@@ -8,6 +8,11 @@ LL |         box [a] => {},
    |              |
    |              data moved here
    |              move occurs because `a` has type `A`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         box [ref a] => {},
+   |              +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/move-out-of-slice-2.rs b/src/test/ui/moves/move-out-of-slice-2.rs
index 59c02d42bf1..2f7394fbfd3 100644
--- a/src/test/ui/moves/move-out-of-slice-2.rs
+++ b/src/test/ui/moves/move-out-of-slice-2.rs
@@ -1,5 +1,6 @@
 #![feature(unsized_locals)]
 //~^ WARN the feature `unsized_locals` is incomplete
+#![allow(unused)]
 
 struct A;
 #[derive(Clone, Copy)]
diff --git a/src/test/ui/moves/move-out-of-slice-2.stderr b/src/test/ui/moves/move-out-of-slice-2.stderr
index 46357ce6f2e..b46854cd6b4 100644
--- a/src/test/ui/moves/move-out-of-slice-2.stderr
+++ b/src/test/ui/moves/move-out-of-slice-2.stderr
@@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0508]: cannot move out of type `[A]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:10:11
+  --> $DIR/move-out-of-slice-2.rs:11:11
    |
 LL |     match *a {
    |           ^^ cannot move out of here
@@ -18,9 +18,14 @@ LL |         [a @ ..] => {}
    |          |
    |          data moved here
    |          move occurs because `a` has type `[A]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [ref a @ ..] => {}
+   |          +++
 
 error[E0508]: cannot move out of type `[A]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:16:11
+  --> $DIR/move-out-of-slice-2.rs:17:11
    |
 LL |     match *b {
    |           ^^ cannot move out of here
@@ -30,9 +35,14 @@ LL |         [_, _, b @ .., _] => {}
    |                |
    |                data moved here
    |                move occurs because `b` has type `[A]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [_, _, ref b @ .., _] => {}
+   |                +++
 
 error[E0508]: cannot move out of type `[C]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:24:11
+  --> $DIR/move-out-of-slice-2.rs:25:11
    |
 LL |     match *c {
    |           ^^ cannot move out of here
@@ -42,9 +52,14 @@ LL |         [c @ ..] => {}
    |          |
    |          data moved here
    |          move occurs because `c` has type `[C]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [ref c @ ..] => {}
+   |          +++
 
 error[E0508]: cannot move out of type `[C]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:30:11
+  --> $DIR/move-out-of-slice-2.rs:31:11
    |
 LL |     match *d {
    |           ^^ cannot move out of here
@@ -54,6 +69,11 @@ LL |         [_, _, d @ .., _] => {}
    |                |
    |                data moved here
    |                move occurs because `d` has type `[C]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [_, _, ref d @ .., _] => {}
+   |                +++
 
 error: aborting due to 4 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
index a49ee31b466..0b1a623a013 100644
--- a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
+++ b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
@@ -8,11 +8,8 @@ LL |     consume(x.into_iter().next().unwrap());
 LL |     touch(&x[0]);
    |            ^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     consume(x.clone().into_iter().next().unwrap());
diff --git a/src/test/ui/moves/moves-based-on-type-block-bad.stderr b/src/test/ui/moves/moves-based-on-type-block-bad.stderr
index 5ed91a0d559..df09ababa5a 100644
--- a/src/test/ui/moves/moves-based-on-type-block-bad.stderr
+++ b/src/test/ui/moves/moves-based-on-type-block-bad.stderr
@@ -2,13 +2,18 @@ error[E0507]: cannot move out of `hellothere.x` as enum variant `Bar` which is b
   --> $DIR/moves-based-on-type-block-bad.rs:22:19
    |
 LL |             match hellothere.x {
-   |                   ^^^^^^^^^^^^ help: consider borrowing here: `&hellothere.x`
+   |                   ^^^^^^^^^^^^
 LL |                 box E::Foo(_) => {}
 LL |                 box E::Bar(x) => println!("{}", x.to_string()),
    |                            -
    |                            |
    |                            data moved here
    |                            move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |             match &hellothere.x {
+   |                   +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/moves-based-on-type-exprs.stderr b/src/test/ui/moves/moves-based-on-type-exprs.stderr
index 838b1282cb4..ae76889f104 100644
--- a/src/test/ui/moves/moves-based-on-type-exprs.stderr
+++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr
@@ -160,11 +160,8 @@ LL |     let _y = x.into_iter().next().unwrap();
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     let _y = x.clone().into_iter().next().unwrap();
@@ -180,11 +177,8 @@ LL |     let _y = [x.into_iter().next().unwrap(); 1];
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     let _y = [x.clone().into_iter().next().unwrap(); 1];
diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr
index 45cf3723483..a0f790dba15 100644
--- a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr
+++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr
@@ -1,4 +1,4 @@
-error[E0271]: expected `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to be a closure that returns `()`, but it returns `!`
+error[E0271]: expected `[closure@fallback-closure-wrap.rs:18:40]` to be a closure that returns `()`, but it returns `!`
   --> $DIR/fallback-closure-wrap.rs:18:31
    |
 LL |       let error = Closure::wrap(Box::new(move || {
diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
index 6dc039fc35d..2db1cc4b776 100644
--- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
+++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
@@ -5,7 +5,7 @@ LL |     foo(panic!())
    |     --- ^^^^^^^^
    |     |   |
    |     |   the trait `T` is not implemented for `()`
-   |     |   this tail expression is of type `_`
+   |     |   this tail expression is of type `()`
    |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr
index 0910e9ad77a..de5c9c56016 100644
--- a/src/test/ui/never_type/issue-52443.stderr
+++ b/src/test/ui/never_type/issue-52443.stderr
@@ -46,9 +46,6 @@ LL |     [(); { for _ in 0usize.. {}; 0}];
    |
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL | impl<I: Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constants
diff --git a/src/test/ui/never_type/issue-96335.stderr b/src/test/ui/never_type/issue-96335.stderr
index 168cf2f8353..e148b983e8e 100644
--- a/src/test/ui/never_type/issue-96335.stderr
+++ b/src/test/ui/never_type/issue-96335.stderr
@@ -26,9 +26,6 @@ LL |     0.....{loop{}1};
             found struct `RangeTo<{integer}>`
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/range.rs:LL:COL
-   |
-LL |     pub const fn new(start: Idx, end: Idx) -> Self {
-   |                  ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/cannot-move-block-spans.stderr b/src/test/ui/nll/cannot-move-block-spans.stderr
index 56a5cdff073..0dc5c08ea5f 100644
--- a/src/test/ui/nll/cannot-move-block-spans.stderr
+++ b/src/test/ui/nll/cannot-move-block-spans.stderr
@@ -2,28 +2,37 @@ error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:5:15
    |
 LL |     let x = { *r };
-   |               ^^
-   |               |
-   |               move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&*r`
+   |               ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = { *r };
+LL +     let x = { r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:6:22
    |
 LL |     let y = unsafe { *r };
-   |                      ^^
-   |                      |
-   |                      move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*r`
+   |                      ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let y = unsafe { *r };
+LL +     let y = unsafe { r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:7:26
    |
 LL |     let z = loop { break *r; };
-   |                          ^^
-   |                          |
-   |                          move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                          help: consider borrowing here: `&*r`
+   |                          ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let z = loop { break *r; };
+LL +     let z = loop { break r; };
+   |
 
 error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:11:15
@@ -33,7 +42,11 @@ LL |     let x = { arr[0] };
    |               |
    |               cannot move out of here
    |               move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&arr[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let x = { &arr[0] };
+   |               +
 
 error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:12:22
@@ -43,7 +56,11 @@ LL |     let y = unsafe { arr[0] };
    |                      |
    |                      cannot move out of here
    |                      move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&arr[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let y = unsafe { &arr[0] };
+   |                      +
 
 error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:13:26
@@ -53,34 +70,47 @@ LL |     let z = loop { break arr[0]; };
    |                          |
    |                          cannot move out of here
    |                          move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
-   |                          help: consider borrowing here: `&arr[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let z = loop { break &arr[0]; };
+   |                          +
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:17:38
    |
 LL |     let x = { let mut u = 0; u += 1; *r };
-   |                                      ^^
-   |                                      |
-   |                                      move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                                      help: consider borrowing here: `&*r`
+   |                                      ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = { let mut u = 0; u += 1; *r };
+LL +     let x = { let mut u = 0; u += 1; r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:18:45
    |
 LL |     let y = unsafe { let mut u = 0; u += 1; *r };
-   |                                             ^^
-   |                                             |
-   |                                             move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                                             help: consider borrowing here: `&*r`
+   |                                             ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let y = unsafe { let mut u = 0; u += 1; *r };
+LL +     let y = unsafe { let mut u = 0; u += 1; r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:19:49
    |
 LL |     let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
-   |                                                 ^^
-   |                                                 |
-   |                                                 move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                                                 help: consider borrowing here: `&*r`
+   |                                                 ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
+LL +     let z = loop { let mut u = 0; u += 1; break r; u += 2; };
+   |
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
index c0a17a67ee2..7f9cbc3c30a 100644
--- a/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
+++ b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
@@ -36,7 +36,11 @@ LL |     let p = s.url; p
    |             |
    |             cannot move out of here
    |             move occurs because `s.url` has type `&mut String`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&s.url`
+   |
+help: consider borrowing here
+   |
+LL |     let p = &s.url; p
+   |             +
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/nll/move-errors.stderr b/src/test/ui/nll/move-errors.stderr
index b03fcf70bab..58b8aa31d4c 100644
--- a/src/test/ui/nll/move-errors.stderr
+++ b/src/test/ui/nll/move-errors.stderr
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference
   --> $DIR/move-errors.rs:6:13
    |
 LL |     let b = *a;
-   |             ^^
-   |             |
-   |             move occurs because `*a` has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*a`
+   |             ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let b = *a;
+LL +     let b = a;
+   |
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:12:13
@@ -15,25 +18,35 @@ LL |     let b = a[0];
    |             |
    |             cannot move out of here
    |             move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&a[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let b = &a[0];
+   |             +
 
 error[E0507]: cannot move out of `**r` which is behind a shared reference
   --> $DIR/move-errors.rs:19:13
    |
 LL |     let s = **r;
-   |             ^^^
-   |             |
-   |             move occurs because `**r` has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&**r`
+   |             ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let s = **r;
+LL +     let s = *r;
+   |
 
 error[E0507]: cannot move out of an `Rc`
   --> $DIR/move-errors.rs:27:13
    |
 LL |     let s = *r;
-   |             ^^
-   |             |
-   |             move occurs because value has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*r`
+   |             ^^ move occurs because value has type `A`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let s = *r;
+LL +     let s = r;
+   |
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:32:13
@@ -43,16 +56,26 @@ LL |     let a = [A("".to_string())][0];
    |             |
    |             cannot move out of here
    |             move occurs because value has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&[A("".to_string())][0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &[A("".to_string())][0];
+   |             +
 
 error[E0507]: cannot move out of `a` which is behind a shared reference
   --> $DIR/move-errors.rs:38:16
    |
 LL |     let A(s) = *a;
-   |           -    ^^ help: consider borrowing here: `&*a`
+   |           -    ^^
    |           |
    |           data moved here
    |           move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let A(s) = *a;
+LL +     let A(s) = a;
+   |
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:44:19
@@ -62,6 +85,11 @@ LL |     let C(D(s)) = c;
    |             |
    |             data moved here
    |             move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let C(D(ref s)) = c;
+   |             +++
 
 error[E0507]: cannot move out of `*a` which is behind a shared reference
   --> $DIR/move-errors.rs:51:9
@@ -73,10 +101,7 @@ error[E0508]: cannot move out of type `[B; 1]`, a non-copy array
   --> $DIR/move-errors.rs:74:11
    |
 LL |     match x[0] {
-   |           ^^^^
-   |           |
-   |           cannot move out of here
-   |           help: consider borrowing here: `&x[0]`
+   |           ^^^^ cannot move out of here
 LL |
 LL |         B::U(d) => (),
    |              - data moved here
@@ -84,6 +109,10 @@ LL |         B::V(s) => (),
    |              - ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing here
+   |
+LL |     match &x[0] {
+   |           +
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:83:11
@@ -96,6 +125,11 @@ LL |         B::U(D(s)) => (),
    |                |
    |                data moved here
    |                move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         B::U(D(ref s)) => (),
+   |                +++
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:92:11
@@ -108,6 +142,11 @@ LL |         (D(s), &t) => (),
    |            |
    |            data moved here
    |            move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (D(ref s), &t) => (),
+   |            +++
 
 error[E0507]: cannot move out of `*x.1` which is behind a shared reference
   --> $DIR/move-errors.rs:92:11
@@ -120,6 +159,11 @@ LL |         (D(s), &t) => (),
    |                 |
    |                 data moved here
    |                 move occurs because `t` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (D(s), &ref t) => (),
+   |                 +++
 
 error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:102:11
@@ -133,18 +177,32 @@ LL |         F(s, mut t) => (),
    |           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         F(ref s, mut t) => (),
+   |           +++
+help: consider borrowing the pattern binding
+   |
+LL |         F(s, ref mut t) => (),
+   |              +++
 
 error[E0507]: cannot move out of `x` as enum variant `Err` which is behind a shared reference
   --> $DIR/move-errors.rs:110:11
    |
 LL |     match *x {
-   |           ^^ help: consider borrowing here: `&*x`
+   |           ^^
 LL |
 LL |         Ok(s) | Err(s) => (),
    |            -
    |            |
    |            data moved here
    |            move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *x {
+LL +     match x {
+   |
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/no-capture-arc.stderr b/src/test/ui/no-capture-arc.stderr
index 9ae41e78c22..296e1fb3f26 100644
--- a/src/test/ui/no-capture-arc.stderr
+++ b/src/test/ui/no-capture-arc.stderr
@@ -13,11 +13,6 @@ LL |     assert_eq!((*arc_v)[2], 3);
    |                ^^^^^^^^ value borrowed here after move
    |
    = note: borrow occurs due to deref coercion to `Vec<i32>`
-note: deref defined here
-  --> $SRC_DIR/alloc/src/sync.rs:LL:COL
-   |
-LL |     type Target = T;
-   |     ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/no-reuse-move-arc.stderr b/src/test/ui/no-reuse-move-arc.stderr
index 564b0585474..bcd481c33f3 100644
--- a/src/test/ui/no-reuse-move-arc.stderr
+++ b/src/test/ui/no-reuse-move-arc.stderr
@@ -13,11 +13,6 @@ LL |     assert_eq!((*arc_v)[2], 3);
    |                ^^^^^^^^ value borrowed here after move
    |
    = note: borrow occurs due to deref coercion to `Vec<i32>`
-note: deref defined here
-  --> $SRC_DIR/alloc/src/sync.rs:LL:COL
-   |
-LL |     type Target = T;
-   |     ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr
index c864b93dbbb..75561f4119a 100644
--- a/src/test/ui/no-send-res-ports.stderr
+++ b/src/test/ui/no-send-res-ports.stderr
@@ -31,9 +31,6 @@ LL |     thread::spawn(move|| {
    |                   ^^^^^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL |     F: Send + 'static,
-   |        ^^^^ required by this bound in `spawn`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr
index f61ee661bb7..37d94cf0ebd 100644
--- a/src/test/ui/not-clone-closure.stderr
+++ b/src/test/ui/not-clone-closure.stderr
@@ -1,13 +1,11 @@
 error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
-  --> $DIR/not-clone-closure.rs:11:17
+  --> $DIR/not-clone-closure.rs:11:23
    |
 LL |     let hello = move || {
    |                 ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
 ...
 LL |     let hello = hello.clone();
-   |                 ^^^^^ ----- required by a bound introduced by this call
-   |                 |
-   |                 within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
+   |                       ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
    |
 note: required because it's used within this closure
   --> $DIR/not-clone-closure.rs:7:17
diff --git a/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs
new file mode 100644
index 00000000000..f00cde4a74c
--- /dev/null
+++ b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs
@@ -0,0 +1,34 @@
+// Checks that integers with seeming uppercase base prefixes do not get bogus capitalization
+// suggestions.
+
+fn main() {
+    _ = 123X1a3;
+    //~^ ERROR invalid suffix `X1a3` for number literal
+    //~| NOTE invalid suffix `X1a3`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 456O123;
+    //~^ ERROR invalid suffix `O123` for number literal
+    //~| NOTE invalid suffix `O123`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 789B101;
+    //~^ ERROR invalid suffix `B101` for number literal
+    //~| NOTE invalid suffix `B101`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 0XYZ;
+    //~^ ERROR invalid suffix `XYZ` for number literal
+    //~| NOTE invalid suffix `XYZ`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 0OPQ;
+    //~^ ERROR invalid suffix `OPQ` for number literal
+    //~| NOTE invalid suffix `OPQ`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 0BCD;
+    //~^ ERROR invalid suffix `BCD` for number literal
+    //~| NOTE invalid suffix `BCD`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+}
diff --git a/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr
new file mode 100644
index 00000000000..380c16ca789
--- /dev/null
+++ b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr
@@ -0,0 +1,50 @@
+error: invalid suffix `X1a3` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:5:9
+   |
+LL |     _ = 123X1a3;
+   |         ^^^^^^^ invalid suffix `X1a3`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `O123` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:10:9
+   |
+LL |     _ = 456O123;
+   |         ^^^^^^^ invalid suffix `O123`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `B101` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:15:9
+   |
+LL |     _ = 789B101;
+   |         ^^^^^^^ invalid suffix `B101`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `XYZ` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:20:9
+   |
+LL |     _ = 0XYZ;
+   |         ^^^^ invalid suffix `XYZ`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `OPQ` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:25:9
+   |
+LL |     _ = 0OPQ;
+   |         ^^^^ invalid suffix `OPQ`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `BCD` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:30:9
+   |
+LL |     _ = 0BCD;
+   |         ^^^^ invalid suffix `BCD`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/on-unimplemented/sum.stderr b/src/test/ui/on-unimplemented/sum.stderr
index 0c99e63f0e5..2a316dba778 100644
--- a/src/test/ui/on-unimplemented/sum.stderr
+++ b/src/test/ui/on-unimplemented/sum.stderr
@@ -1,38 +1,42 @@
 error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
-  --> $DIR/sum.rs:4:5
+  --> $DIR/sum.rs:4:25
    |
 LL |     vec![(), ()].iter().sum::<i32>();
-   |     ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call
-   |     |
-   |     value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |                         ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
    |
    = help: the trait `Sum<&()>` is not implemented for `i32`
    = help: the following other types implement trait `Sum<A>`:
              <i32 as Sum<&'a i32>>
              <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:4:18
+   |
+LL |     vec![(), ()].iter().sum::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
 note: required by a bound in `std::iter::Iterator::sum`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         S: Sum<Self::Item>,
-   |            ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum`
 
 error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator
-  --> $DIR/sum.rs:7:5
+  --> $DIR/sum.rs:7:25
    |
 LL |     vec![(), ()].iter().product::<i32>();
-   |     ^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |     |
-   |     value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
+   |                         ^^^^^^^ value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
    |
    = help: the trait `Product<&()>` is not implemented for `i32`
    = help: the following other types implement trait `Product<A>`:
              <i32 as Product<&'a i32>>
              <i32 as Product>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:7:18
+   |
+LL |     vec![(), ()].iter().product::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
 note: required by a bound in `std::iter::Iterator::product`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         P: Product<Self::Item>,
-   |            ^^^^^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::product`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
index 920720a4f53..10d42b7e3c0 100644
--- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
@@ -35,11 +35,8 @@ note: an implementation of `BitOr<_>` might be missing for `E`
    |
 LL | enum E { A, B }
    | ^^^^^^ must implement `BitOr<_>`
-note: the following trait must be implemented
+note: the trait `BitOr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait BitOr<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/overloaded/overloaded-calls-nontuple.stderr b/src/test/ui/overloaded/overloaded-calls-nontuple.stderr
index 794535aeb11..2e160078259 100644
--- a/src/test/ui/overloaded/overloaded-calls-nontuple.stderr
+++ b/src/test/ui/overloaded/overloaded-calls-nontuple.stderr
@@ -6,9 +6,6 @@ LL | impl FnMut<isize> for S {
    |
 note: required by a bound in `FnMut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait FnMut<Args: Tuple>: FnOnce<Args> {
-   |                       ^^^^^ required by this bound in `FnMut`
 
 error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
   --> $DIR/overloaded-calls-nontuple.rs:18:6
@@ -18,9 +15,6 @@ LL | impl FnOnce<isize> for S {
    |
 note: required by a bound in `FnOnce`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait FnOnce<Args: Tuple> {
-   |                        ^^^^^ required by this bound in `FnOnce`
 
 error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
   --> $DIR/overloaded-calls-nontuple.rs:12:5
diff --git a/src/test/ui/parser/increment-autofix-2.fixed b/src/test/ui/parser/increment-autofix-2.fixed
new file mode 100644
index 00000000000..580ebaf5dbb
--- /dev/null
+++ b/src/test/ui/parser/increment-autofix-2.fixed
@@ -0,0 +1,63 @@
+// run-rustfix
+
+struct Foo {
+    bar: Bar,
+}
+
+struct Bar {
+    qux: i32,
+}
+
+pub fn post_regular() {
+    let mut i = 0;
+    i += 1; //~ ERROR Rust has no postfix increment operator
+    println!("{}", i);
+}
+
+pub fn post_while() {
+    let mut i = 0;
+    while { let tmp = i; i += 1; tmp } < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", i);
+    }
+}
+
+pub fn post_regular_tmp() {
+    let mut tmp = 0;
+    tmp += 1; //~ ERROR Rust has no postfix increment operator
+    println!("{}", tmp);
+}
+
+pub fn post_while_tmp() {
+    let mut tmp = 0;
+    while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", tmp);
+    }
+}
+
+pub fn post_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    foo.bar.qux += 1;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+pub fn post_field_tmp() {
+    struct S {
+        tmp: i32
+    }
+    let mut s = S { tmp: 0 };
+    s.tmp += 1;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", s.tmp);
+}
+
+pub fn pre_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    foo.bar.qux += 1;
+    //~^ ERROR Rust has no prefix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/increment-notfixed.rs b/src/test/ui/parser/increment-autofix-2.rs
index 15f159e53d2..ebe5fa6ca1e 100644
--- a/src/test/ui/parser/increment-notfixed.rs
+++ b/src/test/ui/parser/increment-autofix-2.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+
 struct Foo {
     bar: Bar,
 }
@@ -35,7 +37,7 @@ pub fn post_while_tmp() {
 }
 
 pub fn post_field() {
-    let foo = Foo { bar: Bar { qux: 0 } };
+    let mut foo = Foo { bar: Bar { qux: 0 } };
     foo.bar.qux++;
     //~^ ERROR Rust has no postfix increment operator
     println!("{}", foo.bar.qux);
@@ -45,14 +47,14 @@ pub fn post_field_tmp() {
     struct S {
         tmp: i32
     }
-    let s = S { tmp: 0 };
+    let mut s = S { tmp: 0 };
     s.tmp++;
     //~^ ERROR Rust has no postfix increment operator
     println!("{}", s.tmp);
 }
 
 pub fn pre_field() {
-    let foo = Foo { bar: Bar { qux: 0 } };
+    let mut foo = Foo { bar: Bar { qux: 0 } };
     ++foo.bar.qux;
     //~^ ERROR Rust has no prefix increment operator
     println!("{}", foo.bar.qux);
diff --git a/src/test/ui/parser/increment-notfixed.stderr b/src/test/ui/parser/increment-autofix-2.stderr
index ae55ae06714..11e985480d6 100644
--- a/src/test/ui/parser/increment-notfixed.stderr
+++ b/src/test/ui/parser/increment-autofix-2.stderr
@@ -1,18 +1,16 @@
 error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:11:6
+  --> $DIR/increment-autofix-2.rs:13:6
    |
 LL |     i++;
    |      ^^ not a valid postfix operator
    |
 help: use `+= 1` instead
    |
-LL |     { let tmp = i; i += 1; tmp };
-   |     +++++++++++  ~~~~~~~~~~~~~~~
 LL |     i += 1;
    |       ~~~~
 
 error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:17:12
+  --> $DIR/increment-autofix-2.rs:19:12
    |
 LL |     while i++ < 5 {
    |     -----  ^^ not a valid postfix operator
@@ -23,24 +21,20 @@ help: use `+= 1` instead
    |
 LL |     while { let tmp = i; i += 1; tmp } < 5 {
    |           +++++++++++  ~~~~~~~~~~~~~~~
-LL |     while i += 1 < 5 {
-   |             ~~~~
 
 error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:25:8
+  --> $DIR/increment-autofix-2.rs:27:8
    |
 LL |     tmp++;
    |        ^^ not a valid postfix operator
    |
 help: use `+= 1` instead
    |
-LL |     { let tmp_ = tmp; tmp += 1; tmp_ };
-   |     ++++++++++++    ~~~~~~~~~~~~~~~~~~
 LL |     tmp += 1;
    |         ~~~~
 
 error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:31:14
+  --> $DIR/increment-autofix-2.rs:33:14
    |
 LL |     while tmp++ < 5 {
    |     -----    ^^ not a valid postfix operator
@@ -51,37 +45,31 @@ help: use `+= 1` instead
    |
 LL |     while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
    |           ++++++++++++    ~~~~~~~~~~~~~~~~~~
-LL |     while tmp += 1 < 5 {
-   |               ~~~~
 
 error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:39:16
+  --> $DIR/increment-autofix-2.rs:41:16
    |
 LL |     foo.bar.qux++;
    |                ^^ not a valid postfix operator
    |
 help: use `+= 1` instead
    |
-LL |     { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp };
-   |     +++++++++++            ~~~~~~~~~~~~~~~~~~~~~~~~~
 LL |     foo.bar.qux += 1;
    |                 ~~~~
 
 error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:49:10
+  --> $DIR/increment-autofix-2.rs:51:10
    |
 LL |     s.tmp++;
    |          ^^ not a valid postfix operator
    |
 help: use `+= 1` instead
    |
-LL |     { let tmp = s.tmp; s.tmp += 1; tmp };
-   |     +++++++++++      ~~~~~~~~~~~~~~~~~~~
 LL |     s.tmp += 1;
    |           ~~~~
 
 error: Rust has no prefix increment operator
-  --> $DIR/increment-notfixed.rs:56:5
+  --> $DIR/increment-autofix-2.rs:58:5
    |
 LL |     ++foo.bar.qux;
    |     ^^ not a valid prefix operator
diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.rs b/src/test/ui/parser/issue-104867-inc-dec-2.rs
new file mode 100644
index 00000000000..a006421a975
--- /dev/null
+++ b/src/test/ui/parser/issue-104867-inc-dec-2.rs
@@ -0,0 +1,52 @@
+fn test1() {
+    let mut i = 0;
+    let _ = i + ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test2() {
+    let mut i = 0;
+    let _ = ++i + i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test3() {
+    let mut i = 0;
+    let _ = ++i + ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test4() {
+    let mut i = 0;
+    let _ = i + i++; //~ ERROR Rust has no postfix increment operator
+    // won't suggest since we can not handle the precedences
+}
+
+fn test5() {
+    let mut i = 0;
+    let _ = i++ + i; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test6() {
+    let mut i = 0;
+    let _ = i++ + i++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test7() {
+    let mut i = 0;
+    let _ = ++i + i++; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test8() {
+    let mut i = 0;
+    let _ = i++ + ++i; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test9() {
+    let mut i = 0;
+    let _ = (1 + 2 + i)++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test10() {
+    let mut i = 0;
+    let _ = (i++ + 1) + 2; //~ ERROR Rust has no postfix increment operator
+}
+
+fn main() { }
diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.stderr b/src/test/ui/parser/issue-104867-inc-dec-2.stderr
new file mode 100644
index 00000000000..4e2d0546851
--- /dev/null
+++ b/src/test/ui/parser/issue-104867-inc-dec-2.stderr
@@ -0,0 +1,107 @@
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:3:17
+   |
+LL |     let _ = i + ++i;
+   |                 ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = i + { i += 1; i };
+   |                 ~   +++++++++
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:8:13
+   |
+LL |     let _ = ++i + i;
+   |             ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { i += 1; i } + i;
+   |             ~   +++++++++
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:13:13
+   |
+LL |     let _ = ++i + ++i;
+   |             ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { i += 1; i } + ++i;
+   |             ~   +++++++++
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:18:18
+   |
+LL |     let _ = i + i++;
+   |                  ^^ not a valid postfix operator
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:24:14
+   |
+LL |     let _ = i++ + i;
+   |              ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = i; i += 1; tmp } + i;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:29:14
+   |
+LL |     let _ = i++ + i++;
+   |              ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = i; i += 1; tmp } + i++;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:34:13
+   |
+LL |     let _ = ++i + i++;
+   |             ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { i += 1; i } + i++;
+   |             ~   +++++++++
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:39:14
+   |
+LL |     let _ = i++ + ++i;
+   |              ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = i; i += 1; tmp } + ++i;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:44:24
+   |
+LL |     let _ = (1 + 2 + i)++;
+   |                        ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = (1 + 2 + i); (1 + 2 + i) += 1; tmp };
+   |             +++++++++++            ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:49:15
+   |
+LL |     let _ = (i++ + 1) + 2;
+   |               ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = ({ let tmp = i; i += 1; tmp } + 1) + 2;
+   |              +++++++++++  ~~~~~~~~~~~~~~~
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/parser/issue-104867-inc-dec.rs b/src/test/ui/parser/issue-104867-inc-dec.rs
new file mode 100644
index 00000000000..760c67b4bed
--- /dev/null
+++ b/src/test/ui/parser/issue-104867-inc-dec.rs
@@ -0,0 +1,45 @@
+struct S {
+    x: i32,
+}
+
+fn test1() {
+    let mut i = 0;
+    i++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test2() {
+    let s = S { x: 0 };
+    s.x++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test3() {
+    let mut i = 0;
+    if i++ == 1 {} //~ ERROR Rust has no postfix increment operator
+}
+
+fn test4() {
+    let mut i = 0;
+    ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test5() {
+    let mut i = 0;
+    if ++i == 1 { } //~ ERROR Rust has no prefix increment operator
+}
+
+fn test6() {
+    let mut i = 0;
+    loop { break; }
+    i++; //~ ERROR Rust has no postfix increment operator
+    loop { break; }
+    ++i;
+}
+
+fn test7() {
+    let mut i = 0;
+    loop { break; }
+    ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-104867-inc-dec.stderr b/src/test/ui/parser/issue-104867-inc-dec.stderr
new file mode 100644
index 00000000000..78bfd3e82f0
--- /dev/null
+++ b/src/test/ui/parser/issue-104867-inc-dec.stderr
@@ -0,0 +1,81 @@
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:7:6
+   |
+LL |     i++;
+   |      ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     i += 1;
+   |       ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:12:8
+   |
+LL |     s.x++;
+   |        ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     s.x += 1;
+   |         ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:17:9
+   |
+LL |     if i++ == 1 {}
+   |         ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     if { let tmp = i; i += 1; tmp } == 1 {}
+   |        +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:22:5
+   |
+LL |     ++i;
+   |     ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL -     ++i;
+LL +     i += 1;
+   |
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:27:8
+   |
+LL |     if ++i == 1 { }
+   |        ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     if { i += 1; i } == 1 { }
+   |        ~   +++++++++
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:33:6
+   |
+LL |     i++;
+   |      ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     i += 1;
+   |       ~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:41:5
+   |
+LL |     ++i;
+   |     ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL -     ++i;
+LL +     i += 1;
+   |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/issues/issue-39616.rs b/src/test/ui/parser/issue-39616.rs
index 46b5aa334ca..46b5aa334ca 100644
--- a/src/test/ui/issues/issue-39616.rs
+++ b/src/test/ui/parser/issue-39616.rs
diff --git a/src/test/ui/issues/issue-39616.stderr b/src/test/ui/parser/issue-39616.stderr
index 393d1f2e2ce..393d1f2e2ce 100644
--- a/src/test/ui/issues/issue-39616.stderr
+++ b/src/test/ui/parser/issue-39616.stderr
diff --git a/src/test/ui/issues/issue-49257.rs b/src/test/ui/parser/issue-49257.rs
index a7fa19d52fd..a7fa19d52fd 100644
--- a/src/test/ui/issues/issue-49257.rs
+++ b/src/test/ui/parser/issue-49257.rs
diff --git a/src/test/ui/issues/issue-49257.stderr b/src/test/ui/parser/issue-49257.stderr
index 846467f7f22..846467f7f22 100644
--- a/src/test/ui/issues/issue-49257.stderr
+++ b/src/test/ui/parser/issue-49257.stderr
diff --git a/src/test/ui/parser/issues/issue-62894.stderr b/src/test/ui/parser/issues/issue-62894.stderr
index ae89926914e..07a203bf416 100644
--- a/src/test/ui/parser/issues/issue-62894.stderr
+++ b/src/test/ui/parser/issues/issue-62894.stderr
@@ -42,11 +42,9 @@ LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
 LL |
 LL | fn main() {}
    | ^^ unexpected token
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     ($left:expr, $right:expr $(,)?) => {
-   |      ---------- while parsing argument for this `expr` macro fragment
+   = note: while parsing argument for this `expr` macro fragment
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr
index 546ad84eeee..79643660e8b 100644
--- a/src/test/ui/parser/kw-in-trait-bounds.stderr
+++ b/src/test/ui/parser/kw-in-trait-bounds.stderr
@@ -91,44 +91,36 @@ error[E0405]: cannot find trait `r#fn` in this scope
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |          ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:17:4
    |
 LL | G: fn(),
    |    ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:3:27
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |                           ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:3:41
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |                                         ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#struct` in this scope
   --> $DIR/kw-in-trait-bounds.rs:24:10
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed
new file mode 100644
index 00000000000..5f04fc83d37
--- /dev/null
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(unused_variables)]
+fn main() {
+    struct U;
+
+    // A tuple is a "non-reference pattern".
+    // A `mut` binding pattern resets the binding mode to by-value.
+
+    let mut p = (U, U);
+    let (a, ref mut b) = &mut p;
+    //~^ ERROR cannot move out of a mutable reference
+}
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs
new file mode 100644
index 00000000000..5dc1ae2feb5
--- /dev/null
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(unused_variables)]
+fn main() {
+    struct U;
+
+    // A tuple is a "non-reference pattern".
+    // A `mut` binding pattern resets the binding mode to by-value.
+
+    let mut p = (U, U);
+    let (a, mut b) = &mut p;
+    //~^ ERROR cannot move out of a mutable reference
+}
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr
new file mode 100644
index 00000000000..d3ab533e35e
--- /dev/null
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr
@@ -0,0 +1,17 @@
+error[E0507]: cannot move out of a mutable reference
+  --> $DIR/move-ref-patterns-default-binding-modes-fixable.rs:10:22
+   |
+LL |     let (a, mut b) = &mut p;
+   |             -----    ^^^^^^
+   |             |
+   |             data moved here
+   |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let (a, ref mut b) = &mut p;
+   |             +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs
index 1dd66aad57a..6c913c24513 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs
@@ -7,8 +7,4 @@ fn main() {
     let p = (U, U);
     let (a, mut b) = &p;
     //~^ ERROR cannot move out of a shared reference
-
-    let mut p = (U, U);
-    let (a, mut b) = &mut p;
-    //~^ ERROR cannot move out of a mutable reference
 }
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr
index 6952c743a30..65030b62250 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr
@@ -6,16 +6,12 @@ LL |     let (a, mut b) = &p;
    |             |
    |             data moved here
    |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
-
-error[E0507]: cannot move out of a mutable reference
-  --> $DIR/move-ref-patterns-default-binding-modes.rs:12:22
    |
-LL |     let (a, mut b) = &mut p;
-   |             -----    ^^^^^^
-   |             |
-   |             data moved here
-   |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |     let (a, ref mut b) = &p;
+   |             +++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/pattern/pat-tuple-bad-type.stderr b/src/test/ui/pattern/pat-tuple-bad-type.stderr
index 3342b8e4002..da369d33397 100644
--- a/src/test/ui/pattern/pat-tuple-bad-type.stderr
+++ b/src/test/ui/pattern/pat-tuple-bad-type.stderr
@@ -9,8 +9,8 @@ LL |         (..) => {}
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _;
-   |          +++
+LL |     let x: /* Type */;
+   |          ++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/pat-tuple-bad-type.rs:10:9
diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
index e6a4e5f19b7..beba7def96f 100644
--- a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
+++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
@@ -193,8 +193,8 @@ LL |     let x @ ..;
    |
 help: consider giving this pattern a type
    |
-LL |     let x @ ..: _;
-   |               +++
+LL |     let x @ ..: /* Type */;
+   |               ++++++++++++
 
 error: aborting due to 23 previous errors
 
diff --git a/src/test/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr b/src/test/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr
index f3dca9bcb07..2a016048f2f 100644
--- a/src/test/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr
+++ b/src/test/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr
@@ -6,12 +6,9 @@ LL |     match Some(1) {
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
index b450a9aeddf..17e1a2304a1 100644
--- a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
+++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
@@ -66,12 +66,9 @@ LL |     match None {
    |
 note: `Option<HiddenEnum>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<HiddenEnum>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
diff --git a/src/test/ui/pattern/usefulness/issue-35609.stderr b/src/test/ui/pattern/usefulness/issue-35609.stderr
index c9781d52e6d..12113957d63 100644
--- a/src/test/ui/pattern/usefulness/issue-35609.stderr
+++ b/src/test/ui/pattern/usefulness/issue-35609.stderr
@@ -107,9 +107,6 @@ LL |     match Some(A) {
    |
 note: `Option<Enum>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   | ^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `Option<Enum>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
diff --git a/src/test/ui/pattern/usefulness/issue-3601.stderr b/src/test/ui/pattern/usefulness/issue-3601.stderr
index eb8c63919b6..59d7bcd4b5e 100644
--- a/src/test/ui/pattern/usefulness/issue-3601.stderr
+++ b/src/test/ui/pattern/usefulness/issue-3601.stderr
@@ -6,12 +6,6 @@ LL |         box NodeKind::Element(ed) => match ed.kind {
    |
 note: `Box<ElementKind>` defined here
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | / pub struct Box<
-LL | |     T: ?Sized,
-LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
-   | |_^
    = note: the matched value is of type `Box<ElementKind>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr
index b0d7fe5eb68..e4dd35a5995 100644
--- a/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr
+++ b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr
@@ -19,15 +19,11 @@ LL |     match Some(Some(North)) {
    |
 note: `Option<Option<Direction>>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
-   |     |
-   |     not covered
-   |     not covered
+   = note: not covered
+   |
+   = note: not covered
    = note: the matched value is of type `Option<Option<Direction>>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/src/test/ui/pattern/usefulness/match-privately-empty.stderr b/src/test/ui/pattern/usefulness/match-privately-empty.stderr
index 4607cfaae17..86f75d15cfd 100644
--- a/src/test/ui/pattern/usefulness/match-privately-empty.stderr
+++ b/src/test/ui/pattern/usefulness/match-privately-empty.stderr
@@ -6,12 +6,9 @@ LL |     match private::DATA {
    |
 note: `Option<Private>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<Private>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
index 4234600d0d0..e2260f50bfe 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
@@ -36,12 +36,9 @@ LL |     match Some(10) {
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
diff --git a/src/test/ui/print_type_sizes/async.rs b/src/test/ui/print_type_sizes/async.rs
index 3491ad5afbc..1598b069691 100644
--- a/src/test/ui/print_type_sizes/async.rs
+++ b/src/test/ui/print_type_sizes/async.rs
@@ -1,19 +1,11 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type lib
 // edition:2021
 // build-pass
 // ignore-pass
 
-#![feature(start)]
-
 async fn wait() {}
 
-async fn test(arg: [u8; 8192]) {
+pub async fn test(arg: [u8; 8192]) {
     wait().await;
     drop(arg);
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _ = test([0; 8192]);
-    0
-}
diff --git a/src/test/ui/print_type_sizes/async.stdout b/src/test/ui/print_type_sizes/async.stdout
index 94ad09ef296..6e47bb4930d 100644
--- a/src/test/ui/print_type_sizes/async.stdout
+++ b/src/test/ui/print_type_sizes/async.stdout
@@ -1,4 +1,4 @@
-print-type-size type: `[async fn body@$DIR/async.rs:10:32: 13:2]`: 16386 bytes, alignment: 1 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Suspend0`: 16385 bytes
 print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
@@ -16,14 +16,14 @@ print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment
 print-type-size     variant `MaybeUninit`: 8192 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 8192 bytes
-print-type-size type: `[async fn body@$DIR/async.rs:8:17: 8:19]`: 1 bytes, alignment: 1 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
 print-type-size     variant `Returned`: 0 bytes
 print-type-size     variant `Panicked`: 0 bytes
-print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1 bytes
-print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 1 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 1 bytes
diff --git a/src/test/ui/print_type_sizes/generator.rs b/src/test/ui/print_type_sizes/generator.rs
index a46db612104..d1cd36274ef 100644
--- a/src/test/ui/print_type_sizes/generator.rs
+++ b/src/test/ui/print_type_sizes/generator.rs
@@ -1,8 +1,8 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 
-#![feature(start, generators, generator_trait)]
+#![feature(generators, generator_trait)]
 
 use std::ops::Generator;
 
@@ -13,8 +13,6 @@ fn generator<const C: usize>(array: [u8; C]) -> impl Generator<Yield = (), Retur
     }
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn foo() {
     let _ = generator([0; 8192]);
-    0
 }
diff --git a/src/test/ui/print_type_sizes/generator_discr_placement.rs b/src/test/ui/print_type_sizes/generator_discr_placement.rs
new file mode 100644
index 00000000000..1a85fe95bb6
--- /dev/null
+++ b/src/test/ui/print_type_sizes/generator_discr_placement.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z print-type-sizes --crate-type lib
+// build-pass
+// ignore-pass
+
+// Tests a generator that has its discriminant as the *final* field.
+
+// Avoid emitting panic handlers, like the rest of these tests...
+#![feature(generators)]
+
+pub fn foo() {
+    let a = || {
+        {
+            let w: i32 = 4;
+            yield;
+            drop(w);
+        }
+        {
+            let z: i32 = 7;
+            yield;
+            drop(z);
+        }
+    };
+}
diff --git a/src/test/ui/print_type_sizes/generator_discr_placement.stdout b/src/test/ui/print_type_sizes/generator_discr_placement.stdout
new file mode 100644
index 00000000000..7f8f4ccae7c
--- /dev/null
+++ b/src/test/ui/print_type_sizes/generator_discr_placement.stdout
@@ -0,0 +1,11 @@
+print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 7 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.w`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Suspend1`: 7 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.z`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Unresumed`: 0 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
diff --git a/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs
index 3ef7b60db2c..05097087d5a 100644
--- a/src/test/ui/print_type_sizes/generics.rs
+++ b/src/test/ui/print_type_sizes/generics.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -8,24 +8,6 @@
 // monomorphized, in the MIR of the original function in which they
 // occur, to have their size reported.
 
-#![feature(start)]
-
-// In an ad-hoc attempt to avoid the injection of unwinding code
-// (which clutters the output of `-Z print-type-sizes` with types from
-// `unwind::libunwind`):
-//
-//   * I am not using Default to build values because that seems to
-//     cause the injection of unwinding code. (Instead I just make `fn new`
-//     methods.)
-//
-//   * Pair derive Copy to ensure that we don't inject
-//     unwinding code into generic uses of Pair when T itself is also
-//     Copy.
-//
-//     (I suspect this reflect some naivety within the rust compiler
-//      itself; it should be checking for drop glue, i.e., a destructor
-//      somewhere in the monomorphized types. It should not matter whether
-//      the type is Copy.)
 #[derive(Copy, Clone)]
 pub struct Pair<T> {
     _car: T,
@@ -61,11 +43,9 @@ pub fn f1<T:Copy>(x: T) {
         Pair::new(FiftyBytes::new(), FiftyBytes::new());
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn start() {
     let _b: Pair<u8> = Pair::new(0, 0);
     let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
     let ref _z: ZeroSized = ZeroSized;
     f1::<SevenBytes>(SevenBytes::new());
-    0
 }
diff --git a/src/test/ui/print_type_sizes/multiple_types.rs b/src/test/ui/print_type_sizes/multiple_types.rs
index f1ad27ec131..91590389247 100644
--- a/src/test/ui/print_type_sizes/multiple_types.rs
+++ b/src/test/ui/print_type_sizes/multiple_types.rs
@@ -1,11 +1,9 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This file illustrates that when multiple structural types occur in
 // a function, every one of them is included in the output.
 
-#![feature(start)]
-
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -13,11 +11,3 @@ pub enum Enum {
     Small(SevenBytes),
     Large(FiftyBytes),
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _e: Enum;
-    let _f: FiftyBytes;
-    let _s: SevenBytes;
-    0
-}
diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs
index 0716cee21c6..5e620f248b6 100644
--- a/src/test/ui/print_type_sizes/niche-filling.rs
+++ b/src/test/ui/print_type_sizes/niche-filling.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -14,7 +14,6 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
-#![feature(start)]
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
 
@@ -56,7 +55,7 @@ pub struct NestedNonZero {
 
 impl Default for NestedNonZero {
     fn default() -> Self {
-        NestedNonZero { pre: 0, val: NonZeroU32::new(1).unwrap(), post: 0 }
+        NestedNonZero { pre: 0, val: unsafe { NonZeroU32::new_unchecked(1) }, post: 0 }
     }
 }
 
@@ -76,8 +75,7 @@ pub union Union2<A: Copy, B: Copy> {
     b: B,
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _x: MyOption<NonZeroU32> = Default::default();
     let _y: EmbeddedDiscr = Default::default();
     let _z: MyOption<IndirectNonZero> = Default::default();
@@ -96,6 +94,4 @@ fn start(_: isize, _: *const *const u8) -> isize {
     // ...even when theoretically possible.
     let _j: MyOption<Union1<NonZeroU32>> = Default::default();
     let _k: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
-
-    0
 }
diff --git a/src/test/ui/print_type_sizes/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs
index e45e4794a35..2ec5d9e64bf 100644
--- a/src/test/ui/print_type_sizes/no_duplicates.rs
+++ b/src/test/ui/print_type_sizes/no_duplicates.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -8,16 +8,12 @@
 // (even if multiple functions), it is only printed once in the
 // print-type-sizes output.
 
-#![feature(start)]
-
 pub struct SevenBytes([u8; 7]);
 
 pub fn f1() {
     let _s: SevenBytes = SevenBytes([0; 7]);
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _s: SevenBytes = SevenBytes([0; 7]);
-    0
 }
diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs
index 269cc3cc282..5ddfe4bf4db 100644
--- a/src/test/ui/print_type_sizes/packed.rs
+++ b/src/test/ui/print_type_sizes/packed.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -13,11 +13,10 @@
 // padding and overall computed sizes can be quite different.
 
 #![allow(dead_code)]
-#![feature(start)]
 
 #[derive(Default)]
 #[repr(packed)]
-struct Packed1 {
+pub struct Packed1 {
     a: u8,
     b: u8,
     g: i32,
@@ -28,7 +27,7 @@ struct Packed1 {
 
 #[derive(Default)]
 #[repr(packed(2))]
-struct Packed2 {
+pub struct Packed2 {
     a: u8,
     b: u8,
     g: i32,
@@ -40,7 +39,7 @@ struct Packed2 {
 #[derive(Default)]
 #[repr(packed(2))]
 #[repr(C)]
-struct Packed2C {
+pub struct Packed2C {
     a: u8,
     b: u8,
     g: i32,
@@ -50,7 +49,7 @@ struct Packed2C {
 }
 
 #[derive(Default)]
-struct Padded {
+pub struct Padded {
     a: u8,
     b: u8,
     g: i32,
@@ -58,12 +57,3 @@ struct Padded {
     h: i16,
     d: u8,
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _c: Packed1 = Default::default();
-    let _d: Packed2 = Default::default();
-    let _e: Packed2C = Default::default();
-    let _f: Padded = Default::default();
-    0
-}
diff --git a/src/test/ui/print_type_sizes/padding.rs b/src/test/ui/print_type_sizes/padding.rs
index d1acad16d7e..f41c677dc6c 100644
--- a/src/test/ui/print_type_sizes/padding.rs
+++ b/src/test/ui/print_type_sizes/padding.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This file illustrates how padding is handled: alignment
@@ -9,7 +9,6 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
-#![feature(start)]
 #![allow(dead_code)]
 
 struct S {
@@ -27,8 +26,3 @@ enum E2 {
     A(i8, i32),
     B(S),
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    0
-}
diff --git a/src/test/ui/print_type_sizes/repr-align.rs b/src/test/ui/print_type_sizes/repr-align.rs
index 07544935b2f..0bd11ebc958 100644
--- a/src/test/ui/print_type_sizes/repr-align.rs
+++ b/src/test/ui/print_type_sizes/repr-align.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -11,7 +11,7 @@
 // It avoids using u64/i64 because on some targets that is only 4-byte
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
-#![feature(start)]
+
 #![allow(dead_code)]
 
 #[repr(align(16))]
@@ -24,15 +24,9 @@ enum E {
 }
 
 #[derive(Default)]
-struct S {
+pub struct S {
     a: i32,
     b: i32,
     c: A,
     d: i8,
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _s: S = Default::default();
-    0
-}
diff --git a/src/test/ui/print_type_sizes/repr_int_c.rs b/src/test/ui/print_type_sizes/repr_int_c.rs
index b8067c112ee..6b103776a30 100644
--- a/src/test/ui/print_type_sizes/repr_int_c.rs
+++ b/src/test/ui/print_type_sizes/repr_int_c.rs
@@ -1,10 +1,9 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)`
 // variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug).
 
-#![feature(start)]
 #![allow(dead_code)]
 
 #[repr(C, u8)]
@@ -18,8 +17,3 @@ enum Repru8 {
     A(u16),
     B,
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    0
-}
diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs
index 06a62db4ebb..86fab7b500a 100644
--- a/src/test/ui/print_type_sizes/uninhabited.rs
+++ b/src/test/ui/print_type_sizes/uninhabited.rs
@@ -1,14 +1,12 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
 //     FIXME: consider using an attribute instead of side-effects.
 
 #![feature(never_type)]
-#![feature(start)]
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _x: Option<!> = None;
     let _y: Result<u32, !> = Ok(42);
     let _z: Result<!, !> = loop {};
diff --git a/src/test/ui/print_type_sizes/variants.rs b/src/test/ui/print_type_sizes/variants.rs
index 6c8553cc23d..5a302052026 100644
--- a/src/test/ui/print_type_sizes/variants.rs
+++ b/src/test/ui/print_type_sizes/variants.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This file illustrates two things:
@@ -9,8 +9,6 @@
 // 2. For an enum, the print-type-sizes output will also include the
 //    size of each variant.
 
-#![feature(start)]
-
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -18,9 +16,3 @@ pub enum Enum {
     Small(SevenBytes),
     Large(FiftyBytes),
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _e: Enum;
-    0
-}
diff --git a/src/test/ui/print_type_sizes/zero-sized-fields.rs b/src/test/ui/print_type_sizes/zero-sized-fields.rs
index e02a33109e5..09415824d5d 100644
--- a/src/test/ui/print_type_sizes/zero-sized-fields.rs
+++ b/src/test/ui/print_type_sizes/zero-sized-fields.rs
@@ -1,12 +1,10 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 
 // At one point, zero-sized fields such as those in this file were causing
 // incorrect output from `-Z print-type-sizes`.
 
-#![feature(start)]
-
 struct S1 {
     x: u32,
     y: u32,
@@ -28,8 +26,7 @@ struct S5<TagW, TagZ> {
     tagz: TagZ,
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _s1: S1 = S1 { x: 0, y: 0, tag: () };
 
     let _s5: S5<(), Empty> = S5 {
@@ -43,5 +40,4 @@ fn start(_: isize, _: *const *const u8) -> isize {
         z: 4,
         tagz: Empty {},
     };
-    0
 }
diff --git a/src/test/ui/privacy/associated-item-privacy-trait.rs b/src/test/ui/privacy/associated-item-privacy-trait.rs
index ad9a5e15c4e..c686a21772e 100644
--- a/src/test/ui/privacy/associated-item-privacy-trait.rs
+++ b/src/test/ui/privacy/associated-item-privacy-trait.rs
@@ -19,9 +19,9 @@ mod priv_trait {
         Pub.method();
         //~^ ERROR type `for<'a> fn(&'a Self) {<Self as PrivTr>::method}` is private
         <Pub as PrivTr>::CONST;
-        //~^ ERROR associated constant `<Pub as PrivTr>::CONST` is private
+        //~^ ERROR associated constant `PrivTr::CONST` is private
         let _: <Pub as PrivTr>::AssocTy;
-        //~^ ERROR associated type `<Pub as PrivTr>::AssocTy` is private
+        //~^ ERROR associated type `PrivTr::AssocTy` is private
         pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
         //~^ ERROR trait `PrivTr` is private
         pub trait InSignatureTr: PrivTr {}
diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr
index c4be1a9d9a2..eb905bf7ef8 100644
--- a/src/test/ui/privacy/associated-item-privacy-trait.stderr
+++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr
@@ -31,7 +31,7 @@ LL |     priv_trait::mac!();
    |
    = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: associated constant `<Pub as PrivTr>::CONST` is private
+error: associated constant `PrivTr::CONST` is private
   --> $DIR/associated-item-privacy-trait.rs:21:9
    |
 LL |         <Pub as PrivTr>::CONST;
@@ -42,7 +42,7 @@ LL |     priv_trait::mac!();
    |
    = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: associated type `<Pub as PrivTr>::AssocTy` is private
+error: associated type `PrivTr::AssocTy` is private
   --> $DIR/associated-item-privacy-trait.rs:23:16
    |
 LL |         let _: <Pub as PrivTr>::AssocTy;
diff --git a/src/test/ui/privacy/private-inferred-type-3.rs b/src/test/ui/privacy/private-inferred-type-3.rs
index 0337aedd008..cdbdcf60b2c 100644
--- a/src/test/ui/privacy/private-inferred-type-3.rs
+++ b/src/test/ui/privacy/private-inferred-type-3.rs
@@ -1,7 +1,7 @@
 // aux-build:private-inferred-type.rs
 
 // error-pattern:type `fn() {ext::priv_fn}` is private
-// error-pattern:static `PRIV_STATIC` is private
+// error-pattern:static `ext::PRIV_STATIC` is private
 // error-pattern:type `ext::PrivEnum` is private
 // error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
 // error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
diff --git a/src/test/ui/privacy/private-inferred-type-3.stderr b/src/test/ui/privacy/private-inferred-type-3.stderr
index 00b61512de6..42faeb4bf34 100644
--- a/src/test/ui/privacy/private-inferred-type-3.stderr
+++ b/src/test/ui/privacy/private-inferred-type-3.stderr
@@ -6,7 +6,7 @@ LL |     ext::m!();
    |
    = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: static `PRIV_STATIC` is private
+error: static `ext::PRIV_STATIC` is private
   --> $DIR/private-inferred-type-3.rs:16:5
    |
 LL |     ext::m!();
diff --git a/src/test/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/src/test/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr
index ac49e04e3c0..14e5df21ef6 100644
--- a/src/test/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr
+++ b/src/test/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr
@@ -7,9 +7,6 @@ LL | #[derive(PartialOrd, AddImpl)]
    = help: the trait `PartialEq` is not implemented for `PriorityQueue<T>`
 note: required by a bound in `PartialOrd`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
-   |                                           ^^^^^^^^^^^^^^ required by this bound in `PartialOrd`
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `PriorityQueue<T>: Eq` is not satisfied
@@ -20,9 +17,6 @@ LL | #[derive(PartialOrd, AddImpl)]
    |
 note: required by a bound in `Ord`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait Ord: Eq + PartialOrd<Self> {
-   |                ^^ required by this bound in `Ord`
    = note: this error originates in the derive macro `AddImpl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `T` with `T`
@@ -38,9 +32,6 @@ LL | #[derive(PartialOrd, AddImpl)]
    |          ^^^^^^^^^^
 note: required by a bound in `Ord`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait Ord: Eq + PartialOrd<Self> {
-   |                     ^^^^^^^^^^^^^^^^ required by this bound in `Ord`
    = note: this error originates in the derive macro `AddImpl` which comes from the expansion of the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr
index 65ce24e5522..a3b27fd7bcc 100644
--- a/src/test/ui/proc-macro/parent-source-spans.stderr
+++ b/src/test/ui/proc-macro/parent-source-spans.stderr
@@ -144,11 +144,9 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     one!("hello", "world");
    |     ---------------------- in this macro invocation
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     -- similarly named tuple variant `Ok` defined here
+   = note: similarly named tuple variant `Ok` defined here
    |
    = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -160,11 +158,9 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     two!("yay", "rust");
    |     ------------------- in this macro invocation
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     -- similarly named tuple variant `Ok` defined here
+   = note: similarly named tuple variant `Ok` defined here
    |
    = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -176,11 +172,9 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     three!("hip", "hop");
    |     -------------------- in this macro invocation
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     -- similarly named tuple variant `Ok` defined here
+   = note: similarly named tuple variant `Ok` defined here
    |
    = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `three` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr
index a534b9d5377..3c3f24d0ff2 100644
--- a/src/test/ui/proc-macro/resolve-error.stderr
+++ b/src/test/ui/proc-macro/resolve-error.stderr
@@ -72,22 +72,18 @@ error: cannot find derive macro `Dlone` in this scope
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub macro Clone($item:item) {
-   | --------------- similarly named derive macro `Clone` defined here
+   = note: similarly named derive macro `Clone` defined here
 
 error: cannot find derive macro `Dlone` in this scope
   --> $DIR/resolve-error.rs:35:10
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub macro Clone($item:item) {
-   | --------------- similarly named derive macro `Clone` defined here
+   = note: similarly named derive macro `Clone` defined here
 
 error: cannot find attribute `FooWithLongNan` in this scope
   --> $DIR/resolve-error.rs:32:3
diff --git a/src/test/ui/proc-macro/signature.stderr b/src/test/ui/proc-macro/signature.stderr
index 59b3e44c74a..79f2001da00 100644
--- a/src/test/ui/proc-macro/signature.stderr
+++ b/src/test/ui/proc-macro/signature.stderr
@@ -14,9 +14,6 @@ LL | | }
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `ProcMacro::custom_derive`
   --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
-   |
-LL |         expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ProcMacro::custom_derive`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/proc-macro/span-api-tests.rs b/src/test/ui/proc-macro/span-api-tests.rs
index 914ad54ed03..3f04ba866b7 100644
--- a/src/test/ui/proc-macro/span-api-tests.rs
+++ b/src/test/ui/proc-macro/span-api-tests.rs
@@ -2,6 +2,7 @@
 // ignore-pretty
 // aux-build:span-api-tests.rs
 // aux-build:span-test-macros.rs
+// compile-flags: -Ztranslate-remapped-path-to-local-path=yes
 
 #[macro_use]
 extern crate span_test_macros;
diff --git a/src/test/ui/range/issue-54505-no-literals.stderr b/src/test/ui/range/issue-54505-no-literals.stderr
index 4cbf8869d0c..070dc844563 100644
--- a/src/test/ui/range/issue-54505-no-literals.stderr
+++ b/src/test/ui/range/issue-54505-no-literals.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     take_range(std::ops::Range { start: 0, end: 1 });
    |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |     |          |
-   |     |          expected reference, found struct `std::ops::Range`
+   |     |          expected reference, found struct `Range`
    |     |          help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
    |     arguments to this function are incorrect
    |
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
 LL |     take_range(::std::ops::Range { start: 0, end: 1 });
    |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |     |          |
-   |     |          expected reference, found struct `std::ops::Range`
+   |     |          expected reference, found struct `Range`
    |     |          help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
    |     arguments to this function are incorrect
    |
diff --git a/src/test/ui/range/issue-54505.stderr b/src/test/ui/range/issue-54505.stderr
index 38df6e14496..9eec169404c 100644
--- a/src/test/ui/range/issue-54505.stderr
+++ b/src/test/ui/range/issue-54505.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     take_range(0..1);
    |     ---------- ^^^^
    |     |          |
-   |     |          expected reference, found struct `std::ops::Range`
+   |     |          expected reference, found struct `Range`
    |     |          help: consider borrowing here: `&(0..1)`
    |     arguments to this function are incorrect
    |
diff --git a/src/test/ui/range/issue-73553-misinterp-range-literal.stderr b/src/test/ui/range/issue-73553-misinterp-range-literal.stderr
index 6badd998f96..d08d9b1345d 100644
--- a/src/test/ui/range/issue-73553-misinterp-range-literal.stderr
+++ b/src/test/ui/range/issue-73553-misinterp-range-literal.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     demo(tell(1)..tell(10));
    |     ---- ^^^^^^^^^^^^^^^^^
    |     |    |
-   |     |    expected reference, found struct `std::ops::Range`
+   |     |    expected `&Range<usize>`, found struct `Range`
    |     |    help: consider borrowing here: `&(tell(1)..tell(10))`
    |     arguments to this function are incorrect
    |
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
 LL |     demo(1..10);
    |     ---- ^^^^^
    |     |    |
-   |     |    expected reference, found struct `std::ops::Range`
+   |     |    expected `&Range<usize>`, found struct `Range`
    |     |    help: consider borrowing here: `&(1..10)`
    |     arguments to this function are incorrect
    |
diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr
index aaea91ce0cb..3956390368f 100644
--- a/src/test/ui/range/range-1.stderr
+++ b/src/test/ui/range/range-1.stderr
@@ -32,9 +32,6 @@ LL |     let range = *arr..;
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by a bound in `RangeFrom`
   --> $SRC_DIR/core/src/ops/range.rs:LL:COL
-   |
-LL | pub struct RangeFrom<Idx> {
-   |                      ^^^ required by this bound in `RangeFrom`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/auxiliary/issue-11225-1.rs b/src/test/ui/reachable/auxiliary/issue-11225-1.rs
index 2c6f899a0f4..2c6f899a0f4 100644
--- a/src/test/ui/issues/auxiliary/issue-11225-1.rs
+++ b/src/test/ui/reachable/auxiliary/issue-11225-1.rs
diff --git a/src/test/ui/issues/auxiliary/issue-11225-2.rs b/src/test/ui/reachable/auxiliary/issue-11225-2.rs
index 4381f0a4edf..4381f0a4edf 100644
--- a/src/test/ui/issues/auxiliary/issue-11225-2.rs
+++ b/src/test/ui/reachable/auxiliary/issue-11225-2.rs
diff --git a/src/test/ui/issues/auxiliary/issue-11225-3.rs b/src/test/ui/reachable/auxiliary/issue-11225-3.rs
index 266e42a10b5..266e42a10b5 100644
--- a/src/test/ui/issues/auxiliary/issue-11225-3.rs
+++ b/src/test/ui/reachable/auxiliary/issue-11225-3.rs
diff --git a/src/test/ui/issues/issue-11225-1.rs b/src/test/ui/reachable/issue-11225-1.rs
index d1f2ea5e7de..d1f2ea5e7de 100644
--- a/src/test/ui/issues/issue-11225-1.rs
+++ b/src/test/ui/reachable/issue-11225-1.rs
diff --git a/src/test/ui/issues/issue-11225-2.rs b/src/test/ui/reachable/issue-11225-2.rs
index d41c75443f1..d41c75443f1 100644
--- a/src/test/ui/issues/issue-11225-2.rs
+++ b/src/test/ui/reachable/issue-11225-2.rs
diff --git a/src/test/ui/issues/issue-11225-3.rs b/src/test/ui/reachable/issue-11225-3.rs
index e69496baa26..e69496baa26 100644
--- a/src/test/ui/issues/issue-11225-3.rs
+++ b/src/test/ui/reachable/issue-11225-3.rs
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
index f2307899d3c..86ad6aa847c 100644
--- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
@@ -8,12 +8,9 @@ LL |     let Ok(x) = res;
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Result<u32, &R<'_>>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, &R<'_>>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
diff --git a/src/test/ui/resolve/issue-104700-inner_scope.rs b/src/test/ui/resolve/issue-104700-inner_scope.rs
new file mode 100644
index 00000000000..e8f28c113e3
--- /dev/null
+++ b/src/test/ui/resolve/issue-104700-inner_scope.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let foo = 1;
+    {
+        let bar = 2;
+        let test_func = |x| x > 3;
+    }
+    if bar == 2 { //~ ERROR cannot find value
+        println!("yes");
+    }
+    test_func(1); //~ ERROR cannot find function
+}
diff --git a/src/test/ui/resolve/issue-104700-inner_scope.stderr b/src/test/ui/resolve/issue-104700-inner_scope.stderr
new file mode 100644
index 00000000000..051b234fc72
--- /dev/null
+++ b/src/test/ui/resolve/issue-104700-inner_scope.stderr
@@ -0,0 +1,21 @@
+error[E0425]: cannot find value `bar` in this scope
+  --> $DIR/issue-104700-inner_scope.rs:7:8
+   |
+LL |     if bar == 2 {
+   |        ^^^
+   |
+help: the binding `bar` is available in a different scope in the same function
+  --> $DIR/issue-104700-inner_scope.rs:4:13
+   |
+LL |         let bar = 2;
+   |             ^^^
+
+error[E0425]: cannot find function `test_func` in this scope
+  --> $DIR/issue-104700-inner_scope.rs:10:5
+   |
+LL |     test_func(1);
+   |     ^^^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr
index 939392733f0..558e6b7b118 100644
--- a/src/test/ui/resolve/issue-5035-2.stderr
+++ b/src/test/ui/resolve/issue-5035-2.stderr
@@ -6,6 +6,10 @@ LL | fn foo(_x: K) {}
    |
    = help: the trait `Sized` is not implemented for `(dyn I + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn foo(_x: impl K) {}
+   |            ++++
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | fn foo(_x: &K) {}
diff --git a/src/test/ui/resolve/issue-85348.stderr b/src/test/ui/resolve/issue-85348.stderr
index f839dd927db..42b43f825d1 100644
--- a/src/test/ui/resolve/issue-85348.stderr
+++ b/src/test/ui/resolve/issue-85348.stderr
@@ -21,8 +21,8 @@ LL |         let mut N;
    |
 help: consider giving `N` an explicit type
    |
-LL |         let mut N: _;
-   |                  +++
+LL |         let mut N: /* Type */;
+   |                  ++++++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr
index 9a2d61ea405..cf478210132 100644
--- a/src/test/ui/resolve/levenshtein.stderr
+++ b/src/test/ui/resolve/levenshtein.stderr
@@ -18,11 +18,9 @@ error[E0412]: cannot find type `Opiton` in this scope
    |
 LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
    |          ^^^^^^ help: an enum with a similar name exists: `Option`
+  --> $SRC_DIR/core/src/option.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   | ------------------ similarly named enum `Option` defined here
+   = note: similarly named enum `Option` defined here
 
 error[E0412]: cannot find type `Baz` in this scope
   --> $DIR/levenshtein.rs:16:14
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr
index 6d5d5bad9fe..964302e924c 100644
--- a/src/test/ui/resolve/resolve-primitive-fallback.stderr
+++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr
@@ -28,9 +28,6 @@ LL |     std::mem::size_of(u16);
    |
 note: function defined here
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |              ^^^^^^^
 help: remove the extra argument
    |
 LL |     std::mem::size_of();
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
index 9577952119a..a19750cc73a 100644
--- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -9,9 +9,6 @@ LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
    = note: required for `Result<f32, ParseFloatError>` to implement `Termination`
 note: required by a bound in `assert_test_result`
   --> $SRC_DIR/test/src/lib.rs:LL:COL
-   |
-LL | pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
-   |                              ^^^^^^^^^^^ required by this bound in `assert_test_result`
    = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/rfc-2005-default-binding-mode/for.stderr b/src/test/ui/rfc-2005-default-binding-mode/for.stderr
index 9cc20a7bf31..07991af6ef9 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/for.stderr
+++ b/src/test/ui/rfc-2005-default-binding-mode/for.stderr
@@ -6,6 +6,11 @@ LL |     for (n, mut m) in &tups {
    |             |
    |             data moved here
    |             move occurs because `m` has type `Foo`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     for (n, ref mut m) in &tups {
+   |             +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
index 06699b947be..e97fdcce1c1 100644
--- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
@@ -8,11 +8,6 @@ LL |     let _ = dbg!(a);
 LL |     let _ = dbg!(a);
    |                  ^ value used here after move
    |
-help: borrow this binding in the pattern to avoid moving the value
-  --> $SRC_DIR/std/src/macros.rs:LL:COL
-   |
-LL |             ref tmp => {
-   |             +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index 91c00115180..3028f8dbdbf 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -1516,7 +1516,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:157:8
    |
 LL |     if true..(let 0 = 0) {}
-   |        ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1545,7 +1545,7 @@ error[E0308]: mismatched types
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |            |
-   |            expected `bool`, found struct `std::ops::Range`
+   |            expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1554,7 +1554,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:171:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1565,7 +1565,7 @@ error[E0308]: mismatched types
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |            |
-   |            expected `bool`, found struct `std::ops::Range`
+   |            expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1574,7 +1574,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:175:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1585,7 +1585,7 @@ error[E0308]: mismatched types
 LL |     if let Range { start: F, end } = F..|| true {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
    |            |
-   |            expected fn pointer, found struct `std::ops::Range`
+   |            expected fn pointer, found struct `Range`
    |
    = note: expected fn pointer `fn() -> bool`
                   found struct `std::ops::Range<_>`
@@ -1607,7 +1607,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:182:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1618,7 +1618,7 @@ error[E0308]: mismatched types
 LL |     if let Range { start: true, end } = t..&&false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
    |            |
-   |            expected `bool`, found struct `std::ops::Range`
+   |            expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1639,7 +1639,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:190:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1710,7 +1710,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:249:11
    |
 LL |     while true..(let 0 = 0) {}
-   |           ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1739,7 +1739,7 @@ error[E0308]: mismatched types
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |               |
-   |               expected `bool`, found struct `std::ops::Range`
+   |               expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1748,7 +1748,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:263:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1759,7 +1759,7 @@ error[E0308]: mismatched types
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |               |
-   |               expected `bool`, found struct `std::ops::Range`
+   |               expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1768,7 +1768,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:267:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1779,7 +1779,7 @@ error[E0308]: mismatched types
 LL |     while let Range { start: F, end } = F..|| true {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
    |               |
-   |               expected fn pointer, found struct `std::ops::Range`
+   |               expected fn pointer, found struct `Range`
    |
    = note: expected fn pointer `fn() -> bool`
                   found struct `std::ops::Range<_>`
@@ -1801,7 +1801,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:274:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1812,7 +1812,7 @@ error[E0308]: mismatched types
 LL |     while let Range { start: true, end } = t..&&false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
    |               |
-   |               expected `bool`, found struct `std::ops::Range`
+   |               expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1833,7 +1833,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:282:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1883,7 +1883,7 @@ error[E0308]: mismatched types
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |          |
-   |          expected `bool`, found struct `std::ops::Range`
+   |          expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
index c64930db9be..f9d0d1f7875 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
-  --> $DIR/const-default-method-bodies.rs:24:5
+  --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
-   |     ^^^^^^^^^^^^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+   |                  ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
    |
 note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
   --> $DIR/const-default-method-bodies.rs:24:5
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
index 925ae53e324..633b7cc255a 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:5
+  --> $DIR/cross-crate.rs:17:14
    |
 LL |     NonConst.func();
-   |     ^^^^^^^^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
   --> $DIR/cross-crate.rs:17:5
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
index 11db0c2b8f2..9e97d3f1137 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:5
+  --> $DIR/cross-crate.rs:17:14
    |
 LL |     NonConst.func();
-   |     ^^^^^^^^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
   --> $DIR/cross-crate.rs:17:5
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
index c2c16921c2e..21ecddaffbb 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
    |
 LL |         ().a()
-   |         ^^ - required by a bound introduced by this call
-   |         |
-   |         the trait `~const Tr` is not implemented for `()`
+   |            ^ the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
   --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
index b52eb2c0332..13fc719f28c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:15:5
+  --> $DIR/super-traits-fail-2.rs:15:7
    |
 LL |     x.a();
-   |     ^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const Foo` is not implemented for `T`
+   |       ^ the trait `~const Foo` is not implemented for `T`
    |
 note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
   --> $DIR/super-traits-fail-2.rs:15:5
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
index b52eb2c0332..13fc719f28c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:15:5
+  --> $DIR/super-traits-fail-2.rs:15:7
    |
 LL |     x.a();
-   |     ^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const Foo` is not implemented for `T`
+   |       ^ the trait `~const Foo` is not implemented for `T`
    |
 note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
   --> $DIR/super-traits-fail-2.rs:15:5
diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr
index eea94643e0a..5d4d692b2cf 100644
--- a/src/test/ui/span/issue-39018.stderr
+++ b/src/test/ui/span/issue-39018.stderr
@@ -26,11 +26,8 @@ note: an implementation of `Add<_>` might be missing for `World`
    |
 LL | enum World {
    | ^^^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot add `String` to `&str`
   --> $DIR/issue-39018.rs:11:22
diff --git a/src/test/ui/span/issue-71363.rs b/src/test/ui/span/issue-71363.rs
index f187d0efa84..8014f379625 100644
--- a/src/test/ui/span/issue-71363.rs
+++ b/src/test/ui/span/issue-71363.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ui-testing=no
+// compile-flags: -Z ui-testing=no
 
 struct MyError;
 impl std::error::Error for MyError {}
diff --git a/src/test/ui/span/method-and-field-eager-resolution.stderr b/src/test/ui/span/method-and-field-eager-resolution.stderr
index 7d240589a3f..f6efbe40bc2 100644
--- a/src/test/ui/span/method-and-field-eager-resolution.stderr
+++ b/src/test/ui/span/method-and-field-eager-resolution.stderr
@@ -9,8 +9,8 @@ LL |     x.0;
    |
 help: consider giving `x` an explicit type
    |
-LL |     let mut x: _ = Default::default();
-   |              +++
+LL |     let mut x: /* Type */ = Default::default();
+   |              ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/method-and-field-eager-resolution.rs:11:9
@@ -23,8 +23,8 @@ LL |     x[0];
    |
 help: consider giving `x` an explicit type
    |
-LL |     let mut x: _ = Default::default();
-   |              +++
+LL |     let mut x: /* Type */ = Default::default();
+   |              ++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr
index b76a3ab307a..48a2e763af6 100644
--- a/src/test/ui/span/missing-unit-argument.stderr
+++ b/src/test/ui/span/missing-unit-argument.stderr
@@ -6,9 +6,6 @@ LL |     let _: Result<(), String> = Ok();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: provide the argument
    |
 LL |     let _: Result<(), String> = Ok(());
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
index 33ca7a2c210..37788612f43 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -27,7 +27,7 @@ LL | default impl<T> Foo for T {
    | ^^^^^^^^^^^^^^^^---^^^^^-
    | |
    | unsatisfied trait bound introduced here
-note: the following trait must be implemented
+note: the trait `Foo` must be implemented
   --> $DIR/specialization-trait-not-implemented.rs:7:1
    |
 LL | trait Foo {
diff --git a/src/test/ui/stability-attribute/stability-in-private-module.stderr b/src/test/ui/stability-attribute/stability-in-private-module.stderr
index e64f2acbd35..2f02a24960e 100644
--- a/src/test/ui/stability-attribute/stability-in-private-module.stderr
+++ b/src/test/ui/stability-attribute/stability-in-private-module.stderr
@@ -6,9 +6,6 @@ LL |     let _ = std::thread::thread_info::current_thread();
    |
 note: the module `thread_info` is defined here
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL | use crate::sys_common::thread_info;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/std-uncopyable-atomics.stderr b/src/test/ui/std-uncopyable-atomics.stderr
index 9db9fcf40f8..8c5d0b96096 100644
--- a/src/test/ui/std-uncopyable-atomics.stderr
+++ b/src/test/ui/std-uncopyable-atomics.stderr
@@ -2,37 +2,49 @@ error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:9:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:11:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:13:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:15:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicPtr<usize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicPtr<usize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-21058.rs b/src/test/ui/stdlib-unit-tests/issue-21058.rs
index 6facf0b2dd5..6facf0b2dd5 100644
--- a/src/test/ui/issues/issue-21058.rs
+++ b/src/test/ui/stdlib-unit-tests/issue-21058.rs
diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr
index 019305def29..cb1a6fcacfc 100644
--- a/src/test/ui/str/str-idx.stderr
+++ b/src/test/ui/str/str-idx.stderr
@@ -24,9 +24,6 @@ LL |     let _ = s.get(4);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const fn get<I: ~const SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
-   |                         ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:5:29
@@ -42,9 +39,6 @@ LL |     let _ = s.get_unchecked(4);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_unchecked`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const unsafe fn get_unchecked<I: ~const SliceIndex<str>>(&self, i: I) -> &I::Output {
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked`
 
 error[E0277]: the type `str` cannot be indexed by `char`
   --> $DIR/str-idx.rs:6:19
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr
index b165c482590..ca4b86ba306 100644
--- a/src/test/ui/str/str-mut-idx.stderr
+++ b/src/test/ui/str/str-mut-idx.stderr
@@ -48,9 +48,6 @@ LL |     s.get_mut(1);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const fn get_mut<I: ~const SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
-   |                             ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_mut`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-mut-idx.rs:11:25
@@ -66,9 +63,6 @@ LL |     s.get_unchecked_mut(1);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const unsafe fn get_unchecked_mut<I: ~const SliceIndex<str>>(
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked_mut`
 
 error[E0277]: the type `str` cannot be indexed by `char`
   --> $DIR/str-mut-idx.rs:13:7
diff --git a/src/test/ui/structs/struct-record-suggestion.stderr b/src/test/ui/structs/struct-record-suggestion.stderr
index f4fd655e698..9b751d1b66c 100644
--- a/src/test/ui/structs/struct-record-suggestion.stderr
+++ b/src/test/ui/structs/struct-record-suggestion.stderr
@@ -18,7 +18,7 @@ error[E0308]: mismatched types
   --> $DIR/struct-record-suggestion.rs:23:20
    |
 LL |     let q = B { b: 1..Default::default() };
-   |                    ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `std::ops::Range`
+   |                    ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `Range`
    |
    = note: expected type `u32`
             found struct `std::ops::Range<{integer}>`
diff --git a/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
index 0a91c442d2c..44a39efdf25 100644
--- a/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
+++ b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
@@ -13,9 +13,6 @@ LL |     let _: Option<(i32, bool)> = Some(1, 2);
                found type `{integer}`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: remove the extra argument
    |
 LL |     let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
@@ -52,9 +49,6 @@ LL |     let _: Option<(i8,)> = Some();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: provide the argument
    |
 LL |     let _: Option<(i8,)> = Some(/* (i8,) */);
@@ -72,9 +66,6 @@ LL |     let _: Option<(i32,)> = Some(5_usize);
                found type `usize`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 
 error[E0308]: mismatched types
   --> $DIR/args-instead-of-tuple-errors.rs:17:34
@@ -88,9 +79,6 @@ LL |     let _: Option<(i32,)> = Some((5_usize));
                found type `usize`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/suggestions/args-instead-of-tuple.stderr b/src/test/ui/suggestions/args-instead-of-tuple.stderr
index 20f9e5259a4..c8499010d68 100644
--- a/src/test/ui/suggestions/args-instead-of-tuple.stderr
+++ b/src/test/ui/suggestions/args-instead-of-tuple.stderr
@@ -6,9 +6,6 @@ LL |     let _: Result<(i32, i8), ()> = Ok(1, 2);
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |     let _: Result<(i32, i8), ()> = Ok((1, 2));
@@ -22,9 +19,6 @@ LL |     let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi");
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |     let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi"));
@@ -38,9 +32,6 @@ LL |     let _: Option<()> = Some();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: provide the argument
    |
 LL |     let _: Option<()> = Some(());
@@ -58,9 +49,6 @@ LL |     let _: Option<(i32,)> = Some(3);
                found type `{integer}`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: use a trailing comma to create a tuple with one element
    |
 LL |     let _: Option<(i32,)> = Some((3,));
@@ -78,9 +66,6 @@ LL |     let _: Option<(i32,)> = Some((3));
                found type `{integer}`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: use a trailing comma to create a tuple with one element
    |
 LL |     let _: Option<(i32,)> = Some((3,));
diff --git a/src/test/ui/suggestions/as-ref-2.stderr b/src/test/ui/suggestions/as-ref-2.stderr
index e15e45d86b9..e2129b4502a 100644
--- a/src/test/ui/suggestions/as-ref-2.stderr
+++ b/src/test/ui/suggestions/as-ref-2.stderr
@@ -10,11 +10,8 @@ LL |     let _x: Option<Struct> = foo.map(|s| bar(&s));
 LL |     let _y = foo;
    |              ^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `foo`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn map<U, F>(self, f: F) -> Option<U>
-   |                            ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr
index 54122cb7360..b871c9b45a5 100644
--- a/src/test/ui/suggestions/attribute-typos.stderr
+++ b/src/test/ui/suggestions/attribute-typos.stderr
@@ -15,11 +15,9 @@ error: cannot find attribute `tests` in this scope
    |
 LL | #[tests]
    |   ^^^^^ help: an attribute macro with a similar name exists: `test`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     pub macro test($item:item) {
-   |     -------------- similarly named attribute macro `test` defined here
+   = note: similarly named attribute macro `test` defined here
 
 error: cannot find attribute `deprcated` in this scope
   --> $DIR/attribute-typos.rs:1:3
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.stderr b/src/test/ui/suggestions/borrow-for-loop-head.stderr
index 0cc8994fe1f..cbdb94877bd 100644
--- a/src/test/ui/suggestions/borrow-for-loop-head.stderr
+++ b/src/test/ui/suggestions/borrow-for-loop-head.stderr
@@ -16,11 +16,8 @@ LL |     for i in &a {
 LL |         for j in a {
    |                  ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
    |
-note: this function takes ownership of the receiver `self`, which moves `a`
+note: `into_iter` takes ownership of the receiver `self`, which moves `a`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<i32>`'s content to avoid moving into the `for` loop
    |
 LL |         for j in &a {
diff --git a/src/test/ui/suggestions/bound-suggestions.stderr b/src/test/ui/suggestions/bound-suggestions.stderr
index d53715937f7..cd27947f02f 100644
--- a/src/test/ui/suggestions/bound-suggestions.stderr
+++ b/src/test/ui/suggestions/bound-suggestions.stderr
@@ -78,9 +78,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Foo<T>: Sized {
@@ -94,9 +91,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Bar: std::fmt::Display + Sized {
@@ -110,9 +104,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Baz: Sized where Self: std::fmt::Display {
@@ -126,9 +117,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Qux<T>: Sized where Self: std::fmt::Display {
@@ -142,9 +130,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Bat<T>: std::fmt::Display + Sized {
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed
new file mode 100644
index 00000000000..4f9e93a47ed
--- /dev/null
+++ b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+fn wat<T: Clone>(t: &T) -> T {
+    t.clone() //~ ERROR E0308
+}
+
+#[derive(Clone)]
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+    t.clone() //~ ERROR E0308
+}
+
+fn main() {
+    wat(&42);
+    wut(&Foo);
+}
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs
new file mode 100644
index 00000000000..89b077d671a
--- /dev/null
+++ b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+fn wat<T>(t: &T) -> T {
+    t.clone() //~ ERROR E0308
+}
+
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+    t.clone() //~ ERROR E0308
+}
+
+fn main() {
+    wat(&42);
+    wut(&Foo);
+}
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
new file mode 100644
index 00000000000..26ab515d9b4
--- /dev/null
+++ b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
@@ -0,0 +1,43 @@
+error[E0308]: mismatched types
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+   |
+LL | fn wat<T>(t: &T) -> T {
+   |        -            - expected `T` because of return type
+   |        |
+   |        this type parameter
+LL |     t.clone()
+   |     ^^^^^^^^^ expected type parameter `T`, found `&T`
+   |
+   = note: expected type parameter `T`
+                   found reference `&T`
+note: `T` does not implement `Clone`, so `&T` was cloned instead
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+   |
+LL |     t.clone()
+   |     ^
+help: consider restricting type parameter `T`
+   |
+LL | fn wat<T: Clone>(t: &T) -> T {
+   |         +++++++
+
+error[E0308]: mismatched types
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+   |
+LL | fn wut(t: &Foo) -> Foo {
+   |                    --- expected `Foo` because of return type
+LL |     t.clone()
+   |     ^^^^^^^^^ expected struct `Foo`, found `&Foo`
+   |
+note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+   |
+LL |     t.clone()
+   |     ^
+help: consider annotating `Foo` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/derive-clone-for-eq.stderr b/src/test/ui/suggestions/derive-clone-for-eq.stderr
index 0645f0cdde7..0a18b770405 100644
--- a/src/test/ui/suggestions/derive-clone-for-eq.stderr
+++ b/src/test/ui/suggestions/derive-clone-for-eq.stderr
@@ -11,9 +11,6 @@ LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
    |                   ^^^^^^^^^^^^     ^^^^^^^^^
 note: required by a bound in `Eq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait Eq: PartialEq<Self> {
-   |               ^^^^^^^^^^^^^^^ required by this bound in `Eq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.stderr b/src/test/ui/suggestions/derive-trait-for-method-call.stderr
index 7cc372f2422..14e8a2675dd 100644
--- a/src/test/ui/suggestions/derive-trait-for-method-call.stderr
+++ b/src/test/ui/suggestions/derive-trait-for-method-call.stderr
@@ -20,11 +20,8 @@ LL |     let y = x.test();
            `Enum: Clone`
            `Enum: Default`
            `CloneEnum: Default`
-note: the following trait must be implemented
+note: the trait `Default` must be implemented
   --> $SRC_DIR/core/src/default.rs:LL:COL
-   |
-LL | pub trait Default: Sized {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider annotating `Enum` with `#[derive(Clone)]`
    |
 LL | #[derive(Clone)]
@@ -69,16 +66,12 @@ LL | struct Foo<X, Y> (X, Y);
 ...
 LL |     let y = x.test();
    |               ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
+  --> $SRC_DIR/std/src/time.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/time.rs:LL:COL
-   |
-LL | pub struct Instant(time::Instant);
-   | ------------------ doesn't satisfy `Instant: Default`
-   |
-  ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   = note: doesn't satisfy `Instant: Default`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<Enum>: Clone`
+   = note: doesn't satisfy `Vec<Enum>: Clone`
    |
    = note: the following trait bounds were not satisfied:
            `Vec<Enum>: Clone`
diff --git a/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr b/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
index 7bdc8e00f44..0cd6267b3b3 100644
--- a/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
+++ b/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
@@ -3,11 +3,9 @@ error[E0573]: expected type, found module `result`
    |
 LL | impl result {
    |      ^^^^^^ help: an enum with a similar name exists: `Result`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | --------------------- similarly named enum `Result` defined here
+   = note: similarly named enum `Result` defined here
 
 error[E0573]: expected type, found variant `Err`
   --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:3:25
diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
index bf0c1dc27ce..e19d497f21d 100644
--- a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
+++ b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
@@ -38,31 +38,25 @@ pub fn main() {
 
     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the borrow
     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the borrow
     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the borrow
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         &(Either::Two(_t), Either::One(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        //~^ HELP consider removing the borrow
         _ => (),
     }
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u))
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         | &(Either::Two(_t), Either::One(_u)) => (),
         // FIXME: would really like a suggestion here too
         _ => (),
@@ -70,51 +64,42 @@ pub fn main() {
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         &(Either::Two(ref _t), Either::One(ref _u)) => (),
         _ => (),
     }
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         (Either::Two(_t), Either::One(_u)) => (),
         _ => (),
     }
     fn f5(&(X(_t), X(_u)): &(X, X)) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the borrow
 
     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the mutable borrow
     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the mutable borrow
     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the mutable borrow
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         &mut (Either::Two(_t), Either::One(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        //~^ HELP consider removing the mutable borrow
         _ => (),
     }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u))
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         | &mut (Either::Two(_t), Either::One(_u)) => (),
         // FIXME: would really like a suggestion here too
         _ => (),
@@ -122,29 +107,25 @@ pub fn main() {
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         &mut (Either::Two(ref _t), Either::One(ref _u)) => (),
         _ => (),
     }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (),
         _ => (),
     }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         (Either::Two(_t), Either::One(_u)) => (),
         _ => (),
     }
     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the mutable borrow
 }
diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
index 40ad671f966..b96b3713f2a 100644
--- a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
+++ b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
@@ -2,40 +2,52 @@ error[E0507]: cannot move out of a shared reference
   --> $DIR/duplicate-suggestions.rs:39:27
    |
 LL |     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
-   |         ---------------   ^^^^^^^^^^^^^^^^^^^^^^^
-   |         |   |      |
-   |         |   |      ...and here
-   |         |   data moved here
-   |         help: consider removing the `&`: `(X(_t), X(_u))`
+   |             --     --     ^^^^^^^^^^^^^^^^^^^^^^^
+   |             |      |
+   |             |      ...and here
+   |             data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+LL +     let (X(_t), X(_u)) = &(x.clone(), x.clone());
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:43:50
+  --> $DIR/duplicate-suggestions.rs:42:50
    |
 LL |     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
-   |            -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^
-   |            |             |                |
-   |            |             |                ...and here
-   |            |             data moved here
-   |            help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                          --               --     ^^^^^^^^^^^^^^^^^^^^^^^
+   |                          |                |
+   |                          |                ...and here
+   |                          data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL +     if let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:47:53
+  --> $DIR/duplicate-suggestions.rs:45:53
    |
 LL |     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
-   |               -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^
-   |               |             |                |
-   |               |             |                ...and here
-   |               |             data moved here
-   |               help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                             --               --     ^^^^^^^^^^^^^^^^^^^^^^^
+   |                             |                |
+   |                             |                ...and here
+   |                             data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL +     while let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:51:11
+  --> $DIR/duplicate-suggestions.rs:48:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,22 +56,24 @@ LL |         &(Either::One(_t), Either::Two(_u)) => (),
    |                       --               -- ...and here
    |                       |
    |                       data moved here
-...
+LL |
 LL |         &(Either::Two(_t), Either::One(_u)) => (),
    |                       -- ...and here   -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL |         (Either::One(_t), Either::Two(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: consider removing the `&`
+LL -         &(Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
+help: consider removing the borrow
+   |
+LL -         &(Either::Two(_t), Either::One(_u)) => (),
+LL +         (Either::Two(_t), Either::One(_u)) => (),
    |
-LL |         (Either::Two(_t), Either::One(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:61:11
+  --> $DIR/duplicate-suggestions.rs:56:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
@@ -70,82 +84,98 @@ LL |         &(Either::One(_t), Either::Two(_u))
    |                       data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~         (Either::One(_t), Either::Two(_u))
-LL +
-LL +
-LL ~         | &(Either::Two(_t), Either::One(_u)) => (),
+LL -         &(Either::One(_t), Either::Two(_u))
+LL +         (Either::One(_t), Either::Two(_u))
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:70:11
+  --> $DIR/duplicate-suggestions.rs:64:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &(Either::One(_t), Either::Two(_u)) => (),
-   |         -----------------------------------
-   |         |             |                |
-   |         |             |                ...and here
-   |         |             data moved here
-   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                       --               -- ...and here
+   |                       |
+   |                       data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -         &(Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:78:11
+  --> $DIR/duplicate-suggestions.rs:71:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &(Either::One(_t), Either::Two(_u)) => (),
-   |         -----------------------------------
-   |         |             |                |
-   |         |             |                ...and here
-   |         |             data moved here
-   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                       --               -- ...and here
+   |                       |
+   |                       data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -         &(Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:91:31
+  --> $DIR/duplicate-suggestions.rs:82:31
    |
 LL |     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
-   |         -------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |       |      |
-   |         |       |      ...and here
-   |         |       data moved here
-   |         help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |                 --     --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 |      |
+   |                 |      ...and here
+   |                 data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+LL +     let (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:95:54
+  --> $DIR/duplicate-suggestions.rs:85:54
    |
 LL |     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
-   |            ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |            |                 |                |
-   |            |                 |                ...and here
-   |            |                 data moved here
-   |            help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                              --               --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              |                |
+   |                              |                ...and here
+   |                              data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL +     if let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:99:57
+  --> $DIR/duplicate-suggestions.rs:88:57
    |
 LL |     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
-   |               ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |               |                 |                |
-   |               |                 |                ...and here
-   |               |                 data moved here
-   |               help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                                 --               --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                 |                |
+   |                                 |                ...and here
+   |                                 data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL +     while let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:103:11
+  --> $DIR/duplicate-suggestions.rs:91:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,22 +184,24 @@ LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
    |                           --               -- ...and here
    |                           |
    |                           data moved here
-...
+LL |
 LL |         &mut (Either::Two(_t), Either::One(_u)) => (),
    |                           -- ...and here   -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
    |
-LL |         (Either::One(_t), Either::Two(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::Two(_t), Either::One(_u)) => (),
+LL +         (Either::Two(_t), Either::One(_u)) => (),
    |
-LL |         (Either::Two(_t), Either::One(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:113:11
+  --> $DIR/duplicate-suggestions.rs:99:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -180,82 +212,97 @@ LL |         &mut (Either::One(_t), Either::Two(_u))
    |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         (Either::One(_t), Either::Two(_u))
-LL +
-LL +
-LL ~         | &mut (Either::Two(_t), Either::One(_u)) => (),
+LL -         &mut (Either::One(_t), Either::Two(_u))
+LL +         (Either::One(_t), Either::Two(_u))
    |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:122:11
+  --> $DIR/duplicate-suggestions.rs:107:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
-   |         ---------------------------------------
-   |         |                 |                |
-   |         |                 |                ...and here
-   |         |                 data moved here
-   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:130:11
+  --> $DIR/duplicate-suggestions.rs:114:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
-   |         ---------------------------------------
-   |         |                 |                |
-   |         |                 |                ...and here
-   |         |                 data moved here
-   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:138:11
+  --> $DIR/duplicate-suggestions.rs:121:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
-   |         ---------------------------------------
-   |         |                 |                |
-   |         |                 |                ...and here
-   |         |                 data moved here
-   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:86:11
+  --> $DIR/duplicate-suggestions.rs:78:11
    |
 LL |     fn f5(&(X(_t), X(_u)): &(X, X)) { }
    |           ^^^^--^^^^^--^^
-   |           |   |      |
-   |           |   |      ...and here
-   |           |   data moved here
-   |           help: consider removing the `&`: `(X(_t), X(_u))`
+   |               |      |
+   |               |      ...and here
+   |               data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     fn f5(&(X(_t), X(_u)): &(X, X)) { }
+LL +     fn f5((X(_t), X(_u)): &(X, X)) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:146:11
+  --> $DIR/duplicate-suggestions.rs:128:11
    |
 LL |     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
    |           ^^^^^^^^--^^^^^--^^
-   |           |       |      |
-   |           |       |      ...and here
-   |           |       data moved here
-   |           help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |                   |      |
+   |                   |      ...and here
+   |                   data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+LL +     fn f6((X(_t), X(_u)): &mut (X, X)) { }
+   |
 
 error: aborting due to 17 previous errors
 
diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs
index f1e043c30f2..44eac3691a3 100644
--- a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs
+++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs
@@ -28,26 +28,21 @@ fn move_into_fn() {
         let X(_t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         while let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t)
             | Either::Two(_t) => (),
         }
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -56,26 +51,21 @@ fn move_into_fn() {
         let X(mut _t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         while let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t)
             | Either::Two(mut _t) => (),
         }
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -95,26 +85,21 @@ fn move_into_fnmut() {
         let X(_t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         while let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t)
             | Either::Two(_t) => (),
         }
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -123,26 +108,21 @@ fn move_into_fnmut() {
         let X(mut _t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         while let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t)
             | Either::Two(mut _t) => (),
         }
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -150,7 +130,6 @@ fn move_into_fnmut() {
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t) => (),
             Either::Two(ref mut _t) => (),
             // FIXME: should suggest removing `ref` too
diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
index e06ee4290ab..edda2cbc735 100644
--- a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
+++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
@@ -7,13 +7,18 @@ LL |     let x = X(Y);
 LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 LL |         let X(_t) = x;
-   |               --    ^ help: consider borrowing here: `&x`
+   |               --    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(_t) = &x;
+   |                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:32:34
+  --> $DIR/move-into-closure.rs:31:34
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -22,13 +27,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         if let Either::One(_t) = e { }
-   |                            --    ^ help: consider borrowing here: `&e`
+   |                            --    ^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(_t) = &e { }
+   |                                  +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:36:37
+  --> $DIR/move-into-closure.rs:34:37
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -37,13 +47,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         while let Either::One(_t) = e { }
-   |                               --    ^ help: consider borrowing here: `&e`
+   |                               --    ^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(_t) = &e { }
+   |                                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:40:15
+  --> $DIR/move-into-closure.rs:37:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -52,16 +67,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t)
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:47:15
+  --> $DIR/move-into-closure.rs:43:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -70,16 +90,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t) => (),
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:56:25
+  --> $DIR/move-into-closure.rs:51:25
    |
 LL |     let x = X(Y);
    |         - captured outer variable
@@ -88,13 +113,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         let X(mut _t) = x;
-   |               ------    ^ help: consider borrowing here: `&x`
+   |               ------    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(mut _t) = &x;
+   |                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:60:38
+  --> $DIR/move-into-closure.rs:54:38
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -103,13 +133,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         if let Either::One(mut _t) = em { }
-   |                            ------    ^^ help: consider borrowing here: `&em`
+   |                            ------    ^^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(mut _t) = &em { }
+   |                                      +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:64:41
+  --> $DIR/move-into-closure.rs:57:41
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -118,13 +153,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         while let Either::One(mut _t) = em { }
-   |                               ------    ^^ help: consider borrowing here: `&em`
+   |                               ------    ^^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(mut _t) = &em { }
+   |                                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:68:15
+  --> $DIR/move-into-closure.rs:60:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -133,16 +173,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t)
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:75:15
+  --> $DIR/move-into-closure.rs:66:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -151,16 +196,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t) => (),
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:95:21
+  --> $DIR/move-into-closure.rs:85:21
    |
 LL |     let x = X(Y);
    |         - captured outer variable
@@ -168,13 +218,18 @@ LL |     let x = X(Y);
 LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 LL |         let X(_t) = x;
-   |               --    ^ help: consider borrowing here: `&x`
+   |               --    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(_t) = &x;
+   |                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:99:34
+  --> $DIR/move-into-closure.rs:88:34
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -183,13 +238,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         if let Either::One(_t) = e { }
-   |                            --    ^ help: consider borrowing here: `&e`
+   |                            --    ^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(_t) = &e { }
+   |                                  +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:103:37
+  --> $DIR/move-into-closure.rs:91:37
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -198,13 +258,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         while let Either::One(_t) = e { }
-   |                               --    ^ help: consider borrowing here: `&e`
+   |                               --    ^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(_t) = &e { }
+   |                                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:107:15
+  --> $DIR/move-into-closure.rs:94:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -213,16 +278,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t)
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:114:15
+  --> $DIR/move-into-closure.rs:100:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -231,16 +301,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t) => (),
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:123:25
+  --> $DIR/move-into-closure.rs:108:25
    |
 LL |     let x = X(Y);
    |         - captured outer variable
@@ -249,13 +324,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         let X(mut _t) = x;
-   |               ------    ^ help: consider borrowing here: `&x`
+   |               ------    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(mut _t) = &x;
+   |                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:127:38
+  --> $DIR/move-into-closure.rs:111:38
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -264,13 +344,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         if let Either::One(mut _t) = em { }
-   |                            ------    ^^ help: consider borrowing here: `&em`
+   |                            ------    ^^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(mut _t) = &em { }
+   |                                      +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:131:41
+  --> $DIR/move-into-closure.rs:114:41
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -279,13 +364,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         while let Either::One(mut _t) = em { }
-   |                               ------    ^^ help: consider borrowing here: `&em`
+   |                               ------    ^^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(mut _t) = &em { }
+   |                                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:135:15
+  --> $DIR/move-into-closure.rs:117:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -294,16 +384,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t)
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:142:15
+  --> $DIR/move-into-closure.rs:123:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -312,16 +407,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t) => (),
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:150:15
+  --> $DIR/move-into-closure.rs:130:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -330,13 +430,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t) => (),
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error: aborting due to 21 previous errors
 
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.rs b/src/test/ui/suggestions/dont-suggest-ref/simple.rs
index c53ac3d2cd6..1e40e60a1ce 100644
--- a/src/test/ui/suggestions/dont-suggest-ref/simple.rs
+++ b/src/test/ui/suggestions/dont-suggest-ref/simple.rs
@@ -37,27 +37,22 @@ pub fn main() {
 
     let X(_t) = *s;
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION s
+    //~| HELP consider removing the dereference here
     if let Either::One(_t) = *r { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION r
+    //~| HELP consider removing the dereference here
     while let Either::One(_t) = *r { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION r
+    //~| HELP consider removing the dereference here
     match *r {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION r
+        //~| HELP consider removing the dereference here
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match *r {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION r
+        //~| HELP consider removing the dereference here
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -65,35 +60,29 @@ pub fn main() {
 
     let X(_t) = *sm;
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION sm
+    //~| HELP consider removing the dereference here
     if let Either::One(_t) = *rm { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION rm
+    //~| HELP consider removing the dereference here
     while let Either::One(_t) = *rm { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION rm
+    //~| HELP consider removing the dereference here
     match *rm {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION rm
+        //~| HELP consider removing the dereference here
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match *rm {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION rm
+        //~| HELP consider removing the dereference here
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
     }
     match *rm {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION rm
+        //~| HELP consider removing the dereference here
         Either::One(_t) => (),
         Either::Two(ref mut _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -102,26 +91,21 @@ pub fn main() {
     let X(_t) = vs[0];
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vs[0]
     if let Either::One(_t) = vr[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vr[0]
     while let Either::One(_t) = vr[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vr[0]
     match vr[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vr[0]
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match vr[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vr[0]
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -130,26 +114,21 @@ pub fn main() {
     let X(_t) = vsm[0];
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vsm[0]
     if let Either::One(_t) = vrm[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vrm[0]
     while let Either::One(_t) = vrm[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vrm[0]
     match vrm[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vrm[0]
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match vrm[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vrm[0]
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -157,7 +136,6 @@ pub fn main() {
     match vrm[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vrm[0]
         Either::One(_t) => (),
         Either::Two(ref mut _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -167,89 +145,73 @@ pub fn main() {
 
     let &X(_t) = s;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &Either::One(_t) = r { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &Either::One(_t) = r { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match r {
         //~^ ERROR cannot move
         &Either::One(_t)
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         | &Either::Two(_t) => (),
         // FIXME: would really like a suggestion here too
     }
     match r {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &Either::Two(ref _t) => (),
     }
     match r {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
     fn f1(&X(_t): &X) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
 
     let &mut X(_t) = sm;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &mut Either::One(_t) = rm { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &mut Either::One(_t) = rm { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::Two(_t)
+        //~^ HELP consider removing
     }
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref _t) => (),
     }
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref mut _t) => (),
     }
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
     fn f2(&mut X(_t): &mut X) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
 
     // move from tuple of &Either/&X
 
@@ -257,108 +219,118 @@ pub fn main() {
 
     let (&X(_t),) = (&x.clone(),);
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     if let (&Either::One(_t),) = (&e.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     while let (&Either::One(_t),) = (&e.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     match (&e.clone(),) {
         //~^ ERROR cannot move
         (&Either::One(_t),)
+        //~^ HELP consider borrowing the pattern binding
         | (&Either::Two(_t),) => (),
     }
     fn f3((&X(_t),): (&X,)) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
 
     let (&mut X(_t),) = (&mut xm.clone(),);
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     match (&mut em.clone(),) {
         //~^ ERROR cannot move
         (&mut Either::One(_t),) => (),
+        //~^ HELP consider borrowing the pattern binding
         (&mut Either::Two(_t),) => (),
+        //~^ HELP consider borrowing the pattern binding
     }
     fn f4((&mut X(_t),): (&mut X,)) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
 
     // move from &Either/&X value
 
     let &X(_t) = &x;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &Either::One(_t) = &e { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &Either::One(_t) = &e { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match &e {
         //~^ ERROR cannot move
         &Either::One(_t)
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         | &Either::Two(_t) => (),
         // FIXME: would really like a suggestion here too
     }
     match &e {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &Either::Two(ref _t) => (),
     }
     match &e {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
 
     let &mut X(_t) = &mut xm;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &mut Either::One(_t) = &mut em { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &mut Either::One(_t) = &mut em { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t)
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         | &mut Either::Two(_t) => (),
         // FIXME: would really like a suggestion here too
     }
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref _t) => (),
     }
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref mut _t) => (),
     }
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
 }
+
+struct Testing {
+    a: Option<String>
+}
+
+fn testing(a: &Testing) {
+    let Some(_s) = a.a else {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing the pattern binding
+        return;
+    };
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
index e5443290f9e..52632652423 100644
--- a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
+++ b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
@@ -2,262 +2,398 @@ error[E0507]: cannot move out of `s` which is behind a shared reference
   --> $DIR/simple.rs:38:17
    |
 LL |     let X(_t) = *s;
-   |           --    ^^ help: consider borrowing here: `&*s`
+   |           --    ^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let X(_t) = *s;
+LL +     let X(_t) = s;
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:42:30
+  --> $DIR/simple.rs:41:30
    |
 LL |     if let Either::One(_t) = *r { }
-   |                        --    ^^ help: consider borrowing here: `&*r`
+   |                        --    ^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     if let Either::One(_t) = *r { }
+LL +     if let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:46:33
+  --> $DIR/simple.rs:44:33
    |
 LL |     while let Either::One(_t) = *r { }
-   |                           --    ^^ help: consider borrowing here: `&*r`
+   |                           --    ^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     while let Either::One(_t) = *r { }
+LL +     while let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
-  --> $DIR/simple.rs:50:11
+  --> $DIR/simple.rs:47:11
    |
 LL |     match *r {
-   |           ^^ help: consider borrowing here: `&*r`
+   |           ^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *r {
+LL +     match r {
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:57:11
+  --> $DIR/simple.rs:53:11
    |
 LL |     match *r {
-   |           ^^ help: consider borrowing here: `&*r`
+   |           ^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *r {
+LL +     match r {
+   |
 
 error[E0507]: cannot move out of `sm` which is behind a mutable reference
-  --> $DIR/simple.rs:66:17
+  --> $DIR/simple.rs:61:17
    |
 LL |     let X(_t) = *sm;
-   |           --    ^^^ help: consider borrowing here: `&*sm`
+   |           --    ^^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let X(_t) = *sm;
+LL +     let X(_t) = sm;
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:70:30
+  --> $DIR/simple.rs:64:30
    |
 LL |     if let Either::One(_t) = *rm { }
-   |                        --    ^^^ help: consider borrowing here: `&*rm`
+   |                        --    ^^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     if let Either::One(_t) = *rm { }
+LL +     if let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:74:33
+  --> $DIR/simple.rs:67:33
    |
 LL |     while let Either::One(_t) = *rm { }
-   |                           --    ^^^ help: consider borrowing here: `&*rm`
+   |                           --    ^^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     while let Either::One(_t) = *rm { }
+LL +     while let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
-  --> $DIR/simple.rs:78:11
+  --> $DIR/simple.rs:70:11
    |
 LL |     match *rm {
-   |           ^^^ help: consider borrowing here: `&*rm`
+   |           ^^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *rm {
+LL +     match rm {
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:85:11
+  --> $DIR/simple.rs:76:11
    |
 LL |     match *rm {
-   |           ^^^ help: consider borrowing here: `&*rm`
+   |           ^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *rm {
+LL +     match rm {
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:93:11
+  --> $DIR/simple.rs:83:11
    |
 LL |     match *rm {
-   |           ^^^ help: consider borrowing here: `&*rm`
+   |           ^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *rm {
+LL +     match rm {
+   |
 
 error[E0507]: cannot move out of index of `Vec<X>`
-  --> $DIR/simple.rs:102:17
+  --> $DIR/simple.rs:91:17
    |
 LL |     let X(_t) = vs[0];
-   |           --    ^^^^^ help: consider borrowing here: `&vs[0]`
+   |           --    ^^^^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let X(_t) = &vs[0];
+   |                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:106:30
+  --> $DIR/simple.rs:94:30
    |
 LL |     if let Either::One(_t) = vr[0] { }
-   |                        --    ^^^^^ help: consider borrowing here: `&vr[0]`
+   |                        --    ^^^^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     if let Either::One(_t) = &vr[0] { }
+   |                              +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:110:33
+  --> $DIR/simple.rs:97:33
    |
 LL |     while let Either::One(_t) = vr[0] { }
-   |                           --    ^^^^^ help: consider borrowing here: `&vr[0]`
+   |                           --    ^^^^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     while let Either::One(_t) = &vr[0] { }
+   |                                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:114:11
+  --> $DIR/simple.rs:100:11
    |
 LL |     match vr[0] {
-   |           ^^^^^ help: consider borrowing here: `&vr[0]`
+   |           ^^^^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vr[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:121:11
+  --> $DIR/simple.rs:106:11
    |
 LL |     match vr[0] {
-   |           ^^^^^ help: consider borrowing here: `&vr[0]`
+   |           ^^^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vr[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<X>`
-  --> $DIR/simple.rs:130:17
+  --> $DIR/simple.rs:114:17
    |
 LL |     let X(_t) = vsm[0];
-   |           --    ^^^^^^ help: consider borrowing here: `&vsm[0]`
+   |           --    ^^^^^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let X(_t) = &vsm[0];
+   |                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:134:30
+  --> $DIR/simple.rs:117:30
    |
 LL |     if let Either::One(_t) = vrm[0] { }
-   |                        --    ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |                        --    ^^^^^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     if let Either::One(_t) = &vrm[0] { }
+   |                              +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:138:33
+  --> $DIR/simple.rs:120:33
    |
 LL |     while let Either::One(_t) = vrm[0] { }
-   |                           --    ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |                           --    ^^^^^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     while let Either::One(_t) = &vrm[0] { }
+   |                                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:142:11
+  --> $DIR/simple.rs:123:11
    |
 LL |     match vrm[0] {
-   |           ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |           ^^^^^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vrm[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:149:11
+  --> $DIR/simple.rs:129:11
    |
 LL |     match vrm[0] {
-   |           ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |           ^^^^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vrm[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:157:11
+  --> $DIR/simple.rs:136:11
    |
 LL |     match vrm[0] {
-   |           ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |           ^^^^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vrm[0] {
+   |           +
 
 error[E0507]: cannot move out of `s` which is behind a shared reference
-  --> $DIR/simple.rs:168:18
+  --> $DIR/simple.rs:146:18
    |
 LL |     let &X(_t) = s;
-   |         ------   ^
-   |         |  |
-   |         |  data moved here
-   |         |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `X(_t)`
+   |            --    ^
+   |            |
+   |            data moved here
+   |            move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &X(_t) = s;
+LL +     let X(_t) = s;
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:172:31
+  --> $DIR/simple.rs:149:31
    |
 LL |     if let &Either::One(_t) = r { }
-   |            ----------------   ^
-   |            |            |
-   |            |            data moved here
-   |            |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&`: `Either::One(_t)`
+   |                         --    ^
+   |                         |
+   |                         data moved here
+   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let &Either::One(_t) = r { }
+LL +     if let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:176:34
+  --> $DIR/simple.rs:152:34
    |
 LL |     while let &Either::One(_t) = r { }
-   |               ----------------   ^
-   |               |            |
-   |               |            data moved here
-   |               |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&`: `Either::One(_t)`
+   |                            --    ^
+   |                            |
+   |                            data moved here
+   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     while let &Either::One(_t) = r { }
+LL +     while let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
-  --> $DIR/simple.rs:180:11
+  --> $DIR/simple.rs:155:11
    |
 LL |     match r {
    |           ^
@@ -268,160 +404,215 @@ LL |         &Either::One(_t)
    |                      data moved here
    |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~         Either::One(_t)
-LL +
-LL +
-LL ~         | &Either::Two(_t) => (),
+LL -         &Either::One(_t)
+LL +         Either::One(_t)
    |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:188:11
+  --> $DIR/simple.rs:162:11
    |
 LL |     match r {
    |           ^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:195:11
+  --> $DIR/simple.rs:168:11
    |
 LL |     match r {
    |           ^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `sm` which is behind a mutable reference
-  --> $DIR/simple.rs:207:22
+  --> $DIR/simple.rs:178:22
    |
 LL |     let &mut X(_t) = sm;
-   |         ----------   ^^
-   |         |      |
-   |         |      data moved here
-   |         |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `X(_t)`
+   |                --    ^^
+   |                |
+   |                data moved here
+   |                move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     let &mut X(_t) = sm;
+LL +     let X(_t) = sm;
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:211:35
+  --> $DIR/simple.rs:181:35
    |
 LL |     if let &mut Either::One(_t) = rm { }
-   |            --------------------   ^^
-   |            |                |
-   |            |                data moved here
-   |            |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |                             --    ^^
+   |                             |
+   |                             data moved here
+   |                             move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     if let &mut Either::One(_t) = rm { }
+LL +     if let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:215:38
+  --> $DIR/simple.rs:184:38
    |
 LL |     while let &mut Either::One(_t) = rm { }
-   |               --------------------   ^^
-   |               |                |
-   |               |                data moved here
-   |               |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |                                --    ^^
+   |                                |
+   |                                data moved here
+   |                                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     while let &mut Either::One(_t) = rm { }
+LL +     while let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
-  --> $DIR/simple.rs:219:11
+  --> $DIR/simple.rs:187:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
    |                          -- data moved here
-...
+LL |
 LL |         &mut Either::Two(_t) => (),
    |                          -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL |         Either::One(_t) => (),
-   |         ~~~~~~~~~~~~~~~
-help: consider removing the `&mut`
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::Two(_t) => (),
+LL +         Either::Two(_t) => (),
    |
-LL |         Either::Two(_t) => (),
-   |         ~~~~~~~~~~~~~~~
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:228:11
+  --> $DIR/simple.rs:194:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:235:11
+  --> $DIR/simple.rs:200:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:242:11
+  --> $DIR/simple.rs:206:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:258:21
+  --> $DIR/simple.rs:220:21
    |
 LL |     let (&X(_t),) = (&x.clone(),);
    |             --      ^^^^^^^^^^^^^
    |             |
    |             data moved here
    |             move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let (&X(ref _t),) = (&x.clone(),);
+   |             +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:260:34
+  --> $DIR/simple.rs:223:34
    |
 LL |     if let (&Either::One(_t),) = (&e.clone(),) { }
    |                          --      ^^^^^^^^^^^^^
    |                          |
    |                          data moved here
    |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     if let (&Either::One(ref _t),) = (&e.clone(),) { }
+   |                          +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:262:37
+  --> $DIR/simple.rs:226:37
    |
 LL |     while let (&Either::One(_t),) = (&e.clone(),) { }
    |                             --      ^^^^^^^^^^^^^
    |                             |
    |                             data moved here
    |                             move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     while let (&Either::One(ref _t),) = (&e.clone(),) { }
+   |                             +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:264:11
+  --> $DIR/simple.rs:229:11
    |
 LL |     match (&e.clone(),) {
    |           ^^^^^^^^^^^^^
@@ -431,79 +622,123 @@ LL |         (&Either::One(_t),)
    |                       |
    |                       data moved here
    |                       move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (&Either::One(ref _t),)
+   |                       +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:272:25
+  --> $DIR/simple.rs:239:25
    |
 LL |     let (&mut X(_t),) = (&mut xm.clone(),);
    |                 --      ^^^^^^^^^^^^^^^^^^
    |                 |
    |                 data moved here
    |                 move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let (&mut X(ref _t),) = (&mut xm.clone(),);
+   |                 +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:274:38
+  --> $DIR/simple.rs:242:38
    |
 LL |     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
    |                              --      ^^^^^^^^^^^^^^^^^^
    |                              |
    |                              data moved here
    |                              move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     if let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+   |                              +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:276:41
+  --> $DIR/simple.rs:245:41
    |
 LL |     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
    |                                 --      ^^^^^^^^^^^^^^^^^^
    |                                 |
    |                                 data moved here
    |                                 move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     while let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+   |                                 +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:278:11
+  --> $DIR/simple.rs:248:11
    |
 LL |     match (&mut em.clone(),) {
    |           ^^^^^^^^^^^^^^^^^^
 LL |
 LL |         (&mut Either::One(_t),) => (),
    |                           -- data moved here
+LL |
 LL |         (&mut Either::Two(_t),) => (),
    |                           -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         (&mut Either::One(ref _t),) => (),
+   |                           +++
+help: consider borrowing the pattern binding
+   |
+LL |         (&mut Either::Two(ref _t),) => (),
+   |                           +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:288:18
+  --> $DIR/simple.rs:261:18
    |
 LL |     let &X(_t) = &x;
-   |         ------   ^^
-   |         |  |
-   |         |  data moved here
-   |         |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `X(_t)`
+   |            --    ^^
+   |            |
+   |            data moved here
+   |            move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &X(_t) = &x;
+LL +     let X(_t) = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:292:31
+  --> $DIR/simple.rs:264:31
    |
 LL |     if let &Either::One(_t) = &e { }
-   |            ----------------   ^^
-   |            |            |
-   |            |            data moved here
-   |            |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&`: `Either::One(_t)`
+   |                         --    ^^
+   |                         |
+   |                         data moved here
+   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let &Either::One(_t) = &e { }
+LL +     if let Either::One(_t) = &e { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:296:34
+  --> $DIR/simple.rs:267:34
    |
 LL |     while let &Either::One(_t) = &e { }
-   |               ----------------   ^^
-   |               |            |
-   |               |            data moved here
-   |               |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&`: `Either::One(_t)`
+   |                            --    ^^
+   |                            |
+   |                            data moved here
+   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     while let &Either::One(_t) = &e { }
+LL +     while let Either::One(_t) = &e { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:300:11
+  --> $DIR/simple.rs:270:11
    |
 LL |     match &e {
    |           ^^
@@ -514,72 +749,95 @@ LL |         &Either::One(_t)
    |                      data moved here
    |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~         Either::One(_t)
-LL +
-LL +
-LL ~         | &Either::Two(_t) => (),
+LL -         &Either::One(_t)
+LL +         Either::One(_t)
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:308:11
+  --> $DIR/simple.rs:277:11
    |
 LL |     match &e {
    |           ^^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:315:11
+  --> $DIR/simple.rs:283:11
    |
 LL |     match &e {
    |           ^^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:323:22
+  --> $DIR/simple.rs:290:22
    |
 LL |     let &mut X(_t) = &mut xm;
-   |         ----------   ^^^^^^^
-   |         |      |
-   |         |      data moved here
-   |         |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `X(_t)`
+   |                --    ^^^^^^^
+   |                |
+   |                data moved here
+   |                move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     let &mut X(_t) = &mut xm;
+LL +     let X(_t) = &mut xm;
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:327:35
+  --> $DIR/simple.rs:293:35
    |
 LL |     if let &mut Either::One(_t) = &mut em { }
-   |            --------------------   ^^^^^^^
-   |            |                |
-   |            |                data moved here
-   |            |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |                             --    ^^^^^^^
+   |                             |
+   |                             data moved here
+   |                             move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     if let &mut Either::One(_t) = &mut em { }
+LL +     if let Either::One(_t) = &mut em { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:331:38
+  --> $DIR/simple.rs:296:38
    |
 LL |     while let &mut Either::One(_t) = &mut em { }
-   |               --------------------   ^^^^^^^
-   |               |                |
-   |               |                data moved here
-   |               |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |                                --    ^^^^^^^
+   |                                |
+   |                                data moved here
+   |                                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     while let &mut Either::One(_t) = &mut em { }
+LL +     while let Either::One(_t) = &mut em { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:335:11
+  --> $DIR/simple.rs:299:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
@@ -590,91 +848,138 @@ LL |         &mut Either::One(_t)
    |                          data moved here
    |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         Either::One(_t)
-LL +
-LL +
-LL ~         | &mut Either::Two(_t) => (),
+LL -         &mut Either::One(_t)
+LL +         Either::One(_t)
    |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:343:11
+  --> $DIR/simple.rs:306:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:350:11
+  --> $DIR/simple.rs:312:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:357:11
+  --> $DIR/simple.rs:318:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:202:11
+  --> $DIR/simple.rs:174:11
    |
 LL |     fn f1(&X(_t): &X) { }
    |           ^^^--^
-   |           |  |
-   |           |  data moved here
-   |           |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |           help: consider removing the `&`: `X(_t)`
+   |              |
+   |              data moved here
+   |              move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     fn f1(&X(_t): &X) { }
+LL +     fn f1(X(_t): &X) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:249:11
+  --> $DIR/simple.rs:212:11
    |
 LL |     fn f2(&mut X(_t): &mut X) { }
    |           ^^^^^^^--^
-   |           |      |
-   |           |      data moved here
-   |           |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |           help: consider removing the `&mut`: `X(_t)`
+   |                  |
+   |                  data moved here
+   |                  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     fn f2(&mut X(_t): &mut X) { }
+LL +     fn f2(X(_t): &mut X) { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:269:11
+  --> $DIR/simple.rs:235:11
    |
 LL |     fn f3((&X(_t),): (&X,)) { }
    |           ^^^^--^^^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     fn f3((&X(ref _t),): (&X,)) { }
+   |               +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:283:11
+  --> $DIR/simple.rs:255:11
    |
 LL |     fn f4((&mut X(_t),): (&mut X,)) { }
    |           ^^^^^^^^--^^^
    |                   |
    |                   data moved here
    |                   move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     fn f4((&mut X(ref _t),): (&mut X,)) { }
+   |                   +++
+
+error[E0507]: cannot move out of `a.a` as enum variant `Some` which is behind a shared reference
+  --> $DIR/simple.rs:331:20
+   |
+LL |     let Some(_s) = a.a else {
+   |              --    ^^^
+   |              |
+   |              data moved here
+   |              move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let Some(ref _s) = a.a else {
+   |              +++
 
-error: aborting due to 60 previous errors
+error: aborting due to 61 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
index 34ff59a9bb0..b1e04dab8f6 100644
--- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
+++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -41,9 +41,6 @@ LL |     Pin::new(x)
            found type parameter `F`
 note: associated function defined here
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL |     pub const fn new(pointer: P) -> Pin<P> {
-   |                  ^^^
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
   --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14
@@ -56,9 +53,6 @@ LL |     Pin::new(x)
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
-   |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
   --> $DIR/expected-boxed-future-isnt-pinned.rs:24:14
@@ -71,9 +65,6 @@ LL |     Pin::new(Box::new(x))
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
-   |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error[E0308]: mismatched types
   --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5
@@ -90,9 +81,6 @@ LL | |     }
            found `async` block `[async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |              ^^^^^^^^^^^^^^^
 help: you need to pin and box this expression
    |
 LL ~     Box::pin(async {
diff --git a/src/test/ui/suggestions/for-i-in-vec.stderr b/src/test/ui/suggestions/for-i-in-vec.stderr
index 88be9e30a76..c5b81e6b871 100644
--- a/src/test/ui/suggestions/for-i-in-vec.stderr
+++ b/src/test/ui/suggestions/for-i-in-vec.stderr
@@ -7,11 +7,8 @@ LL |         for _ in self.v {
    |                  `self.v` moved due to this implicit call to `.into_iter()`
    |                  move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `self.v`
+note: `into_iter` takes ownership of the receiver `self`, which moves `self.v`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<u32>`'s content to avoid moving into the `for` loop
    |
 LL |         for _ in &self.v {
@@ -40,11 +37,8 @@ LL |     for loader in *LOADERS {
    |                   value moved due to this implicit call to `.into_iter()`
    |                   move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves value
+note: `into_iter` takes ownership of the receiver `self`, which moves value
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<&u8>`'s content to avoid moving into the `for` loop
    |
 LL |     for loader in &*LOADERS {
diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr
index 42ca3a78d8f..7791b308d5d 100644
--- a/src/test/ui/suggestions/imm-ref-trait-object.stderr
+++ b/src/test/ui/suggestions/imm-ref-trait-object.stderr
@@ -3,11 +3,9 @@ error: the `min` method cannot be invoked on a trait object
    |
 LL |      t.min().unwrap()
    |        ^^^
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         Self: Sized,
-   |               ----- this has a `Sized` requirement
+   = note: this has a `Sized` requirement
    |
    = note: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
 
diff --git a/src/test/ui/suggestions/import-trait-for-method-call.stderr b/src/test/ui/suggestions/import-trait-for-method-call.stderr
index bac8de79872..f159b51a269 100644
--- a/src/test/ui/suggestions/import-trait-for-method-call.stderr
+++ b/src/test/ui/suggestions/import-trait-for-method-call.stderr
@@ -3,11 +3,9 @@ error[E0599]: no method named `finish` found for struct `DefaultHasher` in the c
    |
 LL |     h.finish()
    |       ^^^^^^ method not found in `DefaultHasher`
+  --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
-   |
-LL |     fn finish(&self) -> u64;
-   |        ------ the method is available for `DefaultHasher` here
+   = note: the method is available for `DefaultHasher` here
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
diff --git a/src/test/ui/suggestions/issue-104287.stderr b/src/test/ui/suggestions/issue-104287.stderr
index 4b302dd6509..79812a2985e 100644
--- a/src/test/ui/suggestions/issue-104287.stderr
+++ b/src/test/ui/suggestions/issue-104287.stderr
@@ -11,12 +11,6 @@ LL |     simd_gt::<()>(x);
    |     ^^^^^^^------ help: remove these generics
    |     |
    |     expected 0 generic arguments
-   |
-note: associated function defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/ord.rs:LL:COL
-   |
-LL |     fn simd_gt(self, other: Self) -> Self::Mask;
-   |        ^^^^^^^
 
 error[E0425]: cannot find function `simd_gt` in this scope
   --> $DIR/issue-104287.rs:6:5
diff --git a/src/test/ui/suggestions/issue-104327.rs b/src/test/ui/suggestions/issue-104327.rs
new file mode 100644
index 00000000000..dd621ae7100
--- /dev/null
+++ b/src/test/ui/suggestions/issue-104327.rs
@@ -0,0 +1,12 @@
+trait Bar {}
+
+trait Foo {
+    fn f() {}
+}
+
+impl Foo for dyn Bar {}
+
+fn main() {
+    Foo::f();
+    //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type
+}
diff --git a/src/test/ui/suggestions/issue-104327.stderr b/src/test/ui/suggestions/issue-104327.stderr
new file mode 100644
index 00000000000..acec3a55d52
--- /dev/null
+++ b/src/test/ui/suggestions/issue-104327.stderr
@@ -0,0 +1,17 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/issue-104327.rs:10:5
+   |
+LL |     fn f() {}
+   |     --------- `Foo::f` defined here
+...
+LL |     Foo::f();
+   |     ^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     <(dyn Bar + 'static) as Foo>::f();
+   |     +++++++++++++++++++++++    +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/suggestions/issue-104328.rs b/src/test/ui/suggestions/issue-104328.rs
new file mode 100644
index 00000000000..c3707baf79f
--- /dev/null
+++ b/src/test/ui/suggestions/issue-104328.rs
@@ -0,0 +1,12 @@
+#![feature(object_safe_for_dispatch)]
+
+trait Foo {
+    fn f() {}
+}
+
+impl Foo for dyn Sized {}
+
+fn main() {
+    Foo::f();
+    //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type
+}
diff --git a/src/test/ui/suggestions/issue-104328.stderr b/src/test/ui/suggestions/issue-104328.stderr
new file mode 100644
index 00000000000..b31b84781ba
--- /dev/null
+++ b/src/test/ui/suggestions/issue-104328.stderr
@@ -0,0 +1,17 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/issue-104328.rs:10:5
+   |
+LL |     fn f() {}
+   |     --------- `Foo::f` defined here
+...
+LL |     Foo::f();
+   |     ^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     <(dyn Sized + 'static) as Foo>::f();
+   |     +++++++++++++++++++++++++    +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/suggestions/issue-105226.rs b/src/test/ui/suggestions/issue-105226.rs
new file mode 100644
index 00000000000..f123dbf4cae
--- /dev/null
+++ b/src/test/ui/suggestions/issue-105226.rs
@@ -0,0 +1,22 @@
+use std::fmt;
+
+struct S {
+}
+
+impl S {
+    fn hello<P>(&self, val: &P) where P: fmt::Display; {
+        //~^ ERROR non-item in item list
+        //~| ERROR associated function in `impl` without body
+        println!("val: {}", val);
+    }
+}
+
+impl S {
+    fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
+    //~^ ERROR associated function in `impl` without body
+}
+
+fn main() {
+    let s = S{};
+    s.hello(&32);
+}
diff --git a/src/test/ui/suggestions/issue-105226.stderr b/src/test/ui/suggestions/issue-105226.stderr
new file mode 100644
index 00000000000..f16a8090103
--- /dev/null
+++ b/src/test/ui/suggestions/issue-105226.stderr
@@ -0,0 +1,31 @@
+error: non-item in item list
+  --> $DIR/issue-105226.rs:7:56
+   |
+LL | impl S {
+   |        - item list starts here
+LL |     fn hello<P>(&self, val: &P) where P: fmt::Display; {
+   |                                                      - ^ non-item starts here
+   |                                                      |
+   |                                                      help: consider removing this semicolon
+...
+LL | }
+   | - item list ends here
+
+error: associated function in `impl` without body
+  --> $DIR/issue-105226.rs:7:5
+   |
+LL |     fn hello<P>(&self, val: &P) where P: fmt::Display; {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                                      |
+   |                                                      help: provide a definition for the function: `{ <body> }`
+
+error: associated function in `impl` without body
+  --> $DIR/issue-105226.rs:15:5
+   |
+LL |     fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                                            |
+   |                                                            help: provide a definition for the function: `{ <body> }`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/suggestions/issue-62843.stderr b/src/test/ui/suggestions/issue-62843.stderr
index 62f0943d4c9..b6e271de807 100644
--- a/src/test/ui/suggestions/issue-62843.stderr
+++ b/src/test/ui/suggestions/issue-62843.stderr
@@ -10,9 +10,6 @@ LL |     println!("{:?}", line.find(pattern));
    = note: required for `String` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::find`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
-   |                        ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::find`
 help: consider borrowing here
    |
 LL |     println!("{:?}", line.find(&pattern));
diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
index 684db23e135..a5e6f5b5ffc 100644
--- a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
+++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
-  --> $DIR/issue-71394-no-from-impl.rs:3:20
+  --> $DIR/issue-71394-no-from-impl.rs:3:25
    |
 LL |     let _: &[i8] = data.into();
-   |                    ^^^^ ---- required by a bound introduced by this call
-   |                    |
-   |                    the trait `From<&[u8]>` is not implemented for `&[i8]`
+   |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
    |
    = help: the following other types implement trait `From<T>`:
              <[T; LANES] as From<Simd<T, LANES>>>
diff --git a/src/test/ui/suggestions/issue-89064.stderr b/src/test/ui/suggestions/issue-89064.stderr
index 8b2a3881628..93d8da226c8 100644
--- a/src/test/ui/suggestions/issue-89064.stderr
+++ b/src/test/ui/suggestions/issue-89064.stderr
@@ -62,11 +62,6 @@ error[E0107]: this associated function takes 0 generic arguments but 1 generic a
 LL |     let _ = 42.into::<Option<_>>();
    |                ^^^^ expected 0 generic arguments
    |
-note: associated function defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn into(self) -> T;
-   |        ^^^^
 help: consider moving this generic argument to the `Into` trait, which takes up to 1 argument
    |
 LL |     let _ = Into::<Option<_>>::into(42);
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
index d121932c842..6910b77d9bc 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -9,9 +9,6 @@ LL |     let fp = BufWriter::new(fp);
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
 note: required by a bound in `BufWriter::<W>::new`
   --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
-   |
-LL | impl<W: Write> BufWriter<W> {
-   |         ^^^^^ required by this bound in `BufWriter::<W>::new`
 
 error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
   --> $DIR/mut-borrow-needed-by-trait.rs:17:14
@@ -22,20 +19,15 @@ LL |     let fp = BufWriter::new(fp);
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
 note: required by a bound in `BufWriter`
   --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
-   |
-LL | pub struct BufWriter<W: Write> {
-   |                         ^^^^^ required by this bound in `BufWriter`
 
-error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn std::io::Write>`, but its trait bounds were not satisfied
+error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied
   --> $DIR/mut-borrow-needed-by-trait.rs:21:5
    |
 LL |     writeln!(fp, "hello world").unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn std::io::Write>` due to unsatisfied trait bounds
-   |
-  ::: $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
+  --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
    |
-LL | pub struct BufWriter<W: Write> {
-   | ------------------------------ doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
+   = note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
    |
    = note: the following trait bounds were not satisfied:
            `&dyn std::io::Write: std::io::Write`
diff --git a/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr b/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr
index debb8cabaea..97d05d9dcff 100644
--- a/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr
+++ b/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr
@@ -9,6 +9,11 @@ LL |         (None, &c) => &c.unwrap(),
    |                 |
    |                 data moved here
    |                 move occurs because `c` has type `Option<String>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (None, &ref c) => &c.unwrap(),
+   |                 +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/option-content-move.stderr b/src/test/ui/suggestions/option-content-move.stderr
index a6f1ebc975f..3e0271d0257 100644
--- a/src/test/ui/suggestions/option-content-move.stderr
+++ b/src/test/ui/suggestions/option-content-move.stderr
@@ -7,11 +7,8 @@ LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |                    move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `selection.1`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap(self) -> T {
-   |                         ^^^^
 
 error[E0507]: cannot move out of `selection.1` which is behind a shared reference
   --> $DIR/option-content-move.rs:27:20
@@ -22,11 +19,8 @@ LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |                    move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `selection.1`
+note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     pub fn unwrap(self) -> T
-   |                   ^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/restrict-type-not-param.stderr b/src/test/ui/suggestions/restrict-type-not-param.stderr
index e7d9c5ecbe4..5434472ceec 100644
--- a/src/test/ui/suggestions/restrict-type-not-param.stderr
+++ b/src/test/ui/suggestions/restrict-type-not-param.stderr
@@ -11,11 +11,8 @@ note: an implementation of `Add<_>` might be missing for `Wrapper<T>`
    |
 LL | struct Wrapper<T>(T);
    | ^^^^^^^^^^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | fn qux<T>(a: Wrapper<T>, b: T) -> T where Wrapper<T>: Add<T, Output = T> {
diff --git a/src/test/ui/suggestions/sugg-else-for-closure.stderr b/src/test/ui/suggestions/sugg-else-for-closure.stderr
index 55a0eee1817..da4db46aad3 100644
--- a/src/test/ui/suggestions/sugg-else-for-closure.stderr
+++ b/src/test/ui/suggestions/sugg-else-for-closure.stderr
@@ -10,9 +10,6 @@ LL |     let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
                 found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
 note: associated function defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap_or(self, default: T) -> T
-   |                  ^^^^^^^^^
 help: try calling `unwrap_or_else` instead
    |
 LL |     let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap());
diff --git a/src/test/ui/suggestions/suggest-change-mut.stderr b/src/test/ui/suggestions/suggest-change-mut.stderr
index 889b11a7410..d194afeaf93 100644
--- a/src/test/ui/suggestions/suggest-change-mut.stderr
+++ b/src/test/ui/suggestions/suggest-change-mut.stderr
@@ -8,9 +8,6 @@ LL |         let mut stream_reader = BufReader::new(&stream);
    |
 note: required by a bound in `BufReader::<R>::new`
   --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
-   |
-LL | impl<R: Read> BufReader<R> {
-   |         ^^^^ required by this bound in `BufReader::<R>::new`
 help: consider removing the leading `&`-reference
    |
 LL -         let mut stream_reader = BufReader::new(&stream);
@@ -30,11 +27,9 @@ error[E0599]: the method `read_until` exists for struct `BufReader<&T>`, but its
    |
 LL |         stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed");
    |                       ^^^^^^^^^^ method cannot be called on `BufReader<&T>` due to unsatisfied trait bounds
+  --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
-   |
-LL | pub struct BufReader<R> {
-   | ----------------------- doesn't satisfy `BufReader<&T>: BufRead`
+   = note: doesn't satisfy `BufReader<&T>: BufRead`
    |
    = note: the following trait bounds were not satisfied:
            `&T: std::io::Read`
diff --git a/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr b/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr
index 3d1f2492360..018083f9e03 100644
--- a/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr
+++ b/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr
@@ -52,11 +52,9 @@ error[E0599]: no method named `try_into` found for type `i32` in the current sco
    |
 LL |     let _i: i16 = 0_i32.try_into().unwrap();
    |                         ^^^^^^^^ method not found in `i32`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn try_into(self) -> Result<T, Self::Error>;
-   |        -------- the method is available for `i32` here
+   = note: the method is available for `i32` here
    |
    = help: items from traits can only be used if the trait is in scope
    = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
index 951ff23d635..fcff02e09db 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
@@ -24,11 +24,6 @@ error[E0107]: this struct takes at least 1 generic argument but 0 generic argume
 LL |     let _: Vec<A:B> = A::B;
    |            ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |            ^^^ -
 help: add missing generic argument
    |
 LL |     let _: Vec<T, A:B> = A::B;
diff --git a/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr b/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
index 773f1392ae7..34eaa8322c8 100644
--- a/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
+++ b/src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/unnecessary_dot_for_floating_point_literal.rs:2:18
    |
 LL |     let _: f64 = 0..10;
-   |            ---   ^^^^^ expected `f64`, found struct `std::ops::Range`
+   |            ---   ^^^^^ expected `f64`, found struct `Range`
    |            |
    |            expected due to this
    |
@@ -47,7 +47,7 @@ error[E0308]: mismatched types
   --> $DIR/unnecessary_dot_for_floating_point_literal.rs:5:18
    |
 LL |     let _: f64 = std::ops::Range { start: 0, end: 1 };
-   |            ---   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `std::ops::Range`
+   |            ---   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `Range`
    |            |
    |            expected due to this
    |
diff --git a/src/test/ui/traits/alias/generic-default-in-dyn.stderr b/src/test/ui/traits/alias/generic-default-in-dyn.stderr
index 76a068e864a..0d3f794aa0f 100644
--- a/src/test/ui/traits/alias/generic-default-in-dyn.stderr
+++ b/src/test/ui/traits/alias/generic-default-in-dyn.stderr
@@ -12,11 +12,9 @@ error[E0393]: the type parameter `Rhs` must be explicitly specified
    |
 LL | struct Foo<T>(dyn SendEqAlias<T>);
    |                   ^^^^^^^^^^^^^^ missing reference to `Rhs`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait PartialEq<Rhs: ?Sized = Self> {
-   | --------------------------------------- type parameter `Rhs` must be specified for this
+   = note: type parameter `Rhs` must be specified for this
    |
    = note: because of the default `Self` reference, type parameters must be specified on object types
 
@@ -25,11 +23,9 @@ error[E0393]: the type parameter `Rhs` must be explicitly specified
    |
 LL | struct Bar<T>(dyn SendEqAlias<T>, T);
    |                   ^^^^^^^^^^^^^^ missing reference to `Rhs`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait PartialEq<Rhs: ?Sized = Self> {
-   | --------------------------------------- type parameter `Rhs` must be specified for this
+   = note: type parameter `Rhs` must be specified for this
    |
    = note: because of the default `Self` reference, type parameters must be specified on object types
 
diff --git a/src/test/ui/traits/alias/object-fail.stderr b/src/test/ui/traits/alias/object-fail.stderr
index 325bc6d2808..048a150df8c 100644
--- a/src/test/ui/traits/alias/object-fail.stderr
+++ b/src/test/ui/traits/alias/object-fail.stderr
@@ -7,8 +7,7 @@ LL |     let _: &dyn EqAlias = &123;
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-LL | pub trait Eq: PartialEq<Self> {
-   |               ^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
 
 error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified
   --> $DIR/object-fail.rs:9:17
diff --git a/src/test/ui/traits/assoc-type-in-superbad.rs b/src/test/ui/traits/assoc-type-in-superbad.rs
index d7d6241ef70..65340b2a209 100644
--- a/src/test/ui/traits/assoc-type-in-superbad.rs
+++ b/src/test/ui/traits/assoc-type-in-superbad.rs
@@ -10,7 +10,7 @@ pub trait Foo: Iterator<Item = <Self as Foo>::Key> {
 
 impl Foo for IntoIter<i32> {
     type Key = u32;
-    //~^ ERROR expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+    //~^ ERROR expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
 }
 
 fn main() {}
diff --git a/src/test/ui/traits/assoc-type-in-superbad.stderr b/src/test/ui/traits/assoc-type-in-superbad.stderr
index 3e2d9d9038a..7fa1d2c2eed 100644
--- a/src/test/ui/traits/assoc-type-in-superbad.stderr
+++ b/src/test/ui/traits/assoc-type-in-superbad.stderr
@@ -1,4 +1,4 @@
-error[E0271]: expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+error[E0271]: expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
   --> $DIR/assoc-type-in-superbad.rs:12:16
    |
 LL |     type Key = u32;
diff --git a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
index 9ca446a0a89..5be33498641 100644
--- a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
+++ b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
@@ -9,11 +9,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
    |                                              ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -29,11 +27,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
    |                                                      ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -49,11 +45,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
    |                                             ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -69,11 +63,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
    |                                                         ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -89,11 +81,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
    |                                                   ^^^^^^ help: a trait with a similar name exists: `ToString`
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/traits/bad-sized.stderr b/src/test/ui/traits/bad-sized.stderr
index 6f9113fff51..fb9900bc57b 100644
--- a/src/test/ui/traits/bad-sized.stderr
+++ b/src/test/ui/traits/bad-sized.stderr
@@ -18,9 +18,6 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    = help: the trait `Sized` is not implemented for `dyn Trait`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
   --> $DIR/bad-sized.rs:4:37
@@ -31,9 +28,6 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    = help: the trait `Sized` is not implemented for `dyn Trait`
 note: required by a bound in `Vec::<T>::new`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | impl<T> Vec<T> {
-   |      ^ required by this bound in `Vec::<T>::new`
 
 error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
   --> $DIR/bad-sized.rs:4:37
@@ -44,9 +38,6 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    = help: the trait `Sized` is not implemented for `dyn Trait`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/traits/bound/not-on-bare-trait.stderr b/src/test/ui/traits/bound/not-on-bare-trait.stderr
index 8da0b6d6b85..36b08a7d309 100644
--- a/src/test/ui/traits/bound/not-on-bare-trait.stderr
+++ b/src/test/ui/traits/bound/not-on-bare-trait.stderr
@@ -20,6 +20,10 @@ LL | fn foo(_x: Foo + Send) {
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn foo(_x: impl Foo + Send) {
+   |            ++++
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | fn foo(_x: &Foo + Send) {
diff --git a/src/test/ui/issues/issue-38404.rs b/src/test/ui/traits/issue-38404.rs
index 1a92acc3404..1a92acc3404 100644
--- a/src/test/ui/issues/issue-38404.rs
+++ b/src/test/ui/traits/issue-38404.rs
diff --git a/src/test/ui/issues/issue-38404.stderr b/src/test/ui/traits/issue-38404.stderr
index d7721d7e69c..d7721d7e69c 100644
--- a/src/test/ui/issues/issue-38404.stderr
+++ b/src/test/ui/traits/issue-38404.stderr
diff --git a/src/test/ui/issues/issue-50480.rs b/src/test/ui/traits/issue-50480.rs
index 10597caf5b2..10597caf5b2 100644
--- a/src/test/ui/issues/issue-50480.rs
+++ b/src/test/ui/traits/issue-50480.rs
diff --git a/src/test/ui/issues/issue-50480.stderr b/src/test/ui/traits/issue-50480.stderr
index 0bb1f9ae035..0bb1f9ae035 100644
--- a/src/test/ui/issues/issue-50480.stderr
+++ b/src/test/ui/traits/issue-50480.stderr
diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr
index b6a04585583..0b57a8212bd 100644
--- a/src/test/ui/traits/issue-77982.stderr
+++ b/src/test/ui/traits/issue-77982.stderr
@@ -12,9 +12,6 @@ LL |     opts.get(opt.as_ref());
              where T: ?Sized;
 note: required by a bound in `HashMap::<K, V, S>::get`
   --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL |         K: Borrow<Q>,
-   |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
 help: consider specifying the generic argument
    |
 LL |     opts.get::<Q>(opt.as_ref());
@@ -46,7 +43,15 @@ LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
    |                                            |
    |                                            required by a bound introduced by this call
    |
-   = note: cannot satisfy `u32: From<_>`
+   = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
+           - impl From<Ipv4Addr> for u32;
+           - impl From<NonZeroU32> for u32;
+           - impl From<bool> for u32;
+           - impl From<char> for u32;
+           - impl From<u16> for u32;
+           - impl From<u8> for u32;
+           - impl<T> From<!> for T;
+           - impl<T> From<T> for T;
 help: try using a fully qualified path to specify the expected types
    |
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
diff --git a/src/test/ui/traits/issue-85735.stderr b/src/test/ui/traits/issue-85735.stderr
index fa280135beb..9e80497ca6e 100644
--- a/src/test/ui/traits/issue-85735.stderr
+++ b/src/test/ui/traits/issue-85735.stderr
@@ -4,7 +4,14 @@ error[E0283]: type annotations needed: cannot satisfy `T: FnMut<(&'a (),)>`
 LL |     T: FnMut(&'a ()),
    |        ^^^^^^^^^^^^^
    |
-   = note: cannot satisfy `T: FnMut<(&'a (),)>`
+note: multiple `impl`s or `where` clauses satisfying `T: FnMut<(&'a (),)>` found
+  --> $DIR/issue-85735.rs:7:8
+   |
+LL |     T: FnMut(&'a ()),
+   |        ^^^^^^^^^^^^^
+LL |
+LL |     T: FnMut(&'b ()),
+   |        ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/issue-97576.stderr b/src/test/ui/traits/issue-97576.stderr
index 146d38d076a..9062a0fab63 100644
--- a/src/test/ui/traits/issue-97576.stderr
+++ b/src/test/ui/traits/issue-97576.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied
-  --> $DIR/issue-97576.rs:8:18
+  --> $DIR/issue-97576.rs:8:22
    |
 LL |             bar: bar.into(),
-   |                  ^^^ ---- required by a bound introduced by this call
-   |                  |
-   |                  the trait `From<impl ToString>` is not implemented for `String`
+   |                      ^^^^ the trait `From<impl ToString>` is not implemented for `String`
    |
    = note: required for `impl ToString` to implement `Into<String>`
 
diff --git a/src/test/ui/traits/mutual-recursion-issue-75860.stderr b/src/test/ui/traits/mutual-recursion-issue-75860.stderr
index 920f66121e0..23e182738f7 100644
--- a/src/test/ui/traits/mutual-recursion-issue-75860.stderr
+++ b/src/test/ui/traits/mutual-recursion-issue-75860.stderr
@@ -7,9 +7,6 @@ LL |     iso(left, right)
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`)
 note: required by a bound in `Option`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   |                 ^ required by this bound in `Option`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/object/issue-44454-1.rs b/src/test/ui/traits/object/issue-44454-1.rs
new file mode 100644
index 00000000000..bbaf3188a89
--- /dev/null
+++ b/src/test/ui/traits/object/issue-44454-1.rs
@@ -0,0 +1,22 @@
+// Taken from https://github.com/rust-lang/rust/issues/44454#issue-256435333
+
+trait Animal<X>: 'static {}
+
+fn foo<Y, X>()
+where
+    Y: Animal<X> + ?Sized,
+{
+    // `Y` implements `Animal<X>` so `Y` is 'static.
+    baz::<Y>()
+}
+
+fn bar<'a>(_arg: &'a i32) {
+    foo::<dyn Animal<&'a i32>, &'a i32>() //~ ERROR: lifetime may not live long enough
+}
+
+fn baz<T: 'static + ?Sized>() {}
+
+fn main() {
+    let a = 5;
+    bar(&a);
+}
diff --git a/src/test/ui/traits/object/issue-44454-1.stderr b/src/test/ui/traits/object/issue-44454-1.stderr
new file mode 100644
index 00000000000..859487f50ac
--- /dev/null
+++ b/src/test/ui/traits/object/issue-44454-1.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-44454-1.rs:14:5
+   |
+LL | fn bar<'a>(_arg: &'a i32) {
+   |        -- lifetime `'a` defined here
+LL |     foo::<dyn Animal<&'a i32>, &'a i32>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/traits/object/issue-44454-2.rs b/src/test/ui/traits/object/issue-44454-2.rs
new file mode 100644
index 00000000000..f5178bcdbe2
--- /dev/null
+++ b/src/test/ui/traits/object/issue-44454-2.rs
@@ -0,0 +1,22 @@
+// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1175925928
+
+trait Trait<ARG: 'static>: 'static {
+    type Assoc: AsRef<str>;
+}
+
+fn hr<T: ?Sized, ARG>(x: T::Assoc) -> Box<dyn AsRef<str> + 'static>
+where
+    T: Trait<ARG>
+{
+    Box::new(x)
+}
+
+fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> {
+    type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>;
+    hr::<DynTrait, _>(x) //~ ERROR: borrowed data escapes outside of function
+}
+
+fn main() {
+    let extended = extend_lt(&String::from("hello"));
+    println!("{}", extended.as_ref().as_ref());
+}
diff --git a/src/test/ui/traits/object/issue-44454-2.stderr b/src/test/ui/traits/object/issue-44454-2.stderr
new file mode 100644
index 00000000000..7f574769b7f
--- /dev/null
+++ b/src/test/ui/traits/object/issue-44454-2.stderr
@@ -0,0 +1,17 @@
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/issue-44454-2.rs:16:5
+   |
+LL | fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> {
+   |              --  - `x` is a reference that is only valid in the function body
+   |              |
+   |              lifetime `'a` defined here
+LL |     type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>;
+LL |     hr::<DynTrait, _>(x)
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     `x` escapes the function body here
+   |     argument requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/traits/object/issue-44454-3.rs b/src/test/ui/traits/object/issue-44454-3.rs
new file mode 100644
index 00000000000..bff72703534
--- /dev/null
+++ b/src/test/ui/traits/object/issue-44454-3.rs
@@ -0,0 +1,33 @@
+// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1332781290
+
+use std::any::Any;
+
+trait Animal<X>: 'static {}
+
+trait Projector {
+    type Foo;
+}
+
+impl<X> Projector for dyn Animal<X> {
+    type Foo = X;
+}
+
+fn make_static<'a, T>(t: &'a T) -> &'static T {
+    let x: <dyn Animal<&'a T> as Projector>::Foo = t;
+    let any = generic::<dyn Animal<&'a T>, &'a T>(x);
+    //~^ ERROR: lifetime may not live long enough
+    any.downcast_ref::<&'static T>().unwrap()
+}
+
+fn generic<T: Projector + Animal<U> + ?Sized, U>(x: <T as Projector>::Foo) -> Box<dyn Any> {
+    make_static_any(x)
+}
+
+fn make_static_any<U: 'static>(u: U) -> Box<dyn Any> {
+    Box::new(u)
+}
+
+fn main() {
+    let a = make_static(&"salut".to_string());
+    println!("{}", *a);
+}
diff --git a/src/test/ui/traits/object/issue-44454-3.stderr b/src/test/ui/traits/object/issue-44454-3.stderr
new file mode 100644
index 00000000000..294684d26bd
--- /dev/null
+++ b/src/test/ui/traits/object/issue-44454-3.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-44454-3.rs:17:15
+   |
+LL | fn make_static<'a, T>(t: &'a T) -> &'static T {
+   |                -- lifetime `'a` defined here
+LL |     let x: <dyn Animal<&'a T> as Projector>::Foo = t;
+LL |     let any = generic::<dyn Animal<&'a T>, &'a T>(x);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/traits/static-method-generic-inference.stderr b/src/test/ui/traits/static-method-generic-inference.stderr
index 5f74d0c3b92..575ace2374e 100644
--- a/src/test/ui/traits/static-method-generic-inference.stderr
+++ b/src/test/ui/traits/static-method-generic-inference.stderr
@@ -9,8 +9,8 @@ LL |     let _f: base::Foo = base::HasNew::new();
    |
 help: use the fully-qualified path to the only available implementation
    |
-LL |     let _f: base::Foo = base::<Foo as HasNew>::new();
-   |                               +++++++       +
+LL |     let _f: base::Foo = <Foo as base::HasNew>::new();
+   |                         +++++++             +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/suggest-deferences/issue-39029.stderr b/src/test/ui/traits/suggest-deferences/issue-39029.stderr
index eb2b88059d4..49e20c6a76a 100644
--- a/src/test/ui/traits/suggest-deferences/issue-39029.stderr
+++ b/src/test/ui/traits/suggest-deferences/issue-39029.stderr
@@ -9,9 +9,6 @@ LL |     let _errors = TcpListener::bind(&bad);
    = note: required for `&NoToSocketAddrs` to implement `ToSocketAddrs`
 note: required by a bound in `TcpListener::bind`
   --> $SRC_DIR/std/src/net/tcp.rs:LL:COL
-   |
-LL |     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
-   |                    ^^^^^^^^^^^^^ required by this bound in `TcpListener::bind`
 help: consider dereferencing here
    |
 LL |     let _errors = TcpListener::bind(&*bad);
diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.stderr b/src/test/ui/traits/suggest-deferences/root-obligation.stderr
index 76663ace7ed..1363fb8c47a 100644
--- a/src/test/ui/traits/suggest-deferences/root-obligation.stderr
+++ b/src/test/ui/traits/suggest-deferences/root-obligation.stderr
@@ -11,9 +11,6 @@ LL |         .filter(|c| "aeiou".contains(c))
    = note: required for `&char` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::contains`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-   |                            ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::contains`
 help: consider dereferencing here
    |
 LL |         .filter(|c| "aeiou".contains(*c))
diff --git a/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed
new file mode 100644
index 00000000000..ea3d1bf853a
--- /dev/null
+++ b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+    fn from(_unchecked: usize) -> Self {
+        TargetStruct
+    }
+}
+
+fn main() {
+    let a = &3;
+    let _b: TargetStruct = (*a).into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
diff --git a/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs
new file mode 100644
index 00000000000..9eda68027b2
--- /dev/null
+++ b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+    fn from(_unchecked: usize) -> Self {
+        TargetStruct
+    }
+}
+
+fn main() {
+    let a = &3;
+    let _b: TargetStruct = a.into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
diff --git a/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr
new file mode 100644
index 00000000000..ede31a2c7bc
--- /dev/null
+++ b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+  --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30
+   |
+LL |     let _b: TargetStruct = a.into();
+   |                              ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct`
+   |
+   = note: required for `&{integer}` to implement `Into<TargetStruct>`
+help: consider dereferencing here
+   |
+LL |     let _b: TargetStruct = (*a).into();
+   |                            ++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/suggest-where-clause.stderr b/src/test/ui/traits/suggest-where-clause.stderr
index 747e2477b9c..44e63b78cce 100644
--- a/src/test/ui/traits/suggest-where-clause.stderr
+++ b/src/test/ui/traits/suggest-where-clause.stderr
@@ -9,9 +9,6 @@ LL |     mem::size_of::<U>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn check<T: Iterator, U: ?Sized>() {
@@ -34,9 +31,6 @@ LL | struct Misc<T:?Sized>(T);
    |        ^^^^
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn check<T: Iterator, U: ?Sized>() {
@@ -80,9 +74,6 @@ LL |     mem::size_of::<[T]>();
    = help: the trait `Sized` is not implemented for `[T]`
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 
 error[E0277]: the size for values of type `[&U]` cannot be known at compilation time
   --> $DIR/suggest-where-clause.rs:31:20
@@ -93,9 +84,6 @@ LL |     mem::size_of::<[&U]>();
    = help: the trait `Sized` is not implemented for `[&U]`
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/transmutability/issue-101739-2.stderr b/src/test/ui/transmutability/issue-101739-2.stderr
index 3f83d6583b0..1b3d202590d 100644
--- a/src/test/ui/transmutability/issue-101739-2.stderr
+++ b/src/test/ui/transmutability/issue-101739-2.stderr
@@ -8,12 +8,6 @@ LL | /             ASSUME_LIFETIMES,
 LL | |             ASSUME_VALIDITY,
 LL | |             ASSUME_VISIBILITY,
    | |_____________________________- help: remove these generic arguments
-   |
-note: trait defined here, with at most 3 generic parameters: `Src`, `Context`, `ASSUME`
-  --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
-   |
-LL | pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
-   |                  ^^^^^^^^^^^^^^^^^^^^^ ---  -------  ------------------------------------------
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/tuple/wrong_argument_ice-3.stderr b/src/test/ui/tuple/wrong_argument_ice-3.stderr
index f3a547fa238..fe3712ef839 100644
--- a/src/test/ui/tuple/wrong_argument_ice-3.stderr
+++ b/src/test/ui/tuple/wrong_argument_ice-3.stderr
@@ -13,9 +13,6 @@ LL |         groups.push(new_group, vec![process]);
              found struct `Vec<String>`
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL |     pub fn push(&mut self, value: T) {
-   |            ^^^^
 help: remove the extra argument
    |
 LL |         groups.push(/* (Vec<String>, Vec<Process>) */);
diff --git a/src/test/ui/tuple/wrong_argument_ice.stderr b/src/test/ui/tuple/wrong_argument_ice.stderr
index ec07f1e70cf..452413fc516 100644
--- a/src/test/ui/tuple/wrong_argument_ice.stderr
+++ b/src/test/ui/tuple/wrong_argument_ice.stderr
@@ -6,9 +6,6 @@ LL |         self.acc.push_back(self.current_provides, self.current_requires);
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/collections/vec_deque/mod.rs:LL:COL
-   |
-LL |     pub fn push_back(&mut self, value: T) {
-   |            ^^^^^^^^^
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |         self.acc.push_back((self.current_provides, self.current_requires));
diff --git a/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
index 48b7946ea82..9cc15f14a99 100644
--- a/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
+++ b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
@@ -6,8 +6,8 @@ LL |         |x| x.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |x: _| x.len()
-   |           +++
+LL |         |x: /* Type */| x.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/closures_in_branches.rs:21:10
@@ -17,8 +17,8 @@ LL |         |x| x.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |x: _| x.len()
-   |           +++
+LL |         |x: /* Type */| x.len()
+   |           ++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57961.rs b/src/test/ui/type-alias-impl-trait/issue-57961.rs
index 24b3a045856..4aa5966ff25 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57961.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-57961.rs
@@ -8,7 +8,7 @@ trait Foo {
 
 impl Foo for () {
     type Bar = std::vec::IntoIter<u32>;
-    //~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
+    //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
 }
 
 fn incoherent() {
diff --git a/src/test/ui/type-alias-impl-trait/issue-57961.stderr b/src/test/ui/type-alias-impl-trait/issue-57961.stderr
index fb40895c49f..8d11b488889 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57961.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57961.stderr
@@ -1,4 +1,4 @@
-error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
+error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
   --> $DIR/issue-57961.rs:10:16
    |
 LL | type X = impl Sized;
diff --git a/src/test/ui/issues/issue-37515.rs b/src/test/ui/type-alias/issue-37515.rs
index b3a870d505a..b3a870d505a 100644
--- a/src/test/ui/issues/issue-37515.rs
+++ b/src/test/ui/type-alias/issue-37515.rs
diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/type-alias/issue-37515.stderr
index f1e83ca74d8..f1e83ca74d8 100644
--- a/src/test/ui/issues/issue-37515.stderr
+++ b/src/test/ui/type-alias/issue-37515.stderr
diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr
index 6819d14bb01..fd43e1114c8 100644
--- a/src/test/ui/type/ascription/issue-34255-1.stderr
+++ b/src/test/ui/type/ascription/issue-34255-1.stderr
@@ -25,11 +25,6 @@ error[E0107]: missing generics for struct `Vec`
 LL |         input_cells: Vec::new()
    |                      ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |            ^^^ -
 help: add missing generic argument
    |
 LL |         input_cells: Vec<T>::new()
diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr
index 4af4c22f751..87bba3166be 100644
--- a/src/test/ui/type/type-annotation-needed.stderr
+++ b/src/test/ui/type/type-annotation-needed.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `foo`
    |
 LL | fn foo<T: Into<String>>(x: i32) {}
    |           ^^^^^^^^^^^^ required by this bound in `foo`
-help: consider specifying the type argument in the function call
+help: consider specifying the generic argument
    |
 LL |     foo::<T>(42);
    |        +++++
diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.stderr b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
index de578ca93ed..ba8d15d0b73 100644
--- a/src/test/ui/type/type-ascription-instead-of-initializer.stderr
+++ b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
@@ -15,9 +15,6 @@ LL |     let x: Vec::with_capacity(10, 20);
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL |     pub fn with_capacity(capacity: usize) -> Self {
-   |            ^^^^^^^^^^^^^
 help: remove the extra argument
    |
 LL |     let x: Vec::with_capacity(10);
diff --git a/src/test/ui/type/type-ascription-precedence.stderr b/src/test/ui/type/type-ascription-precedence.stderr
index a8139063db1..edc5aeffdcd 100644
--- a/src/test/ui/type/type-ascription-precedence.stderr
+++ b/src/test/ui/type/type-ascription-precedence.stderr
@@ -33,11 +33,8 @@ note: an implementation of `std::ops::Neg` might be missing for `Z`
    |
 LL | struct Z;
    | ^^^^^^^^ must implement `std::ops::Neg`
-note: the following trait must be implemented
+note: the trait `std::ops::Neg` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Neg {
-   | ^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/type-ascription-precedence.rs:45:5
@@ -55,7 +52,7 @@ error[E0308]: mismatched types
   --> $DIR/type-ascription-precedence.rs:53:5
    |
 LL |     (S .. S): S;
-   |     ^^^^^^^^ expected struct `S`, found struct `std::ops::Range`
+   |     ^^^^^^^^ expected struct `S`, found struct `Range`
    |
    = note: expected struct `S`
               found struct `std::ops::Range<S>`
diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr
index 75feb5698eb..d15fd23418b 100644
--- a/src/test/ui/type/type-check/issue-40294.stderr
+++ b/src/test/ui/type/type-check/issue-40294.stderr
@@ -4,7 +4,13 @@ error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo`
 LL |     where &'a T : Foo,
    |                   ^^^
    |
-   = note: cannot satisfy `&'a T: Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found
+  --> $DIR/issue-40294.rs:6:19
+   |
+LL |     where &'a T : Foo,
+   |                   ^^^
+LL |           &'b T : Foo
+   |                   ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type/type-check/unknown_type_for_closure.stderr b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
index 9ae97f390d3..e5e29aabf37 100644
--- a/src/test/ui/type/type-check/unknown_type_for_closure.stderr
+++ b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
@@ -12,8 +12,8 @@ LL |     let x = |_| {};
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     let x = |_: _| {};
-   |               +++
+LL |     let x = |_: /* Type */| {};
+   |               ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/unknown_type_for_closure.rs:10:14
diff --git a/src/test/ui/type/type-path-err-node-types.stderr b/src/test/ui/type/type-path-err-node-types.stderr
index c1ae10efac4..1aed1dbe4ba 100644
--- a/src/test/ui/type/type-path-err-node-types.stderr
+++ b/src/test/ui/type/type-path-err-node-types.stderr
@@ -30,8 +30,8 @@ LL |     let _ = |a, b: _| -> _ { 0 };
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     let _ = |a: _, b: _| -> _ { 0 };
-   |               +++
+LL |     let _ = |a: /* Type */, b: _| -> _ { 0 };
+   |               ++++++++++++
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr
index ff487466902..5b00d387aba 100644
--- a/src/test/ui/type_length_limit.stderr
+++ b/src/test/ui/type_length_limit.stderr
@@ -1,9 +1,6 @@
 error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL | pub fn drop<T>(_x: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^
-   |
    = help: consider adding a `#![type_length_limit="10"]` attribute to your crate
    = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
 
diff --git a/src/test/ui/typeck/explain_clone_autoref.stderr b/src/test/ui/typeck/explain_clone_autoref.stderr
index faac680ea19..ff36e18d283 100644
--- a/src/test/ui/typeck/explain_clone_autoref.stderr
+++ b/src/test/ui/typeck/explain_clone_autoref.stderr
@@ -12,6 +12,10 @@ note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
    |
 LL |     nc.clone()
    |     ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/issue-104582.rs b/src/test/ui/typeck/issue-104582.rs
new file mode 100644
index 00000000000..104669dadbe
--- /dev/null
+++ b/src/test/ui/typeck/issue-104582.rs
@@ -0,0 +1,5 @@
+fn main(){
+    let my_var: String(String?);
+    //~^ ERROR: invalid `?` in type
+    //~| ERROR: parenthesized type parameters may only be used with a `Fn` trait
+}
diff --git a/src/test/ui/typeck/issue-104582.stderr b/src/test/ui/typeck/issue-104582.stderr
new file mode 100644
index 00000000000..61b6b23642c
--- /dev/null
+++ b/src/test/ui/typeck/issue-104582.stderr
@@ -0,0 +1,25 @@
+error: invalid `?` in type
+  --> $DIR/issue-104582.rs:2:30
+   |
+LL |     let my_var: String(String?);
+   |                              ^ `?` is only allowed on expressions, not types
+   |
+help: if you meant to express that the type might not contain a value, use the `Option` wrapper type
+   |
+LL |     let my_var: String(Option<String>);
+   |                        +++++++      ~
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-104582.rs:2:17
+   |
+LL |     let my_var: String(String?);
+   |                 ^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses
+   |
+help: use angle brackets instead
+   |
+LL |     let my_var: String<String?>;
+   |                       ~       ~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0214`.
diff --git a/src/test/ui/typeck/issue-13853.stderr b/src/test/ui/typeck/issue-13853.stderr
index 657bda5f62b..876ac2c67ef 100644
--- a/src/test/ui/typeck/issue-13853.stderr
+++ b/src/test/ui/typeck/issue-13853.stderr
@@ -5,7 +5,7 @@ LL |     fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I
    |                  - this type parameter              - expected `I` because of return type
 ...
 LL |         self.iter()
-   |         ^^^^^^^^^^^ expected type parameter `I`, found struct `std::slice::Iter`
+   |         ^^^^^^^^^^^ expected type parameter `I`, found struct `Iter`
    |
    = note: expected type parameter `I`
                       found struct `std::slice::Iter<'_, N>`
diff --git a/src/test/ui/issues/issue-33575.rs b/src/test/ui/typeck/issue-33575.rs
index de544afae73..de544afae73 100644
--- a/src/test/ui/issues/issue-33575.rs
+++ b/src/test/ui/typeck/issue-33575.rs
diff --git a/src/test/ui/issues/issue-33575.stderr b/src/test/ui/typeck/issue-33575.stderr
index bbd8042d1cd..bbd8042d1cd 100644
--- a/src/test/ui/issues/issue-33575.stderr
+++ b/src/test/ui/typeck/issue-33575.stderr
diff --git a/src/test/ui/typeck/issue-46112.stderr b/src/test/ui/typeck/issue-46112.stderr
index 91381e8ef4a..f488463ae3c 100644
--- a/src/test/ui/typeck/issue-46112.stderr
+++ b/src/test/ui/typeck/issue-46112.stderr
@@ -10,9 +10,6 @@ LL | fn main() { test(Ok(())); }
            found unit type `()`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: try wrapping the expression in `Some`
    |
 LL | fn main() { test(Ok(Some(()))); }
diff --git a/src/test/ui/typeck/issue-75883.stderr b/src/test/ui/typeck/issue-75883.stderr
index 3861e0507f6..f5adcabe3e9 100644
--- a/src/test/ui/typeck/issue-75883.stderr
+++ b/src/test/ui/typeck/issue-75883.stderr
@@ -6,11 +6,6 @@ LL |     pub fn run() -> Result<_> {
    |                     |
    |                     expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL |     pub fn run() -> Result<_, E> {
@@ -24,11 +19,6 @@ LL |     pub fn interact(&mut self) -> Result<_> {
    |                                   |
    |                                   expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL |     pub fn interact(&mut self) -> Result<_, E> {
diff --git a/src/test/ui/typeck/issue-83693.stderr b/src/test/ui/typeck/issue-83693.stderr
index 1e45c2d35df..ce4f73b820a 100644
--- a/src/test/ui/typeck/issue-83693.stderr
+++ b/src/test/ui/typeck/issue-83693.stderr
@@ -3,11 +3,9 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL | impl F {
    |      ^ help: a trait with a similar name exists: `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0412]: cannot find type `TestResult` in this scope
   --> $DIR/issue-83693.rs:9:22
diff --git a/src/test/ui/typeck/issue-84768.stderr b/src/test/ui/typeck/issue-84768.stderr
index 04dc0e36520..00d23389720 100644
--- a/src/test/ui/typeck/issue-84768.stderr
+++ b/src/test/ui/typeck/issue-84768.stderr
@@ -16,9 +16,6 @@ LL |     <F as FnOnce(&mut u8)>::call_once(f, 1)
                found type `{integer}`
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-   |                           ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/typeck/issue-92481.rs b/src/test/ui/typeck/issue-92481.rs
new file mode 100644
index 00000000000..0a6b1843d99
--- /dev/null
+++ b/src/test/ui/typeck/issue-92481.rs
@@ -0,0 +1,14 @@
+//check-fail
+
+#![crate_type="lib"]
+
+fn r({) {
+    Ok {             //~ ERROR mismatched types [E0308]
+        d..||_=m
+    }
+}
+//~^^^^^ ERROR expected parameter name, found `{`
+//~| ERROR expected one of `,`, `:`, or `}`, found `..`
+//~^^^^^ ERROR cannot find value `d` in this scope [E0425]
+//~| ERROR cannot find value `m` in this scope [E0425]
+//~| ERROR variant `Result<_, _>::Ok` has no field named `d` [E0559]
diff --git a/src/test/ui/typeck/issue-92481.stderr b/src/test/ui/typeck/issue-92481.stderr
new file mode 100644
index 00000000000..cd778a649b6
--- /dev/null
+++ b/src/test/ui/typeck/issue-92481.stderr
@@ -0,0 +1,60 @@
+error: expected parameter name, found `{`
+  --> $DIR/issue-92481.rs:5:6
+   |
+LL | fn r({) {
+   |      ^ expected parameter name
+
+error: expected one of `,`, `:`, or `}`, found `..`
+  --> $DIR/issue-92481.rs:5:6
+   |
+LL | fn r({) {
+   |      ^ unclosed delimiter
+LL |     Ok {
+LL |         d..||_=m
+   |          -^
+   |          |
+   |          help: `}` may belong here
+
+error[E0425]: cannot find value `d` in this scope
+  --> $DIR/issue-92481.rs:7:9
+   |
+LL |         d..||_=m
+   |         ^ not found in this scope
+
+error[E0425]: cannot find value `m` in this scope
+  --> $DIR/issue-92481.rs:7:16
+   |
+LL |         d..||_=m
+   |                ^ not found in this scope
+
+error[E0559]: variant `Result<_, _>::Ok` has no field named `d`
+  --> $DIR/issue-92481.rs:7:9
+   |
+LL |         d..||_=m
+   |         ^ field does not exist
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: `Result<_, _>::Ok` defined here
+   |
+help: `Result<_, _>::Ok` is a tuple variant, use the appropriate syntax
+   |
+LL |     Result<_, _>::Ok(/* fields */)
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/issue-92481.rs:6:5
+   |
+LL |   fn r({) {
+   |           - help: a return type might be missing here: `-> _`
+LL | /     Ok {
+LL | |         d..||_=m
+LL | |     }
+   | |_____^ expected `()`, found enum `Result`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<_, _>`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0308, E0425, E0559.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/struct-enum-wrong-args.stderr b/src/test/ui/typeck/struct-enum-wrong-args.stderr
index ea94bcbc290..fbced928a8a 100644
--- a/src/test/ui/typeck/struct-enum-wrong-args.stderr
+++ b/src/test/ui/typeck/struct-enum-wrong-args.stderr
@@ -6,9 +6,6 @@ LL |     let _ = Some(3, 2);
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: remove the extra argument
    |
 LL |     let _ = Some(3);
@@ -24,9 +21,6 @@ LL |     let _ = Ok(3, 6, 2);
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: remove the extra arguments
    |
 LL |     let _ = Ok(3);
@@ -40,9 +34,6 @@ LL |     let _ = Ok();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: provide the argument
    |
 LL |     let _ = Ok(/* value */);
diff --git a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
index bf74dd7dec0..331540d1e42 100644
--- a/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
+++ b/src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
@@ -5,12 +5,6 @@ LL | fn foo1<T:Copy<U>, U>(x: T) {}
    |           ^^^^--- help: remove these generics
    |           |
    |           expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14
@@ -19,12 +13,6 @@ LL | trait Trait: Copy<dyn Send> {}
    |              ^^^^---------- help: remove these generics
    |              |
    |              expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:7:21
@@ -33,12 +21,6 @@ LL | struct MyStruct1<T: Copy<T>>;
    |                     ^^^^--- help: remove these generics
    |                     |
    |                     expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:10:25
@@ -47,12 +29,6 @@ LL | struct MyStruct2<'a, T: Copy<'a>>;
    |                         ^^^^---- help: remove these generics
    |                         |
    |                         expected 0 lifetime arguments
-   |
-note: trait defined here, with 0 lifetime parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
@@ -61,12 +37,6 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
    |               ^^^^ -- help: remove this lifetime argument
    |               |
    |               expected 0 lifetime arguments
-   |
-note: trait defined here, with 0 lifetime parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
@@ -75,12 +45,6 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
    |               ^^^^     - help: remove this generic argument
    |               |
    |               expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
index ed56e1cf957..a2fe627868a 100644
--- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
+++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -23,9 +23,6 @@ LL |     <i32 as Add<i32>>::add(1u32, 2);
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |        ^^^
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1i32, 2);
@@ -41,9 +38,6 @@ LL |     <i32 as Add<i32>>::add(1, 2u32);
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |        ^^^
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1, 2i32);
diff --git a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
index 1c18eb0fc49..cfbe1c6f2cb 100644
--- a/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
+++ b/src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
@@ -6,9 +6,6 @@ LL | fn a<F: Fn<usize>>(f: F) {}
    |
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   |                    ^^^^^ required by this bound in `Fn`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
index e5ca0edd7a9..99ec5178340 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
@@ -1,8 +1,8 @@
-error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope
+error[E0599]: no method named `call` found for closure `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` in the current scope
   --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
    |
 LL |     mut_.call((0, ));
-   |          ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]`
+   |          ^^^^ method not found in `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index c7882963407..d33a61ca848 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -6,12 +6,9 @@ LL |     let _ = match x {
    |
 note: `Result<u32, &Void>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, &Void>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -88,12 +85,9 @@ LL |     let _ = match x {
    |
 note: `Result<u32, Void>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, Void>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -111,12 +105,9 @@ LL |     let Ok(x) = x;
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Result<u32, Void>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, Void>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr
index ca02de4c61b..7f931b49a58 100644
--- a/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr
+++ b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr
@@ -14,10 +14,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:62:13
    |
 LL |     let a = u.x.0;
-   |             ^^^^^
-   |             |
-   |             move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&u.x.0`
+   |             ^^^^^ move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &u.x.0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:64:13
@@ -46,10 +48,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:76:13
    |
 LL |     let a = (u.x.0).0;
-   |             ^^^^^^^^^
-   |             |
-   |             move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&(u.x.0).0`
+   |             ^^^^^^^^^ move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &(u.x.0).0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:78:13
diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr
index ca02de4c61b..7f931b49a58 100644
--- a/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr
+++ b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr
@@ -14,10 +14,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:62:13
    |
 LL |     let a = u.x.0;
-   |             ^^^^^
-   |             |
-   |             move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&u.x.0`
+   |             ^^^^^ move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &u.x.0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:64:13
@@ -46,10 +48,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:76:13
    |
 LL |     let a = (u.x.0).0;
-   |             ^^^^^^^^^
-   |             |
-   |             move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&(u.x.0).0`
+   |             ^^^^^^^^^ move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &(u.x.0).0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:78:13
diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr
index 148fb504670..65ff72fe474 100644
--- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr
+++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr
@@ -6,9 +6,6 @@ LL | #[derive(Clone)]
    |
 note: required by a bound in `AssertParamIsCopy`
   --> $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `U1` with `#[derive(Copy)]`
    |
diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr
index 148fb504670..65ff72fe474 100644
--- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr
+++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr
@@ -6,9 +6,6 @@ LL | #[derive(Clone)]
    |
 note: required by a bound in `AssertParamIsCopy`
   --> $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `U1` with `#[derive(Copy)]`
    |
diff --git a/src/test/ui/union/union-derive-eq.mirunsafeck.stderr b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr
index 99505f31639..9e55390b54d 100644
--- a/src/test/ui/union/union-derive-eq.mirunsafeck.stderr
+++ b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr
@@ -9,9 +9,6 @@ LL |     a: PartialEqNotEq,
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]`
    |
diff --git a/src/test/ui/union/union-derive-eq.thirunsafeck.stderr b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr
index 99505f31639..9e55390b54d 100644
--- a/src/test/ui/union/union-derive-eq.thirunsafeck.stderr
+++ b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr
@@ -9,9 +9,6 @@ LL |     a: PartialEqNotEq,
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]`
    |
diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr
index 98a9bd07ed2..db42ed9baf1 100644
--- a/src/test/ui/unique-object-noncopyable.stderr
+++ b/src/test/ui/unique-object-noncopyable.stderr
@@ -9,14 +9,10 @@ LL |   trait Foo {
 ...
 LL |       let _z = y.clone();
    |                  ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
-   |
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
-LL | / pub struct Box<
-LL | |     T: ?Sized,
-LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
-   | |_- doesn't satisfy `Box<dyn Foo>: Clone`
+   = note: doesn't satisfy `Box<dyn Foo>: Clone`
    |
    = note: the following trait bounds were not satisfied:
            `dyn Foo: Sized`
diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr
index 7af9c684b72..de6611324ca 100644
--- a/src/test/ui/unique-pinned-nocopy.stderr
+++ b/src/test/ui/unique-pinned-nocopy.stderr
@@ -6,14 +6,10 @@ LL |   struct R {
 ...
 LL |       let _j = i.clone();
    |                  ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
-   |
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
-LL | / pub struct Box<
-LL | |     T: ?Sized,
-LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
-   | |_- doesn't satisfy `Box<R>: Clone`
+   = note: doesn't satisfy `Box<R>: Clone`
    |
    = note: the following trait bounds were not satisfied:
            `R: Clone`
diff --git a/src/test/ui/unop-move-semantics.stderr b/src/test/ui/unop-move-semantics.stderr
index d52a92b8888..2a3ca14433f 100644
--- a/src/test/ui/unop-move-semantics.stderr
+++ b/src/test/ui/unop-move-semantics.stderr
@@ -11,9 +11,6 @@ LL |     x.clone();
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn not(self) -> Self::Output;
-   |            ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     !x.clone();
@@ -57,9 +54,6 @@ LL |     !*m;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn not(self) -> Self::Output;
-   |            ^^^^
 
 error[E0507]: cannot move out of `*n` which is behind a shared reference
   --> $DIR/unop-move-semantics.rs:26:6
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
index d8bffd4f9cf..9e3c345dd80 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.stderr
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -59,7 +59,7 @@ LL |         y.foo();
 LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `y`
   --> $DIR/borrow-after-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
index 71534818141..49b906bbe02 100644
--- a/src/test/ui/unsized-locals/double-move.stderr
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -55,7 +55,7 @@ LL |         y.foo();
 LL |         y.foo();
    |         ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `y`
   --> $DIR/double-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
diff --git a/src/test/ui/unsized/issue-71659.stderr b/src/test/ui/unsized/issue-71659.stderr
index 50060e53a49..d7b95f55769 100644
--- a/src/test/ui/unsized/issue-71659.stderr
+++ b/src/test/ui/unsized/issue-71659.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
-  --> $DIR/issue-71659.rs:30:13
+  --> $DIR/issue-71659.rs:30:15
    |
 LL |     let x = x.cast::<[i32]>();
-   |             ^ ---- required by a bound introduced by this call
-   |             |
-   |             the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
+   |               ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
    |
 note: required by a bound in `Cast::cast`
   --> $DIR/issue-71659.rs:19:15
diff --git a/src/test/ui/use/use-after-move-self-based-on-type.stderr b/src/test/ui/use/use-after-move-self-based-on-type.stderr
index 7fdc4ab251f..1bdf49801f9 100644
--- a/src/test/ui/use/use-after-move-self-based-on-type.stderr
+++ b/src/test/ui/use/use-after-move-self-based-on-type.stderr
@@ -8,7 +8,7 @@ LL |         self.bar();
 LL |         return self.x;
    |                ^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `self`
+note: `S::bar` takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self-based-on-type.rs:15:16
    |
 LL |     pub fn bar(self) {}
diff --git a/src/test/ui/use/use-after-move-self.stderr b/src/test/ui/use/use-after-move-self.stderr
index 073deee63b9..59cc22eadb0 100644
--- a/src/test/ui/use/use-after-move-self.stderr
+++ b/src/test/ui/use/use-after-move-self.stderr
@@ -8,7 +8,7 @@ LL |         self.bar();
 LL |         return *self.x;
    |                ^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `self`
+note: `S::bar` takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self.rs:13:16
    |
 LL |     pub fn bar(self) {}
diff --git a/src/test/ui/walk-struct-literal-with.stderr b/src/test/ui/walk-struct-literal-with.stderr
index 4384e345e85..2b85fa9bed4 100644
--- a/src/test/ui/walk-struct-literal-with.stderr
+++ b/src/test/ui/walk-struct-literal-with.stderr
@@ -8,7 +8,7 @@ LL |     let end = Mine{other_val:1, ..start.make_string_bar()};
 LL |     println!("{}", start.test);
    |                    ^^^^^^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `start`
+note: `Mine::make_string_bar` takes ownership of the receiver `self`, which moves `start`
   --> $DIR/walk-struct-literal-with.rs:7:28
    |
 LL |     fn make_string_bar(mut self) -> Mine{
diff --git a/src/test/ui/wf/hir-wf-canonicalized.rs b/src/test/ui/wf/hir-wf-canonicalized.rs
new file mode 100644
index 00000000000..bdb84409d00
--- /dev/null
+++ b/src/test/ui/wf/hir-wf-canonicalized.rs
@@ -0,0 +1,18 @@
+// incremental
+
+trait Foo {
+    type V;
+}
+
+trait Callback<T: Foo>: Fn(&Bar<'_, T>, &T::V) {}
+
+struct Bar<'a, T> {
+    callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+    //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied
+    //~| ERROR the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied
+    //~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time
+}
+
+impl<T: Foo> Bar<'_, Bar<'_, T>> {}
+
+fn main() {}
diff --git a/src/test/ui/wf/hir-wf-canonicalized.stderr b/src/test/ui/wf/hir-wf-canonicalized.stderr
new file mode 100644
index 00000000000..9fd0f9c81eb
--- /dev/null
+++ b/src/test/ui/wf/hir-wf-canonicalized.stderr
@@ -0,0 +1,32 @@
+error[E0277]: the trait bound `Bar<'a, T>: Foo` is not satisfied
+  --> $DIR/hir-wf-canonicalized.rs:10:15
+   |
+LL |     callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar<'a, T>`
+
+error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied
+  --> $DIR/hir-wf-canonicalized.rs:10:15
+   |
+LL |     callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)`
+
+error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time
+  --> $DIR/hir-wf-canonicalized.rs:10:15
+   |
+LL |     callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)`
+note: required by a bound in `Bar`
+  --> $DIR/hir-wf-canonicalized.rs:9:16
+   |
+LL | struct Bar<'a, T> {
+   |                ^ required by this bound in `Bar`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | struct Bar<'a, T: ?Sized> {
+   |                 ++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
index b04588c5716..7bc19dd2e21 100644
--- a/src/test/ui/wf/hir-wf-check-erase-regions.stderr
+++ b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
@@ -9,9 +9,6 @@ LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    = note: required for `&T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
-   |
-LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
-   |                                      ^^^^^^^^^^^^ required by this bound in `Flatten`
 
 error[E0277]: `&T` is not an iterator
   --> $DIR/hir-wf-check-erase-regions.rs:10:27
@@ -24,9 +21,6 @@ LL |     fn into_iter(self) -> Self::IntoIter {
    = note: required for `&T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
-   |
-LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
-   |                                      ^^^^^^^^^^^^ required by this bound in `Flatten`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/wf/wf-impl-self-type.stderr b/src/test/ui/wf/wf-impl-self-type.stderr
index 371321793ad..1ca368729fe 100644
--- a/src/test/ui/wf/wf-impl-self-type.stderr
+++ b/src/test/ui/wf/wf-impl-self-type.stderr
@@ -7,9 +7,6 @@ LL | impl Foo for Option<[u8]> {}
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Option`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   |                 ^ required by this bound in `Option`
 
 error: aborting due to previous error
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 70898e522116f6c23971e2a554b2dc85fd4c84c
+Subproject cc0a320879c17207bbfb96b5d778e28a2c62030
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 38329659e02..31183266acf 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1244,7 +1244,7 @@ fn is_mixed_projection_predicate<'tcx>(
         let mut projection_ty = projection_predicate.projection_ty;
         loop {
             match projection_ty.self_ty().kind() {
-                ty::Projection(inner_projection_ty) => {
+                ty::Alias(ty::Projection, inner_projection_ty) => {
                     projection_ty = *inner_projection_ty;
                 }
                 ty::Param(param_ty) => {
@@ -1330,7 +1330,7 @@ fn replace_types<'tcx>(
                     && let Some(term_ty) = projection_predicate.term.ty()
                     && let ty::Param(term_param_ty) = term_ty.kind()
                 {
-                    let item_def_id = projection_predicate.projection_ty.item_def_id;
+                    let item_def_id = projection_predicate.projection_ty.def_id;
                     let assoc_item = cx.tcx.associated_item(item_def_id);
                     let projection = cx.tcx
                         .mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
@@ -1390,8 +1390,8 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
                 continue;
             },
             ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
-            ty::Projection(_) if ty.has_non_region_param() => TyPosition::new_deref_stable_for_result(precedence, ty),
-            ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Opaque(..) | ty::Placeholder(_) | ty::Dynamic(..) => {
+            ty::Alias(ty::Projection, _) if ty.has_non_region_param() => TyPosition::new_deref_stable_for_result(precedence, ty),
+            ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Alias(ty::Opaque, ..) | ty::Placeholder(_) | ty::Dynamic(..) => {
                 Position::ReborrowStable(precedence).into()
             },
             ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => {
@@ -1417,7 +1417,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
             | ty::Closure(..)
             | ty::Never
             | ty::Tuple(_)
-            | ty::Projection(_) => {
+            | ty::Alias(ty::Projection, _) => {
                 Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
             },
         };
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 9e596ca8157..3f0b165f2b6 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -15,7 +15,7 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::{
     self, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate,
-    TraitRef, Ty, TyCtxt,
+    Ty, TyCtxt,
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
@@ -513,9 +513,9 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
         tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
             params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
                 tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
-                    trait_ref: TraitRef::new(
+                    trait_ref: tcx.mk_trait_ref(
                         eq_trait_id,
-                        tcx.mk_substs(std::iter::once(tcx.mk_param_from_def(param))),
+                        [tcx.mk_param_from_def(param)],
                     ),
                     constness: BoundConstness::NotConst,
                     polarity: ImplPolarity::Positive,
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index 61934a91426..989f83cf80d 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Clause, EarlyBinder, Opaque, PredicateKind};
+use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
@@ -62,11 +62,11 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
             return;
         }
         let ret_ty = return_ty(cx, hir_id);
-        if let Opaque(id, subst) = *ret_ty.kind() {
-            let preds = cx.tcx.explicit_item_bounds(id);
+        if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() {
+            let preds = cx.tcx.explicit_item_bounds(def_id);
             let mut is_future = false;
             for &(p, _span) in preds {
-                let p = EarlyBinder(p).subst(cx.tcx, subst);
+                let p = EarlyBinder(p).subst(cx.tcx, substs);
                 if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
                     if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
                         is_future = true;
diff --git a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs b/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs
index e0a607f9a95..6a4861747d2 100644
--- a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs
+++ b/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs
@@ -33,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidUtf8InUnchecked {
         if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) {
             match &arg.kind {
                 ExprKind::Lit(Spanned { node: lit, .. }) => {
-                    if let LitKind::ByteStr(bytes) = &lit
+                    if let LitKind::ByteStr(bytes, _) = &lit
                         && std::str::from_utf8(bytes).is_err()
                     {
                         lint(cx, expr.span);
diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs
index 84dd61a1e4b..424c0d9e798 100644
--- a/src/tools/clippy/clippy_lints/src/large_include_file.rs
+++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs
@@ -60,7 +60,7 @@ impl LateLintPass<'_> for LargeIncludeFile {
             then {
                 let len = match &lit.node {
                     // include_bytes
-                    LitKind::ByteStr(bstr) => bstr.len(),
+                    LitKind::ByteStr(bstr, _) => bstr.len(),
                     // include_str
                     LitKind::Str(sym, _) => sym.as_str().len(),
                     _ => return,
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 4c133c06a15..73841f9aa9a 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -493,7 +493,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
                 .filter_by_name_unhygienic(is_empty)
                 .any(|item| is_is_empty(cx, item))
         }),
-        ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
+        ty::Alias(ty::Projection, ref proj) => has_is_empty_impl(cx, proj.def_id),
         ty::Adt(id, _) => has_is_empty_impl(cx, id.did()),
         ty::Array(..) | ty::Slice(..) | ty::Str => true,
         _ => false,
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 168c1e4d2e6..158e6caa4de 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
@@ -282,7 +282,7 @@ impl<'a> NormalizedPat<'a> {
                 // TODO: Handle negative integers. They're currently treated as a wild match.
                 ExprKind::Lit(lit) => match lit.node {
                     LitKind::Str(sym, _) => Self::LitStr(sym),
-                    LitKind::ByteStr(ref bytes) => Self::LitBytes(bytes),
+                    LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Byte(val) => Self::LitInt(val.into()),
                     LitKind::Char(val) => Self::LitInt(val.into()),
                     LitKind::Int(val, _) => Self::LitInt(val),
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index b088e642e0e..f4d3ef3b742 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -151,7 +151,7 @@ fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty:
         && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty])
         && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
             cx.param_env,
-            cx.tcx.mk_projection(into_iter_item_proj.item_def_id, into_iter_item_proj.substs)
+            cx.tcx.mk_projection(into_iter_item_proj.def_id, into_iter_item_proj.substs)
         )
     {
         iter_item_ty == into_iter_item_ty
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 0c052d86eda..bd7daf0773c 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -299,7 +299,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 };
                 kind!("Float(_, {float_ty})");
             },
-            LitKind::ByteStr(ref vec) => {
+            LitKind::ByteStr(ref vec, _) => {
                 bind!(self, vec);
                 kind!("ByteStr(ref {vec})");
                 chain!(self, "let [{:?}] = **{vec}", vec.value);
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index c6bf98b7b8b..43f0df145f0 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -69,7 +69,9 @@ fn lit_search_pat(lit: &LitKind) -> (Pat, Pat) {
         LitKind::Str(_, StrStyle::Cooked) => (Pat::Str("\""), Pat::Str("\"")),
         LitKind::Str(_, StrStyle::Raw(0)) => (Pat::Str("r"), Pat::Str("\"")),
         LitKind::Str(_, StrStyle::Raw(_)) => (Pat::Str("r#"), Pat::Str("#")),
-        LitKind::ByteStr(_) => (Pat::Str("b\""), Pat::Str("\"")),
+        LitKind::ByteStr(_, StrStyle::Cooked) => (Pat::Str("b\""), Pat::Str("\"")),
+        LitKind::ByteStr(_, StrStyle::Raw(0)) => (Pat::Str("br\""), Pat::Str("\"")),
+        LitKind::ByteStr(_, StrStyle::Raw(_)) => (Pat::Str("br#\""), Pat::Str("#")),
         LitKind::Byte(_) => (Pat::Str("b'"), Pat::Str("'")),
         LitKind::Char(_) => (Pat::Str("'"), Pat::Str("'")),
         LitKind::Int(_, LitIntType::Signed(IntTy::Isize)) => (Pat::Num, Pat::Str("isize")),
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 315aea9aa09..7a637d32bab 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -210,7 +210,7 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
     match *lit {
         LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
         LitKind::Byte(b) => Constant::Int(u128::from(b)),
-        LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)),
+        LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
         LitKind::Char(c) => Constant::Char(c),
         LitKind::Int(n, _) => Constant::Int(n),
         LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 90192f46cbf..652f8b4d3c5 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -97,7 +97,7 @@ use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::ty as rustc_ty;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::binding::BindingMode;
-use rustc_middle::ty::fast_reject::SimplifiedTypeGen::{
+use rustc_middle::ty::fast_reject::SimplifiedType::{
     ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType,
     PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
 };
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index e053a9dc888..8bf542ada04 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -82,7 +82,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
             ty::Ref(_, _, hir::Mutability::Mut) => {
                 return Err((span, "mutable references in const fn are unstable".into()));
             },
-            ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
+            ty::Alias(ty::Opaque, ..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
             ty::FnPtr(..) => {
                 return Err((span, "function pointers in const fn are unstable".into()));
             },
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index bfb2d472a39..a6bcb134d40 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -17,7 +17,7 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::{
     self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate, PredicateKind,
-    ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
+    AliasTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
     VariantDef, VariantDiscr,
 };
 use rustc_middle::ty::{GenericArg, GenericArgKind};
@@ -79,7 +79,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
                 return true;
             }
 
-            if let ty::Opaque(def_id, _) = *inner_ty.kind() {
+            if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *inner_ty.kind() {
                 for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
                     match predicate.kind().skip_binder() {
                         // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
@@ -250,7 +250,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
             is_must_use_ty(cx, *ty)
         },
         ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
-        ty::Opaque(def_id, _) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
             for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
                 if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() {
                     if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
@@ -631,7 +631,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
             Some(ExprFnSig::Closure(decl, subs.as_closure().sig()))
         },
         ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))),
-        ty::Opaque(id, _) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(id), cx.tcx.opt_parent(id)),
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(def_id), cx.tcx.opt_parent(def_id)),
         ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
         ty::Dynamic(bounds, _, _) => {
             let lang_items = cx.tcx.lang_items();
@@ -650,7 +650,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
                 _ => None,
             }
         },
-        ty::Projection(proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
+        ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
             Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty),
             _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)),
         },
@@ -685,7 +685,7 @@ fn sig_from_bounds<'tcx>(
                 inputs = Some(i);
             },
             PredicateKind::Clause(ty::Clause::Projection(p))
-                if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output()
+                if Some(p.projection_ty.def_id) == lang_items.fn_once_output()
                     && p.projection_ty.self_ty() == ty =>
             {
                 if output.is_some() {
@@ -701,14 +701,14 @@ fn sig_from_bounds<'tcx>(
     inputs.map(|ty| ExprFnSig::Trait(ty, output, predicates_id))
 }
 
-fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
+fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
     let mut inputs = None;
     let mut output = None;
     let lang_items = cx.tcx.lang_items();
 
     for (pred, _) in cx
         .tcx
-        .bound_explicit_item_bounds(ty.item_def_id)
+        .bound_explicit_item_bounds(ty.def_id)
         .subst_iter_copied(cx.tcx, ty.substs)
     {
         match pred.kind().skip_binder() {
@@ -726,7 +726,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
                 inputs = Some(i);
             },
             PredicateKind::Clause(ty::Clause::Projection(p))
-                if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() =>
+                if Some(p.projection_ty.def_id) == lang_items.fn_once_output() =>
             {
                 if output.is_some() {
                     // Multiple different fn trait impls. Is this even allowed?
@@ -980,13 +980,13 @@ pub fn make_projection<'tcx>(
     container_id: DefId,
     assoc_ty: Symbol,
     substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
-) -> Option<ProjectionTy<'tcx>> {
+) -> Option<AliasTy<'tcx>> {
     fn helper<'tcx>(
         tcx: TyCtxt<'tcx>,
         container_id: DefId,
         assoc_ty: Symbol,
         substs: SubstsRef<'tcx>,
-    ) -> Option<ProjectionTy<'tcx>> {
+    ) -> Option<AliasTy<'tcx>> {
         let Some(assoc_item) = tcx
             .associated_items(container_id)
             .find_by_name_and_kind(tcx, Ident::with_dummy_span(assoc_ty), AssocKind::Type, container_id)
@@ -1039,10 +1039,10 @@ pub fn make_projection<'tcx>(
             }
         }
 
-        Some(ProjectionTy {
+        Some(tcx.mk_alias_ty(
+            assoc_item.def_id,
             substs,
-            item_def_id: assoc_item.def_id,
-        })
+        ))
     }
     helper(
         tcx,
@@ -1065,7 +1065,7 @@ pub fn make_normalized_projection<'tcx>(
     assoc_ty: Symbol,
     substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
 ) -> Option<Ty<'tcx>> {
-    fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: ProjectionTy<'tcx>) -> Option<Ty<'tcx>> {
+    fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
         #[cfg(debug_assertions)]
         if let Some((i, subst)) = ty
             .substs
@@ -1081,7 +1081,7 @@ pub fn make_normalized_projection<'tcx>(
             );
             return None;
         }
-        match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.item_def_id, ty.substs)) {
+        match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.def_id, ty.substs)) {
             Ok(ty) => Some(ty),
             Err(e) => {
                 debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 1542b1c17ad..72a43108dc4 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1924,7 +1924,15 @@ impl<'test> TestCx<'test> {
                     rustc.args(&["--json", "future-incompat"]);
                 }
                 rustc.arg("-Ccodegen-units=1");
+                // Hide line numbers to reduce churn
                 rustc.arg("-Zui-testing");
+                // Hide libstd sources from ui tests to make sure we generate the stderr
+                // output that users will see.
+                // Without this, we may be producing good diagnostics in-tree but users
+                // will not see half the information.
+                rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX");
+                rustc.arg("-Ztranslate-remapped-path-to-local-path=no");
+
                 rustc.arg("-Zdeduplicate-diagnostics=no");
                 // FIXME: use this for other modes too, for perf?
                 rustc.arg("-Cstrip=debuginfo");
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index a7a61a1f44c..32ae3fad570 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -22,8 +22,9 @@ use rustc_middle::{
 };
 use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::Symbol;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Size, Align};
 use rustc_target::spec::abi::Abi;
+use rustc_const_eval::const_eval::CheckAlignment;
 
 use crate::{
     concurrency::{data_race, weak_memory},
@@ -781,8 +782,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     const PANIC_ON_ALLOC_FAIL: bool = false;
 
     #[inline(always)]
-    fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
-        ecx.machine.check_alignment != AlignmentCheck::None
+    fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> CheckAlignment {
+        if ecx.machine.check_alignment == AlignmentCheck::None {
+            CheckAlignment::No
+        } else {
+            CheckAlignment::Error
+        }
     }
 
     #[inline(always)]
@@ -790,6 +795,15 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx.machine.check_alignment == AlignmentCheck::Int
     }
 
+    fn alignment_check_failed(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        has: Align,
+        required: Align,
+        _check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()> {
+        throw_ub!(AlignmentCheckFailed { has, required })
+    }
+
     #[inline(always)]
     fn enforce_validity(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
         ecx.machine.validate
diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs
index 2ac703b957b..c503eeeb9b3 100644
--- a/src/tools/rustfmt/src/attr.rs
+++ b/src/tools/rustfmt/src/attr.rs
@@ -260,7 +260,9 @@ impl Rewrite for ast::NestedMetaItem {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         match self {
             ast::NestedMetaItem::MetaItem(ref meta_item) => meta_item.rewrite(context, shape),
-            ast::NestedMetaItem::Lit(ref l) => rewrite_literal(context, l.token_lit, l.span, shape),
+            ast::NestedMetaItem::Lit(ref l) => {
+                rewrite_literal(context, l.as_token_lit(), l.span, shape)
+            }
         }
     }
 }
@@ -308,18 +310,18 @@ impl Rewrite for ast::MetaItem {
                     }),
                 )?
             }
-            ast::MetaItemKind::NameValue(ref literal) => {
+            ast::MetaItemKind::NameValue(ref lit) => {
                 let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?;
                 // 3 = ` = `
                 let lit_shape = shape.shrink_left(path.len() + 3)?;
-                // `rewrite_literal` returns `None` when `literal` exceeds max
+                // `rewrite_literal` returns `None` when `lit` exceeds max
                 // width. Since a literal is basically unformattable unless it
                 // is a string literal (and only if `format_strings` is set),
                 // we might be better off ignoring the fact that the attribute
                 // is longer than the max width and continue on formatting.
                 // See #2479 for example.
-                let value = rewrite_literal(context, literal.token_lit, literal.span, lit_shape)
-                    .unwrap_or_else(|| context.snippet(literal.span).to_owned());
+                let value = rewrite_literal(context, lit.as_token_lit(), lit.span, lit_shape)
+                    .unwrap_or_else(|| context.snippet(lit.span).to_owned());
                 format!("{} = {}", path, value)
             }
         })
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 7ee8c5d3bad..75454cbdc5f 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -57,6 +57,7 @@ const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
     ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"),
+    ("cranelift-egraph", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-entity", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-frontend", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-isle", "Apache-2.0 WITH LLVM-exception"),
@@ -67,6 +68,7 @@ const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
     ("mach", "BSD-2-Clause"),
     ("regalloc2", "Apache-2.0 WITH LLVM-exception"),
     ("target-lexicon", "Apache-2.0 WITH LLVM-exception"),
+    ("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"),
 ];
 
 const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
@@ -291,6 +293,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     "cranelift-codegen",
     "cranelift-codegen-meta",
     "cranelift-codegen-shared",
+    "cranelift-egraph",
     "cranelift-entity",
     "cranelift-frontend",
     "cranelift-isle",
@@ -299,6 +302,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     "cranelift-native",
     "cranelift-object",
     "crc32fast",
+    "fallible-iterator",
     "fxhash",
     "getrandom",
     "gimli",
@@ -315,9 +319,11 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     "region",
     "slice-group-by",
     "smallvec",
+    "stable_deref_trait",
     "target-lexicon",
     "version_check",
     "wasi",
+    "wasmtime-jit-icache-coherence",
     "winapi",
     "winapi-i686-pc-windows-gnu",
     "winapi-x86_64-pc-windows-gnu",
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index ee326e190ff..19e2528bb24 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -10,7 +10,7 @@ use std::path::Path;
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 939;
-const ISSUES_ENTRY_LIMIT: usize = 2070;
+const ISSUES_ENTRY_LIMIT: usize = 2040;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     for dir in Walk::new(&path.join("test/ui")) {
diff --git a/triagebot.toml b/triagebot.toml
index 49945e5c533..46a3bab42a1 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -467,8 +467,8 @@ compiler-team-contributors = [
     "@compiler-errors",
     "@eholk",
     "@jackh726",
-    "@fee1-dead",
     "@TaKO8Ki",
+    "@Nilstrieb",
 ]
 compiler = [
     "compiler-team",