about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml33
-rw-r--r--Cargo.lock2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0118.md27
-rw-r--r--compiler/rustc_graphviz/src/lib.rs17
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs73
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs27
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs40
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs19
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs11
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs1
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs1
-rw-r--r--compiler/rustc_middle/src/mir/abstract_const.rs20
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs5
-rw-r--r--compiler/rustc_middle/src/query/mod.rs29
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs20
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs66
-rw-r--r--compiler/rustc_middle/src/ty/outlives.rs33
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs30
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs16
-rw-r--r--compiler/rustc_middle/src/ty/query/keys.rs16
-rw-r--r--compiler/rustc_middle/src/ty/query/on_disk_cache.rs6
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs15
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs20
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs80
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_mir/src/const_eval/machine.rs71
-rw-r--r--compiler/rustc_mir/src/dataflow/framework/engine.rs3
-rw-r--r--compiler/rustc_mir/src/dataflow/framework/graphviz.rs2
-rw-r--r--compiler/rustc_mir/src/interpret/intrinsics.rs43
-rw-r--r--compiler/rustc_mir/src/monomorphize/collector.rs47
-rw-r--r--compiler/rustc_mir/src/monomorphize/partitioning/default.rs32
-rw-r--r--compiler/rustc_mir/src/monomorphize/partitioning/merging.rs15
-rw-r--r--compiler/rustc_mir/src/monomorphize/partitioning/mod.rs25
-rw-r--r--compiler/rustc_mir/src/transform/instcombine.rs2
-rw-r--r--compiler/rustc_mir/src/transform/mod.rs6
-rw-r--r--compiler/rustc_mir/src/transform/simplify_try.rs11
-rw-r--r--compiler/rustc_mir/src/util/graphviz.rs6
-rw-r--r--compiler/rustc_privacy/src/lib.rs9
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs16
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/lib.rs14
-rw-r--r--compiler/rustc_session/src/config.rs4
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs378
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs15
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs20
-rw-r--r--compiler/rustc_typeck/src/check/_match.rs2
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs3
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs3
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls.rs25
-rw-r--r--compiler/rustc_typeck/src/collect.rs12
-rw-r--r--config.toml.example17
-rw-r--r--library/alloc/src/collections/binary_heap.rs4
-rw-r--r--library/alloc/src/collections/btree/node.rs45
-rw-r--r--library/alloc/src/collections/vec_deque.rs6
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/slice.rs4
-rw-r--r--library/alloc/src/string.rs3
-rw-r--r--library/alloc/src/vec.rs7
-rw-r--r--library/alloc/tests/str.rs21
-rw-r--r--library/alloc/tests/vec.rs2
-rw-r--r--library/core/src/future/mod.rs4
-rw-r--r--library/core/src/future/pending.rs12
-rw-r--r--library/core/src/future/ready.rs8
-rw-r--r--library/core/src/hint.rs5
-rw-r--r--library/core/src/iter/adapters/flatten.rs7
-rw-r--r--library/core/src/iter/adapters/fuse.rs7
-rw-r--r--library/core/src/mem/mod.rs57
-rw-r--r--library/core/src/num/dec2flt/algorithm.rs20
-rw-r--r--library/core/src/num/dec2flt/mod.rs10
-rw-r--r--library/core/src/num/mod.rs20
-rw-r--r--library/core/src/slice/index.rs75
-rw-r--r--library/core/src/slice/iter.rs100
-rw-r--r--library/core/src/slice/mod.rs118
-rw-r--r--library/core/src/task/poll.rs8
-rw-r--r--library/core/src/time.rs18
-rw-r--r--library/core/tests/lib.rs4
-rw-r--r--library/core/tests/num/i32.rs29
-rw-r--r--library/core/tests/slice.rs49
-rw-r--r--library/core/tests/time.rs101
-rw-r--r--library/std/src/future.rs2
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sys/unix/process/process_fuchsia.rs3
-rw-r--r--library/std/src/sys/unix/process/zircon.rs1
-rw-r--r--library/std/src/sys/windows/mutex.rs84
-rw-r--r--library/std/src/thread/local.rs5
-rw-r--r--src/bootstrap/README.md38
-rw-r--r--src/bootstrap/builder.rs43
-rw-r--r--src/bootstrap/builder/tests.rs14
-rw-r--r--src/bootstrap/config.rs124
-rw-r--r--src/bootstrap/doc.rs4
-rw-r--r--src/bootstrap/format.rs8
-rw-r--r--src/bootstrap/sanity.rs4
-rw-r--r--src/bootstrap/test.rs8
-rw-r--r--src/ci/azure-pipelines/auto.yml2
-rw-r--r--src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile13
-rw-r--r--src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config17
-rw-r--r--src/ci/docker/host-x86_64/dist-various-1/Dockerfile6
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-git.sh15
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-headers.sh16
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-perl.sh21
-rw-r--r--src/ci/github-actions/ci.yml40
m---------src/doc/book0
m---------src/doc/nomicon0
m---------src/doc/reference0
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/unstable-book/src/library-features/asm.md19
-rw-r--r--src/doc/unstable-book/src/library-features/llvm-asm.md6
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/lib.rs12
-rw-r--r--src/librustdoc/passes/doc_test_lints.rs16
-rw-r--r--src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.32bit.mir (renamed from src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.32bit)0
-rw-r--r--src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir (renamed from src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.64bit)0
-rw-r--r--src/test/mir-opt/combine_array_len.norm2.InstCombine.32bit.diff (renamed from src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.32bit)0
-rw-r--r--src/test/mir-opt/combine_array_len.norm2.InstCombine.64bit.diff (renamed from src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.64bit)0
-rw-r--r--src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir (renamed from src/test/mir-opt/const_allocation.main.ConstProp.after.mir.32bit)0
-rw-r--r--src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir (renamed from src/test/mir-opt/const_allocation.main.ConstProp.after.mir.64bit)0
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir (renamed from src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit)0
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir (renamed from src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit)0
-rw-r--r--src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir (renamed from src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.32bit)0
-rw-r--r--src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir (renamed from src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.64bit)0
-rw-r--r--src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff (renamed from src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.32bit)0
-rw-r--r--src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff (renamed from src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.64bit)0
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff (renamed from src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.32bit)0
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff (renamed from src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.64bit)0
-rw-r--r--src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff (renamed from src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit)0
-rw-r--r--src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff (renamed from src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit)0
-rw-r--r--src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff (renamed from src/test/mir-opt/const_prop/large_array_index.main.ConstProp.diff.32bit)0
-rw-r--r--src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff (renamed from src/test/mir-opt/const_prop/large_array_index.main.ConstProp.diff.64bit)0
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff (renamed from src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit)0
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff (renamed from src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit)0
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir (renamed from src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.32bit)0
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir (renamed from src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.64bit)0
-rw-r--r--src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff (renamed from src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.32bit)0
-rw-r--r--src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff (renamed from src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.64bit)0
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff (renamed from src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.32bit)0
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff (renamed from src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.64bit)0
-rw-r--r--src/test/mir-opt/graphviz.main.mir_map.0.dot.mir10
-rw-r--r--src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff (renamed from src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.32bit)0
-rw-r--r--src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff (renamed from src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.64bit)0
-rw-r--r--src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.32bit.mir (renamed from src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.mir.32bit)0
-rw-r--r--src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.64bit.mir (renamed from src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.mir.64bit)0
-rw-r--r--src/test/mir-opt/issue_72181.bar.mir_map.0.32bit.mir (renamed from src/test/mir-opt/issue_72181.bar.mir_map.0.mir.32bit)0
-rw-r--r--src/test/mir-opt/issue_72181.bar.mir_map.0.64bit.mir (renamed from src/test/mir-opt/issue_72181.bar.mir_map.0.mir.64bit)0
-rw-r--r--src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir (renamed from src/test/mir-opt/issue_72181.foo.mir_map.0.mir.32bit)0
-rw-r--r--src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir (renamed from src/test/mir-opt/issue_72181.foo.mir_map.0.mir.64bit)0
-rw-r--r--src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir (renamed from src/test/mir-opt/issue_72181.main.mir_map.0.mir.32bit)0
-rw-r--r--src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir (renamed from src/test/mir-opt/issue_72181.main.mir_map.0.mir.64bit)0
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff (renamed from src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit)0
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff (renamed from src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit)0
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff (renamed from src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit)0
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff (renamed from src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit)0
-rw-r--r--src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff (renamed from src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit)0
-rw-r--r--src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff (renamed from src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit)0
-rw-r--r--src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff (renamed from src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit)0
-rw-r--r--src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff (renamed from src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit)0
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff (renamed from src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit)0
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff (renamed from src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit)0
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff (renamed from src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit)0
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff (renamed from src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit)0
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir (renamed from src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.32bit)0
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir (renamed from src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.64bit)0
-rw-r--r--src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.32bit.mir (renamed from src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.32bit)0
-rw-r--r--src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.64bit.mir (renamed from src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.64bit)0
-rw-r--r--src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir (renamed from src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.32bit)0
-rw-r--r--src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir (renamed from src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.64bit)0
-rw-r--r--src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff27
-rw-r--r--src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff (renamed from src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit)0
-rw-r--r--src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff (renamed from src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit)0
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff (renamed from src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit)0
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff (renamed from src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit)0
-rw-r--r--src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.32bit.mir (renamed from src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir.32bit)0
-rw-r--r--src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.64bit.mir (renamed from src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir.64bit)0
-rw-r--r--src/test/mir-opt/spanview_block.main.mir_map.0.html.mir67
-rw-r--r--src/test/mir-opt/spanview_statement.main.mir_map.0.html.mir67
-rw-r--r--src/test/mir-opt/spanview_terminator.main.mir_map.0.html.mir66
-rw-r--r--src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.32bit.mir (renamed from src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.32bit)0
-rw-r--r--src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.64bit.mir (renamed from src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.64bit)0
-rw-r--r--src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.32bit.mir (renamed from src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.32bit)0
-rw-r--r--src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.64bit.mir (renamed from src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.64bit)0
-rw-r--r--src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir (renamed from src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir.32bit)0
-rw-r--r--src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir (renamed from src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir.64bit)0
-rw-r--r--src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir (renamed from src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.32bit)0
-rw-r--r--src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir (renamed from src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.64bit)0
-rw-r--r--src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff (renamed from src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.32bit)0
-rw-r--r--src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff (renamed from src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.64bit)0
-rw-r--r--src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.32bit.mir (renamed from src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.32bit)0
-rw-r--r--src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir (renamed from src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.64bit)0
-rw-r--r--src/test/rustdoc-ui/coverage/doc-examples.stdout4
-rw-r--r--src/test/rustdoc-ui/private-doc-test.rs12
-rw-r--r--src/test/ui/closures/issue-72408-nested-closures-exponential.rs59
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/auxiliary/const_evaluatable_lib.rs9
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/cross_crate.rs15
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs13
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr36
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/fn_call.rs30
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/less_than.rs14
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs15
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr18
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr16
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/simple.rs7
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/unop.rs14
-rw-r--r--src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr (renamed from src/test/ui/const-generics/cannot-infer-const-args.full.stderr)2
-rw-r--r--src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr (renamed from src/test/ui/const-generics/cannot-infer-const-args.min.stderr)2
-rw-r--r--src/test/ui/const-generics/infer/cannot-infer-const-args.rs (renamed from src/test/ui/const-generics/cannot-infer-const-args.rs)0
-rw-r--r--src/test/ui/const-generics/infer/method-chain.full.stderr11
-rw-r--r--src/test/ui/const-generics/infer/method-chain.min.stderr11
-rw-r--r--src/test/ui/const-generics/infer/method-chain.rs22
-rw-r--r--src/test/ui/const-generics/infer/uninferred-consts.full.stderr (renamed from src/test/ui/const-generics/uninferred-consts.full.stderr)6
-rw-r--r--src/test/ui/const-generics/infer/uninferred-consts.min.stderr (renamed from src/test/ui/const-generics/uninferred-consts.min.stderr)6
-rw-r--r--src/test/ui/const-generics/infer/uninferred-consts.rs (renamed from src/test/ui/const-generics/uninferred-consts.rs)0
-rw-r--r--src/test/ui/const-generics/issues/issue-64494.min.stderr4
-rw-r--r--src/test/ui/const-generics/issues/issue-67739.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr18
-rw-r--r--src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr18
-rw-r--r--src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs18
-rw-r--r--src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr2
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr2
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-61936.rs12
-rw-r--r--src/test/ui/consts/duration-consts-2.rs67
-rw-r--r--src/test/ui/error-codes/E0118-2.rs8
-rw-r--r--src/test/ui/error-codes/E0118-2.stderr12
-rw-r--r--src/test/ui/error-codes/E0118.stderr4
-rw-r--r--src/test/ui/infinite/infinite-instantiation.stderr2
-rw-r--r--src/test/ui/issues/issue-22638.rs2
-rw-r--r--src/test/ui/issues/issue-22638.stderr12
-rw-r--r--src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs4
-rw-r--r--src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr10
-rw-r--r--src/test/ui/issues/issue-67552.stderr2
-rw-r--r--src/test/ui/issues/issue-8727.stderr2
-rw-r--r--src/test/ui/mir/issue-76803-branches-not-same.rs19
-rw-r--r--src/test/ui/numbers-arithmetic/arith-0.rs8
-rw-r--r--src/test/ui/numbers-arithmetic/arith-1.rs24
-rw-r--r--src/test/ui/numbers-arithmetic/arith-2.rs9
-rw-r--r--src/test/ui/privacy/private-in-public-ill-formed.rs6
-rw-r--r--src/test/ui/privacy/private-in-public-ill-formed.stderr10
-rw-r--r--src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr2
-rw-r--r--src/test/ui/recursion/recursion.stderr2
-rw-r--r--src/test/ui/str-multiline.rs13
-rw-r--r--src/test/ui/string-escapes.rs7
-rw-r--r--src/test/ui/trait-impl-bound-suggestions.fixed20
-rw-r--r--src/test/ui/trait-impl-bound-suggestions.rs20
-rw-r--r--src/test/ui/trait-impl-bound-suggestions.stderr17
-rw-r--r--src/test/ui/type/type-check-defaults.stderr4
-rw-r--r--src/test/ui/type_length_limit.rs2
-rw-r--r--src/test/ui/type_length_limit.stderr4
-rw-r--r--src/tools/build-manifest/src/main.rs1
-rw-r--r--src/tools/compiletest/src/runtest.rs9
-rw-r--r--src/tools/lint-docs/src/lib.rs5
m---------src/tools/rust-analyzer49
261 files changed, 2708 insertions, 993 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 50ae8c313d6..490258f9c09 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -378,36 +378,7 @@ jobs:
           - name: dist-x86_64-apple
             env:
               SCRIPT: "./x.py dist"
-              RUST_CONFIGURE_ARGS: "--host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            os: macos-latest
-          - name: dist-x86_64-apple-alt
-            env:
-              SCRIPT: "./x.py dist"
-              RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-            os: macos-latest
-          - name: x86_64-apple
-            env:
-              SCRIPT: "./x.py --stage 2 test"
-              RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.8
-              MACOSX_STD_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-            os: macos-latest
-          - name: dist-x86_64-apple
-            env:
-              SCRIPT: "./x.py dist"
-              RUST_CONFIGURE_ARGS: "--host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
+              RUST_CONFIGURE_ARGS: "--host=x86_64-apple-darwin --target=x86_64-apple-darwin,aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
               RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
               MACOSX_DEPLOYMENT_TARGET: 10.7
               NO_LLVM_ASSERTIONS: 1
@@ -508,7 +479,7 @@ jobs:
             os: windows-latest-xl
           - name: dist-i686-msvc
             env:
-              RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i586-pc-windows-msvc --enable-full-tools --enable-profiler"
+              RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler"
               SCRIPT: python x.py dist
               DIST_REQUIRE_ALL_TOOLS: 1
             os: windows-latest-xl
diff --git a/Cargo.lock b/Cargo.lock
index d3f777bc663..7b9edca3cec 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3605,6 +3605,7 @@ dependencies = [
 name = "rustc_infer"
 version = "0.0.0"
 dependencies = [
+ "arrayvec",
  "rustc_ast",
  "rustc_data_structures",
  "rustc_errors",
@@ -3744,6 +3745,7 @@ dependencies = [
 name = "rustc_middle"
 version = "0.0.0"
 dependencies = [
+ "arrayvec",
  "bitflags",
  "chalk-ir",
  "measureme",
diff --git a/compiler/rustc_error_codes/src/error_codes/E0118.md b/compiler/rustc_error_codes/src/error_codes/E0118.md
index 5cb5f506e0a..345ec341c3f 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0118.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0118.md
@@ -1,10 +1,10 @@
-An inherent implementation was defined for something which isn't a struct nor
-an enum.
+An inherent implementation was defined for something which isn't a struct,
+enum, union, or trait object.
 
 Erroneous code example:
 
 ```compile_fail,E0118
-impl (u8, u8) { // error: no base type found for inherent implementation
+impl (u8, u8) { // error: no nominal type found for inherent implementation
     fn get_state(&self) -> String {
         // ...
     }
@@ -41,3 +41,24 @@ impl TypeWrapper {
     }
 }
 ```
+
+Instead of defining an inherent implementation on a reference, you could also
+move the reference inside the implementation:
+
+```compile_fail,E0118
+struct Foo;
+
+impl &Foo { // error: no nominal type found for inherent implementation
+    fn bar(self, other: Self) {}
+}
+```
+
+becomes
+
+```
+struct Foo;
+
+impl Foo {
+    fn bar(&self, other: &Self) {}
+}
+```
diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs
index 29ec3572016..58db81bc1dc 100644
--- a/compiler/rustc_graphviz/src/lib.rs
+++ b/compiler/rustc_graphviz/src/lib.rs
@@ -591,14 +591,14 @@ pub trait GraphWalk<'a> {
     fn target(&'a self, edge: &Self::Edge) -> Self::Node;
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 pub enum RenderOption {
     NoEdgeLabels,
     NoNodeLabels,
     NoEdgeStyles,
     NoNodeStyles,
 
-    Monospace,
+    Fontname(String),
     DarkTheme,
 }
 
@@ -633,11 +633,14 @@ where
     // Global graph properties
     let mut graph_attrs = Vec::new();
     let mut content_attrs = Vec::new();
-    if options.contains(&RenderOption::Monospace) {
-        let font = r#"fontname="Courier, monospace""#;
-        graph_attrs.push(font);
-        content_attrs.push(font);
-    };
+    let font;
+    if let Some(fontname) = options.iter().find_map(|option| {
+        if let RenderOption::Fontname(fontname) = option { Some(fontname) } else { None }
+    }) {
+        font = format!(r#"fontname="{}""#, fontname);
+        graph_attrs.push(&font[..]);
+        content_attrs.push(&font[..]);
+    }
     if options.contains(&RenderOption::DarkTheme) {
         graph_attrs.push(r#"bgcolor="black""#);
         content_attrs.push(r#"color="white""#);
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 5dba4106c94..a8c1a370cef 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -21,4 +21,5 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+arrayvec = { version = "0.5.1", default-features = false }
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index ae4612a89f2..5bd6c667fd7 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -31,6 +31,9 @@ use super::unify_key::replace_if_possible;
 use super::unify_key::{ConstVarValue, ConstVariableValue};
 use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use super::{InferCtxt, MiscVariable, TypeTrace};
+use arrayvec::ArrayVec;
+use rustc_data_structures::fx::FxHashMap;
+use std::hash::Hash;
 
 use crate::traits::{Obligation, PredicateObligations};
 
@@ -44,6 +47,63 @@ use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{IntType, UintType};
 use rustc_span::DUMMY_SP;
 
+/// Small-storage-optimized implementation of a map
+/// made specifically for caching results.
+///
+/// Stores elements in a small array up to a certain length
+/// and switches to `HashMap` when that length is exceeded.
+enum MiniMap<K, V> {
+    Array(ArrayVec<[(K, V); 8]>),
+    Map(FxHashMap<K, V>),
+}
+
+impl<K: Eq + Hash, V> MiniMap<K, V> {
+    /// Creates an empty `MiniMap`.
+    pub fn new() -> Self {
+        MiniMap::Array(ArrayVec::new())
+    }
+
+    /// Inserts or updates value in the map.
+    pub fn insert(&mut self, key: K, value: V) {
+        match self {
+            MiniMap::Array(array) => {
+                for pair in array.iter_mut() {
+                    if pair.0 == key {
+                        pair.1 = value;
+                        return;
+                    }
+                }
+                if let Err(error) = array.try_push((key, value)) {
+                    let mut map: FxHashMap<K, V> = array.drain(..).collect();
+                    let (key, value) = error.element();
+                    map.insert(key, value);
+                    *self = MiniMap::Map(map);
+                }
+            }
+            MiniMap::Map(map) => {
+                map.insert(key, value);
+            }
+        }
+    }
+
+    /// Return value by key if any.
+    pub fn get(&self, key: &K) -> Option<&V> {
+        match self {
+            MiniMap::Array(array) => {
+                for pair in array {
+                    if pair.0 == *key {
+                        return Some(&pair.1);
+                    }
+                }
+                return None;
+            }
+            MiniMap::Map(map) => {
+                return map.get(key);
+            }
+        }
+    }
+}
+
 #[derive(Clone)]
 pub struct CombineFields<'infcx, 'tcx> {
     pub infcx: &'infcx InferCtxt<'infcx, 'tcx>,
@@ -379,6 +439,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
             needs_wf: false,
             root_ty: ty,
             param_env: self.param_env,
+            cache: MiniMap::new(),
         };
 
         let ty = match generalize.relate(ty, ty) {
@@ -438,6 +499,8 @@ struct Generalizer<'cx, 'tcx> {
     root_ty: Ty<'tcx>,
 
     param_env: ty::ParamEnv<'tcx>,
+
+    cache: MiniMap<Ty<'tcx>, RelateResult<'tcx, Ty<'tcx>>>,
 }
 
 /// Result from a generalization operation. This includes
@@ -535,13 +598,16 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
 
+        if let Some(result) = self.cache.get(&t) {
+            return result.clone();
+        }
         debug!("generalize: t={:?}", t);
 
         // Check to see whether the type we are generalizing references
         // any other type variable related to `vid` via
         // subtyping. This is basically our "occurs check", preventing
         // us from creating infinitely sized types.
-        match *t.kind() {
+        let result = match *t.kind() {
             ty::Infer(ty::TyVar(vid)) => {
                 let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
                 let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid);
@@ -598,7 +664,10 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 Ok(t)
             }
             _ => relate::super_relate_tys(self, t, t),
-        }
+        };
+
+        self.cache.insert(t, result.clone());
+        return result;
     }
 
     fn regions(
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 4de84e5ba39..f87406c2ce4 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
@@ -6,9 +6,10 @@ use rustc_hir::def::{DefKind, Namespace};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
 use rustc_middle::hir::map::Map;
+use rustc_middle::infer::unify_key::ConstVariableOriginKind;
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, DefIdTree, Ty};
+use rustc_middle::ty::{self, DefIdTree, InferConst, Ty};
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
@@ -569,14 +570,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             local_visitor.visit_expr(expr);
         }
 
+        let mut param_name = None;
+        let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
+            let origin = self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
+            if let ConstVariableOriginKind::ConstParameterDefinition(param) = origin.kind {
+                param_name = Some(param);
+            }
+            origin.span
+        } else {
+            local_visitor.target_span
+        };
+
         let error_code = error_code.into();
-        let mut err = self.tcx.sess.struct_span_err_with_code(
-            local_visitor.target_span,
-            "type annotations needed",
-            error_code,
-        );
+        let mut err =
+            self.tcx.sess.struct_span_err_with_code(span, "type annotations needed", error_code);
 
-        err.note("unable to infer the value of a const parameter");
+        if let Some(param_name) = param_name {
+            err.note(&format!("cannot infer the value of the const parameter `{}`", param_name));
+        } else {
+            err.note("unable to infer the value of a const parameter");
+        }
 
         err
     }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 89142edb2dc..e3c613b1d6a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -85,7 +85,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
                 debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
                 if sub == &ty::ReStatic
-                    && v.0.into_iter().find(|t| t.span.desugaring_kind().is_none()).is_some()
+                    && v.0.into_iter().any(|t| t.span.desugaring_kind().is_none())
                 {
                     // If the failure is due to a `'static` requirement coming from a `dyn` or
                     // `impl` Trait that *isn't* caused by `async fn` desugaring, handle this case
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index d6f1ca3cf95..e06bfb59580 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -3,6 +3,7 @@ use crate::infer::{GenericKind, VerifyBound};
 use rustc_data_structures::captures::Captures;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
+use rustc_middle::ty::walk::MiniSet;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
 /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
@@ -31,16 +32,23 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     /// Returns a "verify bound" that encodes what we know about
     /// `generic` and the regions it outlives.
     pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
+        let mut visited = MiniSet::new();
         match generic {
             GenericKind::Param(param_ty) => self.param_bound(param_ty),
-            GenericKind::Projection(projection_ty) => self.projection_bound(projection_ty),
+            GenericKind::Projection(projection_ty) => {
+                self.projection_bound(projection_ty, &mut visited)
+            }
         }
     }
 
-    fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
+    fn type_bound(
+        &self,
+        ty: Ty<'tcx>,
+        visited: &mut MiniSet<GenericArg<'tcx>>,
+    ) -> VerifyBound<'tcx> {
         match *ty.kind() {
             ty::Param(p) => self.param_bound(p),
-            ty::Projection(data) => self.projection_bound(data),
+            ty::Projection(data) => self.projection_bound(data, visited),
             ty::FnDef(_, substs) => {
                 // HACK(eddyb) ignore lifetimes found shallowly in `substs`.
                 // This is inconsistent with `ty::Adt` (including all substs),
@@ -50,9 +58,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
                 let mut bounds = substs
                     .iter()
                     .filter_map(|child| match child.unpack() {
-                        GenericArgKind::Type(ty) => Some(self.type_bound(ty)),
+                        GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)),
                         GenericArgKind::Lifetime(_) => None,
-                        GenericArgKind::Const(_) => Some(self.recursive_bound(child)),
+                        GenericArgKind::Const(_) => Some(self.recursive_bound(child, visited)),
                     })
                     .filter(|bound| {
                         // Remove bounds that must hold, since they are not interesting.
@@ -66,7 +74,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
                     ),
                 }
             }
-            _ => self.recursive_bound(ty.into()),
+            _ => self.recursive_bound(ty.into(), visited),
         }
     }
 
@@ -137,7 +145,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         self.declared_projection_bounds_from_trait(projection_ty)
     }
 
-    pub fn projection_bound(&self, projection_ty: ty::ProjectionTy<'tcx>) -> VerifyBound<'tcx> {
+    pub fn projection_bound(
+        &self,
+        projection_ty: ty::ProjectionTy<'tcx>,
+        visited: &mut MiniSet<GenericArg<'tcx>>,
+    ) -> VerifyBound<'tcx> {
         debug!("projection_bound(projection_ty={:?})", projection_ty);
 
         let projection_ty_as_ty =
@@ -166,21 +178,25 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
 
         // see the extensive comment in projection_must_outlive
         let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
-        let recursive_bound = self.recursive_bound(ty.into());
+        let recursive_bound = self.recursive_bound(ty.into(), visited);
 
         VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound)
     }
 
-    fn recursive_bound(&self, parent: GenericArg<'tcx>) -> VerifyBound<'tcx> {
+    fn recursive_bound(
+        &self,
+        parent: GenericArg<'tcx>,
+        visited: &mut MiniSet<GenericArg<'tcx>>,
+    ) -> VerifyBound<'tcx> {
         let mut bounds = parent
-            .walk_shallow()
+            .walk_shallow(visited)
             .filter_map(|child| match child.unpack() {
-                GenericArgKind::Type(ty) => Some(self.type_bound(ty)),
+                GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)),
                 GenericArgKind::Lifetime(lt) => {
                     // Ignore late-bound regions.
                     if !lt.is_late_bound() { Some(VerifyBound::OutlivedBy(lt)) } else { None }
                 }
-                GenericArgKind::Const(_) => Some(self.recursive_bound(child)),
+                GenericArgKind::Const(_) => Some(self.recursive_bound(child, visited)),
             })
             .filter(|bound| {
                 // Remove bounds that must hold, since they are not interesting.
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index efdb7489ba5..5b5dbcf192c 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -961,7 +961,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
             continue;
         }
 
-        let span = sugared_span.take().unwrap_or_else(|| attr.span);
+        let span = sugared_span.take().unwrap_or(attr.span);
 
         if attr.is_doc_comment() || cx.sess().check_name(attr, sym::doc) {
             cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 3976475cb06..e76c2cb356f 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -170,7 +170,7 @@ impl Collector<'tcx> {
             feature_err(
                 &self.tcx.sess.parse_sess,
                 sym::static_nobundle,
-                span.unwrap_or_else(|| rustc_span::DUMMY_SP),
+                span.unwrap_or(rustc_span::DUMMY_SP),
                 "kind=\"static-nobundle\" is unstable",
             )
             .emit();
@@ -179,7 +179,7 @@ impl Collector<'tcx> {
             feature_err(
                 &self.tcx.sess.parse_sess,
                 sym::raw_dylib,
-                span.unwrap_or_else(|| rustc_span::DUMMY_SP),
+                span.unwrap_or(rustc_span::DUMMY_SP),
                 "kind=\"raw-dylib\" is unstable",
             )
             .emit();
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 43d76e9fdb4..a2e2cf1ca02 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -562,6 +562,12 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
     }
 }
 
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
+        ty::codec::RefDecodable::decode(d)
+    }
+}
+
 impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
         ty::codec::RefDecodable::decode(d)
@@ -1191,6 +1197,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, tcx))
     }
 
+    fn get_mir_abstract_const(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        id: DefIndex,
+    ) -> Option<&'tcx [mir::abstract_const::Node<'tcx>]> {
+        self.root
+            .tables
+            .mir_abstract_consts
+            .get(self, id)
+            .filter(|_| !self.is_proc_macro(id))
+            .map_or(None, |v| Some(v.decode((self, tcx))))
+    }
+
     fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet<u32> {
         self.root
             .tables
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 94abfac19c6..d4f577a7d1b 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -112,6 +112,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     }
     optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
     promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
+    mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) }
     unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
     mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
     fn_sig => { cdata.fn_sig(def_id.index, tcx) }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 1e313b7edfc..eb091d86b82 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -321,6 +321,12 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
     }
 }
 
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        (**self).encode(s)
+    }
+}
+
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
         (**self).encode(s)
@@ -1109,6 +1115,11 @@ impl EncodeContext<'a, 'tcx> {
             if !unused.is_empty() {
                 record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
             }
+
+            let abstract_const = self.tcx.mir_abstract_const(def_id);
+            if let Some(abstract_const) = abstract_const {
+                record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
+            }
         }
     }
 
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 1ba5962d119..ba540c94411 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -284,6 +284,7 @@ define_tables! {
     super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
     mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
+    mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
     unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
     // `def_keys` and `def_path_hashes` represent a lazy version of a
     // `DefPathTable`. This allows us to avoid deserializing an entire
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index a5a860a38b3..1d84ddad7f5 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -28,5 +28,6 @@ rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
 chalk-ir = "0.21.0"
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+arrayvec = { version = "0.5.1", default-features = false }
 measureme = "0.7.1"
 rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 2580ac6bebd..a60a17befef 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -124,6 +124,7 @@ pub struct ConstVariableOrigin {
 pub enum ConstVariableOriginKind {
     MiscVariable,
     ConstInference,
+    // FIXME(const_generics): Consider storing the `DefId` of the param here.
     ConstParameterDefinition(Symbol),
     SubstitutionPlaceholder,
 }
diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs
new file mode 100644
index 00000000000..b85f1e6e5de
--- /dev/null
+++ b/compiler/rustc_middle/src/mir/abstract_const.rs
@@ -0,0 +1,20 @@
+//! A subset of a mir body used for const evaluatability checking.
+use crate::mir;
+use crate::ty;
+
+rustc_index::newtype_index! {
+    /// An index into an `AbstractConst`.
+    pub struct NodeId {
+        derive [HashStable]
+        DEBUG_FORMAT = "n{}",
+    }
+}
+
+/// A node of an `AbstractConst`.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum Node<'tcx> {
+    Leaf(&'tcx ty::Const<'tcx>),
+    Binop(mir::BinOp, NodeId, NodeId),
+    UnaryOp(mir::UnOp, NodeId),
+    FunctionCall(NodeId, &'tcx [NodeId]),
+}
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index d32a7a4062e..be61b676807 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -40,6 +40,7 @@ use std::{iter, mem, option};
 use self::predecessors::{PredecessorCache, Predecessors};
 pub use self::query::*;
 
+pub mod abstract_const;
 pub mod coverage;
 pub mod interpret;
 pub mod mono;
@@ -2285,8 +2286,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
 /// Constants
 ///
 /// Two constants are equal if they are the same constant. Note that
-/// this does not necessarily mean that they are "==" in Rust -- in
-/// particular one must be wary of `NaN`!
+/// this does not necessarily mean that they are `==` in Rust -- in
+/// particular, one must be wary of `NaN`!
 
 #[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, HashStable)]
 pub struct Constant<'tcx> {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 15e3110bc85..44d906dada5 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -244,6 +244,35 @@ rustc_queries! {
             no_hash
         }
 
+        /// Try to build an abstract representation of the given constant.
+        query mir_abstract_const(
+            key: DefId
+        ) -> Option<&'tcx [mir::abstract_const::Node<'tcx>]> {
+            desc {
+                |tcx| "building an abstract representation for {}", tcx.def_path_str(key),
+            }
+        }
+        /// Try to build an abstract representation of the given constant.
+        query mir_abstract_const_of_const_arg(
+            key: (LocalDefId, DefId)
+        ) -> Option<&'tcx [mir::abstract_const::Node<'tcx>]> {
+            desc {
+                |tcx|
+                "building an abstract representation for the const argument {}",
+                tcx.def_path_str(key.0.to_def_id()),
+            }
+        }
+
+        query try_unify_abstract_consts(key: (
+            (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+            (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)
+        )) -> bool {
+            desc {
+                |tcx| "trying to unify the generic constants {} and {}",
+                tcx.def_path_str(key.0.0.did), tcx.def_path_str(key.1.0.did)
+            }
+        }
+
         query mir_drops_elaborated_and_const_checked(
             key: ty::WithOptConstParam<LocalDefId>
         ) -> &'tcx Steal<mir::Body<'tcx>> {
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index e2e5f08462f..8ea34f9161a 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -357,6 +357,26 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>,
     }
 }
 
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::Node<'tcx>] {
+    fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+        Ok(decoder.tcx().arena.alloc_from_iter(
+            (0..decoder.read_usize()?)
+                .map(|_| Decodable::decode(decoder))
+                .collect::<Result<Vec<_>, _>>()?,
+        ))
+    }
+}
+
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::NodeId] {
+    fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+        Ok(decoder.tcx().arena.alloc_from_iter(
+            (0..decoder.read_usize()?)
+                .map(|_| Decodable::decode(decoder))
+                .collect::<Result<Vec<_>, _>>()?,
+        ))
+    }
+}
+
 impl_decodable_via_ref! {
     &'tcx ty::TypeckResults<'tcx>,
     &'tcx ty::List<Ty<'tcx>>,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index aacf61e5b42..56746666e2f 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -66,8 +66,8 @@ use std::mem;
 use std::ops::{Bound, Deref};
 use std::sync::Arc;
 
-/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
-/// except through `tcx.err*()`, which are in this module.
+/// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s
+/// except through the error-reporting functions on a [`tcx`][TyCtxt].
 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
 #[derive(TyEncodable, TyDecodable, HashStable)]
 pub struct DelaySpanBugEmitted(());
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index bc51c8b6cd4..715319747e3 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -202,33 +202,59 @@ pub fn suggest_constraining_type_param(
         //    Suggestion:
         //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
         //                                          - insert: `, T: Zar`
+        //
+        // Additionally, there may be no `where` clause whatsoever in the case that this was
+        // reached because the generic parameter has a default:
+        //
+        //    Message:
+        //      trait Foo<T=()> {... }
+        //             - help: consider further restricting this type parameter with `where T: Zar`
+        //
+        //    Suggestion:
+        //      trait Foo<T=()> where T: Zar {... }
+        //                     - insert: `where T: Zar`
 
-        let mut param_spans = Vec::new();
+        if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
+            && generics.where_clause.predicates.len() == 0
+        {
+            // Suggest a bound, but there is no existing `where` clause *and* the type param has a
+            // default (`<T=Foo>`), so we suggest adding `where T: Bar`.
+            err.span_suggestion_verbose(
+                generics.where_clause.tail_span_for_suggestion(),
+                &msg_restrict_type_further,
+                format!(" where {}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            let mut param_spans = Vec::new();
 
-        for predicate in generics.where_clause.predicates {
-            if let WherePredicate::BoundPredicate(WhereBoundPredicate {
-                span, bounded_ty, ..
-            }) = predicate
-            {
-                if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
-                    if let Some(segment) = path.segments.first() {
-                        if segment.ident.to_string() == param_name {
-                            param_spans.push(span);
+            for predicate in generics.where_clause.predicates {
+                if let WherePredicate::BoundPredicate(WhereBoundPredicate {
+                    span,
+                    bounded_ty,
+                    ..
+                }) = predicate
+                {
+                    if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
+                        if let Some(segment) = path.segments.first() {
+                            if segment.ident.to_string() == param_name {
+                                param_spans.push(span);
+                            }
                         }
                     }
                 }
             }
-        }
 
-        match &param_spans[..] {
-            &[&param_span] => suggest_restrict(param_span.shrink_to_hi()),
-            _ => {
-                err.span_suggestion_verbose(
-                    generics.where_clause.tail_span_for_suggestion(),
-                    &msg_restrict_type_further,
-                    format!(", {}: {}", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
+            match &param_spans[..] {
+                &[&param_span] => suggest_restrict(param_span.shrink_to_hi()),
+                _ => {
+                    err.span_suggestion_verbose(
+                        generics.where_clause.tail_span_for_suggestion(),
+                        &msg_restrict_type_further,
+                        format!(", {}: {}", param_name, constraint),
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
         }
 
diff --git a/compiler/rustc_middle/src/ty/outlives.rs b/compiler/rustc_middle/src/ty/outlives.rs
index 783f116a87d..01649f44c88 100644
--- a/compiler/rustc_middle/src/ty/outlives.rs
+++ b/compiler/rustc_middle/src/ty/outlives.rs
@@ -3,6 +3,7 @@
 // RFC for reference.
 
 use crate::ty::subst::{GenericArg, GenericArgKind};
+use crate::ty::walk::MiniSet;
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use smallvec::SmallVec;
 
@@ -50,12 +51,18 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Push onto `out` all the things that must outlive `'a` for the condition
     /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
     pub fn push_outlives_components(self, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
-        compute_components(self, ty0, out);
+        let mut visited = MiniSet::new();
+        compute_components(self, ty0, out, &mut visited);
         debug!("components({:?}) = {:?}", ty0, out);
     }
 }
 
-fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
+fn compute_components(
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>,
+    out: &mut SmallVec<[Component<'tcx>; 4]>,
+    visited: &mut MiniSet<GenericArg<'tcx>>,
+) {
     // Descend through the types, looking for the various "base"
     // components and collecting them into `out`. This is not written
     // with `collect()` because of the need to sometimes skip subtrees
@@ -73,11 +80,11 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
                 for child in substs {
                     match child.unpack() {
                         GenericArgKind::Type(ty) => {
-                            compute_components(tcx, ty, out);
+                            compute_components(tcx, ty, out, visited);
                         }
                         GenericArgKind::Lifetime(_) => {}
                         GenericArgKind::Const(_) => {
-                            compute_components_recursive(tcx, child, out);
+                            compute_components_recursive(tcx, child, out, visited);
                         }
                     }
                 }
@@ -85,19 +92,19 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
 
             ty::Array(element, _) => {
                 // Don't look into the len const as it doesn't affect regions
-                compute_components(tcx, element, out);
+                compute_components(tcx, element, out, visited);
             }
 
             ty::Closure(_, ref substs) => {
                 for upvar_ty in substs.as_closure().upvar_tys() {
-                    compute_components(tcx, upvar_ty, out);
+                    compute_components(tcx, upvar_ty, out, visited);
                 }
             }
 
             ty::Generator(_, ref substs, _) => {
                 // Same as the closure case
                 for upvar_ty in substs.as_generator().upvar_tys() {
-                    compute_components(tcx, upvar_ty, out);
+                    compute_components(tcx, upvar_ty, out, visited);
                 }
 
                 // We ignore regions in the generator interior as we don't
@@ -135,7 +142,8 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
                     // OutlivesProjectionComponents.  Continue walking
                     // through and constrain Pi.
                     let mut subcomponents = smallvec![];
-                    compute_components_recursive(tcx, ty.into(), &mut subcomponents);
+                    let mut subvisited = MiniSet::new();
+                    compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
                     out.push(Component::EscapingProjection(subcomponents.into_iter().collect()));
                 }
             }
@@ -177,7 +185,7 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
                 // the "bound regions list".  In our representation, no such
                 // list is maintained explicitly, because bound regions
                 // themselves can be readily identified.
-                compute_components_recursive(tcx, ty.into(), out);
+                compute_components_recursive(tcx, ty.into(), out, visited);
             }
         }
 }
@@ -186,11 +194,12 @@ fn compute_components_recursive(
     tcx: TyCtxt<'tcx>,
     parent: GenericArg<'tcx>,
     out: &mut SmallVec<[Component<'tcx>; 4]>,
+    visited: &mut MiniSet<GenericArg<'tcx>>,
 ) {
-    for child in parent.walk_shallow() {
+    for child in parent.walk_shallow(visited) {
         match child.unpack() {
             GenericArgKind::Type(ty) => {
-                compute_components(tcx, ty, out);
+                compute_components(tcx, ty, out, visited);
             }
             GenericArgKind::Lifetime(lt) => {
                 // Ignore late-bound regions.
@@ -199,7 +208,7 @@ fn compute_components_recursive(
                 }
             }
             GenericArgKind::Const(_) => {
-                compute_components_recursive(tcx, child, out);
+                compute_components_recursive(tcx, child, out, visited);
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 709a4018d80..f315292dab5 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -4,6 +4,7 @@ use crate::ty::{self, DefIdTree, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
+use rustc_middle::ty::walk::MiniSet;
 
 // `pretty` is a separate module only for organization.
 mod pretty;
@@ -263,21 +264,33 @@ pub trait Printer<'tcx>: Sized {
 /// function tries to find a "characteristic `DefId`" for a
 /// type. It's just a heuristic so it makes some questionable
 /// decisions and we may want to adjust it later.
-pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
+///
+/// Visited set is needed to avoid full iteration over
+/// deeply nested tuples that have no DefId.
+fn characteristic_def_id_of_type_cached<'a>(
+    ty: Ty<'a>,
+    visited: &mut MiniSet<Ty<'a>>,
+) -> Option<DefId> {
     match *ty.kind() {
         ty::Adt(adt_def, _) => Some(adt_def.did),
 
         ty::Dynamic(data, ..) => data.principal_def_id(),
 
-        ty::Array(subty, _) | ty::Slice(subty) => characteristic_def_id_of_type(subty),
+        ty::Array(subty, _) | ty::Slice(subty) => {
+            characteristic_def_id_of_type_cached(subty, visited)
+        }
 
-        ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
+        ty::RawPtr(mt) => characteristic_def_id_of_type_cached(mt.ty, visited),
 
-        ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
+        ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited),
 
-        ty::Tuple(ref tys) => {
-            tys.iter().find_map(|ty| characteristic_def_id_of_type(ty.expect_ty()))
-        }
+        ty::Tuple(ref tys) => tys.iter().find_map(|ty| {
+            let ty = ty.expect_ty();
+            if visited.insert(ty) {
+                return characteristic_def_id_of_type_cached(ty, visited);
+            }
+            return None;
+        }),
 
         ty::FnDef(def_id, _)
         | ty::Closure(def_id, _)
@@ -302,6 +315,9 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
         | ty::Float(_) => None,
     }
 }
+pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
+    characteristic_def_id_of_type_cached(ty, &mut MiniSet::new())
+}
 
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::RegionKind {
     type Output = P::Region;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 9562d437914..f0bae48cc12 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -273,10 +273,10 @@ pub trait PrettyPrinter<'tcx>:
         }
 
         match self.tcx().trimmed_def_paths(LOCAL_CRATE).get(&def_id) {
-            None => return Ok((self, false)),
+            None => Ok((self, false)),
             Some(symbol) => {
                 self.write_str(&symbol.as_str())?;
-                return Ok((self, true));
+                Ok((self, true))
             }
         }
     }
@@ -1264,6 +1264,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
     used_region_names: FxHashSet<Symbol>,
     region_index: usize,
     binder_depth: usize,
+    printed_type_count: usize,
 
     pub region_highlight_mode: RegionHighlightMode,
 
@@ -1294,6 +1295,7 @@ impl<F> FmtPrinter<'a, 'tcx, F> {
             used_region_names: Default::default(),
             region_index: 0,
             binder_depth: 0,
+            printed_type_count: 0,
             region_highlight_mode: RegionHighlightMode::default(),
             name_resolver: None,
         }))
@@ -1411,8 +1413,14 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
         self.pretty_print_region(region)
     }
 
-    fn print_type(self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
-        self.pretty_print_type(ty)
+    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+        if self.tcx.sess.type_length_limit().value_within_limit(self.printed_type_count) {
+            self.printed_type_count += 1;
+            self.pretty_print_type(ty)
+        } else {
+            write!(self, "...")?;
+            Ok(self)
+        }
     }
 
     fn print_dyn_existential(
diff --git a/compiler/rustc_middle/src/ty/query/keys.rs b/compiler/rustc_middle/src/ty/query/keys.rs
index 3f7a20bba2b..a005990264c 100644
--- a/compiler/rustc_middle/src/ty/query/keys.rs
+++ b/compiler/rustc_middle/src/ty/query/keys.rs
@@ -193,6 +193,22 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
     }
 }
 
+impl<'tcx> Key
+    for (
+        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+    )
+{
+    type CacheSelector = DefaultCacheSelector;
+
+    fn query_crate(&self) -> CrateNum {
+        (self.0).0.did.krate
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        (self.0).0.did.default_span(tcx)
+    }
+}
+
 impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
     type CacheSelector = DefaultCacheSelector;
 
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
index dcfb8d31430..b0c48a860eb 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -760,6 +760,12 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
     }
 }
 
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         RefDecodable::decode(d)
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 7d3634a75b0..c4df0bba726 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -576,7 +576,20 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
             new_val.map(ty::ConstKind::Value)
         }
 
-        // FIXME(const_generics): this is wrong, as it is a projection
+        (
+            ty::ConstKind::Unevaluated(a_def, a_substs, None),
+            ty::ConstKind::Unevaluated(b_def, b_substs, None),
+        ) if tcx.features().const_evaluatable_checked => {
+            if tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) {
+                Ok(a.val)
+            } else {
+                Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
+            }
+        }
+
+        // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
+        // and is the better alternative to waiting until `const_evaluatable_checked` can
+        // be stabilized.
         (
             ty::ConstKind::Unevaluated(a_def, a_substs, a_promoted),
             ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted),
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 9f5fc5a2d3f..d4c8ba08275 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1233,13 +1233,13 @@ rustc_index::newtype_index! {
     /// particular, imagine a type like this:
     ///
     ///     for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
-    ///     ^          ^            |        |         |
-    ///     |          |            |        |         |
-    ///     |          +------------+ 0      |         |
-    ///     |                                |         |
-    ///     +--------------------------------+ 1       |
-    ///     |                                          |
-    ///     +------------------------------------------+ 0
+    ///     ^          ^            |          |           |
+    ///     |          |            |          |           |
+    ///     |          +------------+ 0        |           |
+    ///     |                                  |           |
+    ///     +----------------------------------+ 1         |
+    ///     |                                              |
+    ///     +----------------------------------------------+ 0
     ///
     /// In this type, there are two binders (the outer fn and the inner
     /// fn). We need to be able to determine, for any given region, which
@@ -2280,6 +2280,12 @@ impl<'tcx> TyS<'tcx> {
     ///
     /// Returning true means the type is known to be sized. Returning
     /// `false` means nothing -- could be sized, might not be.
+    ///
+    /// Note that we could never rely on the fact that a type such as `[_]` is
+    /// trivially `!Sized` because we could be in a type environment with a
+    /// bound such as `[_]: Copy`. A function with such a bound obviously never
+    /// can be called, but that doesn't mean it shouldn't typecheck. This is why
+    /// this method doesn't return `Option<bool>`.
     pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool {
         match self.kind() {
             ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 4f55517c6f4..7afa6e6cc05 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -3,7 +3,50 @@
 
 use crate::ty;
 use crate::ty::subst::{GenericArg, GenericArgKind};
+use arrayvec::ArrayVec;
+use rustc_data_structures::fx::FxHashSet;
 use smallvec::{self, SmallVec};
+use std::hash::Hash;
+
+/// Small-storage-optimized implementation of a set
+/// made specifically for walking type tree.
+///
+/// Stores elements in a small array up to a certain length
+/// and switches to `HashSet` when that length is exceeded.
+pub enum MiniSet<T> {
+    Array(ArrayVec<[T; 8]>),
+    Set(FxHashSet<T>),
+}
+
+impl<T: Eq + Hash + Copy> MiniSet<T> {
+    /// Creates an empty `MiniSet`.
+    pub fn new() -> Self {
+        MiniSet::Array(ArrayVec::new())
+    }
+
+    /// Adds a value to the set.
+    ///
+    /// If the set did not have this value present, true is returned.
+    ///
+    /// If the set did have this value present, false is returned.
+    pub fn insert(&mut self, elem: T) -> bool {
+        match self {
+            MiniSet::Array(array) => {
+                if array.iter().any(|e| *e == elem) {
+                    false
+                } else {
+                    if array.try_push(elem).is_err() {
+                        let mut set: FxHashSet<T> = array.iter().copied().collect();
+                        set.insert(elem);
+                        *self = MiniSet::Set(set);
+                    }
+                    true
+                }
+            }
+            MiniSet::Set(set) => set.insert(elem),
+        }
+    }
+}
 
 // The TypeWalker's stack is hot enough that it's worth going to some effort to
 // avoid heap allocations.
@@ -12,11 +55,20 @@ type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>;
 pub struct TypeWalker<'tcx> {
     stack: TypeWalkerStack<'tcx>,
     last_subtree: usize,
+    visited: MiniSet<GenericArg<'tcx>>,
 }
 
+/// An iterator for walking the type tree.
+///
+/// It's very easy to produce a deeply
+/// nested type tree with a lot of
+/// identical subtrees. In order to work efficiently
+/// in this situation walker only visits each type once.
+/// It maintains a set of visited types and
+/// skips any types that are already there.
 impl<'tcx> TypeWalker<'tcx> {
-    pub fn new(root: GenericArg<'tcx>) -> TypeWalker<'tcx> {
-        TypeWalker { stack: smallvec![root], last_subtree: 1 }
+    pub fn new(root: GenericArg<'tcx>) -> Self {
+        Self { stack: smallvec![root], last_subtree: 1, visited: MiniSet::new() }
     }
 
     /// Skips the subtree corresponding to the last type
@@ -41,11 +93,15 @@ impl<'tcx> Iterator for TypeWalker<'tcx> {
 
     fn next(&mut self) -> Option<GenericArg<'tcx>> {
         debug!("next(): stack={:?}", self.stack);
-        let next = self.stack.pop()?;
-        self.last_subtree = self.stack.len();
-        push_inner(&mut self.stack, next);
-        debug!("next: stack={:?}", self.stack);
-        Some(next)
+        loop {
+            let next = self.stack.pop()?;
+            self.last_subtree = self.stack.len();
+            if self.visited.insert(next) {
+                push_inner(&mut self.stack, next);
+                debug!("next: stack={:?}", self.stack);
+                return Some(next);
+            }
+        }
     }
 }
 
@@ -67,9 +123,17 @@ impl GenericArg<'tcx> {
     /// Iterator that walks the immediate children of `self`. Hence
     /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
     /// (but not `i32`, like `walk`).
-    pub fn walk_shallow(self) -> impl Iterator<Item = GenericArg<'tcx>> {
+    ///
+    /// Iterator only walks items once.
+    /// It accepts visited set, updates it with all visited types
+    /// and skips any types that are already there.
+    pub fn walk_shallow(
+        self,
+        visited: &mut MiniSet<GenericArg<'tcx>>,
+    ) -> impl Iterator<Item = GenericArg<'tcx>> {
         let mut stack = SmallVec::new();
         push_inner(&mut stack, self);
+        stack.retain(|a| visited.insert(*a));
         stack.into_iter()
     }
 }
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
index 639428ff07d..eb1f70099fc 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
@@ -387,7 +387,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         if let ReturnConstraint::ClosureUpvar(upvar) = kind {
             let def_id = match self.regioncx.universal_regions().defining_ty {
                 DefiningTy::Closure(def_id, _) => def_id,
-                ty @ _ => bug!("unexpected DefiningTy {:?}", ty),
+                ty => bug!("unexpected DefiningTy {:?}", ty),
             };
 
             let upvar_def_span = self.infcx.tcx.hir().span(upvar);
diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs
index b0357c508a3..02e905505c0 100644
--- a/compiler/rustc_mir/src/const_eval/machine.rs
+++ b/compiler/rustc_mir/src/const_eval/machine.rs
@@ -11,7 +11,7 @@ use rustc_ast::Mutability;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::AssertMessage;
 use rustc_session::Limit;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{sym, Symbol};
 
 use crate::interpret::{
     self, compile_time_machine, AllocId, Allocation, Frame, GlobalId, ImmTy, InterpCx,
@@ -176,6 +176,38 @@ impl interpret::MayLeak for ! {
     }
 }
 
+impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
+    fn guaranteed_eq(&mut self, a: Scalar, b: Scalar) -> bool {
+        match (a, b) {
+            // Comparisons between integers are always known.
+            (Scalar::Raw { .. }, Scalar::Raw { .. }) => a == b,
+            // Equality with integers can never be known for sure.
+            (Scalar::Raw { .. }, Scalar::Ptr(_)) | (Scalar::Ptr(_), Scalar::Raw { .. }) => false,
+            // FIXME: return `true` for when both sides are the same pointer, *except* that
+            // some things (like functions and vtables) do not have stable addresses
+            // so we need to be careful around them (see e.g. #73722).
+            (Scalar::Ptr(_), Scalar::Ptr(_)) => false,
+        }
+    }
+
+    fn guaranteed_ne(&mut self, a: Scalar, b: Scalar) -> bool {
+        match (a, b) {
+            // Comparisons between integers are always known.
+            (Scalar::Raw { .. }, Scalar::Raw { .. }) => a != b,
+            // Comparisons of abstract pointers with null pointers are known if the pointer
+            // is in bounds, because if they are in bounds, the pointer can't be null.
+            (Scalar::Raw { data: 0, .. }, Scalar::Ptr(ptr))
+            | (Scalar::Ptr(ptr), Scalar::Raw { data: 0, .. }) => !self.memory.ptr_may_be_null(ptr),
+            // Inequality with integers other than null can never be known for sure.
+            (Scalar::Raw { .. }, Scalar::Ptr(_)) | (Scalar::Ptr(_), Scalar::Raw { .. }) => false,
+            // FIXME: return `true` for at least some comparisons where we can reliably
+            // determine the result of runtime inequality tests at compile-time.
+            // Examples include comparison of addresses in different static items.
+            (Scalar::Ptr(_), Scalar::Ptr(_)) => false,
+        }
+    }
+}
+
 impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
     compile_time_machine!(<'mir, 'tcx>);
 
@@ -234,12 +266,45 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
         _unwind: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx> {
+        // Shared intrinsics.
         if ecx.emulate_intrinsic(instance, args, ret)? {
             return Ok(());
         }
-        // An intrinsic that we do not support
         let intrinsic_name = ecx.tcx.item_name(instance.def_id());
-        Err(ConstEvalErrKind::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into())
+
+        // CTFE-specific intrinsics.
+        let (dest, ret) = match ret {
+            None => {
+                return Err(ConstEvalErrKind::NeedsRfc(format!(
+                    "calling intrinsic `{}`",
+                    intrinsic_name
+                ))
+                .into());
+            }
+            Some(p) => p,
+        };
+        match intrinsic_name {
+            sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
+                let a = ecx.read_immediate(args[0])?.to_scalar()?;
+                let b = ecx.read_immediate(args[1])?.to_scalar()?;
+                let cmp = if intrinsic_name == sym::ptr_guaranteed_eq {
+                    ecx.guaranteed_eq(a, b)
+                } else {
+                    ecx.guaranteed_ne(a, b)
+                };
+                ecx.write_scalar(Scalar::from_bool(cmp), dest)?;
+            }
+            _ => {
+                return Err(ConstEvalErrKind::NeedsRfc(format!(
+                    "calling intrinsic `{}`",
+                    intrinsic_name
+                ))
+                .into());
+            }
+        }
+
+        ecx.go_to_block(ret);
+        Ok(())
     }
 
     fn assert_panic(
diff --git a/compiler/rustc_mir/src/dataflow/framework/engine.rs b/compiler/rustc_mir/src/dataflow/framework/engine.rs
index 0b5b437d186..4084083bd99 100644
--- a/compiler/rustc_mir/src/dataflow/framework/engine.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/engine.rs
@@ -306,7 +306,8 @@ where
     let mut buf = Vec::new();
 
     let graphviz = graphviz::Formatter::new(body, def_id, results, style);
-    let mut render_opts = vec![dot::RenderOption::Monospace];
+    let mut render_opts =
+        vec![dot::RenderOption::Fontname(tcx.sess.opts.debugging_opts.graphviz_font.clone())];
     if tcx.sess.opts.debugging_opts.graphviz_dark_mode {
         render_opts.push(dot::RenderOption::DarkTheme);
     }
diff --git a/compiler/rustc_mir/src/dataflow/framework/graphviz.rs b/compiler/rustc_mir/src/dataflow/framework/graphviz.rs
index 179c471cf48..94151fbd090 100644
--- a/compiler/rustc_mir/src/dataflow/framework/graphviz.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/graphviz.rs
@@ -578,7 +578,7 @@ where
         return String::new();
     }
 
-    let re = Regex::new("\u{001f}([+-])").unwrap();
+    let re = Regex::new("\t?\u{001f}([+-])").unwrap();
 
     let raw_diff = format!("{:#?}", DebugDiffWithAdapter { new, old, ctxt });
 
diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs
index 3e0a7886f08..47ca71d9642 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics.rs
+++ b/compiler/rustc_mir/src/interpret/intrinsics.rs
@@ -88,6 +88,8 @@ crate fn eval_nullary_intrinsic<'tcx>(
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Returns `true` if emulation happened.
+    /// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own
+    /// intrinsic handling.
     pub fn emulate_intrinsic(
         &mut self,
         instance: ty::Instance<'tcx>,
@@ -328,16 +330,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self);
                 self.write_scalar(offset_ptr, dest)?;
             }
-            sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
-                let a = self.read_immediate(args[0])?.to_scalar()?;
-                let b = self.read_immediate(args[1])?.to_scalar()?;
-                let cmp = if intrinsic_name == sym::ptr_guaranteed_eq {
-                    self.guaranteed_eq(a, b)
-                } else {
-                    self.guaranteed_ne(a, b)
-                };
-                self.write_scalar(Scalar::from_bool(cmp), dest)?;
-            }
             sym::ptr_offset_from => {
                 let a = self.read_immediate(args[0])?.to_scalar()?;
                 let b = self.read_immediate(args[1])?.to_scalar()?;
@@ -448,37 +440,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(true)
     }
 
-    fn guaranteed_eq(&mut self, a: Scalar<M::PointerTag>, b: Scalar<M::PointerTag>) -> bool {
-        match (a, b) {
-            // Comparisons between integers are always known.
-            (Scalar::Raw { .. }, Scalar::Raw { .. }) => a == b,
-            // Equality with integers can never be known for sure.
-            (Scalar::Raw { .. }, Scalar::Ptr(_)) | (Scalar::Ptr(_), Scalar::Raw { .. }) => false,
-            // FIXME: return `true` for when both sides are the same pointer, *except* that
-            // some things (like functions and vtables) do not have stable addresses
-            // so we need to be careful around them.
-            (Scalar::Ptr(_), Scalar::Ptr(_)) => false,
-        }
-    }
-
-    fn guaranteed_ne(&mut self, a: Scalar<M::PointerTag>, b: Scalar<M::PointerTag>) -> bool {
-        match (a, b) {
-            // Comparisons between integers are always known.
-            (Scalar::Raw { .. }, Scalar::Raw { .. }) => a != b,
-            // Comparisons of abstract pointers with null pointers are known if the pointer
-            // is in bounds, because if they are in bounds, the pointer can't be null.
-            (Scalar::Raw { data: 0, .. }, Scalar::Ptr(ptr))
-            | (Scalar::Ptr(ptr), Scalar::Raw { data: 0, .. }) => !self.memory.ptr_may_be_null(ptr),
-            // Inequality with integers other than null can never be known for sure.
-            (Scalar::Raw { .. }, Scalar::Ptr(_)) | (Scalar::Ptr(_), Scalar::Raw { .. }) => false,
-            // FIXME: return `true` for at least some comparisons where we can reliably
-            // determine the result of runtime inequality tests at compile-time.
-            // Examples include comparison of addresses in static items, for these we can
-            // give reliable results.
-            (Scalar::Ptr(_), Scalar::Ptr(_)) => false,
-        }
-    }
-
     pub fn exact_div(
         &mut self,
         a: ImmTy<'tcx, M::PointerTag>,
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs
index 9ea103463d5..0dbb4b1015e 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_mir/src/monomorphize/collector.rs
@@ -418,6 +418,29 @@ fn record_accesses<'a, 'tcx: 'a>(
     inlining_map.lock_mut().record_accesses(caller, &accesses);
 }
 
+// Shrinks string by keeping prefix and suffix of given sizes.
+fn shrink(s: String, before: usize, after: usize) -> String {
+    // An iterator of all byte positions including the end of the string.
+    let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len()));
+
+    let shrunk = format!(
+        "{before}...{after}",
+        before = &s[..positions().nth(before).unwrap_or(s.len())],
+        after = &s[positions().rev().nth(after).unwrap_or(0)..],
+    );
+
+    // Only use the shrunk version if it's really shorter.
+    // This also avoids the case where before and after slices overlap.
+    if shrunk.len() < s.len() { shrunk } else { s }
+}
+
+// Format instance name that is already known to be too long for rustc.
+// Show only the first and last 32 characters to avoid blasting
+// the user's terminal with thousands of lines of type-name.
+fn shrunk_instance_name(instance: &Instance<'tcx>) -> String {
+    shrink(instance.to_string(), 32, 32)
+}
+
 fn check_recursion_limit<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: Instance<'tcx>,
@@ -440,7 +463,10 @@ fn check_recursion_limit<'tcx>(
     // more than the recursion limit is assumed to be causing an
     // infinite expansion.
     if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
-        let error = format!("reached the recursion limit while instantiating `{}`", instance);
+        let error = format!(
+            "reached the recursion limit while instantiating `{}`",
+            shrunk_instance_name(&instance),
+        );
         let mut err = tcx.sess.struct_span_fatal(span, &error);
         err.span_note(
             tcx.def_span(def_id),
@@ -474,26 +500,9 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
     //
     // Bail out in these cases to avoid that bad user experience.
     if !tcx.sess.type_length_limit().value_within_limit(type_length) {
-        // The instance name is already known to be too long for rustc.
-        // Show only the first and last 32 characters to avoid blasting
-        // the user's terminal with thousands of lines of type-name.
-        let shrink = |s: String, before: usize, after: usize| {
-            // An iterator of all byte positions including the end of the string.
-            let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len()));
-
-            let shrunk = format!(
-                "{before}...{after}",
-                before = &s[..positions().nth(before).unwrap_or(s.len())],
-                after = &s[positions().rev().nth(after).unwrap_or(0)..],
-            );
-
-            // Only use the shrunk version if it's really shorter.
-            // This also avoids the case where before and after slices overlap.
-            if shrunk.len() < s.len() { shrunk } else { s }
-        };
         let msg = format!(
             "reached the type-length limit while instantiating `{}`",
-            shrink(instance.to_string(), 32, 32)
+            shrunk_instance_name(&instance),
         );
         let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
         diag.note(&format!(
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
index b48bae83787..827d037f319 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
+++ b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
@@ -11,6 +11,7 @@ use rustc_middle::ty::print::characteristic_def_id_of_type;
 use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt};
 use rustc_span::symbol::Symbol;
 
+use super::PartitioningCx;
 use crate::monomorphize::collector::InliningMap;
 use crate::monomorphize::partitioning::merging;
 use crate::monomorphize::partitioning::{
@@ -22,35 +23,36 @@ pub struct DefaultPartitioning;
 impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
     fn place_root_mono_items(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
     ) -> PreInliningPartitioning<'tcx> {
         let mut roots = FxHashSet::default();
         let mut codegen_units = FxHashMap::default();
-        let is_incremental_build = tcx.sess.opts.incremental.is_some();
+        let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
         let mut internalization_candidates = FxHashSet::default();
 
         // Determine if monomorphizations instantiated in this crate will be made
         // available to downstream crates. This depends on whether we are in
         // share-generics mode and whether the current crate can even have
         // downstream crates.
-        let export_generics = tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics();
+        let export_generics =
+            cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics();
 
-        let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
+        let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
         let cgu_name_cache = &mut FxHashMap::default();
 
         for mono_item in mono_items {
-            match mono_item.instantiation_mode(tcx) {
+            match mono_item.instantiation_mode(cx.tcx) {
                 InstantiationMode::GloballyShared { .. } => {}
                 InstantiationMode::LocalCopy => continue,
             }
 
-            let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item);
+            let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
             let is_volatile = is_incremental_build && mono_item.is_generic_fn();
 
             let codegen_unit_name = match characteristic_def_id {
                 Some(def_id) => compute_codegen_unit_name(
-                    tcx,
+                    cx.tcx,
                     cgu_name_builder,
                     def_id,
                     is_volatile,
@@ -65,7 +67,7 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
 
             let mut can_be_internalized = true;
             let (linkage, visibility) = mono_item_linkage_and_visibility(
-                tcx,
+                cx.tcx,
                 &mono_item,
                 &mut can_be_internalized,
                 export_generics,
@@ -97,17 +99,16 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
 
     fn merge_codegen_units(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-        target_cgu_count: usize,
     ) {
-        merging::merge_codegen_units(tcx, initial_partitioning, target_cgu_count);
+        merging::merge_codegen_units(cx, initial_partitioning);
     }
 
     fn place_inlined_mono_items(
         &mut self,
+        cx: &PartitioningCx<'_, 'tcx>,
         initial_partitioning: PreInliningPartitioning<'tcx>,
-        inlining_map: &InliningMap<'tcx>,
     ) -> PostInliningPartitioning<'tcx> {
         let mut new_partitioning = Vec::new();
         let mut mono_item_placements = FxHashMap::default();
@@ -124,7 +125,7 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
             // Collect all items that need to be available in this codegen unit.
             let mut reachable = FxHashSet::default();
             for root in old_codegen_unit.items().keys() {
-                follow_inlining(*root, inlining_map, &mut reachable);
+                follow_inlining(*root, cx.inlining_map, &mut reachable);
             }
 
             let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name());
@@ -198,9 +199,8 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
 
     fn internalize_symbols(
         &mut self,
-        _tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         partitioning: &mut PostInliningPartitioning<'tcx>,
-        inlining_map: &InliningMap<'tcx>,
     ) {
         if partitioning.codegen_units.len() == 1 {
             // Fast path for when there is only one codegen unit. In this case we
@@ -218,7 +218,7 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
         // Build a map from every monomorphization to all the monomorphizations that
         // reference it.
         let mut accessor_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>> = Default::default();
-        inlining_map.iter_accesses(|accessor, accessees| {
+        cx.inlining_map.iter_accesses(|accessor, accessees| {
             for accessee in accessees {
                 accessor_map.entry(*accessee).or_default().push(accessor);
             }
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/merging.rs b/compiler/rustc_mir/src/monomorphize/partitioning/merging.rs
index d92f1367e7d..5107e697263 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/merging.rs
+++ b/compiler/rustc_mir/src/monomorphize/partitioning/merging.rs
@@ -3,17 +3,16 @@ use std::cmp;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder};
-use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{Symbol, SymbolStr};
 
+use super::PartitioningCx;
 use crate::monomorphize::partitioning::PreInliningPartitioning;
 
 pub fn merge_codegen_units<'tcx>(
-    tcx: TyCtxt<'tcx>,
+    cx: &PartitioningCx<'_, 'tcx>,
     initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-    target_cgu_count: usize,
 ) {
-    assert!(target_cgu_count >= 1);
+    assert!(cx.target_cgu_count >= 1);
     let codegen_units = &mut initial_partitioning.codegen_units;
 
     // Note that at this point in time the `codegen_units` here may not be in a
@@ -32,7 +31,7 @@ pub fn merge_codegen_units<'tcx>(
         codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name().as_str()])).collect();
 
     // Merge the two smallest codegen units until the target size is reached.
-    while codegen_units.len() > target_cgu_count {
+    while codegen_units.len() > cx.target_cgu_count {
         // Sort small cgus to the back
         codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
         let mut smallest = codegen_units.pop().unwrap();
@@ -56,9 +55,9 @@ pub fn merge_codegen_units<'tcx>(
         );
     }
 
-    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
+    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
 
-    if tcx.sess.opts.incremental.is_some() {
+    if cx.tcx.sess.opts.incremental.is_some() {
         // If we are doing incremental compilation, we want CGU names to
         // reflect the path of the source level module they correspond to.
         // For CGUs that contain the code of multiple modules because of the
@@ -84,7 +83,7 @@ pub fn merge_codegen_units<'tcx>(
 
         for cgu in codegen_units.iter_mut() {
             if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
-                if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+                if cx.tcx.sess.opts.debugging_opts.human_readable_cgu_names {
                     cgu.set_name(Symbol::intern(&new_cgu_name));
                 } else {
                     // If we don't require CGU names to be human-readable, we
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
index 0f6f078d968..b60beca6880 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
+++ b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
@@ -108,31 +108,35 @@ use rustc_span::symbol::Symbol;
 use crate::monomorphize::collector::InliningMap;
 use crate::monomorphize::collector::{self, MonoItemCollectionMode};
 
+pub struct PartitioningCx<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    target_cgu_count: usize,
+    inlining_map: &'a InliningMap<'tcx>,
+}
+
 trait Partitioner<'tcx> {
     fn place_root_mono_items(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
     ) -> PreInliningPartitioning<'tcx>;
 
     fn merge_codegen_units(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-        target_cgu_count: usize,
     );
 
     fn place_inlined_mono_items(
         &mut self,
+        cx: &PartitioningCx<'_, 'tcx>,
         initial_partitioning: PreInliningPartitioning<'tcx>,
-        inlining_map: &InliningMap<'tcx>,
     ) -> PostInliningPartitioning<'tcx>;
 
     fn internalize_symbols(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         partitioning: &mut PostInliningPartitioning<'tcx>,
-        inlining_map: &InliningMap<'tcx>,
     );
 }
 
@@ -157,12 +161,13 @@ pub fn partition<'tcx>(
     let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
 
     let mut partitioner = get_partitioner(tcx);
+    let cx = &PartitioningCx { tcx, target_cgu_count: max_cgu_count, inlining_map };
     // In the first step, we place all regular monomorphizations into their
     // respective 'home' codegen unit. Regular monomorphizations are all
     // functions and statics defined in the local crate.
     let mut initial_partitioning = {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
-        partitioner.place_root_mono_items(tcx, mono_items)
+        partitioner.place_root_mono_items(cx, mono_items)
     };
 
     initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
@@ -172,7 +177,7 @@ pub fn partition<'tcx>(
     // Merge until we have at most `max_cgu_count` codegen units.
     {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
-        partitioner.merge_codegen_units(tcx, &mut initial_partitioning, max_cgu_count);
+        partitioner.merge_codegen_units(cx, &mut initial_partitioning);
         debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
     }
 
@@ -182,7 +187,7 @@ pub fn partition<'tcx>(
     // local functions the definition of which is marked with `#[inline]`.
     let mut post_inlining = {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
-        partitioner.place_inlined_mono_items(initial_partitioning, inlining_map)
+        partitioner.place_inlined_mono_items(cx, initial_partitioning)
     };
 
     post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
@@ -193,7 +198,7 @@ pub fn partition<'tcx>(
     // more freedom to optimize.
     if !tcx.sess.link_dead_code() {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
-        partitioner.internalize_symbols(tcx, &mut post_inlining, inlining_map);
+        partitioner.internalize_symbols(cx, &mut post_inlining);
     }
 
     // Finally, sort by codegen unit name, so that we get deterministic results.
diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs
index c4924cf16ab..b224df92e9d 100644
--- a/compiler/rustc_mir/src/transform/instcombine.rs
+++ b/compiler/rustc_mir/src/transform/instcombine.rs
@@ -126,7 +126,7 @@ impl OptimizationFinder<'b, 'tcx> {
             }
         }
 
-        return None;
+        None
     }
 }
 
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index 8025b7c0204..226282fe426 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -329,7 +329,11 @@ fn mir_promoted(
     // this point, before we steal the mir-const result.
     // Also this means promotion can rely on all const checks having been done.
     let _ = tcx.mir_const_qualif_opt_const_arg(def);
-
+    let _ = if let Some(param_did) = def.const_param_did {
+        tcx.mir_abstract_const_of_const_arg((def.did, param_did))
+    } else {
+        tcx.mir_abstract_const(def.did.to_def_id())
+    };
     let mut body = tcx.mir_const(def).steal();
 
     let mut required_consts = Vec::new();
diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs
index 76a60c45575..9a11d927240 100644
--- a/compiler/rustc_mir/src/transform/simplify_try.rs
+++ b/compiler/rustc_mir/src/transform/simplify_try.rs
@@ -612,7 +612,7 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
                     && bb_l.terminator().kind == bb_r.terminator().kind;
                     let statement_check = || {
                         bb_l.statements.iter().zip(&bb_r.statements).try_fold(StatementEquality::TrivialEqual, |acc,(l,r)| {
-                            let stmt_equality = self.statement_equality(*adt_matched_on, &l, bb_l_idx, &r, bb_r_idx);
+                            let stmt_equality = self.statement_equality(*adt_matched_on, &l, bb_l_idx, &r, bb_r_idx, self.tcx.sess.opts.debugging_opts.mir_opt_level);
                             if matches!(stmt_equality, StatementEquality::NotEqual) {
                                 // short circuit
                                 None
@@ -672,6 +672,7 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
         x_bb_idx: BasicBlock,
         y: &Statement<'tcx>,
         y_bb_idx: BasicBlock,
+        mir_opt_level: usize,
     ) -> StatementEquality {
         let helper = |rhs: &Rvalue<'tcx>,
                       place: &Place<'tcx>,
@@ -690,7 +691,13 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
 
             match rhs {
                 Rvalue::Use(operand) if operand.place() == Some(adt_matched_on) => {
-                    StatementEquality::ConsideredEqual(side_to_choose)
+                    // FIXME(76803): This logic is currently broken because it does not take into
+                    // account the current discriminant value.
+                    if mir_opt_level > 2 {
+                        StatementEquality::ConsideredEqual(side_to_choose)
+                    } else {
+                        StatementEquality::NotEqual
+                    }
                 }
                 _ => {
                     trace!(
diff --git a/compiler/rustc_mir/src/util/graphviz.rs b/compiler/rustc_mir/src/util/graphviz.rs
index e89c9437706..4511962d68f 100644
--- a/compiler/rustc_mir/src/util/graphviz.rs
+++ b/compiler/rustc_mir/src/util/graphviz.rs
@@ -55,9 +55,9 @@ where
     writeln!(w, "{} {}Mir_{} {{", kind, cluster, def_name)?;
 
     // Global graph properties
-    let font = r#"fontname="Courier, monospace""#;
-    let mut graph_attrs = vec![font];
-    let mut content_attrs = vec![font];
+    let font = format!(r#"fontname="{}""#, tcx.sess.opts.debugging_opts.graphviz_font);
+    let mut graph_attrs = vec![&font[..]];
+    let mut content_attrs = vec![&font[..]];
 
     let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode;
     if dark_mode {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 03cc718b899..1a95992ed83 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -97,6 +97,15 @@ where
                 ty.visit_with(self)
             }
             ty::PredicateAtom::RegionOutlives(..) => false,
+            ty::PredicateAtom::ConstEvaluatable(..)
+                if self.def_id_visitor.tcx().features().const_evaluatable_checked =>
+            {
+                // FIXME(const_evaluatable_checked): If the constant used here depends on a
+                // private function we may have to do something here...
+                //
+                // For now, let's just pretend that everything is fine.
+                false
+            }
             _ => bug!("unexpected predicate: {:?}", predicate),
         }
     }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index b80da641491..612bc3e7491 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -466,7 +466,7 @@ impl<'a> Resolver<'a> {
                 );
                 err
             }
-            ResolutionError::ParamInNonTrivialAnonConst(name) => {
+            ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
                 let mut err = self.session.struct_span_err(
                     span,
                     "generic parameters must not be used inside of non trivial constant values",
@@ -478,9 +478,17 @@ impl<'a> Resolver<'a> {
                         name
                     ),
                 );
-                err.help(
-                    &format!("it is currently only allowed to use either `{0}` or `{{ {0} }}` as generic constants", name)
-                );
+
+                if is_type {
+                    err.note("type parameters are currently not permitted in anonymous constants");
+                } else {
+                    err.help(
+                        &format!("it is currently only allowed to use either `{0}` or `{{ {0} }}` as generic constants",
+                                 name
+                        )
+                    );
+                }
+
                 err
             }
             ResolutionError::SelfInTyParamDefault => {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 9b5650c260c..2cc87dc6375 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1534,7 +1534,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
             }
         };
 
-        let lifetime_names: Vec<_> = lifetime_names.into_iter().collect();
+        let lifetime_names: Vec<_> = lifetime_names.iter().collect();
         match (&lifetime_names[..], snippet.as_deref()) {
             ([name], Some("&")) => {
                 suggest_existing(err, &name.as_str()[..], &|name| format!("&{} ", name));
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 00a37d908cd..85ddc5f55d1 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -221,7 +221,7 @@ enum ResolutionError<'a> {
     /// generic parameters must not be used inside of non trivial constant values.
     ///
     /// This error is only emitted when using `min_const_generics`.
-    ParamInNonTrivialAnonConst(Symbol),
+    ParamInNonTrivialAnonConst { name: Symbol, is_type: bool },
     /// Error E0735: type parameters with a default cannot use `Self`
     SelfInTyParamDefault,
     /// Error E0767: use of unreachable label
@@ -2638,9 +2638,10 @@ impl<'a> Resolver<'a> {
                                     if record_used {
                                         self.report_error(
                                             span,
-                                            ResolutionError::ParamInNonTrivialAnonConst(
-                                                rib_ident.name,
-                                            ),
+                                            ResolutionError::ParamInNonTrivialAnonConst {
+                                                name: rib_ident.name,
+                                                is_type: true,
+                                            },
                                         );
                                     }
                                     return Res::Err;
@@ -2718,7 +2719,10 @@ impl<'a> Resolver<'a> {
                                 if record_used {
                                     self.report_error(
                                         span,
-                                        ResolutionError::ParamInNonTrivialAnonConst(rib_ident.name),
+                                        ResolutionError::ParamInNonTrivialAnonConst {
+                                            name: rib_ident.name,
+                                            is_type: false,
+                                        },
                                     );
                                 }
                                 return Res::Err;
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 4aecb35294a..3f12596a236 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1762,6 +1762,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0;
     }
 
+    if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
+        debugging_opts.graphviz_font = graphviz_font;
+    }
+
     if !cg.embed_bitcode {
         match cg.lto {
             LtoCli::No | LtoCli::Unspecified => {}
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index c5050dbea73..8cc55f4ebe8 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -911,6 +911,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "set the optimization fuel quota for a crate"),
     graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED],
         "use dark-themed colors in graphviz output (default: no)"),
+    graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED],
+        "use the given `fontname` in graphviz output; can be overridden by setting \
+        environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
     hir_stats: bool = (false, parse_bool, [UNTRACKED],
         "print some statistics about AST and HIR (default: no)"),
     human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index b5882df4729..da1996b92a6 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -12,6 +12,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(bool_to_option)]
+#![feature(box_patterns)]
 #![feature(drain_filter)]
 #![feature(in_band_lifetimes)]
 #![feature(crate_visibility_modifier)]
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index c27d2fcc149..c53c65c00b7 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -182,7 +182,7 @@ fn overlap_within_probe(
     }
 
     if !skip_leak_check.is_yes() {
-        if let Err(_) = infcx.leak_check(true, snapshot) {
+        if infcx.leak_check(true, snapshot).is_err() {
             debug!("overlap: leak check failed");
             return None;
         }
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index fdb87c085b5..2642358dbc5 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -1,10 +1,25 @@
+//! Checking that constant values used in types can be successfully evaluated.
+//!
+//! For concrete constants, this is fairly simple as we can just try and evaluate it.
+//!
+//! When dealing with polymorphic constants, for example `std::mem::size_of::<T>() - 1`,
+//! this is not as easy.
+//!
+//! In this case we try to build an abstract representation of this constant using
+//! `mir_abstract_const` which can then be checked for structural equality with other
+//! generic constants mentioned in the `caller_bounds` of the current environment.
 use rustc_hir::def::DefKind;
+use rustc_index::bit_set::BitSet;
+use rustc_index::vec::IndexVec;
 use rustc_infer::infer::InferCtxt;
+use rustc_middle::mir::abstract_const::{Node, NodeId};
 use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind};
+use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, TypeFoldable};
+use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_session::lint;
-use rustc_span::def_id::DefId;
+use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::Span;
 
 pub fn is_const_evaluatable<'cx, 'tcx>(
@@ -16,18 +31,23 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
 ) -> Result<(), ErrorHandled> {
     debug!("is_const_evaluatable({:?}, {:?})", def, substs);
     if infcx.tcx.features().const_evaluatable_checked {
-        // FIXME(const_evaluatable_checked): Actually look into generic constants to
-        // implement const equality.
-        for pred in param_env.caller_bounds() {
-            match pred.skip_binders() {
-                ty::PredicateAtom::ConstEvaluatable(b_def, b_substs) => {
-                    debug!("is_const_evaluatable: caller_bound={:?}, {:?}", b_def, b_substs);
-                    if b_def == def && b_substs == substs {
-                        debug!("is_const_evaluatable: caller_bound ~~> ok");
-                        return Ok(());
+        if let Some(ct) = AbstractConst::new(infcx.tcx, def, substs) {
+            for pred in param_env.caller_bounds() {
+                match pred.skip_binders() {
+                    ty::PredicateAtom::ConstEvaluatable(b_def, b_substs) => {
+                        debug!("is_const_evaluatable: caller_bound={:?}, {:?}", b_def, b_substs);
+                        if b_def == def && b_substs == substs {
+                            debug!("is_const_evaluatable: caller_bound ~~> ok");
+                            return Ok(());
+                        } else if AbstractConst::new(infcx.tcx, b_def, b_substs)
+                            .map_or(false, |b_ct| try_unify(infcx.tcx, ct, b_ct))
+                        {
+                            debug!("is_const_evaluatable: abstract_const ~~> ok");
+                            return Ok(());
+                        }
                     }
+                    _ => {} // don't care
                 }
-                _ => {} // don't care
             }
         }
     }
@@ -76,3 +96,337 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
     debug!(?concrete, "is_const_evaluatable");
     concrete.map(drop)
 }
+
+/// A tree representing an anonymous constant.
+///
+/// This is only able to represent a subset of `MIR`,
+/// and should not leak any information about desugarings.
+#[derive(Clone, Copy)]
+pub struct AbstractConst<'tcx> {
+    // FIXME: Consider adding something like `IndexSlice`
+    // and use this here.
+    inner: &'tcx [Node<'tcx>],
+    substs: SubstsRef<'tcx>,
+}
+
+impl AbstractConst<'tcx> {
+    pub fn new(
+        tcx: TyCtxt<'tcx>,
+        def: ty::WithOptConstParam<DefId>,
+        substs: SubstsRef<'tcx>,
+    ) -> Option<AbstractConst<'tcx>> {
+        let inner = match (def.did.as_local(), def.const_param_did) {
+            (Some(did), Some(param_did)) => {
+                tcx.mir_abstract_const_of_const_arg((did, param_did))?
+            }
+            _ => tcx.mir_abstract_const(def.did)?,
+        };
+
+        Some(AbstractConst { inner, substs })
+    }
+
+    #[inline]
+    pub fn subtree(self, node: NodeId) -> AbstractConst<'tcx> {
+        AbstractConst { inner: &self.inner[..=node.index()], substs: self.substs }
+    }
+
+    #[inline]
+    pub fn root(self) -> Node<'tcx> {
+        self.inner.last().copied().unwrap()
+    }
+}
+
+struct AbstractConstBuilder<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    body: &'a mir::Body<'tcx>,
+    /// The current WIP node tree.
+    nodes: IndexVec<NodeId, Node<'tcx>>,
+    locals: IndexVec<mir::Local, NodeId>,
+    /// We only allow field accesses if they access
+    /// the result of a checked operation.
+    checked_op_locals: BitSet<mir::Local>,
+}
+
+impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>) -> Option<AbstractConstBuilder<'a, 'tcx>> {
+        // We only allow consts without control flow, so
+        // we check for cycles here which simplifies the
+        // rest of this implementation.
+        if body.is_cfg_cyclic() {
+            return None;
+        }
+
+        // We don't have to look at concrete constants, as we
+        // can just evaluate them.
+        if !body.is_polymorphic {
+            return None;
+        }
+
+        Some(AbstractConstBuilder {
+            tcx,
+            body,
+            nodes: IndexVec::new(),
+            locals: IndexVec::from_elem(NodeId::MAX, &body.local_decls),
+            checked_op_locals: BitSet::new_empty(body.local_decls.len()),
+        })
+    }
+    fn operand_to_node(&mut self, op: &mir::Operand<'tcx>) -> Option<NodeId> {
+        debug!("operand_to_node: op={:?}", op);
+        const ZERO_FIELD: mir::Field = mir::Field::from_usize(0);
+        match op {
+            mir::Operand::Copy(p) | mir::Operand::Move(p) => {
+                // Do not allow any projections.
+                //
+                // One exception are field accesses on the result of checked operations,
+                // which are required to support things like `1 + 2`.
+                if let Some(p) = p.as_local() {
+                    debug_assert!(!self.checked_op_locals.contains(p));
+                    Some(self.locals[p])
+                } else if let &[mir::ProjectionElem::Field(ZERO_FIELD, _)] = p.projection.as_ref() {
+                    // Only allow field accesses if the given local
+                    // contains the result of a checked operation.
+                    if self.checked_op_locals.contains(p.local) {
+                        Some(self.locals[p.local])
+                    } else {
+                        None
+                    }
+                } else {
+                    None
+                }
+            }
+            mir::Operand::Constant(ct) => Some(self.nodes.push(Node::Leaf(ct.literal))),
+        }
+    }
+
+    /// We do not allow all binary operations in abstract consts, so filter disallowed ones.
+    fn check_binop(op: mir::BinOp) -> bool {
+        use mir::BinOp::*;
+        match op {
+            Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Shl | Shr | Eq | Lt | Le
+            | Ne | Ge | Gt => true,
+            Offset => false,
+        }
+    }
+
+    /// While we currently allow all unary operations, we still want to explicitly guard against
+    /// future changes here.
+    fn check_unop(op: mir::UnOp) -> bool {
+        use mir::UnOp::*;
+        match op {
+            Not | Neg => true,
+        }
+    }
+
+    fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Option<()> {
+        debug!("AbstractConstBuilder: stmt={:?}", stmt);
+        match stmt.kind {
+            StatementKind::Assign(box (ref place, ref rvalue)) => {
+                let local = place.as_local()?;
+                match *rvalue {
+                    Rvalue::Use(ref operand) => {
+                        self.locals[local] = self.operand_to_node(operand)?;
+                        Some(())
+                    }
+                    Rvalue::BinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
+                        let lhs = self.operand_to_node(lhs)?;
+                        let rhs = self.operand_to_node(rhs)?;
+                        self.locals[local] = self.nodes.push(Node::Binop(op, lhs, rhs));
+                        if op.is_checkable() {
+                            bug!("unexpected unchecked checkable binary operation");
+                        } else {
+                            Some(())
+                        }
+                    }
+                    Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
+                        let lhs = self.operand_to_node(lhs)?;
+                        let rhs = self.operand_to_node(rhs)?;
+                        self.locals[local] = self.nodes.push(Node::Binop(op, lhs, rhs));
+                        self.checked_op_locals.insert(local);
+                        Some(())
+                    }
+                    Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => {
+                        let operand = self.operand_to_node(operand)?;
+                        self.locals[local] = self.nodes.push(Node::UnaryOp(op, operand));
+                        Some(())
+                    }
+                    _ => None,
+                }
+            }
+            // These are not actually relevant for us here, so we can ignore them.
+            StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => Some(()),
+            _ => None,
+        }
+    }
+
+    /// Possible return values:
+    ///
+    /// - `None`: unsupported terminator, stop building
+    /// - `Some(None)`: supported terminator, finish building
+    /// - `Some(Some(block))`: support terminator, build `block` next
+    fn build_terminator(
+        &mut self,
+        terminator: &mir::Terminator<'tcx>,
+    ) -> Option<Option<mir::BasicBlock>> {
+        debug!("AbstractConstBuilder: terminator={:?}", terminator);
+        match terminator.kind {
+            TerminatorKind::Goto { target } => Some(Some(target)),
+            TerminatorKind::Return => Some(None),
+            TerminatorKind::Call {
+                ref func,
+                ref args,
+                destination: Some((ref place, target)),
+                // We do not care about `cleanup` here. Any branch which
+                // uses `cleanup` will fail const-eval and they therefore
+                // do not matter when checking for const evaluatability.
+                //
+                // Do note that even if `panic::catch_unwind` is made const,
+                // we still do not have to care about this, as we do not look
+                // into functions.
+                cleanup: _,
+                // Do not allow overloaded operators for now,
+                // we probably do want to allow this in the future.
+                //
+                // This is currently fairly irrelevant as it requires `const Trait`s.
+                from_hir_call: true,
+                fn_span: _,
+            } => {
+                let local = place.as_local()?;
+                let func = self.operand_to_node(func)?;
+                let args = self.tcx.arena.alloc_from_iter(
+                    args.iter()
+                        .map(|arg| self.operand_to_node(arg))
+                        .collect::<Option<Vec<NodeId>>>()?,
+                );
+                self.locals[local] = self.nodes.push(Node::FunctionCall(func, args));
+                Some(Some(target))
+            }
+            // We only allow asserts for checked operations.
+            //
+            // These asserts seem to all have the form `!_local.0` so
+            // we only allow exactly that.
+            TerminatorKind::Assert { ref cond, expected: false, target, .. } => {
+                let p = match cond {
+                    mir::Operand::Copy(p) | mir::Operand::Move(p) => p,
+                    mir::Operand::Constant(_) => bug!("unexpected assert"),
+                };
+
+                const ONE_FIELD: mir::Field = mir::Field::from_usize(1);
+                debug!("proj: {:?}", p.projection);
+                if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() {
+                    // Only allow asserts checking the result of a checked operation.
+                    if self.checked_op_locals.contains(p.local) {
+                        return Some(Some(target));
+                    }
+                }
+
+                None
+            }
+            _ => None,
+        }
+    }
+
+    /// Builds the abstract const by walking the mir from start to finish
+    /// and bailing out when encountering an unsupported operation.
+    fn build(mut self) -> Option<&'tcx [Node<'tcx>]> {
+        let mut block = &self.body.basic_blocks()[mir::START_BLOCK];
+        // We checked for a cyclic cfg above, so this should terminate.
+        loop {
+            debug!("AbstractConstBuilder: block={:?}", block);
+            for stmt in block.statements.iter() {
+                self.build_statement(stmt)?;
+            }
+
+            if let Some(next) = self.build_terminator(block.terminator())? {
+                block = &self.body.basic_blocks()[next];
+            } else {
+                return Some(self.tcx.arena.alloc_from_iter(self.nodes));
+            }
+        }
+    }
+}
+
+/// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead.
+pub(super) fn mir_abstract_const<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def: ty::WithOptConstParam<LocalDefId>,
+) -> Option<&'tcx [Node<'tcx>]> {
+    if tcx.features().const_evaluatable_checked {
+        match tcx.def_kind(def.did) {
+            // FIXME(const_evaluatable_checked): We currently only do this for anonymous constants,
+            // meaning that we do not look into associated constants. I(@lcnr) am not yet sure whether
+            // we want to look into them or treat them as opaque projections.
+            //
+            // Right now we do neither of that and simply always fail to unify them.
+            DefKind::AnonConst => (),
+            _ => return None,
+        }
+        let body = tcx.mir_const(def).borrow();
+        AbstractConstBuilder::new(tcx, &body)?.build()
+    } else {
+        None
+    }
+}
+
+pub(super) fn try_unify_abstract_consts<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ((a, a_substs), (b, b_substs)): (
+        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+    ),
+) -> bool {
+    if let Some(a) = AbstractConst::new(tcx, a, a_substs) {
+        if let Some(b) = AbstractConst::new(tcx, b, b_substs) {
+            return try_unify(tcx, a, b);
+        }
+    }
+
+    false
+}
+
+/// Tries to unify two abstract constants using structural equality.
+pub(super) fn try_unify<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    a: AbstractConst<'tcx>,
+    b: AbstractConst<'tcx>,
+) -> bool {
+    match (a.root(), b.root()) {
+        (Node::Leaf(a_ct), Node::Leaf(b_ct)) => {
+            let a_ct = a_ct.subst(tcx, a.substs);
+            let b_ct = b_ct.subst(tcx, b.substs);
+            match (a_ct.val, b_ct.val) {
+                // We can just unify errors with everything to reduce the amount of
+                // emitted errors here.
+                (ty::ConstKind::Error(_), _) | (_, ty::ConstKind::Error(_)) => true,
+                (ty::ConstKind::Param(a_param), ty::ConstKind::Param(b_param)) => {
+                    a_param == b_param
+                }
+                (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val,
+                // If we have `fn a<const N: usize>() -> [u8; N + 1]` and `fn b<const M: usize>() -> [u8; 1 + M]`
+                // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This
+                // means that we only allow inference variables if they are equal.
+                (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val,
+                // FIXME(const_evaluatable_checked): We may want to either actually try
+                // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like
+                // this, for now we just return false here.
+                _ => false,
+            }
+        }
+        (Node::Binop(a_op, al, ar), Node::Binop(b_op, bl, br)) if a_op == b_op => {
+            try_unify(tcx, a.subtree(al), b.subtree(bl))
+                && try_unify(tcx, a.subtree(ar), b.subtree(br))
+        }
+        (Node::UnaryOp(a_op, av), Node::UnaryOp(b_op, bv)) if a_op == b_op => {
+            try_unify(tcx, a.subtree(av), b.subtree(bv))
+        }
+        (Node::FunctionCall(a_f, a_args), Node::FunctionCall(b_f, b_args))
+            if a_args.len() == b_args.len() =>
+        {
+            try_unify(tcx, a.subtree(a_f), b.subtree(b_f))
+                && a_args
+                    .iter()
+                    .zip(b_args)
+                    .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
+        }
+        _ => false,
+    }
+}
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 a9651144e59..bda4351b2f2 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1512,12 +1512,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                 // avoid inundating the user with unnecessary errors, but we now
                 // check upstream for type errors and don't add the obligations to
                 // begin with in those cases.
-                if self
-                    .tcx
-                    .lang_items()
-                    .sized_trait()
-                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
-                {
+                if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
                     self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
                     return;
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 1dd50d69a21..5b4314598de 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -476,6 +476,25 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
 
                 ty::PredicateAtom::ConstEquate(c1, c2) => {
                     debug!("equating consts: c1={:?} c2={:?}", c1, c2);
+                    if self.selcx.tcx().features().const_evaluatable_checked {
+                        // FIXME: we probably should only try to unify abstract constants
+                        // if the constants depend on generic parameters.
+                        //
+                        // Let's just see where this breaks :shrug:
+                        if let (
+                            ty::ConstKind::Unevaluated(a_def, a_substs, None),
+                            ty::ConstKind::Unevaluated(b_def, b_substs, None),
+                        ) = (c1.val, c2.val)
+                        {
+                            if self
+                                .selcx
+                                .tcx()
+                                .try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs)))
+                            {
+                                return ProcessResult::Changed(vec![]);
+                            }
+                        }
+                    }
 
                     let stalled_on = &mut pending_obligation.stalled_on;
 
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index b72e86a4cbd..79495ba7f9b 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -552,6 +552,21 @@ pub fn provide(providers: &mut ty::query::Providers) {
         vtable_methods,
         type_implements_trait,
         subst_and_check_impossible_predicates,
+        mir_abstract_const: |tcx, def_id| {
+            let def_id = def_id.expect_local();
+            if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
+                tcx.mir_abstract_const_of_const_arg(def)
+            } else {
+                const_evaluatable::mir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
+            }
+        },
+        mir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
+            const_evaluatable::mir_abstract_const(
+                tcx,
+                ty::WithOptConstParam { did, const_param_did: Some(param_did) },
+            )
+        },
+        try_unify_abstract_consts: const_evaluatable::try_unify_abstract_consts,
         ..*providers
     };
 }
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 7cc567dabb2..2fad54013ad 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -110,25 +110,15 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
             .map(|i| chalk_ir::AssocTypeId(i.def_id))
             .collect();
 
-        let well_known = if self
-            .interner
-            .tcx
-            .lang_items()
-            .sized_trait()
-            .map(|t| def_id == t)
-            .unwrap_or(false)
-        {
+        let well_known = if self.interner.tcx.lang_items().sized_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Sized)
-        } else if self.interner.tcx.lang_items().copy_trait().map(|t| def_id == t).unwrap_or(false)
-        {
+        } else if self.interner.tcx.lang_items().copy_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Copy)
-        } else if self.interner.tcx.lang_items().clone_trait().map(|t| def_id == t).unwrap_or(false)
-        {
+        } else if self.interner.tcx.lang_items().clone_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Clone)
-        } else if self.interner.tcx.lang_items().drop_trait().map(|t| def_id == t).unwrap_or(false)
-        {
+        } else if self.interner.tcx.lang_items().drop_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Drop)
-        } else if self.interner.tcx.lang_items().fn_trait().map(|t| def_id == t).unwrap_or(false) {
+        } else if self.interner.tcx.lang_items().fn_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Fn)
         } else if self
             .interner
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index 836a4ff78c7..7cb23dc0537 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -164,7 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     // If all the obligations hold (or there are no obligations) the tail expression
                     // we can suggest to return a boxed trait object instead of an opaque type.
-                    if suggest_box { self.ret_type_span.clone() } else { None }
+                    if suggest_box { self.ret_type_span } else { None }
                 }
                 _ => None,
             };
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index dba46f35dca..d5563cdac02 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -1243,10 +1243,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else if check_completeness && !error_happened && !remaining_fields.is_empty() {
             let no_accessible_remaining_fields = remaining_fields
                 .iter()
-                .filter(|(_, (_, field))| {
+                .find(|(_, (_, field))| {
                     field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
                 })
-                .next()
                 .is_none();
 
             if no_accessible_remaining_fields {
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 6be2fdf9f19..54b0671fab5 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -1141,10 +1141,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else if !etc && !unmentioned_fields.is_empty() {
             let no_accessible_unmentioned_fields = unmentioned_fields
                 .iter()
-                .filter(|(field, _)| {
+                .find(|(field, _)| {
                     field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
                 })
-                .next()
                 .is_none();
 
             if no_accessible_unmentioned_fields {
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
index 042ecdbadc6..373acb95c9e 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
@@ -308,18 +308,25 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Error(_) => {}
             _ => {
-                struct_span_err!(
+                let mut err = struct_span_err!(
                     self.tcx.sess,
                     ty.span,
                     E0118,
-                    "no base type found for inherent implementation"
-                )
-                .span_label(ty.span, "impl requires a base type")
-                .note(
-                    "either implement a trait on it or create a newtype \
-                       to wrap it instead",
-                )
-                .emit();
+                    "no nominal type found for inherent implementation"
+                );
+
+                err.span_label(ty.span, "impl requires a nominal type")
+                    .note("either implement a trait on it or create a newtype to wrap it instead");
+
+                if let ty::Ref(_, subty, _) = self_ty.kind() {
+                    err.note(&format!(
+                        "you could also try moving the reference to \
+                            uses of `{}` (such as `self`) within the implementation",
+                        subty
+                    ));
+                }
+
+                err.emit();
             }
         }
     }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 9b8427a4695..731ccfad2b4 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1693,25 +1693,27 @@ pub fn const_evaluatable_predicates_of<'tcx>(
 ) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> {
     #[derive(Default)]
     struct ConstCollector<'tcx> {
-        ct: SmallVec<[(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>); 4]>,
+        ct: SmallVec<[(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>, Span); 4]>,
+        curr_span: Span,
     }
 
     impl<'tcx> TypeVisitor<'tcx> for ConstCollector<'tcx> {
         fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> bool {
             if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
-                self.ct.push((def, substs));
+                self.ct.push((def, substs, self.curr_span));
             }
             false
         }
     }
 
     let mut collector = ConstCollector::default();
-    for (pred, _span) in predicates.predicates.iter() {
+    for &(pred, span) in predicates.predicates.iter() {
+        collector.curr_span = span;
         pred.visit_with(&mut collector);
     }
     warn!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.ct);
-    collector.ct.into_iter().map(move |(def_id, subst)| {
-        (ty::PredicateAtom::ConstEvaluatable(def_id, subst).to_predicate(tcx), DUMMY_SP)
+    collector.ct.into_iter().map(move |(def_id, subst, span)| {
+        (ty::PredicateAtom::ConstEvaluatable(def_id, subst).to_predicate(tcx), span)
     })
 }
 
diff --git a/config.toml.example b/config.toml.example
index 9135843045a..99e6f9dceb4 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -126,6 +126,23 @@
 # General build configuration options
 # =============================================================================
 [build]
+# The default stage to use for the `doc` subcommand
+#doc-stage = 0
+
+# The default stage to use for the `build` subcommand
+#build-stage = 1
+
+# The default stage to use for the `test` subcommand
+#test-stage = 1
+
+# The default stage to use for the `dist` subcommand
+#dist-stage = 2
+
+# The default stage to use for the `install` subcommand
+#install-stage = 2
+
+# The default stage to use for the `bench` subcommand
+#bench-stage = 2
 
 # Build triple for the original snapshot compiler. This must be a compiler that
 # nightlies are already produced for. The current platform must be able to run
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index 40aa4d850f5..24d17fdd880 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -1343,6 +1343,10 @@ impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
 
 #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
 impl<T> From<BinaryHeap<T>> for Vec<T> {
+    /// Converts a `BinaryHeap<T>` into a `Vec<T>`.
+    ///
+    /// This conversion requires no data movement or allocation, and has
+    /// constant time complexity.
     fn from(heap: BinaryHeap<T>) -> Vec<T> {
         heap.data
     }
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index 6c343b17264..8776a5efbe4 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -465,6 +465,22 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
         unsafe { &mut (*self.node.as_ptr()) }
     }
 
+    /// Borrows a mutable reference to one of the keys stored in the node.
+    ///
+    /// # Safety
+    /// The node has more than `idx` initialized elements.
+    pub unsafe fn key_mut_at(&mut self, idx: usize) -> &mut K {
+        unsafe { self.reborrow_mut().into_key_mut_at(idx) }
+    }
+
+    /// Borrows a mutable reference to one of the values stored in the node.
+    ///
+    /// # Safety
+    /// The node has more than `idx` initialized elements.
+    pub unsafe fn val_mut_at(&mut self, idx: usize) -> &mut V {
+        unsafe { self.reborrow_mut().into_val_mut_at(idx) }
+    }
+
     fn keys_mut(&mut self) -> &mut [K] {
         // SAFETY: the caller will not be able to call further methods on self
         // until the key slice reference is dropped, as we have unique access
@@ -555,15 +571,14 @@ impl<'a, K, V, Type> NodeRef<marker::ValMut<'a>, K, V, Type> {
 impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
     /// Adds a key/value pair to the end of the node.
     pub fn push(&mut self, key: K, val: V) {
-        assert!(self.len() < CAPACITY);
-
-        let idx = self.len();
-
+        let len = &mut self.as_leaf_mut().len;
+        let idx = *len as usize;
+        assert!(idx < CAPACITY);
+        *len += 1;
         unsafe {
-            ptr::write(self.keys_mut().get_unchecked_mut(idx), key);
-            ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
+            ptr::write(self.key_mut_at(idx), key);
+            ptr::write(self.val_mut_at(idx), val);
         }
-        self.as_leaf_mut().len += 1;
     }
 
     /// Adds a key/value pair to the beginning of the node.
@@ -600,17 +615,15 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
     /// the end of the node.
     pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
         assert!(edge.height == self.height - 1);
-        assert!(self.len() < CAPACITY);
-
-        let idx = self.len();
 
+        let len = &mut self.as_leaf_mut().len;
+        let idx = *len as usize;
+        assert!(idx < CAPACITY);
+        *len += 1;
         unsafe {
-            ptr::write(self.keys_mut().get_unchecked_mut(idx), key);
-            ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
+            ptr::write(self.key_mut_at(idx), key);
+            ptr::write(self.val_mut_at(idx), val);
             self.as_internal_mut().edges.get_unchecked_mut(idx + 1).write(edge.node);
-
-            self.as_leaf_mut().len += 1;
-
             Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link();
         }
     }
@@ -903,7 +916,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
     /// The returned pointer points to the inserted value.
     fn insert_fit(&mut self, key: K, val: V) -> *mut V {
         self.leafy_insert_fit(key, val);
-        unsafe { self.node.vals_mut().get_unchecked_mut(self.idx) }
+        unsafe { self.node.val_mut_at(self.idx) }
     }
 }
 
diff --git a/library/alloc/src/collections/vec_deque.rs b/library/alloc/src/collections/vec_deque.rs
index 253a3e9f2be..65cfe9a9b49 100644
--- a/library/alloc/src/collections/vec_deque.rs
+++ b/library/alloc/src/collections/vec_deque.rs
@@ -1089,11 +1089,7 @@ impl<T> VecDeque<T> {
     where
         R: RangeBounds<usize>,
     {
-        // SAFETY: This buffer is only used to check the range. It might be partially
-        // uninitialized, but `check_range` needs a contiguous slice.
-        // https://github.com/rust-lang/rust/pull/75207#discussion_r471193682
-        let buffer = unsafe { slice::from_raw_parts(self.ptr(), self.len()) };
-        let Range { start, end } = buffer.check_range(range);
+        let Range { start, end } = slice::check_range(self.len(), range);
         let tail = self.wrap_add(self.tail, start);
         let head = self.wrap_add(self.tail, end);
         (tail, head)
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 5774ebb9b19..7881c101f9f 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -76,6 +76,7 @@
 #![cfg_attr(test, feature(test))]
 #![feature(allocator_api)]
 #![feature(array_chunks)]
+#![feature(array_windows)]
 #![feature(allow_internal_unstable)]
 #![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 677bfdd2349..79403cf8687 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -91,10 +91,14 @@ use crate::borrow::ToOwned;
 use crate::boxed::Box;
 use crate::vec::Vec;
 
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub use core::slice::check_range;
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use core::slice::ArrayChunks;
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use core::slice::ArrayChunksMut;
+#[unstable(feature = "array_windows", issue = "75027")]
+pub use core::slice::ArrayWindows;
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use core::slice::SliceIndex;
 #[stable(feature = "from_ref", since = "1.28.0")]
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index e1724bf3c9a..2b0ce5ede56 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -49,6 +49,7 @@ use core::iter::{FromIterator, FusedIterator};
 use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds};
 use core::ptr;
+use core::slice;
 use core::str::{lossy, pattern::Pattern};
 
 use crate::borrow::{Cow, ToOwned};
@@ -1506,7 +1507,7 @@ impl String {
         // of the vector version. The data is just plain bytes.
         // Because the range removal happens in Drop, if the Drain iterator is leaked,
         // the removal will not happen.
-        let Range { start, end } = self.as_bytes().check_range(range);
+        let Range { start, end } = slice::check_range(self.len(), range);
         assert!(self.is_char_boundary(start));
         assert!(self.is_char_boundary(end));
 
diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index cb4c1c20abc..9dbea0dc9e6 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -174,7 +174,9 @@ use crate::raw_vec::RawVec;
 ///
 /// // ... and that's all!
 /// // you can also do it like this:
-/// let x : &[usize] = &v;
+/// let u: &[usize] = &v;
+/// // or like this:
+/// let u: &[_] = &v;
 /// ```
 ///
 /// In Rust, it's more common to pass slices as arguments rather than vectors
@@ -1310,7 +1312,7 @@ impl<T> Vec<T> {
         // the hole, and the vector length is restored to the new length.
         //
         let len = self.len();
-        let Range { start, end } = self.check_range(range);
+        let Range { start, end } = slice::check_range(len, range);
 
         unsafe {
             // set self.vec length's to start, to be safe in case Drain is leaked
@@ -3037,6 +3039,7 @@ impl<T> AsIntoIter for IntoIter<T> {
 /// A draining iterator for `Vec<T>`.
 ///
 /// This `struct` is created by [`Vec::drain`].
+/// See its documentation for more.
 #[stable(feature = "drain", since = "1.6.0")]
 pub struct Drain<'a, T: 'a> {
     /// Index of tail to preserve
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index b20cf076aca..ed8ee2d8823 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1921,3 +1921,24 @@ fn different_str_pattern_forwarding_lifetimes() {
 
     foo::<&str>("x");
 }
+
+#[test]
+fn test_str_multiline() {
+    let a: String = "this \
+is a test"
+        .to_string();
+    let b: String = "this \
+              is \
+              another \
+              test"
+        .to_string();
+    assert_eq!(a, "this is a test".to_string());
+    assert_eq!(b, "this is another test".to_string());
+}
+
+#[test]
+fn test_str_escapes() {
+    let x = "\\\\\
+    ";
+    assert_eq!(x, r"\\"); // extraneous whitespace stripped
+}
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 563dd7ab645..368ca4c5432 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -919,7 +919,7 @@ fn test_from_iter_partially_drained_in_place_specialization() {
 #[test]
 fn test_from_iter_specialization_with_iterator_adapters() {
     fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {};
-    let src: Vec<usize> = vec![0usize; 65535];
+    let src: Vec<usize> = vec![0usize; 256];
     let srcptr = src.as_ptr();
     let iter = src
         .into_iter()
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index ec343f75f34..bec3adfa984 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -21,9 +21,9 @@ pub use self::future::Future;
 #[unstable(feature = "into_future", issue = "67644")]
 pub use into_future::IntoFuture;
 
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 pub use pending::{pending, Pending};
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 pub use ready::{ready, Ready};
 
 #[unstable(feature = "future_poll_fn", issue = "72302")]
diff --git a/library/core/src/future/pending.rs b/library/core/src/future/pending.rs
index c1a4e0cda03..4fec219ede2 100644
--- a/library/core/src/future/pending.rs
+++ b/library/core/src/future/pending.rs
@@ -11,7 +11,7 @@ use crate::task::{Context, Poll};
 /// documentation for more.
 ///
 /// [`pending`]: fn.pending.html
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 #[must_use = "futures do nothing unless you `.await` or poll them"]
 pub struct Pending<T> {
     _data: marker::PhantomData<T>,
@@ -31,12 +31,12 @@ pub struct Pending<T> {
 /// unreachable!();
 /// # }
 /// ```
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 pub fn pending<T>() -> Pending<T> {
     Pending { _data: marker::PhantomData }
 }
 
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 impl<T> Future for Pending<T> {
     type Output = T;
 
@@ -45,17 +45,17 @@ impl<T> Future for Pending<T> {
     }
 }
 
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 impl<T> Unpin for Pending<T> {}
 
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 impl<T> Debug for Pending<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Pending").finish()
     }
 }
 
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 impl<T> Clone for Pending<T> {
     fn clone(&self) -> Self {
         pending()
diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs
index ddae6cfed4b..fcfd8779b0a 100644
--- a/library/core/src/future/ready.rs
+++ b/library/core/src/future/ready.rs
@@ -8,15 +8,15 @@ use crate::task::{Context, Poll};
 /// documentation for more.
 ///
 /// [`ready`]: fn.ready.html
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 #[derive(Debug, Clone)]
 #[must_use = "futures do nothing unless you `.await` or poll them"]
 pub struct Ready<T>(Option<T>);
 
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 impl<T> Unpin for Ready<T> {}
 
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 impl<T> Future for Ready<T> {
     type Output = T;
 
@@ -42,7 +42,7 @@ impl<T> Future for Ready<T> {
 /// assert_eq!(a.await, 1);
 /// # }
 /// ```
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 pub fn ready<T>(t: T) -> Ready<T> {
     Ready(Some(t))
 }
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index d40a3802867..1192b9e164a 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -111,7 +111,7 @@ pub fn spin_loop() {
 #[inline]
 #[unstable(feature = "test", issue = "50297")]
 #[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
-pub fn black_box<T>(dummy: T) -> T {
+pub fn black_box<T>(mut dummy: T) -> T {
     // We need to "use" the argument in some way LLVM can't introspect, and on
     // targets that support it we can typically leverage inline assembly to do
     // this. LLVM's interpretation of inline assembly is that it's, well, a black
@@ -121,7 +121,8 @@ pub fn black_box<T>(dummy: T) -> T {
     #[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
     // SAFETY: the inline assembly is a no-op.
     unsafe {
-        llvm_asm!("" : : "r"(&dummy));
+        // FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
+        llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
     }
 
     dummy
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 4202e52448d..ddb1aaebc1f 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -7,11 +7,8 @@ use super::Map;
 /// An iterator that maps each element to an iterator, and yields the elements
 /// of the produced iterators.
 ///
-/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`flat_map`]: trait.Iterator.html#method.flat_map
-/// [`Iterator`]: trait.Iterator.html
+/// This `struct` is created by [`Iterator::flat_map`]. See its documentation
+/// for more.
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct FlatMap<I, U: IntoIterator, F> {
diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs
index 409f202780b..c5b3bd5cf11 100644
--- a/library/core/src/iter/adapters/fuse.rs
+++ b/library/core/src/iter/adapters/fuse.rs
@@ -9,11 +9,8 @@ use crate::ops::Try;
 /// An iterator that yields `None` forever after the underlying iterator
 /// yields `None` once.
 ///
-/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`fuse`]: trait.Iterator.html#method.fuse
-/// [`Iterator`]: trait.Iterator.html
+/// This `struct` is created by [`Iterator::fuse`]. See its documentation
+/// for more.
 #[derive(Clone, Debug)]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 6d8ed2f4ffb..aa1b5529df2 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -31,10 +31,10 @@ pub use crate::intrinsics::transmute;
 /// forever in an unreachable state. However, it does not guarantee that pointers
 /// to this memory will remain valid.
 ///
-/// * If you want to leak memory, see [`Box::leak`][leak].
-/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw].
+/// * If you want to leak memory, see [`Box::leak`].
+/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`].
 /// * If you want to dispose of a value properly, running its destructor, see
-/// [`mem::drop`][drop].
+/// [`mem::drop`].
 ///
 /// # Safety
 ///
@@ -132,15 +132,11 @@ pub use crate::intrinsics::transmute;
 /// ownership to `s` — the final step of interacting with `v` to dispose of it without
 /// running its destructor is entirely avoided.
 ///
-/// [drop]: fn.drop.html
-/// [uninit]: fn.uninitialized.html
-/// [clone]: ../clone/trait.Clone.html
-/// [swap]: fn.swap.html
-/// [box]: ../../std/boxed/struct.Box.html
-/// [leak]: ../../std/boxed/struct.Box.html#method.leak
-/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
+/// [`Box`]: ../../std/boxed/struct.Box.html
+/// [`Box::leak`]: ../../std/boxed/struct.Box.html#method.leak
+/// [`Box::into_raw`]: ../../std/boxed/struct.Box.html#method.into_raw
+/// [`mem::drop`]: drop
 /// [ub]: ../../reference/behavior-considered-undefined.html
-/// [`ManuallyDrop`]: struct.ManuallyDrop.html
 #[inline]
 #[rustc_const_stable(feature = "const_forget", since = "1.46.0")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -152,8 +148,6 @@ pub const fn forget<T>(t: T) {
 ///
 /// This function is just a shim intended to be removed when the `unsized_locals` feature gets
 /// stabilized.
-///
-/// [`forget`]: fn.forget.html
 #[inline]
 #[unstable(feature = "forget_unsized", issue = "none")]
 pub fn forget_unsized<T: ?Sized>(t: T) {
@@ -301,7 +295,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) {
 /// assert_eq!(2, mem::size_of::<ExampleUnion>());
 /// ```
 ///
-/// [alignment]: ./fn.align_of.html
+/// [alignment]: align_of
 #[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
@@ -365,7 +359,6 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
 /// [slice]: ../../std/primitive.slice.html
 /// [trait object]: ../../book/ch17-02-trait-objects.html
 /// [extern type]: ../../unstable-book/language-features/extern-types.html
-/// [`size_of_val`]: ../../core/mem/fn.size_of_val.html
 ///
 /// # Examples
 ///
@@ -501,7 +494,6 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
 /// [slice]: ../../std/primitive.slice.html
 /// [trait object]: ../../book/ch17-02-trait-objects.html
 /// [extern type]: ../../unstable-book/language-features/extern-types.html
-/// [`align_of_val`]: ../../core/mem/fn.align_of_val.html
 ///
 /// # Examples
 ///
@@ -540,7 +532,7 @@ pub unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
 /// `needs_drop` explicitly. Types like [`HashMap`], on the other hand, have to drop
 /// values one at a time and should use this API.
 ///
-/// [`drop_in_place`]: ../ptr/fn.drop_in_place.html
+/// [`drop_in_place`]: crate::ptr::drop_in_place
 /// [`HashMap`]: ../../std/collections/struct.HashMap.html
 ///
 /// # Examples
@@ -595,9 +587,9 @@ pub const fn needs_drop<T>() -> bool {
 /// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed].
 /// It is useful for FFI sometimes, but should generally be avoided.
 ///
-/// [zeroed]: union.MaybeUninit.html#method.zeroed
+/// [zeroed]: MaybeUninit::zeroed
 /// [ub]: ../../reference/behavior-considered-undefined.html
-/// [inv]: union.MaybeUninit.html#initialization-invariant
+/// [inv]: MaybeUninit#initialization-invariant
 ///
 /// # Examples
 ///
@@ -650,10 +642,10 @@ pub unsafe fn zeroed<T>() -> T {
 /// (Notice that the rules around uninitialized integers are not finalized yet, but
 /// until they are, it is advisable to avoid them.)
 ///
-/// [`MaybeUninit<T>`]: union.MaybeUninit.html
-/// [uninit]: union.MaybeUninit.html#method.uninit
-/// [assume_init]: union.MaybeUninit.html#method.assume_init
-/// [inv]: union.MaybeUninit.html#initialization-invariant
+/// [`MaybeUninit<T>`]: MaybeUninit
+/// [uninit]: MaybeUninit::uninit
+/// [assume_init]: MaybeUninit::assume_init
+/// [inv]: MaybeUninit#initialization-invariant
 #[inline(always)]
 #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -686,9 +678,6 @@ pub unsafe fn uninitialized<T>() -> T {
 /// assert_eq!(42, x);
 /// assert_eq!(5, y);
 /// ```
-///
-/// [`replace`]: fn.replace.html
-/// [`take`]: fn.take.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn swap<T>(x: &mut T, y: &mut T) {
@@ -754,10 +743,6 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 /// assert_eq!(buffer.get_and_reset(), vec![0, 1]);
 /// assert_eq!(buffer.buf.len(), 0);
 /// ```
-///
-/// [`Clone`]: ../../std/clone/trait.Clone.html
-/// [`replace`]: fn.replace.html
-/// [`swap`]: fn.swap.html
 #[inline]
 #[stable(feature = "mem_take", since = "1.40.0")]
 pub fn take<T: Default>(dest: &mut T) -> T {
@@ -822,10 +807,6 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 /// assert_eq!(buffer.replace_index(0, 2), 0);
 /// assert_eq!(buffer.buf[0], 2);
 /// ```
-///
-/// [`Clone`]: ../../std/clone/trait.Clone.html
-/// [`swap`]: fn.swap.html
-/// [`take`]: fn.take.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[must_use = "if you don't need the old value, you can just assign the new value directly"]
@@ -851,7 +832,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 /// Because `_x` is moved into the function, it is automatically dropped before
 /// the function returns.
 ///
-/// [drop]: ../ops/trait.Drop.html
+/// [drop]: Drop
 ///
 /// # Examples
 ///
@@ -894,8 +875,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 /// println!("x: {}, y: {}", x, y.0); // still available
 /// ```
 ///
-/// [`RefCell`]: ../../std/cell/struct.RefCell.html
-/// [`Copy`]: ../../std/marker/trait.Copy.html
+/// [`RefCell`]: crate::cell::RefCell
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn drop<T>(_x: T) {}
@@ -914,7 +894,6 @@ pub fn drop<T>(_x: T) {}
 /// `T`.
 ///
 /// [ub]: ../../reference/behavior-considered-undefined.html
-/// [size_of]: fn.size_of.html
 ///
 /// # Examples
 ///
@@ -960,8 +939,6 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
 /// Opaque type representing the discriminant of an enum.
 ///
 /// See the [`discriminant`] function in this module for more information.
-///
-/// [`discriminant`]: fn.discriminant.html
 #[stable(feature = "discriminant_value", since = "1.21.0")]
 pub struct Discriminant<T>(<T as DiscriminantKind>::Discriminant);
 
diff --git a/library/core/src/num/dec2flt/algorithm.rs b/library/core/src/num/dec2flt/algorithm.rs
index aaeb4d8a22c..a5fbdc6ee2d 100644
--- a/library/core/src/num/dec2flt/algorithm.rs
+++ b/library/core/src/num/dec2flt/algorithm.rs
@@ -60,12 +60,19 @@ mod fpu_precision {
     fn set_cw(cw: u16) {
         // SAFETY: the `fldcw` instruction has been audited to be able to work correctly with
         // any `u16`
-        unsafe { llvm_asm!("fldcw $0" :: "m" (cw) :: "volatile") }
+        unsafe {
+            asm!(
+                "fldcw ({})",
+                in(reg) &cw,
+                // FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
+                options(att_syntax, nostack),
+            )
+        }
     }
 
     /// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`.
     pub fn set_precision<T>() -> FPUControlWord {
-        let cw = 0u16;
+        let mut cw = 0_u16;
 
         // Compute the value for the Precision Control field that is appropriate for `T`.
         let cw_precision = match size_of::<T>() {
@@ -78,7 +85,14 @@ mod fpu_precision {
         // `FPUControlWord` structure is dropped
         // SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with
         // any `u16`
-        unsafe { llvm_asm!("fnstcw $0" : "=*m" (&cw) ::: "volatile") }
+        unsafe {
+            asm!(
+                "fnstcw ({})",
+                in(reg) &mut cw,
+                // FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
+                options(att_syntax, nostack),
+            )
+        }
 
         // Set the control word to the desired precision. This is achieved by masking away the old
         // precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above.
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index ed6202bb82f..6f3a3a86745 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -166,6 +166,16 @@ from_str_float_impl!(f64);
 ///
 /// This error is used as the error type for the [`FromStr`] implementation
 /// for [`f32`] and [`f64`].
+///
+/// # Example
+///
+/// ```
+/// use std::str::FromStr;
+///
+/// if let Err(e) = f64::from_str("a.12") {
+///     println!("Failed conversion to f64: {}", e);
+/// }
+/// ```
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ParseFloatError {
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 2a936c1867d..050c187e555 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -5286,6 +5286,14 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
 ///
 /// [`str.trim()`]: ../../std/primitive.str.html#method.trim
 /// [`i8::from_str_radix`]: ../../std/primitive.i8.html#method.from_str_radix
+///
+/// # Example
+///
+/// ```
+/// if let Err(e) = i32::from_str_radix("a12", 10) {
+///     println!("Failed conversion to i32: {}", e);
+/// }
+/// ```
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ParseIntError {
@@ -5293,6 +5301,18 @@ pub struct ParseIntError {
 }
 
 /// Enum to store the various types of errors that can cause parsing an integer to fail.
+///
+/// # Example
+///
+/// ```
+/// #![feature(int_error_matching)]
+///
+/// # fn main() {
+/// if let Err(e) = i32::from_str_radix("a12", 10) {
+///     println!("Failed conversion to i32: {:?}", e.kind());
+/// }
+/// # }
+/// ```
 #[unstable(
     feature = "int_error_matching",
     reason = "it can be useful to match errors when making error messages \
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index d67e0ae536d..16fcb6231dc 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -1,6 +1,6 @@
 //! Indexing implementations for `[T]`.
 
-use crate::ops;
+use crate::ops::{self, Bound, Range, RangeBounds};
 use crate::ptr;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -62,6 +62,79 @@ pub(super) fn slice_end_index_overflow_fail() -> ! {
     panic!("attempted to index slice up to maximum usize");
 }
 
+/// Performs bounds-checking of the given range.
+/// The returned [`Range`] is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]
+/// for slices of the given length.
+///
+/// [`get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
+/// [`get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
+///
+/// # Panics
+///
+/// Panics if the range is out of bounds.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(slice_check_range)]
+/// use std::slice;
+///
+/// let v = [10, 40, 30];
+/// assert_eq!(1..2, slice::check_range(v.len(), 1..2));
+/// assert_eq!(0..2, slice::check_range(v.len(), ..2));
+/// assert_eq!(1..3, slice::check_range(v.len(), 1..));
+/// ```
+///
+/// Panics when [`Index::index`] would panic:
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 2..1);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 1..4);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 1..=usize::MAX);
+/// ```
+///
+/// [`Index::index`]: ops::Index::index
+#[track_caller]
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub fn check_range<R: RangeBounds<usize>>(len: usize, range: R) -> Range<usize> {
+    let start = match range.start_bound() {
+        Bound::Included(&start) => start,
+        Bound::Excluded(start) => {
+            start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
+        }
+        Bound::Unbounded => 0,
+    };
+
+    let end = match range.end_bound() {
+        Bound::Included(end) => {
+            end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
+        }
+        Bound::Excluded(&end) => end,
+        Bound::Unbounded => len,
+    };
+
+    if start > end {
+        slice_index_order_fail(start, end);
+    }
+    if end > len {
+        slice_end_index_len_fail(end, len);
+    }
+
+    Range { start, end }
+}
+
 mod private_slice_index {
     use super::ops;
     #[stable(feature = "slice_get_slice", since = "1.28.0")]
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 2e8c3cd43e9..84fa34c75e3 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -1687,6 +1687,106 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
     }
 }
 
+/// A windowed iterator over a slice in overlapping chunks (`N` elements at a
+/// time), starting at the beginning of the slice
+///
+/// This struct is created by the [`array_windows`] method on [slices].
+///
+/// [`array_windows`]: ../../std/primitive.slice.html#method.array_windows
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug, Clone, Copy)]
+#[unstable(feature = "array_windows", issue = "75027")]
+pub struct ArrayWindows<'a, T: 'a, const N: usize> {
+    pub(crate) slice_head: *const T,
+    pub(crate) num: usize,
+    pub(crate) marker: marker::PhantomData<&'a [T; N]>,
+}
+
+#[unstable(feature = "array_windows", issue = "75027")]
+impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> {
+    type Item = &'a [T; N];
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.num == 0 {
+            return None;
+        }
+        // SAFETY:
+        // This is safe because it's indexing into a slice guaranteed to be length > N.
+        let ret = unsafe { &*self.slice_head.cast::<[T; N]>() };
+        // SAFETY: Guaranteed that there are at least 1 item remaining otherwise
+        // earlier branch would've been hit
+        self.slice_head = unsafe { self.slice_head.add(1) };
+
+        self.num -= 1;
+        Some(ret)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.num, Some(self.num))
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.num
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        if self.num <= n {
+            self.num = 0;
+            return None;
+        }
+        // SAFETY:
+        // This is safe because it's indexing into a slice guaranteed to be length > N.
+        let ret = unsafe { &*self.slice_head.add(n).cast::<[T; N]>() };
+        // SAFETY: Guaranteed that there are at least n items remaining
+        self.slice_head = unsafe { self.slice_head.add(n + 1) };
+
+        self.num -= n + 1;
+        Some(ret)
+    }
+
+    #[inline]
+    fn last(mut self) -> Option<Self::Item> {
+        self.nth(self.num.checked_sub(1)?)
+    }
+}
+
+#[unstable(feature = "array_windows", issue = "75027")]
+impl<'a, T, const N: usize> DoubleEndedIterator for ArrayWindows<'a, T, N> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T; N]> {
+        if self.num == 0 {
+            return None;
+        }
+        // SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing.
+        let ret = unsafe { &*self.slice_head.add(self.num - 1).cast::<[T; N]>() };
+        self.num -= 1;
+        Some(ret)
+    }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<&'a [T; N]> {
+        if self.num <= n {
+            self.num = 0;
+            return None;
+        }
+        // SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing.
+        let ret = unsafe { &*self.slice_head.add(self.num - (n + 1)).cast::<[T; N]>() };
+        self.num -= n + 1;
+        Some(ret)
+    }
+}
+
+#[unstable(feature = "array_windows", issue = "75027")]
+impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> {
+    fn is_empty(&self) -> bool {
+        self.num == 0
+    }
+}
+
 /// An iterator over a slice in (non-overlapping) chunks (`N` elements at a
 /// time), starting at the beginning of the slice.
 ///
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 64a707c39f0..8e9d1eb98a8 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -12,7 +12,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::intrinsics::assume;
 use crate::marker::{self, Copy};
 use crate::mem;
-use crate::ops::{Bound, FnMut, Range, RangeBounds};
+use crate::ops::{FnMut, Range, RangeBounds};
 use crate::option::Option;
 use crate::option::Option::{None, Some};
 use crate::ptr::{self, NonNull};
@@ -56,6 +56,9 @@ pub use iter::{RChunks, RChunksExact, RChunksExactMut, RChunksMut};
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use iter::{ArrayChunks, ArrayChunksMut};
 
+#[unstable(feature = "array_windows", issue = "75027")]
+pub use iter::ArrayWindows;
+
 #[unstable(feature = "split_inclusive", issue = "72360")]
 pub use iter::{SplitInclusive, SplitInclusiveMut};
 
@@ -72,8 +75,8 @@ pub use sort::heapsort;
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use index::SliceIndex;
 
-use index::{slice_end_index_len_fail, slice_index_order_fail};
-use index::{slice_end_index_overflow_fail, slice_start_index_overflow_fail};
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub use index::check_range;
 
 #[lang = "slice"]
 #[cfg(not(test))]
@@ -378,79 +381,6 @@ impl<T> [T] {
         unsafe { &mut *index.get_unchecked_mut(self) }
     }
 
-    /// Converts a range over this slice to [`Range`].
-    ///
-    /// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`].
-    ///
-    /// [`get_unchecked`]: #method.get_unchecked
-    /// [`get_unchecked_mut`]: #method.get_unchecked_mut
-    ///
-    /// # Panics
-    ///
-    /// Panics if the range is out of bounds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(slice_check_range)]
-    ///
-    /// let v = [10, 40, 30];
-    /// assert_eq!(1..2, v.check_range(1..2));
-    /// assert_eq!(0..2, v.check_range(..2));
-    /// assert_eq!(1..3, v.check_range(1..));
-    /// ```
-    ///
-    /// Panics when [`Index::index`] would panic:
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(2..1);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(1..4);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(1..=usize::MAX);
-    /// ```
-    ///
-    /// [`Index::index`]: crate::ops::Index::index
-    #[track_caller]
-    #[unstable(feature = "slice_check_range", issue = "76393")]
-    pub fn check_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> {
-        let start = match range.start_bound() {
-            Bound::Included(&start) => start,
-            Bound::Excluded(start) => {
-                start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
-            }
-            Bound::Unbounded => 0,
-        };
-
-        let len = self.len();
-        let end = match range.end_bound() {
-            Bound::Included(end) => {
-                end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
-            }
-            Bound::Excluded(&end) => end,
-            Bound::Unbounded => len,
-        };
-
-        if start > end {
-            slice_index_order_fail(start, end);
-        }
-        if end > len {
-            slice_end_index_len_fail(end, len);
-        }
-
-        Range { start, end }
-    }
-
     /// Returns a raw pointer to the slice's buffer.
     ///
     /// The caller must ensure that the slice outlives the pointer this
@@ -1099,6 +1029,40 @@ impl<T> [T] {
         }
     }
 
+    /// Returns an iterator over overlapping windows of `N` elements of  a slice,
+    /// starting at the beginning of the slice.
+    ///
+    /// This is the const generic equivalent of [`windows`].
+    ///
+    /// If `N` is smaller than the size of the array, it will return no windows.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// error before this method gets stabilized.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(array_windows)]
+    /// let slice = [0, 1, 2, 3];
+    /// let mut iter = slice.array_windows();
+    /// assert_eq!(iter.next().unwrap(), &[0, 1]);
+    /// assert_eq!(iter.next().unwrap(), &[1, 2]);
+    /// assert_eq!(iter.next().unwrap(), &[2, 3]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// [`windows`]: #method.windows
+    #[unstable(feature = "array_windows", issue = "75027")]
+    #[inline]
+    pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
+        assert_ne!(N, 0);
+
+        let num_windows = self.len().saturating_sub(N - 1);
+        ArrayWindows { slice_head: self.as_ptr(), num: num_windows, marker: marker::PhantomData }
+    }
+
     /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end
     /// of the slice.
     ///
@@ -2794,7 +2758,7 @@ impl<T> [T] {
     where
         T: Copy,
     {
-        let Range { start: src_start, end: src_end } = self.check_range(src);
+        let Range { start: src_start, end: src_end } = check_range(self.len(), src);
         let count = src_end - src_start;
         assert!(dest <= self.len() - count, "dest is out of bounds");
         // SAFETY: the conditions for `ptr::copy` have all been checked above,
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 9383e7c45fa..4e987a53b2c 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -112,6 +112,14 @@ impl<T, E> Poll<Option<Result<T, E>>> {
 
 #[stable(feature = "futures_api", since = "1.36.0")]
 impl<T> From<T> for Poll<T> {
+    /// Convert to a `Ready` variant.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use core::task::Poll;
+    /// assert_eq!(Poll::from(true), Poll::Ready(true));
+    /// ```
     fn from(t: T) -> Poll<T> {
         Poll::Ready(t)
     }
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index f39781788d7..6dc542dee58 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -693,7 +693,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn from_secs_f64(secs: f64) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn from_secs_f64(secs: f64) -> Duration {
         const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64;
         let nanos = secs * (NANOS_PER_SEC as f64);
         if !nanos.is_finite() {
@@ -727,7 +728,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn from_secs_f32(secs: f32) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn from_secs_f32(secs: f32) -> Duration {
         const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32;
         let nanos = secs * (NANOS_PER_SEC as f32);
         if !nanos.is_finite() {
@@ -761,7 +763,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn mul_f64(self, rhs: f64) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn mul_f64(self, rhs: f64) -> Duration {
         Duration::from_secs_f64(rhs * self.as_secs_f64())
     }
 
@@ -782,7 +785,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn mul_f32(self, rhs: f32) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn mul_f32(self, rhs: f32) -> Duration {
         Duration::from_secs_f32(rhs * self.as_secs_f32())
     }
 
@@ -802,7 +806,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn div_f64(self, rhs: f64) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn div_f64(self, rhs: f64) -> Duration {
         Duration::from_secs_f64(self.as_secs_f64() / rhs)
     }
 
@@ -824,7 +829,8 @@ impl Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn div_f32(self, rhs: f32) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn div_f32(self, rhs: f32) -> Duration {
         Duration::from_secs_f32(self.as_secs_f32() / rhs)
     }
 
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index a2e294ace18..a5b1b51e06c 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -2,6 +2,7 @@
 #![feature(array_chunks)]
 #![feature(array_methods)]
 #![feature(array_map)]
+#![feature(array_windows)]
 #![feature(bool_to_option)]
 #![feature(bound_cloned)]
 #![feature(box_syntax)]
@@ -10,8 +11,11 @@
 #![feature(core_private_diy_float)]
 #![feature(debug_non_exhaustive)]
 #![feature(dec2flt)]
+#![feature(div_duration)]
+#![feature(duration_consts_2)]
 #![feature(duration_constants)]
 #![feature(duration_saturating_ops)]
+#![feature(duration_zero)]
 #![feature(exact_size_is_empty)]
 #![feature(fixed_size_array)]
 #![feature(flt2dec)]
diff --git a/library/core/tests/num/i32.rs b/library/core/tests/num/i32.rs
index 39250ee84bc..4acc760ffac 100644
--- a/library/core/tests/num/i32.rs
+++ b/library/core/tests/num/i32.rs
@@ -1 +1,30 @@
 int_module!(i32, i32);
+
+#[test]
+fn test_arith_operation() {
+    let a: isize = 10;
+    assert_eq!(a * (a - 1), 90);
+    let i32_a: isize = 10;
+    assert_eq!(i32_a, 10);
+    assert_eq!(i32_a - 10, 0);
+    assert_eq!(i32_a / 10, 1);
+    assert_eq!(i32_a - 20, -10);
+    assert_eq!(i32_a << 10, 10240);
+    assert_eq!(i32_a << 16, 655360);
+    assert_eq!(i32_a * 16, 160);
+    assert_eq!(i32_a * i32_a * i32_a, 1000);
+    assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000);
+    assert_eq!(i32_a * i32_a / i32_a * i32_a, 100);
+    assert_eq!(i32_a * (i32_a - 1) << (2 + i32_a as usize), 368640);
+    let i32_b: isize = 0x10101010;
+    assert_eq!(i32_b + 1 - 1, i32_b);
+    assert_eq!(i32_b << 1, i32_b << 1);
+    assert_eq!(i32_b >> 1, i32_b >> 1);
+    assert_eq!(i32_b & i32_b << 1, 0);
+    assert_eq!(i32_b | i32_b << 1, 0x30303030);
+    let i32_c: isize = 0x10101010;
+    assert_eq!(
+        i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3),
+        i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3)
+    );
+}
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 9b31e532a6a..9556d43f9d7 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -658,6 +658,55 @@ fn test_array_chunks_mut_zip() {
 }
 
 #[test]
+fn test_array_windows_infer() {
+    let v: &[i32] = &[0, 1, 0, 1];
+    assert_eq!(v.array_windows::<2>().count(), 3);
+    let c = v.array_windows();
+    for &[a, b] in c {
+        assert_eq!(a + b, 1);
+    }
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
+    let total = v2.array_windows().map(|&[a, b, c]| a + b + c).sum::<i32>();
+    assert_eq!(total, 3 + 6 + 9 + 12 + 15);
+}
+
+#[test]
+fn test_array_windows_count() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.array_windows::<3>();
+    assert_eq!(c.count(), 4);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.array_windows::<6>();
+    assert_eq!(c2.count(), 0);
+
+    let v3: &[i32] = &[];
+    let c3 = v3.array_windows::<2>();
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_array_windows_nth() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let snd = v.array_windows::<4>().nth(1);
+    assert_eq!(snd, Some(&[1, 2, 3, 4]));
+    let mut arr_windows = v.array_windows::<2>();
+    assert_ne!(arr_windows.nth(0), arr_windows.nth(0));
+    let last = v.array_windows::<3>().last();
+    assert_eq!(last, Some(&[3, 4, 5]));
+}
+
+#[test]
+fn test_array_windows_nth_back() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let snd = v.array_windows::<4>().nth_back(1);
+    assert_eq!(snd, Some(&[1, 2, 3, 4]));
+    let mut arr_windows = v.array_windows::<2>();
+    assert_ne!(arr_windows.nth_back(0), arr_windows.nth_back(0));
+}
+
+#[test]
 fn test_rchunks_count() {
     let v: &[i32] = &[0, 1, 2, 3, 4, 5];
     let c = v.rchunks(3);
diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs
index 4f90eb63b04..7c43885040b 100644
--- a/library/core/tests/time.rs
+++ b/library/core/tests/time.rs
@@ -321,3 +321,104 @@ fn debug_formatting_precision_high() {
     assert_eq!(format!("{:.10?}", Duration::new(4, 001_000_000)), "4.0010000000s");
     assert_eq!(format!("{:.20?}", Duration::new(4, 001_000_000)), "4.00100000000000000000s");
 }
+
+#[test]
+fn duration_const() {
+    // test that the methods of `Duration` are usable in a const context
+
+    const DURATION: Duration = Duration::new(0, 123_456_789);
+
+    const SUB_SEC_MILLIS: u32 = DURATION.subsec_millis();
+    assert_eq!(SUB_SEC_MILLIS, 123);
+
+    const SUB_SEC_MICROS: u32 = DURATION.subsec_micros();
+    assert_eq!(SUB_SEC_MICROS, 123_456);
+
+    const SUB_SEC_NANOS: u32 = DURATION.subsec_nanos();
+    assert_eq!(SUB_SEC_NANOS, 123_456_789);
+
+    const ZERO: Duration = Duration::zero();
+    assert_eq!(ZERO, Duration::new(0, 0));
+
+    const IS_ZERO: bool = ZERO.is_zero();
+    assert!(IS_ZERO);
+
+    const ONE: Duration = Duration::new(1, 0);
+
+    const SECONDS: u64 = ONE.as_secs();
+    assert_eq!(SECONDS, 1);
+
+    const FROM_SECONDS: Duration = Duration::from_secs(1);
+    assert_eq!(FROM_SECONDS, ONE);
+
+    const SECONDS_F32: f32 = ONE.as_secs_f32();
+    assert_eq!(SECONDS_F32, 1.0);
+
+    const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0);
+    assert_eq!(FROM_SECONDS_F32, ONE);
+
+    const SECONDS_F64: f64 = ONE.as_secs_f64();
+    assert_eq!(SECONDS_F64, 1.0);
+
+    const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0);
+    assert_eq!(FROM_SECONDS_F64, ONE);
+
+    const MILLIS: u128 = ONE.as_millis();
+    assert_eq!(MILLIS, 1_000);
+
+    const FROM_MILLIS: Duration = Duration::from_millis(1_000);
+    assert_eq!(FROM_MILLIS, ONE);
+
+    const MICROS: u128 = ONE.as_micros();
+    assert_eq!(MICROS, 1_000_000);
+
+    const FROM_MICROS: Duration = Duration::from_micros(1_000_000);
+    assert_eq!(FROM_MICROS, ONE);
+
+    const NANOS: u128 = ONE.as_nanos();
+    assert_eq!(NANOS, 1_000_000_000);
+
+    const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000);
+    assert_eq!(FROM_NANOS, ONE);
+
+    const MAX: Duration = Duration::new(u64::MAX, 999_999_999);
+
+    const CHECKED_ADD: Option<Duration> = MAX.checked_add(ONE);
+    assert_eq!(CHECKED_ADD, None);
+
+    const CHECKED_SUB: Option<Duration> = ZERO.checked_sub(ONE);
+    assert_eq!(CHECKED_SUB, None);
+
+    const CHECKED_MUL: Option<Duration> = ONE.checked_mul(1);
+    assert_eq!(CHECKED_MUL, Some(ONE));
+
+    const MUL_F32: Duration = ONE.mul_f32(1.0);
+    assert_eq!(MUL_F32, ONE);
+
+    const MUL_F64: Duration = ONE.mul_f64(1.0);
+    assert_eq!(MUL_F64, ONE);
+
+    const CHECKED_DIV: Option<Duration> = ONE.checked_div(1);
+    assert_eq!(CHECKED_DIV, Some(ONE));
+
+    const DIV_F32: Duration = ONE.div_f32(1.0);
+    assert_eq!(DIV_F32, ONE);
+
+    const DIV_F64: Duration = ONE.div_f64(1.0);
+    assert_eq!(DIV_F64, ONE);
+
+    const DIV_DURATION_F32: f32 = ONE.div_duration_f32(ONE);
+    assert_eq!(DIV_DURATION_F32, 1.0);
+
+    const DIV_DURATION_F64: f64 = ONE.div_duration_f64(ONE);
+    assert_eq!(DIV_DURATION_F64, 1.0);
+
+    const SATURATING_ADD: Duration = MAX.saturating_add(ONE);
+    assert_eq!(SATURATING_ADD, MAX);
+
+    const SATURATING_SUB: Duration = ZERO.saturating_sub(ONE);
+    assert_eq!(SATURATING_SUB, ZERO);
+
+    const SATURATING_MUL: Duration = MAX.saturating_mul(2);
+    assert_eq!(SATURATING_MUL, MAX);
+}
diff --git a/library/std/src/future.rs b/library/std/src/future.rs
index 5ff74e55754..9d9c36e9afb 100644
--- a/library/std/src/future.rs
+++ b/library/std/src/future.rs
@@ -9,7 +9,7 @@ pub use core::future::Future;
 pub use core::future::{from_generator, get_context, ResumeTy};
 
 #[doc(inline)]
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 pub use core::future::{pending, ready, Pending, Ready};
 
 #[doc(inline)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index b834361b750..5333d75ec1b 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -315,6 +315,7 @@
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(unsafe_block_in_unsafe_fn)]
+#![feature(unsafe_cell_raw_get)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(vec_into_raw_parts)]
diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs
index 6daf2885bae..fab27cd9f70 100644
--- a/library/std/src/sys/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/unix/process/process_fuchsia.rs
@@ -118,7 +118,8 @@ impl Command {
             FDIO_SPAWN_CLONE_JOB
                 | FDIO_SPAWN_CLONE_LDSVC
                 | FDIO_SPAWN_CLONE_NAMESPACE
-                | FDIO_SPAWN_CLONE_ENVIRON, // this is ignored when envp is non-null
+                | FDIO_SPAWN_CLONE_ENVIRON // this is ignored when envp is non-null
+                | FDIO_SPAWN_CLONE_UTC_CLOCK,
             self.get_program().as_ptr(),
             self.get_argv().as_ptr(),
             envp,
diff --git a/library/std/src/sys/unix/process/zircon.rs b/library/std/src/sys/unix/process/zircon.rs
index 750b8f0762a..69ec275c2b3 100644
--- a/library/std/src/sys/unix/process/zircon.rs
+++ b/library/std/src/sys/unix/process/zircon.rs
@@ -138,6 +138,7 @@ pub const FDIO_SPAWN_CLONE_LDSVC: u32 = 0x0002;
 pub const FDIO_SPAWN_CLONE_NAMESPACE: u32 = 0x0004;
 pub const FDIO_SPAWN_CLONE_STDIO: u32 = 0x0008;
 pub const FDIO_SPAWN_CLONE_ENVIRON: u32 = 0x0010;
+pub const FDIO_SPAWN_CLONE_UTC_CLOCK: u32 = 0x0020;
 pub const FDIO_SPAWN_CLONE_ALL: u32 = 0xFFFF;
 
 // fdio_spawn_etc actions
diff --git a/library/std/src/sys/windows/mutex.rs b/library/std/src/sys/windows/mutex.rs
index 63dfc640908..1e09b95c872 100644
--- a/library/std/src/sys/windows/mutex.rs
+++ b/library/std/src/sys/windows/mutex.rs
@@ -19,20 +19,25 @@
 //! CriticalSection is used and we keep track of who's holding the mutex to
 //! detect recursive locks.
 
-use crate::cell::UnsafeCell;
+use crate::cell::{Cell, UnsafeCell};
 use crate::mem::{self, MaybeUninit};
 use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sys::c;
 use crate::sys::compat;
 
 pub struct Mutex {
+    // This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise.
     lock: AtomicUsize,
-    held: UnsafeCell<bool>,
 }
 
 unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
+struct Inner {
+    remutex: ReentrantMutex,
+    held: Cell<bool>,
+}
+
 #[derive(Clone, Copy)]
 enum Kind {
     SRWLock = 1,
@@ -51,7 +56,6 @@ impl Mutex {
             // This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly
             // initializing an SRWLOCK here.
             lock: AtomicUsize::new(0),
-            held: UnsafeCell::new(false),
         }
     }
     #[inline]
@@ -60,10 +64,11 @@ impl Mutex {
         match kind() {
             Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)),
             Kind::CriticalSection => {
-                let re = self.remutex();
-                (*re).lock();
-                if !self.flag_locked() {
-                    (*re).unlock();
+                let inner = &*self.inner();
+                inner.remutex.lock();
+                if inner.held.replace(true) {
+                    // It was already locked, so we got a recursive lock which we do not want.
+                    inner.remutex.unlock();
                     panic!("cannot recursively lock a mutex");
                 }
             }
@@ -73,23 +78,27 @@ impl Mutex {
         match kind() {
             Kind::SRWLock => c::TryAcquireSRWLockExclusive(raw(self)) != 0,
             Kind::CriticalSection => {
-                let re = self.remutex();
-                if !(*re).try_lock() {
+                let inner = &*self.inner();
+                if !inner.remutex.try_lock() {
                     false
-                } else if self.flag_locked() {
-                    true
-                } else {
-                    (*re).unlock();
+                } else if inner.held.replace(true) {
+                    // It was already locked, so we got a recursive lock which we do not want.
+                    inner.remutex.unlock();
                     false
+                } else {
+                    true
                 }
             }
         }
     }
     pub unsafe fn unlock(&self) {
-        *self.held.get() = false;
         match kind() {
             Kind::SRWLock => c::ReleaseSRWLockExclusive(raw(self)),
-            Kind::CriticalSection => (*self.remutex()).unlock(),
+            Kind::CriticalSection => {
+                let inner = &*(self.lock.load(Ordering::SeqCst) as *const Inner);
+                inner.held.set(false);
+                inner.remutex.unlock();
+            }
         }
     }
     pub unsafe fn destroy(&self) {
@@ -97,38 +106,27 @@ impl Mutex {
             Kind::SRWLock => {}
             Kind::CriticalSection => match self.lock.load(Ordering::SeqCst) {
                 0 => {}
-                n => {
-                    Box::from_raw(n as *mut ReentrantMutex).destroy();
-                }
+                n => Box::from_raw(n as *mut Inner).remutex.destroy(),
             },
         }
     }
 
-    unsafe fn remutex(&self) -> *mut ReentrantMutex {
+    unsafe fn inner(&self) -> *const Inner {
         match self.lock.load(Ordering::SeqCst) {
             0 => {}
-            n => return n as *mut _,
+            n => return n as *const _,
         }
-        let re = box ReentrantMutex::uninitialized();
-        re.init();
-        let re = Box::into_raw(re);
-        match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) {
-            0 => re,
+        let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) };
+        inner.remutex.init();
+        let inner = Box::into_raw(inner);
+        match self.lock.compare_and_swap(0, inner as usize, Ordering::SeqCst) {
+            0 => inner,
             n => {
-                Box::from_raw(re).destroy();
-                n as *mut _
+                Box::from_raw(inner).remutex.destroy();
+                n as *const _
             }
         }
     }
-
-    unsafe fn flag_locked(&self) -> bool {
-        if *self.held.get() {
-            false
-        } else {
-            *self.held.get() = true;
-            true
-        }
-    }
 }
 
 fn kind() -> Kind {
@@ -150,7 +148,7 @@ fn kind() -> Kind {
 }
 
 pub struct ReentrantMutex {
-    inner: UnsafeCell<MaybeUninit<c::CRITICAL_SECTION>>,
+    inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
 }
 
 unsafe impl Send for ReentrantMutex {}
@@ -158,27 +156,27 @@ unsafe impl Sync for ReentrantMutex {}
 
 impl ReentrantMutex {
     pub const fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninit()) }
+        ReentrantMutex { inner: MaybeUninit::uninit() }
     }
 
     pub unsafe fn init(&self) {
-        c::InitializeCriticalSection((&mut *self.inner.get()).as_mut_ptr());
+        c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
     }
 
     pub unsafe fn lock(&self) {
-        c::EnterCriticalSection((&mut *self.inner.get()).as_mut_ptr());
+        c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
     }
 
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
-        c::TryEnterCriticalSection((&mut *self.inner.get()).as_mut_ptr()) != 0
+        c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0
     }
 
     pub unsafe fn unlock(&self) {
-        c::LeaveCriticalSection((&mut *self.inner.get()).as_mut_ptr());
+        c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
     }
 
     pub unsafe fn destroy(&self) {
-        c::DeleteCriticalSection((&mut *self.inner.get()).as_mut_ptr());
+        c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
     }
 }
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 9d8c6f1815e..60a05dc5d54 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -424,10 +424,9 @@ pub mod fast {
         // thread_local's, or it is being recursively initialized.
         //
         // Macos: Inlining this function can cause two `tlv_get_addr` calls to
-        // be performed for every call to `Key::get`. The #[cold] hint makes
-        // that less likely.
+        // be performed for every call to `Key::get`.
         // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
-        #[cold]
+        #[inline(never)]
         unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
             if !mem::needs_drop::<T>() || self.try_register_dtor() {
                 Some(self.inner.initialize(init))
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 975b8be02c8..a69bd1cc3bc 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -26,10 +26,10 @@ The script accepts commands, flags, and arguments to determine what to do:
 
   ```
   # build the whole compiler
-  ./x.py build
+  ./x.py build --stage 2
 
   # build the stage1 compiler
-  ./x.py build --stage 1
+  ./x.py build
 
   # build stage0 libstd
   ./x.py build --stage 0 library/std
@@ -43,8 +43,8 @@ The script accepts commands, flags, and arguments to determine what to do:
   that belong to stage n or earlier:
 
   ```
-  # keep old build products for stage 0 and build stage 1
-  ./x.py build --keep-stage 0 --stage 1
+  # build stage 1, keeping old build products for stage 0
+  ./x.py build --keep-stage 0
   ```
 
 * `test` - a command for executing unit tests. Like the `build` command this
@@ -123,24 +123,8 @@ that (b) leverage Rust as much as possible!
 
 ## Incremental builds
 
-You can configure rustbuild to use incremental compilation. Because
-incremental is new and evolving rapidly, if you want to use it, it is
-recommended that you replace the snapshot with a locally installed
-nightly build of rustc. You will want to keep this up to date.
-
-To follow this course of action, first thing you will want to do is to
-install a nightly, presumably using `rustup`. You will then want to
-configure your directory to use this build, like so:
-
-```sh
-# configure to use local rust instead of downloading a beta.
-# `--local-rust-root` is optional here. If elided, we will
-# use whatever rustc we find on your PATH.
-$ ./configure --local-rust-root=~/.cargo/ --enable-local-rebuild
-```
-
-After that, you can use the `--incremental` flag to actually do
-incremental builds:
+You can configure rustbuild to use incremental compilation with the
+`--incremental` flag:
 
 ```sh
 $ ./x.py build --incremental
@@ -150,9 +134,7 @@ The `--incremental` flag will store incremental compilation artifacts
 in `build/<host>/stage0-incremental`. Note that we only use incremental
 compilation for the stage0 -> stage1 compilation -- this is because
 the stage1 compiler is changing, and we don't try to cache and reuse
-incremental artifacts across different versions of the compiler. For
-this reason, `--incremental` defaults to `--stage 1` (though you can
-manually select a higher stage, if you prefer).
+incremental artifacts across different versions of the compiler.
 
 You can always drop the `--incremental` to build as normal (but you
 will still be using the local nightly as your bootstrap).
@@ -331,8 +313,8 @@ are:
   `Config` struct.
 * Adding a sanity check? Take a look at `bootstrap/sanity.rs`.
 
-If you have any questions feel free to reach out on `#infra` channel in the
-[Rust Discord server][rust-discord] or ask on internals.rust-lang.org. When
+If you have any questions feel free to reach out on the `#t-infra` channel in
+the [Rust Zulip server][rust-zulip] or ask on internals.rust-lang.org. When
 you encounter bugs, please file issues on the rust-lang/rust issue tracker.
 
-[rust-discord]: https://discord.gg/rust-lang
+[rust-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 0f18660c0e1..d2537d65e67 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -526,23 +526,9 @@ impl<'a> Builder<'a> {
     }
 
     fn new_internal(build: &Build, kind: Kind, paths: Vec<PathBuf>) -> Builder<'_> {
-        let top_stage = if let Some(explicit_stage) = build.config.stage {
-            explicit_stage
-        } else {
-            // See https://github.com/rust-lang/compiler-team/issues/326
-            match kind {
-                Kind::Doc => 0,
-                Kind::Build | Kind::Test => 1,
-                Kind::Bench | Kind::Dist | Kind::Install => 2,
-                // These are all bootstrap tools, which don't depend on the compiler.
-                // The stage we pass shouldn't matter, but use 0 just in case.
-                Kind::Check | Kind::Clippy | Kind::Fix | Kind::Run | Kind::Format => 0,
-            }
-        };
-
         Builder {
             build,
-            top_stage,
+            top_stage: build.config.stage,
             kind,
             cache: Cache::new(),
             stack: RefCell::new(Vec::new()),
@@ -566,20 +552,7 @@ impl<'a> Builder<'a> {
             Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(),
         };
 
-        let this = Self::new_internal(build, kind, paths.to_owned());
-
-        // CI should always run stage 2 builds, unless it specifically states otherwise
-        #[cfg(not(test))]
-        if build.config.stage.is_none() && build.ci_env != crate::CiEnv::None {
-            match kind {
-                Kind::Test | Kind::Doc | Kind::Build | Kind::Bench | Kind::Dist | Kind::Install => {
-                    assert_eq!(this.top_stage, 2)
-                }
-                Kind::Check | Kind::Clippy | Kind::Fix | Kind::Run | Kind::Format => {}
-            }
-        }
-
-        this
+        Self::new_internal(build, kind, paths.to_owned())
     }
 
     pub fn execute_cli(&self) {
@@ -710,7 +683,7 @@ impl<'a> Builder<'a> {
 
     /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic
     /// library lookup path.
-    pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Cargo) {
+    pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) {
         // Windows doesn't need dylib path munging because the dlls for the
         // compiler live next to the compiler and the system will find them
         // automatically.
@@ -718,7 +691,7 @@ impl<'a> Builder<'a> {
             return;
         }
 
-        add_dylib_path(vec![self.rustc_libdir(compiler)], &mut cmd.command);
+        add_dylib_path(vec![self.rustc_libdir(compiler)], cmd);
     }
 
     /// Gets a path to the compiler specified.
@@ -1236,7 +1209,7 @@ impl<'a> Builder<'a> {
             cargo.env(format!("CC_{}", target.triple), &cc);
 
             let cflags = self.cflags(target, GitRepo::Rustc).join(" ");
-            cargo.env(format!("CFLAGS_{}", target.triple), cflags.clone());
+            cargo.env(format!("CFLAGS_{}", target.triple), &cflags);
 
             if let Some(ar) = self.ar(target) {
                 let ranlib = format!("{} s", ar.display());
@@ -1421,7 +1394,7 @@ impl<'a> Builder<'a> {
             (out, dur - deps)
         };
 
-        if self.config.print_step_timings {
+        if self.config.print_step_timings && !self.config.dry_run {
             println!("[TIMING] {:?} -- {}.{:03}", step, dur.as_secs(), dur.subsec_millis());
         }
 
@@ -1515,6 +1488,10 @@ impl Cargo {
         self.command.env(key.as_ref(), value.as_ref());
         self
     }
+
+    pub fn add_rustc_lib_path(&mut self, builder: &Builder<'_>, compiler: Compiler) {
+        builder.add_rustc_lib_path(compiler, &mut self.command);
+    }
 }
 
 impl From<Cargo> for Command {
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index c6eac95c345..f96925f9270 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -2,8 +2,8 @@ use super::*;
 use crate::config::{Config, TargetSelection};
 use std::thread;
 
-fn configure(host: &[&str], target: &[&str]) -> Config {
-    let mut config = Config::default_opts();
+fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
+    let mut config = Config::parse(&[cmd.to_owned()]);
     // don't save toolstates
     config.save_toolstates = None;
     config.skip_only_host_steps = false;
@@ -42,7 +42,7 @@ mod defaults {
 
     #[test]
     fn build_default() {
-        let build = Build::new(configure(&[], &[]));
+        let build = Build::new(configure("build", &[], &[]));
         let mut builder = Builder::new(&build);
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
 
@@ -70,7 +70,7 @@ mod defaults {
 
     #[test]
     fn build_stage_0() {
-        let config = Config { stage: Some(0), ..configure(&[], &[]) };
+        let config = Config { stage: 0, ..configure("build", &[], &[]) };
         let build = Build::new(config);
         let mut builder = Builder::new(&build);
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
@@ -92,7 +92,7 @@ mod defaults {
 
     #[test]
     fn doc_default() {
-        let mut config = configure(&[], &[]);
+        let mut config = configure("doc", &[], &[]);
         config.compiler_docs = true;
         config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
         let build = Build::new(config);
@@ -126,7 +126,7 @@ mod dist {
     use pretty_assertions::assert_eq;
 
     fn configure(host: &[&str], target: &[&str]) -> Config {
-        Config { stage: Some(2), ..super::configure(host, target) }
+        Config { stage: 2, ..super::configure("dist", host, target) }
     }
 
     #[test]
@@ -455,7 +455,7 @@ mod dist {
     #[test]
     fn test_with_no_doc_stage0() {
         let mut config = configure(&[], &[]);
-        config.stage = Some(0);
+        config.stage = 0;
         config.cmd = Subcommand::Test {
             paths: vec!["library/std".into()],
             test_args: vec![],
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 7c8c729b5bf..7e2cb772186 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -10,7 +10,6 @@ use std::ffi::OsString;
 use std::fmt;
 use std::fs;
 use std::path::{Path, PathBuf};
-use std::process;
 
 use crate::cache::{Interned, INTERNER};
 use crate::flags::Flags;
@@ -68,7 +67,7 @@ pub struct Config {
     pub skip_only_host_steps: bool,
 
     pub on_fail: Option<String>,
-    pub stage: Option<u32>,
+    pub stage: u32,
     pub keep_stage: Vec<u32>,
     pub src: PathBuf,
     pub jobs: Option<u32>,
@@ -313,6 +312,12 @@ struct Build {
     configure_args: Option<Vec<String>>,
     local_rebuild: Option<bool>,
     print_step_timings: Option<bool>,
+    doc_stage: Option<u32>,
+    build_stage: Option<u32>,
+    test_stage: Option<u32>,
+    install_stage: Option<u32>,
+    dist_stage: Option<u32>,
+    bench_stage: Option<u32>,
 }
 
 /// TOML representation of various global install decisions.
@@ -495,13 +500,12 @@ impl Config {
 
     pub fn parse(args: &[String]) -> Config {
         let flags = Flags::parse(&args);
-        let file = flags.config.clone();
+
         let mut config = Config::default_opts();
         config.exclude = flags.exclude;
         config.rustc_error_format = flags.rustc_error_format;
         config.json_output = flags.json_output;
         config.on_fail = flags.on_fail;
-        config.stage = flags.stage;
         config.jobs = flags.jobs.map(threads_from_config);
         config.cmd = flags.cmd;
         config.incremental = flags.incremental;
@@ -518,8 +522,14 @@ impl Config {
             config.out = dir;
         }
 
-        let toml = file
+        #[cfg(test)]
+        let toml = TomlConfig::default();
+        #[cfg(not(test))]
+        let toml = flags
+            .config
             .map(|file| {
+                use std::process;
+
                 let contents = t!(fs::read_to_string(&file));
                 match toml::from_str(&contents) {
                     Ok(table) => table,
@@ -535,21 +545,21 @@ impl Config {
             })
             .unwrap_or_else(TomlConfig::default);
 
-        let build = toml.build.clone().unwrap_or_default();
+        let build = toml.build.unwrap_or_default();
 
         // If --target was specified but --host wasn't specified, don't run any host-only tests.
         let has_hosts = build.host.is_some() || flags.host.is_some();
         let has_targets = build.target.is_some() || flags.target.is_some();
         config.skip_only_host_steps = !has_hosts && has_targets;
 
-        config.hosts = if let Some(arg_host) = flags.host.clone() {
+        config.hosts = if let Some(arg_host) = flags.host {
             arg_host
         } else if let Some(file_host) = build.host {
             file_host.iter().map(|h| TargetSelection::from_user(h)).collect()
         } else {
             vec![config.build]
         };
-        config.targets = if let Some(arg_target) = flags.target.clone() {
+        config.targets = if let Some(arg_target) = flags.target {
             arg_target
         } else if let Some(file_target) = build.target {
             file_target.iter().map(|h| TargetSelection::from_user(h)).collect()
@@ -579,16 +589,54 @@ impl Config {
         set(&mut config.configure_args, build.configure_args);
         set(&mut config.local_rebuild, build.local_rebuild);
         set(&mut config.print_step_timings, build.print_step_timings);
+
+        // See https://github.com/rust-lang/compiler-team/issues/326
+        config.stage = match config.cmd {
+            Subcommand::Doc { .. } => flags.stage.or(build.doc_stage).unwrap_or(0),
+            Subcommand::Build { .. } => flags.stage.or(build.build_stage).unwrap_or(1),
+            Subcommand::Test { .. } => flags.stage.or(build.test_stage).unwrap_or(1),
+            Subcommand::Bench { .. } => flags.stage.or(build.bench_stage).unwrap_or(2),
+            Subcommand::Dist { .. } => flags.stage.or(build.dist_stage).unwrap_or(2),
+            Subcommand::Install { .. } => flags.stage.or(build.install_stage).unwrap_or(2),
+            // These are all bootstrap tools, which don't depend on the compiler.
+            // The stage we pass shouldn't matter, but use 0 just in case.
+            Subcommand::Clean { .. }
+            | Subcommand::Check { .. }
+            | Subcommand::Clippy { .. }
+            | Subcommand::Fix { .. }
+            | Subcommand::Run { .. }
+            | Subcommand::Format { .. } => flags.stage.unwrap_or(0),
+        };
+
+        // CI should always run stage 2 builds, unless it specifically states otherwise
+        #[cfg(not(test))]
+        if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None {
+            match config.cmd {
+                Subcommand::Test { .. }
+                | Subcommand::Doc { .. }
+                | Subcommand::Build { .. }
+                | Subcommand::Bench { .. }
+                | Subcommand::Dist { .. }
+                | Subcommand::Install { .. } => assert_eq!(config.stage, 2),
+                Subcommand::Clean { .. }
+                | Subcommand::Check { .. }
+                | Subcommand::Clippy { .. }
+                | Subcommand::Fix { .. }
+                | Subcommand::Run { .. }
+                | Subcommand::Format { .. } => {}
+            }
+        }
+
         config.verbose = cmp::max(config.verbose, flags.verbose);
 
-        if let Some(ref install) = toml.install {
-            config.prefix = install.prefix.clone().map(PathBuf::from);
-            config.sysconfdir = install.sysconfdir.clone().map(PathBuf::from);
-            config.datadir = install.datadir.clone().map(PathBuf::from);
-            config.docdir = install.docdir.clone().map(PathBuf::from);
-            set(&mut config.bindir, install.bindir.clone().map(PathBuf::from));
-            config.libdir = install.libdir.clone().map(PathBuf::from);
-            config.mandir = install.mandir.clone().map(PathBuf::from);
+        if let Some(install) = toml.install {
+            config.prefix = install.prefix.map(PathBuf::from);
+            config.sysconfdir = install.sysconfdir.map(PathBuf::from);
+            config.datadir = install.datadir.map(PathBuf::from);
+            config.docdir = install.docdir.map(PathBuf::from);
+            set(&mut config.bindir, install.bindir.map(PathBuf::from));
+            config.libdir = install.libdir.map(PathBuf::from);
+            config.mandir = install.mandir.map(PathBuf::from);
         }
 
         // We want the llvm-skip-rebuild flag to take precedence over the
@@ -611,7 +659,7 @@ impl Config {
         let mut optimize = None;
         let mut ignore_git = None;
 
-        if let Some(ref llvm) = toml.llvm {
+        if let Some(llvm) = toml.llvm {
             match llvm.ccache {
                 Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
                 Some(StringOrBool::Bool(true)) => {
@@ -679,7 +727,7 @@ impl Config {
             }
         }
 
-        if let Some(ref rust) = toml.rust {
+        if let Some(rust) = toml.rust {
             debug = rust.debug;
             debug_assertions = rust.debug_assertions;
             debug_assertions_std = rust.debug_assertions_std;
@@ -699,7 +747,7 @@ impl Config {
             set(&mut config.test_compare_mode, rust.test_compare_mode);
             set(&mut config.llvm_libunwind, rust.llvm_libunwind);
             set(&mut config.backtrace, rust.backtrace);
-            set(&mut config.channel, rust.channel.clone());
+            set(&mut config.channel, rust.channel);
             set(&mut config.rust_dist_src, rust.dist_src);
             set(&mut config.verbose_tests, rust.verbose_tests);
             // in the case "false" is set explicitly, do not overwrite the command line args
@@ -710,9 +758,9 @@ impl Config {
             set(&mut config.lld_enabled, rust.lld);
             set(&mut config.llvm_tools_enabled, rust.llvm_tools);
             config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
-            config.rustc_default_linker = rust.default_linker.clone();
-            config.musl_root = rust.musl_root.clone().map(PathBuf::from);
-            config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
+            config.rustc_default_linker = rust.default_linker;
+            config.musl_root = rust.musl_root.map(PathBuf::from);
+            config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
             set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
             set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
             set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
@@ -729,9 +777,9 @@ impl Config {
             config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
         }
 
-        if let Some(ref t) = toml.target {
+        if let Some(t) = toml.target {
             for (triple, cfg) in t {
-                let mut target = Target::from_triple(triple);
+                let mut target = Target::from_triple(&triple);
 
                 if let Some(ref s) = cfg.llvm_config {
                     target.llvm_config = Some(config.src.join(s));
@@ -745,18 +793,18 @@ impl Config {
                 if let Some(s) = cfg.no_std {
                     target.no_std = s;
                 }
-                target.cc = cfg.cc.clone().map(PathBuf::from);
-                target.cxx = cfg.cxx.clone().map(PathBuf::from);
-                target.ar = cfg.ar.clone().map(PathBuf::from);
-                target.ranlib = cfg.ranlib.clone().map(PathBuf::from);
-                target.linker = cfg.linker.clone().map(PathBuf::from);
+                target.cc = cfg.cc.map(PathBuf::from);
+                target.cxx = cfg.cxx.map(PathBuf::from);
+                target.ar = cfg.ar.map(PathBuf::from);
+                target.ranlib = cfg.ranlib.map(PathBuf::from);
+                target.linker = cfg.linker.map(PathBuf::from);
                 target.crt_static = cfg.crt_static;
-                target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
-                target.musl_libdir = cfg.musl_libdir.clone().map(PathBuf::from);
-                target.wasi_root = cfg.wasi_root.clone().map(PathBuf::from);
-                target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
+                target.musl_root = cfg.musl_root.map(PathBuf::from);
+                target.musl_libdir = cfg.musl_libdir.map(PathBuf::from);
+                target.wasi_root = cfg.wasi_root.map(PathBuf::from);
+                target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
 
-                config.target_config.insert(TargetSelection::from_user(triple), target);
+                config.target_config.insert(TargetSelection::from_user(&triple), target);
             }
         }
 
@@ -774,10 +822,10 @@ impl Config {
             build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", config.build)));
         }
 
-        if let Some(ref t) = toml.dist {
-            config.dist_sign_folder = t.sign_folder.clone().map(PathBuf::from);
-            config.dist_gpg_password_file = t.gpg_password_file.clone().map(PathBuf::from);
-            config.dist_upload_addr = t.upload_addr.clone();
+        if let Some(t) = toml.dist {
+            config.dist_sign_folder = t.sign_folder.map(PathBuf::from);
+            config.dist_gpg_password_file = t.gpg_password_file.map(PathBuf::from);
+            config.dist_upload_addr = t.upload_addr;
             set(&mut config.rust_dist_src, t.src_tarball);
             set(&mut config.missing_tools, t.missing_tools);
         }
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 98a0119e4df..f90e76a4f4e 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -766,6 +766,10 @@ impl Step for RustcBook {
         if builder.config.verbose() {
             cmd.arg("--verbose");
         }
+        // If the lib directories are in an unusual location (changed in
+        // config.toml), then this needs to explicitly update the dylib search
+        // path.
+        builder.add_rustc_lib_path(self.compiler, &mut cmd);
         builder.run(&mut cmd);
         // Run rustbook/mdbook to generate the HTML pages.
         builder.ensure(RustbookSrc {
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index 6f93082e675..0ae9f9712d5 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -105,15 +105,13 @@ pub fn format(build: &Build, check: bool) {
         eprintln!("./x.py fmt is not supported on this channel");
         std::process::exit(1);
     });
-    let src = build.src.clone();
-    let walker = WalkBuilder::new(&build.src).types(matcher).overrides(ignore_fmt).build_parallel();
+    let src = &build.src;
+    let walker = WalkBuilder::new(src).types(matcher).overrides(ignore_fmt).build_parallel();
     walker.run(|| {
-        let src = src.clone();
-        let rustfmt_path = rustfmt_path.clone();
         Box::new(move |entry| {
             let entry = t!(entry);
             if entry.file_type().map_or(false, |t| t.is_file()) {
-                rustfmt(&src, &rustfmt_path, &entry.path(), check);
+                rustfmt(src, &rustfmt_path, &entry.path(), check);
             }
             ignore::WalkState::Continue
         })
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 4d6612a376a..6826d177a4a 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -30,8 +30,8 @@ impl Finder {
         Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() }
     }
 
-    pub fn maybe_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> Option<PathBuf> {
-        let cmd: OsString = cmd.as_ref().into();
+    pub fn maybe_have<S: Into<OsString>>(&mut self, cmd: S) -> Option<PathBuf> {
+        let cmd: OsString = cmd.into();
         let path = &self.path;
         self.cache
             .entry(cmd.clone())
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 045dda2d4cb..ba5f75c49ac 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -270,7 +270,7 @@ impl Step for Rls {
             &[],
         );
 
-        builder.add_rustc_lib_path(compiler, &mut cargo);
+        cargo.add_rustc_lib_path(builder, compiler);
         cargo.arg("--").args(builder.config.cmd.test_args());
 
         if try_run(builder, &mut cargo.into()) {
@@ -328,7 +328,7 @@ impl Step for Rustfmt {
         t!(fs::create_dir_all(&dir));
         cargo.env("RUSTFMT_TEST_DIR", dir);
 
-        builder.add_rustc_lib_path(compiler, &mut cargo);
+        cargo.add_rustc_lib_path(builder, compiler);
 
         if try_run(builder, &mut cargo.into()) {
             builder.save_toolstate("rustfmt", ToolState::TestPass);
@@ -449,7 +449,7 @@ impl Step for Miri {
 
             cargo.arg("--").args(builder.config.cmd.test_args());
 
-            builder.add_rustc_lib_path(compiler, &mut cargo);
+            cargo.add_rustc_lib_path(builder, compiler);
 
             if !try_run(builder, &mut cargo.into()) {
                 return;
@@ -554,7 +554,7 @@ impl Step for Clippy {
 
         cargo.arg("--").args(builder.config.cmd.test_args());
 
-        builder.add_rustc_lib_path(compiler, &mut cargo);
+        cargo.add_rustc_lib_path(builder, compiler);
 
         builder.run(&mut cargo.into());
     }
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index 2dcb55bb973..05177e517d0 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -46,7 +46,7 @@ jobs:
 
       dist-x86_64-apple:
         SCRIPT: ./x.py dist
-        INITIAL_RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
+        INITIAL_RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=x86_64-apple-darwin,aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
         RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
         MACOSX_DEPLOYMENT_TARGET: 10.7
         NO_LLVM_ASSERTIONS: 1
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
index ba93f6ad824..88b13eab2d0 100644
--- a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile
@@ -6,6 +6,14 @@ RUN sh /scripts/cross-apt-packages.sh
 COPY scripts/crosstool-ng-1.24.sh /scripts/
 RUN sh /scripts/crosstool-ng-1.24.sh
 
+WORKDIR /build
+
+COPY scripts/musl-toolchain.sh /build/
+# We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
+RUN CFLAGS="-Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \
+    CXXFLAGS="-Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \
+    bash musl-toolchain.sh aarch64 && rm -rf build
+
 COPY scripts/rustbuild-setup.sh /scripts/
 RUN sh /scripts/rustbuild-setup.sh
 USER rustbuild
@@ -25,7 +33,8 @@ ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \
     AR_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-ar \
     CXX_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-g++
 
-ENV HOSTS=arm-unknown-linux-gnueabi
+ENV HOSTS=arm-unknown-linux-gnueabi,aarch64-unknown-linux-musl
 
-ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs --musl-root-aarch64=/usr/local/aarch64-linux-musl \
+    --set target.aarch64-unknown-linux-musl.crt-static=false
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config b/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config
index 1dcdbd1a900..66709a4004c 100644
--- a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config
+++ b/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config
@@ -14,6 +14,7 @@ CT_CONFIGURE_has_autoconf_2_65_or_newer=y
 CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
 CT_CONFIGURE_has_automake_1_15_or_newer=y
 CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
 CT_CONFIGURE_has_bison_2_7_or_newer=y
 CT_CONFIGURE_has_python=y
 CT_CONFIGURE_has_git=y
@@ -132,12 +133,6 @@ CT_ARCH_ARM=y
 # CT_ARCH_XTENSA is not set
 CT_ARCH="arm"
 CT_ARCH_CHOICE_KSYM="ARM"
-# CT_ARCH_ALPHA_EV4 is not set
-# CT_ARCH_ALPHA_EV45 is not set
-# CT_ARCH_ALPHA_EV5 is not set
-# CT_ARCH_ALPHA_EV56 is not set
-# CT_ARCH_ALPHA_EV6 is not set
-# CT_ARCH_ALPHA_EV67 is not set
 CT_ARCH_CPU=""
 CT_ARCH_TUNE=""
 CT_ARCH_ARM_SHOW=y
@@ -371,8 +366,6 @@ CT_ALL_BINUTILS_CHOICES="BINUTILS"
 # C-library
 #
 CT_LIBC_GLIBC=y
-# CT_LIBC_NEWLIB is not set
-# CT_LIBC_NONE is not set
 # CT_LIBC_UCLIBC is not set
 CT_LIBC="glibc"
 CT_LIBC_CHOICE_KSYM="GLIBC"
@@ -389,6 +382,7 @@ CT_GLIBC_USE="GLIBC"
 CT_GLIBC_PKG_NAME="glibc"
 CT_GLIBC_SRC_RELEASE=y
 CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
 # CT_GLIBC_V_2_28 is not set
 # CT_GLIBC_V_2_27 is not set
 # CT_GLIBC_V_2_26 is not set
@@ -407,7 +401,6 @@ CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
 CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
 CT_GLIBC_2_29_or_older=y
 CT_GLIBC_older_than_2_29=y
-CT_GLIBC_REQUIRE_older_than_2_29=y
 CT_GLIBC_2_27_or_older=y
 CT_GLIBC_older_than_2_27=y
 CT_GLIBC_2_26_or_older=y
@@ -447,12 +440,6 @@ CT_GLIBC_FORCE_UNWIND=y
 CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
 # CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
 CT_GLIBC_MIN_KERNEL="3.2.101"
-# CT_GLIBC_SSP_DEFAULT is not set
-# CT_GLIBC_SSP_NO is not set
-# CT_GLIBC_SSP_YES is not set
-# CT_GLIBC_SSP_ALL is not set
-# CT_GLIBC_SSP_STRONG is not set
-# CT_NEWLIB_USE_REDHAT is not set
 CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
 CT_LIBC_SUPPORT_THREADS_ANY=y
 CT_LIBC_SUPPORT_THREADS_NATIVE=y
diff --git a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile
index 4e48d9b5433..431892697d4 100644
--- a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile
@@ -84,10 +84,6 @@ RUN env \
     CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv7-a" \
     bash musl.sh armv7hf && \
     env \
-    CC=aarch64-linux-gnu-gcc \
-    CXX=aarch64-linux-gnu-g++ \
-    bash musl.sh aarch64 && \
-    env \
     CC=mips-openwrt-linux-gcc \
     CXX=mips-openwrt-linux-g++ \
     bash musl.sh mips && \
@@ -130,7 +126,6 @@ ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf
 ENV TARGETS=$TARGETS,armv5te-unknown-linux-gnueabi
 ENV TARGETS=$TARGETS,armv5te-unknown-linux-musleabi
 ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf
-ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl
 ENV TARGETS=$TARGETS,aarch64-unknown-none
 ENV TARGETS=$TARGETS,aarch64-unknown-none-softfloat
 ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu
@@ -185,7 +180,6 @@ ENV RUST_CONFIGURE_ARGS \
       --musl-root-arm=/musl-arm \
       --musl-root-armhf=/musl-armhf \
       --musl-root-armv7hf=/musl-armv7hf \
-      --musl-root-aarch64=/musl-aarch64 \
       --musl-root-mips=/musl-mips \
       --musl-root-mipsel=/musl-mipsel \
       --musl-root-mips64=/musl-mips64 \
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-git.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-git.sh
deleted file mode 100755
index 38fea2a8094..00000000000
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-git.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-source shared.sh
-
-curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
-
-cd git-2.10.0
-make configure
-hide_output ./configure --prefix=/rustroot
-hide_output make -j10
-hide_output make install
-
-cd ..
-rm -rf git-2.10.0
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-headers.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-headers.sh
deleted file mode 100755
index b623e53583b..00000000000
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-headers.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-source shared.sh
-
-curl https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.2.84.tar.xz | unxz | tar x
-
-cd linux-3.2.84
-hide_output make mrproper
-hide_output make INSTALL_HDR_PATH=dest headers_install
-
-find dest/include \( -name .install -o -name ..install.cmd \) -delete
-yes | cp -fr dest/include/* /usr/include
-
-cd ..
-rm -rf linux-3.2.84
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-perl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-perl.sh
deleted file mode 100755
index a678d353d52..00000000000
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-perl.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-source shared.sh
-
-curl https://www.cpan.org/src/5.0/perl-5.28.0.tar.gz | \
-  tar xzf -
-
-cd perl-5.28.0
-
-# Gotta do some hackery to tell python about our custom OpenSSL build, but other
-# than that fairly normal.
-CC=gcc \
-CFLAGS='-I /rustroot/include -fgnu89-inline' \
-LDFLAGS='-L /rustroot/lib -L /rustroot/lib64' \
-    hide_output ./configure.gnu
-hide_output make -j10
-hide_output make install
-
-cd ..
-rm -rf perl-5.28.0
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index f8d3bc8e8e5..ea7e65a1168 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -439,43 +439,7 @@ jobs:
           - name: dist-x86_64-apple
             env:
               SCRIPT: ./x.py dist
-              RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-            <<: *job-macos-xl
-
-          - name: dist-x86_64-apple-alt
-            env:
-              SCRIPT: ./x.py dist
-              RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-            <<: *job-macos-xl
-
-          - name: x86_64-apple
-            env:
-              SCRIPT: ./x.py --stage 2 test
-              RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.8
-              MACOSX_STD_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-            <<: *job-macos-xl
-
-          ####################
-          #  macOS Builders  #
-          ####################
-
-          - name: dist-x86_64-apple
-            env:
-              SCRIPT: ./x.py dist
-              RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
+              RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=x86_64-apple-darwin,aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
               RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
               MACOSX_DEPLOYMENT_TARGET: 10.7
               NO_LLVM_ASSERTIONS: 1
@@ -624,7 +588,7 @@ jobs:
               RUST_CONFIGURE_ARGS: >-
                 --build=i686-pc-windows-msvc
                 --host=i686-pc-windows-msvc
-                --target=i586-pc-windows-msvc
+                --target=i686-pc-windows-msvc,i586-pc-windows-msvc
                 --enable-full-tools
                 --enable-profiler
               SCRIPT: python x.py dist
diff --git a/src/doc/book b/src/doc/book
-Subproject e5ed97128302d5fa45dbac0e64426bc7649a558
+Subproject cb28dee95e5e50b793e6ba9291c5d1568d3ad72
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 25854752549d44d76fbd7650e17cb4f167a0b8f
+Subproject 6e57e64501f61873ab80cb78a07180a22751a5d
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 25391dba46262f882fa846beefaff54a966a8fa
+Subproject 56a13c082ee90736c08d6abdcd90462517b703d
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index da27d2fbf99..9b2474a95df 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -62,7 +62,7 @@ target | std | host | notes
 `aarch64-linux-android` | ✓ |  | ARM64 Android
 `aarch64-pc-windows-msvc` | ✓ |  | ARM64 Windows MSVC
 `aarch64-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (kernel 4.2, glibc 2.17)
-`aarch64-unknown-linux-musl` | ✓ |  | ARM64 Linux with MUSL
+`aarch64-unknown-linux-musl` | ✓ | ✓ | ARM64 Linux with MUSL
 `aarch64-unknown-none` | * |  | Bare ARM64, hardfloat
 `aarch64-unknown-none-softfloat` | * |  | Bare ARM64, softfloat
 `arm-linux-androideabi` | ✓ |  | ARMv7 Android
diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md
index 28a5fe31fc4..df113f0f161 100644
--- a/src/doc/unstable-book/src/library-features/asm.md
+++ b/src/doc/unstable-book/src/library-features/asm.md
@@ -345,6 +345,25 @@ The `h` modifier will emit the register name for the high byte of that register
 
 If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use.
 
+## Memory address operands
+
+Sometimes assembly instructions require operands passed via memory addresses/memory locations.
+You have to manually use the memory address syntax specified by the respectively architectures.
+For example, in x86/x86_64 and intel assembly syntax, you should wrap inputs/outputs in `[]`
+to indicate they are memory operands:
+
+```rust,allow_fail
+# #![feature(asm, llvm_asm)]
+# fn load_fpu_control_word(control: u16) {
+unsafe {
+    asm!("fldcw [{}]", in(reg) &control, options(nostack));
+
+    // Previously this would have been written with the deprecated `llvm_asm!` like this
+    llvm_asm!("fldcw $0" :: "m" (control) :: "volatile");
+}
+# }
+```
+
 ## Options
 
 By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.
diff --git a/src/doc/unstable-book/src/library-features/llvm-asm.md b/src/doc/unstable-book/src/library-features/llvm-asm.md
index da01d9228f1..a2f029db291 100644
--- a/src/doc/unstable-book/src/library-features/llvm-asm.md
+++ b/src/doc/unstable-book/src/library-features/llvm-asm.md
@@ -159,12 +159,12 @@ specify some extra info about the inline assembly:
 
 Current valid options are:
 
-1. *volatile* - specifying this is analogous to
+1. `volatile` - specifying this is analogous to
    `__asm__ __volatile__ (...)` in gcc/clang.
-2. *alignstack* - certain instructions expect the stack to be
+2. `alignstack` - certain instructions expect the stack to be
    aligned a certain way (i.e. SSE) and specifying this indicates to
    the compiler to insert its usual stack alignment code
-3. *intel* - use intel syntax instead of the default AT&T.
+3. `intel` - use intel syntax instead of the default AT&T.
 
 ```rust
 # #![feature(llvm_asm)]
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 6a75a9bfb74..46ba14aa67e 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -840,7 +840,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
         let mut where_predicates =
             where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
 
-        // Type parameters and have a Sized bound by default unless removed with
+        // Type parameters have a Sized bound by default unless removed with
         // ?Sized. Scan through the predicates and mark any type parameter with
         // a Sized bound, removing the bounds as we find them.
         //
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 73a783d5406..7762e8f8d4f 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -16,6 +16,16 @@
 
 #[macro_use]
 extern crate lazy_static;
+#[macro_use]
+extern crate tracing;
+
+// N.B. these need `extern crate` even in 2018 edition
+// because they're loaded implicitly from the sysroot.
+// The reason they're loaded from the sysroot is because
+// the rustdoc artifacts aren't stored in rustc's cargo target directory.
+// So if `rustc` was specified in Cargo.toml, this would spuriously rebuild crates.
+//
+// Dependencies listed in Cargo.toml do not need `extern crate`.
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
 extern crate rustc_attr;
@@ -42,8 +52,6 @@ extern crate rustc_target;
 extern crate rustc_trait_selection;
 extern crate rustc_typeck;
 extern crate test as testing;
-#[macro_use]
-extern crate tracing;
 
 use std::default::Default;
 use std::env;
diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs
index cbbe86dc433..78af9f9b856 100644
--- a/src/librustdoc/passes/doc_test_lints.rs
+++ b/src/librustdoc/passes/doc_test_lints.rs
@@ -8,7 +8,7 @@ use crate::clean;
 use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
-use crate::html::markdown::{find_testable_code, ErrorCodes, LangString};
+use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
 use rustc_session::lint;
 
 pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
@@ -48,15 +48,11 @@ pub(crate) struct Tests {
     pub(crate) found_tests: usize,
 }
 
-impl Tests {
-    pub(crate) fn new() -> Tests {
-        Tests { found_tests: 0 }
-    }
-}
-
 impl crate::doctest::Tester for Tests {
-    fn add_test(&mut self, _: String, _: LangString, _: usize) {
-        self.found_tests += 1;
+    fn add_test(&mut self, _: String, config: LangString, _: usize) {
+        if config.rust && config.ignore == Ignore::None {
+            self.found_tests += 1;
+        }
     }
 }
 
@@ -85,7 +81,7 @@ pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
         }
     };
 
-    let mut tests = Tests::new();
+    let mut tests = Tests { found_tests: 0 };
 
     find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);
 
diff --git a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.32bit b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.32bit.mir
index 2216c2bc92a..2216c2bc92a 100644
--- a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.32bit
+++ b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.32bit.mir
diff --git a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.64bit b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir
index 2216c2bc92a..2216c2bc92a 100644
--- a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.64bit
+++ b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir
diff --git a/src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.32bit b/src/test/mir-opt/combine_array_len.norm2.InstCombine.32bit.diff
index 61e987cc685..61e987cc685 100644
--- a/src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.32bit
+++ b/src/test/mir-opt/combine_array_len.norm2.InstCombine.32bit.diff
diff --git a/src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.64bit b/src/test/mir-opt/combine_array_len.norm2.InstCombine.64bit.diff
index 61e987cc685..61e987cc685 100644
--- a/src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.64bit
+++ b/src/test/mir-opt/combine_array_len.norm2.InstCombine.64bit.diff
diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.mir.32bit b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
index a137d7fadba..a137d7fadba 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.mir.32bit
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.mir.64bit b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
index ef98cf9c091..ef98cf9c091 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.mir.64bit
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
index c4f10064890..c4f10064890 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
index b16b85c4e95..b16b85c4e95 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.32bit b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
index 99d3a278d69..99d3a278d69 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.32bit
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.64bit b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
index d6e49892d4c..d6e49892d4c 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.64bit
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.32bit b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff
index 1ccda1c5003..1ccda1c5003 100644
--- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.32bit
+++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff
diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.64bit b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff
index 1ccda1c5003..1ccda1c5003 100644
--- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.64bit
+++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.32bit b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
index 245a7de5e99..245a7de5e99 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.32bit
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.64bit b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
index 245a7de5e99..245a7de5e99 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.64bit
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
index 99fa0dcbc90..99fa0dcbc90 100644
--- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit
+++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
index 99fa0dcbc90..99fa0dcbc90 100644
--- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit
+++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.diff.32bit b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff
index b1a9e1cb5d7..b1a9e1cb5d7 100644
--- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.diff.32bit
+++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff
diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.diff.64bit b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff
index b1a9e1cb5d7..b1a9e1cb5d7 100644
--- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.diff.64bit
+++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
index 2c8e7ada39b..2c8e7ada39b 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
index 2c8e7ada39b..2c8e7ada39b 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.32bit b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir
index a78a6341c29..a78a6341c29 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.32bit
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.64bit b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir
index a78a6341c29..a78a6341c29 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.64bit
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir
diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.32bit b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff
index f14004fc25e..f14004fc25e 100644
--- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.32bit
+++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff
diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.64bit b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff
index f14004fc25e..f14004fc25e 100644
--- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.64bit
+++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.32bit b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
index 02c4391baf5..02c4391baf5 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.32bit
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.64bit b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
index 02c4391baf5..02c4391baf5 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.64bit
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
diff --git a/src/test/mir-opt/graphviz.main.mir_map.0.dot.mir b/src/test/mir-opt/graphviz.main.mir_map.0.dot.mir
new file mode 100644
index 00000000000..df4f11f0f21
--- /dev/null
+++ b/src/test/mir-opt/graphviz.main.mir_map.0.dot.mir
@@ -0,0 +1,10 @@
+digraph Mir_0_3 {
+    graph [fontname="Courier, monospace"];
+    node [fontname="Courier, monospace"];
+    edge [fontname="Courier, monospace"];
+    label=<fn main() -&gt; ()<br align="left"/>>;
+    bb0__0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">_0 = const ()<br/></td></tr><tr><td align="left">goto</td></tr></table>>];
+    bb1__0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">1</td></tr><tr><td align="left">resume</td></tr></table>>];
+    bb2__0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">2</td></tr><tr><td align="left">return</td></tr></table>>];
+    bb0__0_3 -> bb2__0_3 [label=""];
+}
diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.32bit b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff
index 2d52f034e52..2d52f034e52 100644
--- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.32bit
+++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff
diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.64bit b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff
index d4e2df6fbfa..d4e2df6fbfa 100644
--- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.64bit
+++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff
diff --git a/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.mir.32bit b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.32bit.mir
index 1cef88fd109..1cef88fd109 100644
--- a/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.mir.32bit
+++ b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.32bit.mir
diff --git a/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.mir.64bit b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.64bit.mir
index 1cef88fd109..1cef88fd109 100644
--- a/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.mir.64bit
+++ b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.64bit.mir
diff --git a/src/test/mir-opt/issue_72181.bar.mir_map.0.mir.32bit b/src/test/mir-opt/issue_72181.bar.mir_map.0.32bit.mir
index 29654c2b1f8..29654c2b1f8 100644
--- a/src/test/mir-opt/issue_72181.bar.mir_map.0.mir.32bit
+++ b/src/test/mir-opt/issue_72181.bar.mir_map.0.32bit.mir
diff --git a/src/test/mir-opt/issue_72181.bar.mir_map.0.mir.64bit b/src/test/mir-opt/issue_72181.bar.mir_map.0.64bit.mir
index 29654c2b1f8..29654c2b1f8 100644
--- a/src/test/mir-opt/issue_72181.bar.mir_map.0.mir.64bit
+++ b/src/test/mir-opt/issue_72181.bar.mir_map.0.64bit.mir
diff --git a/src/test/mir-opt/issue_72181.foo.mir_map.0.mir.32bit b/src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir
index 972a36a30a1..972a36a30a1 100644
--- a/src/test/mir-opt/issue_72181.foo.mir_map.0.mir.32bit
+++ b/src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir
diff --git a/src/test/mir-opt/issue_72181.foo.mir_map.0.mir.64bit b/src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir
index 972a36a30a1..972a36a30a1 100644
--- a/src/test/mir-opt/issue_72181.foo.mir_map.0.mir.64bit
+++ b/src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir
diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.mir.32bit b/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir
index 89b60121496..89b60121496 100644
--- a/src/test/mir-opt/issue_72181.main.mir_map.0.mir.32bit
+++ b/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir
diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.mir.64bit b/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir
index 89b60121496..89b60121496 100644
--- a/src/test/mir-opt/issue_72181.main.mir_map.0.mir.64bit
+++ b/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
index f86755cfa7f..f86755cfa7f 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
index f86755cfa7f..f86755cfa7f 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
index 302612f5a0a..302612f5a0a 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
index 302612f5a0a..302612f5a0a 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff
index 3f01719e01b..3f01719e01b 100644
--- a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit
+++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff
diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff
index 3f01719e01b..3f01719e01b 100644
--- a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit
+++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
index 41f36036a18..41f36036a18 100644
--- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit
+++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
index 41f36036a18..41f36036a18 100644
--- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit
+++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff
index 9fde4888809..9fde4888809 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit
+++ b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff
index 9fde4888809..9fde4888809 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit
+++ b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff
index 2dd0a3edb47..2dd0a3edb47 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit
+++ b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff
index 2dd0a3edb47..2dd0a3edb47 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit
+++ b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.32bit b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index 2885dd8eb78..2885dd8eb78 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.32bit
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.64bit b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 3820f70d515..3820f70d515 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.64bit
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
diff --git a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.32bit b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.32bit.mir
index 4641344f01a..4641344f01a 100644
--- a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.32bit
+++ b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.32bit.mir
diff --git a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.64bit b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.64bit.mir
index 4641344f01a..4641344f01a 100644
--- a/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.64bit
+++ b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.64bit.mir
diff --git a/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.32bit b/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir
index 64ca4b57803..64ca4b57803 100644
--- a/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.32bit
+++ b/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir
diff --git a/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.64bit b/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir
index 64ca4b57803..64ca4b57803 100644
--- a/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.64bit
+++ b/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir
diff --git a/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
index 81a0e6ba0b4..06f359da2e7 100644
--- a/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
@@ -13,27 +13,24 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
--         switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
-+         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
+          switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
       }
   
       bb1: {
--         discriminant(_0) = 0;            // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
--     }
-- 
--     bb2: {
--         unreachable;                     // scope 0 at $DIR/simplify-arm.rs:10:11: 10:12
--     }
-- 
--     bb3: {
+          discriminant(_0) = 0;            // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
+      }
+  
+      bb2: {
+          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:10:11: 10:12
+      }
+  
+      bb3: {
           _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
-+         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
       }
   
--     bb4: {
-+     bb2: {
+      bb4: {
           return;                          // scope 0 at $DIR/simplify-arm.rs:14:2: 14:2
       }
   }
diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff
index adcda7fcde0..adcda7fcde0 100644
--- a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit
+++ b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff
diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff
index adcda7fcde0..adcda7fcde0 100644
--- a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit
+++ b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff
index 68a113f94ef..68a113f94ef 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff
index 68a113f94ef..68a113f94ef 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff
diff --git a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir.32bit b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.32bit.mir
index 8051c61bce9..8051c61bce9 100644
--- a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir.32bit
+++ b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.32bit.mir
diff --git a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir.64bit b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.64bit.mir
index 8051c61bce9..8051c61bce9 100644
--- a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir.64bit
+++ b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.64bit.mir
diff --git a/src/test/mir-opt/spanview_block.main.mir_map.0.html.mir b/src/test/mir-opt/spanview_block.main.mir_map.0.html.mir
new file mode 100644
index 00000000000..8f6b1307971
--- /dev/null
+++ b/src/test/mir-opt/spanview_block.main.mir_map.0.html.mir
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>coverage_of_if_else - Code Regions</title>
+    <style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+    </style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() </span><span><span class="code even" style="--layer: 1" title="0: $DIR/spanview-block.rs:5:11: 5:13:
+    5:11-5:13: Assign: _0 = const ()
+    5:13-5:13: Goto: goto -&gt; bb2"><span class="annotation">0⦊</span>{}<span class="annotation">⦉0</span></span></span><span><span class="code odd" style="--layer: 1" title="2: $DIR/spanview-block.rs:5:13: 5:13:
+    5:13-5:13: Return: return"><span class="annotation">2⦊</span>‸<span class="annotation">⦉2</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/mir-opt/spanview_statement.main.mir_map.0.html.mir b/src/test/mir-opt/spanview_statement.main.mir_map.0.html.mir
new file mode 100644
index 00000000000..072d22473a9
--- /dev/null
+++ b/src/test/mir-opt/spanview_statement.main.mir_map.0.html.mir
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>coverage_of_if_else - Code Regions</title>
+    <style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+    </style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() </span><span><span class="code even" style="--layer: 1" title="0[0]: $DIR/spanview-statement.rs:5:11: 5:13:
+    5:11-5:13: Assign: _0 = const ()"><span class="annotation">0[0]⦊</span>{}<span class="annotation">⦉0[0]</span></span></span><span><span class="code odd" style="--layer: 1" title="0:Goto: $DIR/spanview-statement.rs:5:13: 5:13:
+    5:13-5:13: Goto: goto -&gt; bb2"><span class="annotation">0:Goto⦊</span>‸<span class="annotation">⦉0:Goto</span></span></span><span><span class="code even" style="--layer: 1" title="2:Return: $DIR/spanview-statement.rs:5:13: 5:13:
+    5:13-5:13: Return: return"><span class="annotation">2:Return⦊</span>‸<span class="annotation">⦉2:Return</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/mir-opt/spanview_terminator.main.mir_map.0.html.mir b/src/test/mir-opt/spanview_terminator.main.mir_map.0.html.mir
new file mode 100644
index 00000000000..e023f0f8aea
--- /dev/null
+++ b/src/test/mir-opt/spanview_terminator.main.mir_map.0.html.mir
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>coverage_of_if_else - Code Regions</title>
+    <style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+    </style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 4"><span class="line"><span class="code" style="--layer: 0">fn main() {}</span><span><span class="code even" style="--layer: 1" title="0:Goto: $DIR/spanview-terminator.rs:5:13: 5:13:
+    5:13-5:13: Goto: goto -&gt; bb2"><span class="annotation">0:Goto⦊</span>‸<span class="annotation">⦉0:Goto</span></span></span><span><span class="code odd" style="--layer: 1" title="2:Return: $DIR/spanview-terminator.rs:5:13: 5:13:
+    5:13-5:13: Return: return"><span class="annotation">2:Return⦊</span>‸<span class="annotation">⦉2:Return</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.32bit b/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.32bit.mir
index 315525e08c2..315525e08c2 100644
--- a/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.32bit
+++ b/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.32bit.mir
diff --git a/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.64bit b/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.64bit.mir
index 315525e08c2..315525e08c2 100644
--- a/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.64bit
+++ b/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.64bit.mir
diff --git a/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.32bit b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.32bit.mir
index 832f18e14c2..832f18e14c2 100644
--- a/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.32bit
+++ b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.32bit.mir
diff --git a/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.64bit b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.64bit.mir
index 832f18e14c2..832f18e14c2 100644
--- a/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.64bit
+++ b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.64bit.mir
diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir.32bit b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir
index 2d96f64aeb4..2d96f64aeb4 100644
--- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir.32bit
+++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir
diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir.64bit b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir
index 2d96f64aeb4..2d96f64aeb4 100644
--- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir.64bit
+++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir
diff --git a/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.32bit b/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir
index fd3d707d539..fd3d707d539 100644
--- a/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.32bit
+++ b/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir
diff --git a/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.64bit b/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir
index fd3d707d539..fd3d707d539 100644
--- a/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.64bit
+++ b/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir
diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.32bit b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff
index 2d53fefca55..2d53fefca55 100644
--- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.32bit
+++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff
diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.64bit b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff
index 2d53fefca55..2d53fefca55 100644
--- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.64bit
+++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff
diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.32bit b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.32bit.mir
index 523ecb5ec1a..523ecb5ec1a 100644
--- a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.32bit
+++ b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.32bit.mir
diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.64bit b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir
index 523ecb5ec1a..523ecb5ec1a 100644
--- a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.64bit
+++ b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.64bit.mir
diff --git a/src/test/rustdoc-ui/coverage/doc-examples.stdout b/src/test/rustdoc-ui/coverage/doc-examples.stdout
index 10ed13c9ff5..8188740f873 100644
--- a/src/test/rustdoc-ui/coverage/doc-examples.stdout
+++ b/src/test/rustdoc-ui/coverage/doc-examples.stdout
@@ -1,7 +1,7 @@
 +-------------------------------------+------------+------------+------------+------------+
 | File                                | Documented | Percentage |   Examples | Percentage |
 +-------------------------------------+------------+------------+------------+------------+
-| ...tdoc-ui/coverage/doc-examples.rs |          4 |     100.0% |          2 |      50.0% |
+| ...tdoc-ui/coverage/doc-examples.rs |          4 |     100.0% |          1 |      25.0% |
 +-------------------------------------+------------+------------+------------+------------+
-| Total                               |          4 |     100.0% |          2 |      50.0% |
+| Total                               |          4 |     100.0% |          1 |      25.0% |
 +-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/private-doc-test.rs b/src/test/rustdoc-ui/private-doc-test.rs
new file mode 100644
index 00000000000..379fa45f9fa
--- /dev/null
+++ b/src/test/rustdoc-ui/private-doc-test.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![deny(private_doc_tests)]
+
+mod foo {
+    /// private doc test
+    ///
+    /// ```ignore (used for testing ignored doc tests)
+    /// assert!(false);
+    /// ```
+    fn bar() {}
+}
diff --git a/src/test/ui/closures/issue-72408-nested-closures-exponential.rs b/src/test/ui/closures/issue-72408-nested-closures-exponential.rs
new file mode 100644
index 00000000000..2d6ba936572
--- /dev/null
+++ b/src/test/ui/closures/issue-72408-nested-closures-exponential.rs
@@ -0,0 +1,59 @@
+// build-pass
+
+// Closures include captured types twice in a type tree.
+//
+// Wrapping one closure with another leads to doubling
+// the amount of types in the type tree.
+//
+// This test ensures that rust can handle
+// deeply nested type trees with a lot
+// of duplicated subtrees.
+
+fn dup(f: impl Fn(i32) -> i32) -> impl Fn(i32) -> i32 {
+    move |a| f(a * 2)
+}
+
+fn main() {
+    let f = |a| a;
+
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+
+    // Compiler dies around here if it tries
+    // to walk the tree exhaustively.
+
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+    let f = dup(f);
+
+    println!("Type size was at least {}", f(1));
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/auxiliary/const_evaluatable_lib.rs b/src/test/ui/const-generics/const_evaluatable_checked/auxiliary/const_evaluatable_lib.rs
new file mode 100644
index 00000000000..9745dfed460
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/auxiliary/const_evaluatable_lib.rs
@@ -0,0 +1,9 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
+where
+    [u8; std::mem::size_of::<T>() - 1]: Sized,
+{
+    [0; std::mem::size_of::<T>() - 1]
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate.rs b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate.rs
new file mode 100644
index 00000000000..53b23784387
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate.rs
@@ -0,0 +1,15 @@
+// aux-build:const_evaluatable_lib.rs
+// run-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+extern crate const_evaluatable_lib;
+
+fn user<T>() where [u8; std::mem::size_of::<T>() - 1]: Sized {
+    assert_eq!(const_evaluatable_lib::test1::<T>(), [0; std::mem::size_of::<T>() - 1]);
+}
+
+fn main() {
+    assert_eq!(const_evaluatable_lib::test1::<u32>(), [0; 3]);
+    user::<u32>();
+    user::<u64>();
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs
new file mode 100644
index 00000000000..22369923329
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs
@@ -0,0 +1,13 @@
+// aux-build:const_evaluatable_lib.rs
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+extern crate const_evaluatable_lib;
+
+fn user<T>() {
+    let _ = const_evaluatable_lib::test1::<T>();
+    //~^ ERROR constant expression depends
+    //~| ERROR constant expression depends
+    //~| ERROR constant expression depends
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr
new file mode 100644
index 00000000000..63abb782b93
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr
@@ -0,0 +1,36 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/cross_crate_predicate.rs:7:13
+   |
+LL |     let _ = const_evaluatable_lib::test1::<T>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | 
+  ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
+   |
+LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
+   |                                         ----- required by this bound in `test1`
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/cross_crate_predicate.rs:7:13
+   |
+LL |     let _ = const_evaluatable_lib::test1::<T>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | 
+  ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
+   |
+LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
+   |                                         ----- required by this bound in `test1::{{constant}}#1`
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/cross_crate_predicate.rs:7:13
+   |
+LL |     let _ = const_evaluatable_lib::test1::<T>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/fn_call.rs b/src/test/ui/const-generics/const_evaluatable_checked/fn_call.rs
new file mode 100644
index 00000000000..1b9ec0108b1
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/fn_call.rs
@@ -0,0 +1,30 @@
+// run-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+const fn test_me<T>(a: usize, b: usize) -> usize {
+    if a < b {
+        std::mem::size_of::<T>()
+    } else {
+        std::usize::MAX
+    }
+}
+
+fn test_simple<T>() -> [u8; std::mem::size_of::<T>()]
+where
+    [u8; std::mem::size_of::<T>()]: Sized,
+{
+    [0; std::mem::size_of::<T>()]
+}
+
+fn test_with_args<T, const N: usize>() -> [u8; test_me::<T>(N, N + 1) + N]
+where
+    [u8; test_me::<T>(N, N + 1) + N]: Sized,
+{
+    [0; test_me::<T>(N, N + 1) + N]
+}
+
+fn main() {
+    assert_eq!([0; 8], test_simple::<u64>());
+    assert_eq!([0; 12], test_with_args::<u64, 4>());
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/less_than.rs b/src/test/ui/const-generics/const_evaluatable_checked/less_than.rs
new file mode 100644
index 00000000000..907ea255abb
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/less_than.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+struct Foo<const B: bool>;
+
+fn test<const N: usize>() -> Foo<{ N > 10 }> where Foo<{ N > 10 }>: Sized {
+    Foo
+}
+
+fn main() {
+    let _: Foo<true> = test::<12>();
+    let _: Foo<false> = test::<9>();
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs
new file mode 100644
index 00000000000..d96788f8cd1
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs
@@ -0,0 +1,15 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+// We do not yet want to support let-bindings in abstract consts,
+// so this test should keep failing for now.
+fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
+    //~^ ERROR constant expression depends
+    //~| ERROR constant expression depends
+    Default::default()
+}
+
+fn main() {
+    let x = test::<31>();
+    assert_eq!(x, [0; 32]);
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr
new file mode 100644
index 00000000000..95fb48bd434
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/let-bindings.rs:6:91
+   |
+LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
+   |                                                                                           ^^^^^^^ required by this bound in `test::{{constant}}#0`
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/let-bindings.rs:6:30
+   |
+LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr
index da8ccdaee41..3cac604a7b3 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr
+++ b/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr
@@ -1,10 +1,18 @@
 error: generic parameters must not be used inside of non trivial constant values
-  --> $DIR/simple.rs:8:33
+  --> $DIR/simple.rs:8:53
    |
-LL | type Arr<const N: usize> = [u8; N - 1];
-   |                                 ^ non-trivial anonymous constants must not depend on the parameter `N`
+LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
+   |                                                     ^ non-trivial anonymous constants must not depend on the parameter `N`
    |
    = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
 
-error: aborting due to previous error
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/simple.rs:8:35
+   |
+LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
+   |                                   ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs
index 27dc6b10320..dcf0071cb29 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/simple.rs
+++ b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs
@@ -5,10 +5,9 @@
 #![feature(const_evaluatable_checked)]
 #![allow(incomplete_features)]
 
-type Arr<const N: usize> = [u8; N - 1];
-//[min]~^ ERROR generic parameters must not be used inside of non trivial constant values
-
-fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
+fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
+    //[min]~^ ERROR generic parameters
+    //[min]~| ERROR generic parameters
     Default::default()
 }
 
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unop.rs b/src/test/ui/const-generics/const_evaluatable_checked/unop.rs
new file mode 100644
index 00000000000..8e0768b1c95
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/unop.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+struct Foo<const B: bool>;
+
+fn test<const N: usize>() -> Foo<{ !(N > 10) }> where Foo<{ !(N > 10) }>: Sized {
+    Foo
+}
+
+fn main() {
+    let _: Foo<false> = test::<12>();
+    let _: Foo<true> = test::<9>();
+}
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
index 053139787ed..84e75cc3764 100644
--- a/src/test/ui/const-generics/cannot-infer-const-args.full.stderr
+++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     foo();
    |     ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `X`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
index 053139787ed..84e75cc3764 100644
--- a/src/test/ui/const-generics/cannot-infer-const-args.min.stderr
+++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     foo();
    |     ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `X`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.rs b/src/test/ui/const-generics/infer/cannot-infer-const-args.rs
index 2d74b4788bf..2d74b4788bf 100644
--- a/src/test/ui/const-generics/cannot-infer-const-args.rs
+++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.rs
diff --git a/src/test/ui/const-generics/infer/method-chain.full.stderr b/src/test/ui/const-generics/infer/method-chain.full.stderr
new file mode 100644
index 00000000000..e65bc3f1096
--- /dev/null
+++ b/src/test/ui/const-generics/infer/method-chain.full.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-chain.rs:21:33
+   |
+LL |     Foo.bar().bar().bar().bar().baz();
+   |                                 ^^^
+   |
+   = note: cannot infer the value of the const parameter `N`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/method-chain.min.stderr b/src/test/ui/const-generics/infer/method-chain.min.stderr
new file mode 100644
index 00000000000..e65bc3f1096
--- /dev/null
+++ b/src/test/ui/const-generics/infer/method-chain.min.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-chain.rs:21:33
+   |
+LL |     Foo.bar().bar().bar().bar().baz();
+   |                                 ^^^
+   |
+   = note: cannot infer the value of the const parameter `N`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/method-chain.rs b/src/test/ui/const-generics/infer/method-chain.rs
new file mode 100644
index 00000000000..9389ca20d10
--- /dev/null
+++ b/src/test/ui/const-generics/infer/method-chain.rs
@@ -0,0 +1,22 @@
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+struct Foo;
+
+impl Foo {
+    fn bar(self) -> Foo {
+        Foo
+    }
+
+    fn baz<const N: usize>(self) -> Foo {
+        println!("baz: {}", N);
+        Foo
+    }
+}
+
+fn main() {
+    Foo.bar().bar().bar().bar().baz(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/const-generics/uninferred-consts.full.stderr b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr
index 2c5af9e65f8..e47b6bd5dc6 100644
--- a/src/test/ui/const-generics/uninferred-consts.full.stderr
+++ b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr
@@ -1,10 +1,10 @@
 error[E0282]: type annotations needed
-  --> $DIR/uninferred-consts.rs:14:5
+  --> $DIR/uninferred-consts.rs:14:9
    |
 LL |     Foo.foo();
-   |     ^^^^^^^^^
+   |         ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `N`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/uninferred-consts.min.stderr b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr
index 2c5af9e65f8..e47b6bd5dc6 100644
--- a/src/test/ui/const-generics/uninferred-consts.min.stderr
+++ b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr
@@ -1,10 +1,10 @@
 error[E0282]: type annotations needed
-  --> $DIR/uninferred-consts.rs:14:5
+  --> $DIR/uninferred-consts.rs:14:9
    |
 LL |     Foo.foo();
-   |     ^^^^^^^^^
+   |         ^^^
    |
-   = note: unable to infer the value of a const parameter
+   = note: cannot infer the value of the const parameter `N`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/uninferred-consts.rs b/src/test/ui/const-generics/infer/uninferred-consts.rs
index ec5b3ffe544..ec5b3ffe544 100644
--- a/src/test/ui/const-generics/uninferred-consts.rs
+++ b/src/test/ui/const-generics/infer/uninferred-consts.rs
diff --git a/src/test/ui/const-generics/issues/issue-64494.min.stderr b/src/test/ui/const-generics/issues/issue-64494.min.stderr
index 69fe0974a79..07822f86f52 100644
--- a/src/test/ui/const-generics/issues/issue-64494.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-64494.min.stderr
@@ -4,7 +4,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {}
    |                                      ^^^^^^ non-trivial anonymous constants must not depend on the parameter `T`
    |
-   = help: it is currently only allowed to use either `T` or `{ T }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error: generic parameters must not be used inside of non trivial constant values
   --> $DIR/issue-64494.rs:19:38
@@ -12,7 +12,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {}
    |                                      ^^^^^^ non-trivial anonymous constants must not depend on the parameter `T`
    |
-   = help: it is currently only allowed to use either `T` or `{ T }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error[E0119]: conflicting implementations of trait `MyTrait`:
   --> $DIR/issue-64494.rs:19:1
diff --git a/src/test/ui/const-generics/issues/issue-67739.min.stderr b/src/test/ui/const-generics/issues/issue-67739.min.stderr
index 1254ee7239d..68f1733decb 100644
--- a/src/test/ui/const-generics/issues/issue-67739.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-67739.min.stderr
@@ -4,7 +4,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL |         [0u8; mem::size_of::<Self::Associated>()];
    |                              ^^^^^^^^^^^^^^^^ non-trivial anonymous constants must not depend on the parameter `Self`
    |
-   = help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr
new file mode 100644
index 00000000000..089937e66ca
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-76701-ty-param-in-const.rs:6:21
+   |
+LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-76701-ty-param-in-const.rs:12:37
+   |
+LL | fn const_param<const N: usize>() -> [u8; N + 1] {
+   |                                     ^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr
new file mode 100644
index 00000000000..a39495e0b2d
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr
@@ -0,0 +1,18 @@
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/issue-76701-ty-param-in-const.rs:6:46
+   |
+LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
+   |                                              ^ non-trivial anonymous constants must not depend on the parameter `T`
+   |
+   = note: type parameters are currently not permitted in anonymous constants
+
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/issue-76701-ty-param-in-const.rs:12:42
+   |
+LL | fn const_param<const N: usize>() -> [u8; N + 1] {
+   |                                          ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs
new file mode 100644
index 00000000000..9252b592360
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs
@@ -0,0 +1,18 @@
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
+    //[full]~^ ERROR constant expression depends on a generic parameter
+    //[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values
+    todo!()
+}
+
+fn const_param<const N: usize>() -> [u8; N + 1] {
+    //[full]~^ ERROR constant expression depends on a generic parameter
+    //[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr
index 89ce58564e4..edb77a87430 100644
--- a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr
+++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr
@@ -4,7 +4,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL |     fn t1() -> [u8; std::mem::size_of::<Self>()];
    |                                         ^^^^ non-trivial anonymous constants must not depend on the parameter `Self`
    |
-   = help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error: generic `Self` types are currently not permitted in anonymous constants
   --> $DIR/self-ty-in-const-1.rs:14:41
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
index 461822a9608..e545ae8571f 100644
--- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
+++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
@@ -12,7 +12,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    |                                            ^ non-trivial anonymous constants must not depend on the parameter `T`
    |
-   = help: it is currently only allowed to use either `T` or `{ T }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error: constant values inside of type parameter defaults must not depend on generic parameters
   --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21
diff --git a/src/test/ui/const-generics/type-dependent/issue-61936.rs b/src/test/ui/const-generics/type-dependent/issue-61936.rs
index 1d42afa3f84..f3b19109a7c 100644
--- a/src/test/ui/const-generics/type-dependent/issue-61936.rs
+++ b/src/test/ui/const-generics/type-dependent/issue-61936.rs
@@ -5,21 +5,21 @@
 #![cfg_attr(min, feature(min_const_generics))]
 
 trait SliceExt<T: Clone> {
-    fn array_windows<'a, const N: usize>(&'a self) -> ArrayWindows<'a, T, N>;
+    fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N>;
 }
 
 impl <T: Clone> SliceExt<T> for [T] {
-   fn array_windows<'a, const N: usize>(&'a self) -> ArrayWindows<'a, T, N> {
-       ArrayWindows{ idx: 0, slice: &self }
+   fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N> {
+       ArrayWindowsExample{ idx: 0, slice: &self }
    }
 }
 
-struct ArrayWindows<'a, T, const N: usize> {
+struct ArrayWindowsExample<'a, T, const N: usize> {
     slice: &'a [T],
     idx: usize,
 }
 
-impl <'a, T: Clone, const N: usize> Iterator for ArrayWindows<'a, T, N> {
+impl <'a, T: Clone, const N: usize> Iterator for ArrayWindowsExample<'a, T, N> {
     type Item = [T; N];
     fn next(&mut self) -> Option<Self::Item> {
         // Note: this is unsound for some `T` and not meant as an example
@@ -45,7 +45,7 @@ const FOUR: usize = 4;
 fn main() {
     let v: Vec<usize> = vec![0; 100];
 
-    for array in v.as_slice().array_windows::<FOUR>() {
+    for array in v.as_slice().array_windows_example::<FOUR>() {
         assert_eq!(array, [0, 0, 0, 0])
     }
 }
diff --git a/src/test/ui/consts/duration-consts-2.rs b/src/test/ui/consts/duration-consts-2.rs
deleted file mode 100644
index bc0969e4f1f..00000000000
--- a/src/test/ui/consts/duration-consts-2.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-// run-pass
-
-#![feature(const_panic)]
-#![feature(duration_consts_2)]
-#![feature(div_duration)]
-#![feature(duration_saturating_ops)]
-
-use std::time::Duration;
-
-fn duration() {
-    const ZERO : Duration = Duration::new(0, 0);
-    assert_eq!(ZERO, Duration::from_secs(0));
-
-    const ONE : Duration = Duration::new(0, 1);
-    assert_eq!(ONE, Duration::from_nanos(1));
-
-    const MAX : Duration = Duration::new(u64::MAX, 1_000_000_000 - 1);
-
-    const MAX_CHECKED_ADD_ZERO : Option<Duration> = MAX.checked_add(ZERO);
-    assert_eq!(MAX_CHECKED_ADD_ZERO, Some(MAX));
-
-    const MAX_CHECKED_ADD_ONE : Option<Duration> = MAX.checked_add(ONE);
-    assert_eq!(MAX_CHECKED_ADD_ONE, None);
-
-    const ONE_CHECKED_SUB_ONE : Option<Duration> = ONE.checked_sub(ONE);
-    assert_eq!(ONE_CHECKED_SUB_ONE, Some(ZERO));
-
-    const ZERO_CHECKED_SUB_ONE : Option<Duration> = ZERO.checked_sub(ONE);
-    assert_eq!(ZERO_CHECKED_SUB_ONE, None);
-
-    const ONE_CHECKED_MUL_ONE : Option<Duration> = ONE.checked_mul(1);
-    assert_eq!(ONE_CHECKED_MUL_ONE, Some(ONE));
-
-    const MAX_CHECKED_MUL_TWO : Option<Duration> = MAX.checked_mul(2);
-    assert_eq!(MAX_CHECKED_MUL_TWO, None);
-
-    const ONE_CHECKED_DIV_ONE : Option<Duration> = ONE.checked_div(1);
-    assert_eq!(ONE_CHECKED_DIV_ONE, Some(ONE));
-
-    const ONE_CHECKED_DIV_ZERO : Option<Duration> = ONE.checked_div(0);
-    assert_eq!(ONE_CHECKED_DIV_ZERO, None);
-
-    const MAX_AS_F32 : f32 = MAX.as_secs_f32();
-    assert_eq!(MAX_AS_F32, 18446744000000000000.0_f32);
-
-    const MAX_AS_F64 : f64 = MAX.as_secs_f64();
-    assert_eq!(MAX_AS_F64, 18446744073709552000.0_f64);
-
-    const ONE_AS_F32 : f32 = ONE.div_duration_f32(ONE);
-    assert_eq!(ONE_AS_F32, 1.0_f32);
-
-    const ONE_AS_F64 : f64 = ONE.div_duration_f64(ONE);
-    assert_eq!(ONE_AS_F64, 1.0_f64);
-
-    const MAX_SATURATING_ADD_ONE : Duration = MAX.saturating_add(ONE);
-    assert_eq!(MAX_SATURATING_ADD_ONE, MAX);
-
-    const ZERO_SATURATING_SUB_ONE : Duration = ZERO.saturating_sub(ONE);
-    assert_eq!(ZERO_SATURATING_SUB_ONE, ZERO);
-
-    const MAX_SATURATING_MUL_TWO : Duration = MAX.saturating_mul(2);
-    assert_eq!(MAX_SATURATING_MUL_TWO, MAX);
-}
-
-fn main() {
-    duration();
-}
diff --git a/src/test/ui/error-codes/E0118-2.rs b/src/test/ui/error-codes/E0118-2.rs
new file mode 100644
index 00000000000..fe04190162a
--- /dev/null
+++ b/src/test/ui/error-codes/E0118-2.rs
@@ -0,0 +1,8 @@
+struct Foo;
+
+impl &mut Foo {
+    //~^ ERROR E0118
+    fn bar(self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0118-2.stderr b/src/test/ui/error-codes/E0118-2.stderr
new file mode 100644
index 00000000000..2a1fe231116
--- /dev/null
+++ b/src/test/ui/error-codes/E0118-2.stderr
@@ -0,0 +1,12 @@
+error[E0118]: no nominal type found for inherent implementation
+  --> $DIR/E0118-2.rs:3:6
+   |
+LL | impl &mut Foo {
+   |      ^^^^^^^^ impl requires a nominal type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+   = note: you could also try moving the reference to uses of `Foo` (such as `self`) within the implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0118`.
diff --git a/src/test/ui/error-codes/E0118.stderr b/src/test/ui/error-codes/E0118.stderr
index b0afaeb5c1f..2693a93213a 100644
--- a/src/test/ui/error-codes/E0118.stderr
+++ b/src/test/ui/error-codes/E0118.stderr
@@ -1,8 +1,8 @@
-error[E0118]: no base type found for inherent implementation
+error[E0118]: no nominal type found for inherent implementation
   --> $DIR/E0118.rs:1:6
    |
 LL | impl (u8, u8) {
-   |      ^^^^^^^^ impl requires a base type
+   |      ^^^^^^^^ impl requires a nominal type
    |
    = note: either implement a trait on it or create a newtype to wrap it instead
 
diff --git a/src/test/ui/infinite/infinite-instantiation.stderr b/src/test/ui/infinite/infinite-instantiation.stderr
index 1aaefea9f04..d27d14842ce 100644
--- a/src/test/ui/infinite/infinite-instantiation.stderr
+++ b/src/test/ui/infinite/infinite-instantiation.stderr
@@ -1,4 +1,4 @@
-error: reached the recursion limit while instantiating `function::<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<usize>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+error: reached the recursion limit while instantiating `function::<Option<Option<Option<...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
   --> $DIR/infinite-instantiation.rs:21:9
    |
 LL |         function(counter - 1, t.to_option());
diff --git a/src/test/ui/issues/issue-22638.rs b/src/test/ui/issues/issue-22638.rs
index 72c16fddb4b..89137538425 100644
--- a/src/test/ui/issues/issue-22638.rs
+++ b/src/test/ui/issues/issue-22638.rs
@@ -51,9 +51,9 @@ struct D (Box<A>);
 
 impl D {
     pub fn matches<F: Fn()>(&self, f: &F) {
-        //~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure
         let &D(ref a) = self;
         a.matches(f)
+        //~^ ERROR reached the recursion limit while instantiating `A::matches::<[closure
     }
 }
 
diff --git a/src/test/ui/issues/issue-22638.stderr b/src/test/ui/issues/issue-22638.stderr
index b0df46b11fa..c4255b95b70 100644
--- a/src/test/ui/issues/issue-22638.stderr
+++ b/src/test/ui/issues/issue-22638.stderr
@@ -1,10 +1,14 @@
-error: reached the type-length limit while instantiating `D::matches::$CLOSURE`
-  --> $DIR/issue-22638.rs:53:5
+error: reached the recursion limit while instantiating `A::matches::$CLOSURE`
+  --> $DIR/issue-22638.rs:55:9
+   |
+LL |         a.matches(f)
+   |         ^^^^^^^^^^^^
+   |
+note: `A::matches` defined here
+  --> $DIR/issue-22638.rs:14:5
    |
 LL |     pub fn matches<F: Fn()>(&self, f: &F) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: consider adding a `#![type_length_limit="30408681"]` attribute to your crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs
index fec4b171536..d3d5863ddb3 100644
--- a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs
+++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs
@@ -12,8 +12,8 @@ trait Foo {
 
 impl<T> Foo for T {
     #[allow(unconditional_recursion)]
-    fn recurse(&self) { //~ ERROR reached the type-length limit
-        (self, self).recurse();
+    fn recurse(&self) {
+        (self, self).recurse(); //~ ERROR reached the recursion limit
     }
 }
 
diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
index 6229d90d4b4..a94f190d6b2 100644
--- a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
+++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
@@ -1,10 +1,14 @@
-error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(...))))))))))))))) as Foo>::recurse`
+error: reached the recursion limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(.....), ...), ...) as Foo>::recurse`
+  --> $DIR/issue-37311.rs:16:9
+   |
+LL |         (self, self).recurse();
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `<T as Foo>::recurse` defined here
   --> $DIR/issue-37311.rs:15:5
    |
 LL |     fn recurse(&self) {
    |     ^^^^^^^^^^^^^^^^^
-   |
-   = note: consider adding a `#![type_length_limit="2097149"]` attribute to your crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-67552.stderr b/src/test/ui/issues/issue-67552.stderr
index 8243e52039d..f3e73399b57 100644
--- a/src/test/ui/issues/issue-67552.stderr
+++ b/src/test/ui/issues/issue-67552.stderr
@@ -1,4 +1,4 @@
-error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut Empty>`
+error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &... &mut &mut &mut &mut &mut Empty>`
   --> $DIR/issue-67552.rs:27:9
    |
 LL |         rec(identity(&mut it))
diff --git a/src/test/ui/issues/issue-8727.stderr b/src/test/ui/issues/issue-8727.stderr
index dd57e69f2cf..279e3ffbb4a 100644
--- a/src/test/ui/issues/issue-8727.stderr
+++ b/src/test/ui/issues/issue-8727.stderr
@@ -9,7 +9,7 @@ LL |     generic::<Option<T>>();
    = note: `#[warn(unconditional_recursion)]` on by default
    = help: a `loop` may express intention better if this is on purpose
 
-error: reached the recursion limit while instantiating `generic::<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<Option<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+error: reached the recursion limit while instantiating `generic::<Option<Option<Option<O...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
   --> $DIR/issue-8727.rs:7:5
    |
 LL |     generic::<Option<T>>();
diff --git a/src/test/ui/mir/issue-76803-branches-not-same.rs b/src/test/ui/mir/issue-76803-branches-not-same.rs
new file mode 100644
index 00000000000..a6a57622005
--- /dev/null
+++ b/src/test/ui/mir/issue-76803-branches-not-same.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#[derive(Debug, Eq, PartialEq)]
+pub enum Type {
+    A,
+    B,
+}
+
+
+pub fn encode(v: Type) -> Type {
+    match v {
+        Type::A => Type::B,
+        _ => v,
+    }
+}
+
+fn main() {
+  assert_eq!(Type::B, encode(Type::A));
+}
diff --git a/src/test/ui/numbers-arithmetic/arith-0.rs b/src/test/ui/numbers-arithmetic/arith-0.rs
deleted file mode 100644
index 7943cb908d1..00000000000
--- a/src/test/ui/numbers-arithmetic/arith-0.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-
-
-pub fn main() {
-    let a: isize = 10;
-    println!("{}", a);
-    assert_eq!(a * (a - 1), 90);
-}
diff --git a/src/test/ui/numbers-arithmetic/arith-1.rs b/src/test/ui/numbers-arithmetic/arith-1.rs
deleted file mode 100644
index c13c8d8b765..00000000000
--- a/src/test/ui/numbers-arithmetic/arith-1.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-
-
-pub fn main() {
-    let i32_a: isize = 10;
-    assert_eq!(i32_a, 10);
-    assert_eq!(i32_a - 10, 0);
-    assert_eq!(i32_a / 10, 1);
-    assert_eq!(i32_a - 20, -10);
-    assert_eq!(i32_a << 10, 10240);
-    assert_eq!(i32_a << 16, 655360);
-    assert_eq!(i32_a * 16, 160);
-    assert_eq!(i32_a * i32_a * i32_a, 1000);
-    assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000);
-    assert_eq!(i32_a * i32_a / i32_a * i32_a, 100);
-    assert_eq!(i32_a * (i32_a - 1) << (2 + i32_a as usize), 368640);
-    let i32_b: isize = 0x10101010;
-    assert_eq!(i32_b + 1 - 1, i32_b);
-    assert_eq!(i32_b << 1, i32_b << 1);
-    assert_eq!(i32_b >> 1, i32_b >> 1);
-    assert_eq!(i32_b & i32_b << 1, 0);
-    println!("{}", i32_b | i32_b << 1);
-    assert_eq!(i32_b | i32_b << 1, 0x30303030);
-}
diff --git a/src/test/ui/numbers-arithmetic/arith-2.rs b/src/test/ui/numbers-arithmetic/arith-2.rs
deleted file mode 100644
index 46c280677ce..00000000000
--- a/src/test/ui/numbers-arithmetic/arith-2.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-
-
-
-pub fn main() {
-    let i32_c: isize = 0x10101010;
-    assert_eq!(i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3),
-                 i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3));
-}
diff --git a/src/test/ui/privacy/private-in-public-ill-formed.rs b/src/test/ui/privacy/private-in-public-ill-formed.rs
index 0ef5d89002e..031e2874a2b 100644
--- a/src/test/ui/privacy/private-in-public-ill-formed.rs
+++ b/src/test/ui/privacy/private-in-public-ill-formed.rs
@@ -11,7 +11,8 @@ mod aliases_pub {
         type AssocAlias = m::Pub3;
     }
 
-    impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
+    impl <Priv as PrivTr>::AssocAlias {
+        //~^ ERROR no nominal type found for inherent implementation
         pub fn f(arg: Priv) {} // private type `aliases_pub::Priv` in public interface
     }
 }
@@ -27,7 +28,8 @@ mod aliases_priv {
         type AssocAlias = Priv3;
     }
 
-    impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
+    impl <Priv as PrivTr>::AssocAlias {
+        //~^ ERROR no nominal type found for inherent implementation
         pub fn f(arg: Priv) {} // OK
     }
 }
diff --git a/src/test/ui/privacy/private-in-public-ill-formed.stderr b/src/test/ui/privacy/private-in-public-ill-formed.stderr
index a1a326f2873..e7c94bc301b 100644
--- a/src/test/ui/privacy/private-in-public-ill-formed.stderr
+++ b/src/test/ui/privacy/private-in-public-ill-formed.stderr
@@ -1,16 +1,16 @@
-error[E0118]: no base type found for inherent implementation
+error[E0118]: no nominal type found for inherent implementation
   --> $DIR/private-in-public-ill-formed.rs:14:10
    |
 LL |     impl <Priv as PrivTr>::AssocAlias {
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a base type
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
    |
    = note: either implement a trait on it or create a newtype to wrap it instead
 
-error[E0118]: no base type found for inherent implementation
-  --> $DIR/private-in-public-ill-formed.rs:30:10
+error[E0118]: no nominal type found for inherent implementation
+  --> $DIR/private-in-public-ill-formed.rs:31:10
    |
 LL |     impl <Priv as PrivTr>::AssocAlias {
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a base type
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
    |
    = note: either implement a trait on it or create a newtype to wrap it instead
 
diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
index 536e26d2955..4d77b3d295c 100644
--- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
+++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
@@ -1,4 +1,4 @@
-error: reached the recursion limit while instantiating `drop_in_place::<S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>> - shim(Some(S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>))`
+error: reached the recursion limit while instantiating `drop_in_place::<S<fn(fn(fn(fn(fn...)))))))))))))))))))))))))))))>))`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
 LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
diff --git a/src/test/ui/recursion/recursion.stderr b/src/test/ui/recursion/recursion.stderr
index db4c99eeb8b..085bf82ef8b 100644
--- a/src/test/ui/recursion/recursion.stderr
+++ b/src/test/ui/recursion/recursion.stderr
@@ -1,4 +1,4 @@
-error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Cons<Nil>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
   --> $DIR/recursion.rs:17:11
    |
 LL |     _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
diff --git a/src/test/ui/str-multiline.rs b/src/test/ui/str-multiline.rs
deleted file mode 100644
index 2b2e001d8bb..00000000000
--- a/src/test/ui/str-multiline.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-
-pub fn main() {
-    let a: String = "this \
-is a test".to_string();
-    let b: String =
-        "this \
-              is \
-              another \
-              test".to_string();
-    assert_eq!(a, "this is a test".to_string());
-    assert_eq!(b, "this is another test".to_string());
-}
diff --git a/src/test/ui/string-escapes.rs b/src/test/ui/string-escapes.rs
deleted file mode 100644
index cee5e27786c..00000000000
--- a/src/test/ui/string-escapes.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-
-fn main() {
-    let x = "\\\\\
-    ";
-    assert_eq!(x, r"\\"); // extraneous whitespace stripped
-}
diff --git a/src/test/ui/trait-impl-bound-suggestions.fixed b/src/test/ui/trait-impl-bound-suggestions.fixed
new file mode 100644
index 00000000000..db3a95f5c4f
--- /dev/null
+++ b/src/test/ui/trait-impl-bound-suggestions.fixed
@@ -0,0 +1,20 @@
+// run-rustfix
+
+#[allow(unused)]
+use std::fmt::Debug;
+// Rustfix should add this, or use `std::fmt::Debug` instead.
+
+#[allow(dead_code)]
+struct ConstrainedStruct<X: Copy> {
+    x: X
+}
+
+#[allow(dead_code)]
+trait InsufficientlyConstrainedGeneric<X=()> where X: Copy {
+    fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
+        //~^ ERROR the trait bound `X: Copy` is not satisfied
+        ConstrainedStruct { x }
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/trait-impl-bound-suggestions.rs b/src/test/ui/trait-impl-bound-suggestions.rs
new file mode 100644
index 00000000000..bf75175179e
--- /dev/null
+++ b/src/test/ui/trait-impl-bound-suggestions.rs
@@ -0,0 +1,20 @@
+// run-rustfix
+
+#[allow(unused)]
+use std::fmt::Debug;
+// Rustfix should add this, or use `std::fmt::Debug` instead.
+
+#[allow(dead_code)]
+struct ConstrainedStruct<X: Copy> {
+    x: X
+}
+
+#[allow(dead_code)]
+trait InsufficientlyConstrainedGeneric<X=()> {
+    fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
+        //~^ ERROR the trait bound `X: Copy` is not satisfied
+        ConstrainedStruct { x }
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/trait-impl-bound-suggestions.stderr b/src/test/ui/trait-impl-bound-suggestions.stderr
new file mode 100644
index 00000000000..3a21e9c6b2a
--- /dev/null
+++ b/src/test/ui/trait-impl-bound-suggestions.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `X: Copy` is not satisfied
+  --> $DIR/trait-impl-bound-suggestions.rs:14:52
+   |
+LL | struct ConstrainedStruct<X: Copy> {
+   |                             ---- required by this bound in `ConstrainedStruct`
+...
+LL |     fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
+   |                                                    ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `X`
+   |
+help: consider further restricting type parameter `X`
+   |
+LL | trait InsufficientlyConstrainedGeneric<X=()> where X: Copy {
+   |                                              ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr
index fa6f3422410..d8c7f595e62 100644
--- a/src/test/ui/type/type-check-defaults.stderr
+++ b/src/test/ui/type/type-check-defaults.stderr
@@ -56,8 +56,8 @@ LL | trait Base<T = String>: Super<T> { }
    |
 help: consider further restricting type parameter `T`
    |
-LL | trait Base<T = String>: Super<T>, T: Copy { }
-   |                                 ^^^^^^^^^
+LL | trait Base<T = String>: Super<T> where T: Copy { }
+   |                                  ^^^^^^^^^^^^^
 
 error[E0277]: cannot add `u8` to `i32`
   --> $DIR/type-check-defaults.rs:24:66
diff --git a/src/test/ui/type_length_limit.rs b/src/test/ui/type_length_limit.rs
index 1f1c8ad9626..921cded5037 100644
--- a/src/test/ui/type_length_limit.rs
+++ b/src/test/ui/type_length_limit.rs
@@ -4,7 +4,7 @@
 // Test that the type length limit can be changed.
 
 #![allow(dead_code)]
-#![type_length_limit="256"]
+#![type_length_limit="4"]
 
 macro_rules! link {
     ($id:ident, $t:ty) => {
diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr
index f12f259d2f6..cf3d64d734b 100644
--- a/src/test/ui/type_length_limit.stderr
+++ b/src/test/ui/type_length_limit.stderr
@@ -1,10 +1,10 @@
-error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((((G,... G), (G, G, G), (G, G, G))))))>>`
+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) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: consider adding a `#![type_length_limit="1094"]` attribute to your crate
+   = note: consider adding a `#![type_length_limit="8"]` attribute to your crate
 
 error: aborting due to previous error
 
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 58022484fa6..ff9ee67763b 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -16,6 +16,7 @@ use std::process::{Command, Stdio};
 
 static HOSTS: &[&str] = &[
     "aarch64-unknown-linux-gnu",
+    "aarch64-unknown-linux-musl",
     "arm-unknown-linux-gnueabi",
     "arm-unknown-linux-gnueabihf",
     "armv7-unknown-linux-gnueabihf",
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 965b20f5202..acad316d807 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -3156,12 +3156,12 @@ impl<'test> TestCx<'test> {
 
         if self.config.bless {
             for e in
-                glob(&format!("{}/{}.*.mir{}", test_dir.display(), test_crate, bit_width)).unwrap()
+                glob(&format!("{}/{}.*{}.mir", test_dir.display(), test_crate, bit_width)).unwrap()
             {
                 std::fs::remove_file(e.unwrap()).unwrap();
             }
             for e in
-                glob(&format!("{}/{}.*.diff{}", test_dir.display(), test_crate, bit_width)).unwrap()
+                glob(&format!("{}/{}.*{}.diff", test_dir.display(), test_crate, bit_width)).unwrap()
             {
                 std::fs::remove_file(e.unwrap()).unwrap();
             }
@@ -3181,7 +3181,7 @@ impl<'test> TestCx<'test> {
                     let trimmed = test_name.trim_end_matches(".diff");
                     let test_against = format!("{}.after.mir", trimmed);
                     from_file = format!("{}.before.mir", trimmed);
-                    expected_file = format!("{}{}", test_name, bit_width);
+                    expected_file = format!("{}{}.diff", trimmed, bit_width);
                     assert!(
                         test_names.next().is_none(),
                         "two mir pass names specified for MIR diff"
@@ -3199,7 +3199,8 @@ impl<'test> TestCx<'test> {
                     from_file = format!("{}.{}.mir", test_name, first_pass);
                     to_file = Some(second_file);
                 } else {
-                    expected_file = format!("{}{}", test_name, bit_width);
+                    expected_file =
+                        format!("{}{}.mir", test_name.trim_end_matches(".mir"), bit_width);
                     from_file = test_name.to_string();
                     assert!(
                         test_names.next().is_none(),
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index 5323bc357c0..92b3d186fa1 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -402,9 +402,12 @@ fn generate_lint_output(
                 None => {
                     let rendered: Vec<&str> =
                         msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
+                    let non_json: Vec<&str> =
+                        stderr.lines().filter(|line| !line.starts_with('{')).collect();
                     Err(format!(
-                        "did not find lint `{}` in output of example, got:\n{}",
+                        "did not find lint `{}` in output of example, got:\n{}\n{}",
                         name,
+                        non_json.join("\n"),
                         rendered.join("\n")
                     )
                     .into())
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject 0275b08d1521606fa733f76fe5d5707717456fb
+Subproject 0d03fe6ef57d3956e92382e0e1f1a916015191c