about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorTim Diekmann <21277928+TimDiekmann@users.noreply.github.com>2020-08-03 02:18:20 +0200
committerGitHub <noreply@github.com>2020-08-03 02:18:20 +0200
commit24ddf76ed7bc453826e6e843cd0ca289e02185f1 (patch)
tree2833654479a3749e6646890af4bdbc071b181f3b /src
parentdb7d07b83bee302be977468caa6931f651b4f77a (diff)
parent81e754c359c471f91263813c46c67955071716a7 (diff)
downloadrust-24ddf76ed7bc453826e6e843cd0ca289e02185f1.tar.gz
rust-24ddf76ed7bc453826e6e843cd0ca289e02185f1.zip
Merge branch 'master' into remove-in-place-alloc
Diffstat (limited to 'src')
-rw-r--r--src/README.md2
-rw-r--r--src/bootstrap/bin/rustc.rs4
-rw-r--r--src/bootstrap/builder.rs60
-rw-r--r--src/bootstrap/builder/tests.rs1015
-rw-r--r--src/bootstrap/compile.rs4
-rw-r--r--src/bootstrap/config.rs2
-rw-r--r--src/bootstrap/dist.rs12
-rw-r--r--src/bootstrap/doc.rs3
-rw-r--r--src/bootstrap/flags.rs2
-rw-r--r--src/bootstrap/mk/Makefile.in34
-rw-r--r--src/bootstrap/test.rs51
-rw-r--r--src/ci/azure-pipelines/auto.yml2
-rw-r--r--src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/arm-android/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/armhf-gnu/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/disabled/dist-armv7-android/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/disabled/dist-i686-android/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-i686-freebsd/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-various-1/Dockerfile2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh10
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile6
-rw-r--r--src/ci/docker/host-x86_64/wasm32/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-full-bootstrap/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-8/Dockerfile8
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile2
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh6
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile2
-rw-r--r--src/ci/github-actions/ci.yml14
-rwxr-xr-xsrc/ci/scripts/symlink-build-dir.sh2
-rw-r--r--src/ci/shared.sh5
-rw-r--r--src/doc/rustdoc/src/lints.md2
-rw-r--r--src/doc/unstable-book/src/language-features/plugin.md32
-rw-r--r--src/etc/test-float-parse/runtests.py11
-rw-r--r--src/librustc_ast/Cargo.toml2
-rw-r--r--src/librustc_ast/token.rs117
-rw-r--r--src/librustc_ast/tokenstream.rs125
-rw-r--r--src/librustc_ast_lowering/Cargo.toml2
-rw-r--r--src/librustc_ast_lowering/item.rs2
-rw-r--r--src/librustc_ast_lowering/lib.rs2
-rw-r--r--src/librustc_ast_lowering/pat.rs2
-rw-r--r--src/librustc_ast_lowering/path.rs2
-rw-r--r--src/librustc_ast_passes/Cargo.toml2
-rw-r--r--src/librustc_ast_passes/feature_gate.rs2
-rw-r--r--src/librustc_ast_pretty/Cargo.toml2
-rw-r--r--src/librustc_ast_pretty/pp.rs2
-rw-r--r--src/librustc_ast_pretty/pprust.rs4
-rw-r--r--src/librustc_builtin_macros/Cargo.toml2
-rw-r--r--src/librustc_codegen_llvm/Cargo.toml2
-rw-r--r--src/librustc_codegen_llvm/callee.rs7
-rw-r--r--src/librustc_codegen_llvm/consts.rs2
-rw-r--r--src/librustc_codegen_llvm/context.rs15
-rw-r--r--src/librustc_codegen_llvm/coverageinfo/mapgen.rs272
-rw-r--r--src/librustc_codegen_llvm/coverageinfo/mod.rs154
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs113
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs180
-rw-r--r--src/librustc_codegen_ssa/Cargo.toml2
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs23
-rw-r--r--src/librustc_codegen_ssa/back/write.rs4
-rw-r--r--src/librustc_codegen_ssa/coverageinfo/ffi.rs67
-rw-r--r--src/librustc_codegen_ssa/coverageinfo/map.rs495
-rw-r--r--src/librustc_codegen_ssa/coverageinfo/mod.rs3
-rw-r--r--src/librustc_codegen_ssa/lib.rs3
-rw-r--r--src/librustc_codegen_ssa/traits/coverageinfo.rs4
-rw-r--r--src/librustc_data_structures/Cargo.toml2
-rw-r--r--src/librustc_driver/Cargo.toml4
-rw-r--r--src/librustc_driver/lib.rs21
-rw-r--r--src/librustc_error_codes/error_codes/E0720.md8
-rw-r--r--src/librustc_error_codes/error_codes/E0728.md6
-rw-r--r--src/librustc_error_codes/error_codes/E0730.md28
-rw-r--r--src/librustc_error_codes/error_codes/E0733.md14
-rw-r--r--src/librustc_error_codes/error_codes/E0734.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0740.md4
-rw-r--r--src/librustc_error_codes/error_codes/E0741.md12
-rw-r--r--src/librustc_error_codes/error_codes/E0743.md11
-rw-r--r--src/librustc_error_codes/error_codes/E0744.md8
-rw-r--r--src/librustc_errors/Cargo.toml2
-rw-r--r--src/librustc_expand/Cargo.toml2
-rw-r--r--src/librustc_expand/mbe.rs4
-rw-r--r--src/librustc_expand/mbe/macro_parser.rs206
-rw-r--r--src/librustc_expand/mbe/macro_rules.rs175
-rw-r--r--src/librustc_expand/mbe/quoted.rs22
-rw-r--r--src/librustc_hir/Cargo.toml2
-rw-r--r--src/librustc_incremental/Cargo.toml2
-rw-r--r--src/librustc_infer/Cargo.toml2
-rw-r--r--src/librustc_infer/infer/combine.rs4
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs2
-rw-r--r--src/librustc_interface/Cargo.toml2
-rw-r--r--src/librustc_interface/passes.rs12
-rw-r--r--src/librustc_lint/Cargo.toml2
-rw-r--r--src/librustc_lint/builtin.rs105
-rw-r--r--src/librustc_lint/context.rs2
-rw-r--r--src/librustc_lint/lib.rs7
-rw-r--r--src/librustc_lint/types.rs202
-rw-r--r--src/librustc_lint/unused.rs24
-rw-r--r--src/librustc_metadata/Cargo.toml2
-rw-r--r--src/librustc_metadata/creader.rs90
-rw-r--r--src/librustc_metadata/dependency_format.rs6
-rw-r--r--src/librustc_metadata/lib.rs1
-rw-r--r--src/librustc_metadata/locator.rs32
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs15
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs7
-rw-r--r--src/librustc_metadata/rmeta/mod.rs5
-rw-r--r--src/librustc_middle/Cargo.toml2
-rw-r--r--src/librustc_middle/middle/cstore.rs8
-rw-r--r--src/librustc_middle/middle/stability.rs20
-rw-r--r--src/librustc_middle/mir/coverage/mod.rs8
-rw-r--r--src/librustc_middle/mir/interpret/queries.rs2
-rw-r--r--src/librustc_middle/mir/interpret/value.rs2
-rw-r--r--src/librustc_middle/query/mod.rs14
-rw-r--r--src/librustc_middle/ty/consts.rs2
-rw-r--r--src/librustc_middle/ty/consts/kind.rs10
-rw-r--r--src/librustc_middle/ty/context.rs91
-rw-r--r--src/librustc_middle/ty/layout.rs4
-rw-r--r--src/librustc_middle/ty/mod.rs27
-rw-r--r--src/librustc_middle/ty/query/keys.rs11
-rw-r--r--src/librustc_middle/ty/query/mod.rs12
-rw-r--r--src/librustc_middle/ty/sty.rs15
-rw-r--r--src/librustc_middle/ty/util.rs156
-rw-r--r--src/librustc_mir/Cargo.toml2
-rw-r--r--src/librustc_mir/const_eval/machine.rs2
-rw-r--r--src/librustc_mir/interpret/cast.rs15
-rw-r--r--src/librustc_mir/interpret/eval_context.rs111
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs31
-rw-r--r--src/librustc_mir/interpret/memory.rs146
-rw-r--r--src/librustc_mir/interpret/mod.rs1
-rw-r--r--src/librustc_mir/interpret/place.rs2
-rw-r--r--src/librustc_mir/interpret/step.rs2
-rw-r--r--src/librustc_mir/interpret/traits.rs8
-rw-r--r--src/librustc_mir/interpret/util.rs73
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_mir/transform/const_prop.rs2
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs2
-rw-r--r--src/librustc_mir/transform/inline.rs2
-rw-r--r--src/librustc_mir/transform/instrument_coverage.rs196
-rw-r--r--src/librustc_mir/transform/mod.rs22
-rw-r--r--src/librustc_mir/transform/promote_consts.rs42
-rw-r--r--src/librustc_mir/transform/simplify.rs69
-rw-r--r--src/librustc_mir/transform/validate.rs2
-rw-r--r--src/librustc_mir/util/pretty.rs62
-rw-r--r--src/librustc_mir_build/Cargo.toml2
-rw-r--r--src/librustc_mir_build/build/block.rs10
-rw-r--r--src/librustc_mir_build/build/expr/as_constant.rs2
-rw-r--r--src/librustc_mir_build/build/expr/as_operand.rs2
-rw-r--r--src/librustc_mir_build/build/expr/as_place.rs2
-rw-r--r--src/librustc_mir_build/build/expr/as_rvalue.rs2
-rw-r--r--src/librustc_mir_build/build/expr/as_temp.rs8
-rw-r--r--src/librustc_mir_build/build/expr/category.rs2
-rw-r--r--src/librustc_mir_build/build/expr/into.rs18
-rw-r--r--src/librustc_mir_build/build/expr/stmt.rs10
-rw-r--r--src/librustc_mir_build/build/into.rs2
-rw-r--r--src/librustc_mir_build/build/matches/mod.rs39
-rw-r--r--src/librustc_mir_build/build/matches/simplify.rs4
-rw-r--r--src/librustc_mir_build/build/matches/test.rs6
-rw-r--r--src/librustc_mir_build/build/matches/util.rs2
-rw-r--r--src/librustc_mir_build/build/mod.rs18
-rw-r--r--src/librustc_mir_build/build/scope.rs8
-rw-r--r--src/librustc_mir_build/lib.rs6
-rw-r--r--src/librustc_mir_build/thir/constant.rs (renamed from src/librustc_mir_build/hair/constant.rs)0
-rw-r--r--src/librustc_mir_build/thir/cx/block.rs (renamed from src/librustc_mir_build/hair/cx/block.rs)8
-rw-r--r--src/librustc_mir_build/thir/cx/expr.rs (renamed from src/librustc_mir_build/hair/cx/expr.rs)12
-rw-r--r--src/librustc_mir_build/thir/cx/mod.rs (renamed from src/librustc_mir_build/hair/cx/mod.rs)6
-rw-r--r--src/librustc_mir_build/thir/cx/to_ref.rs (renamed from src/librustc_mir_build/hair/cx/to_ref.rs)6
-rw-r--r--src/librustc_mir_build/thir/mod.rs (renamed from src/librustc_mir_build/hair/mod.rs)20
-rw-r--r--src/librustc_mir_build/thir/pattern/_match.rs (renamed from src/librustc_mir_build/hair/pattern/_match.rs)0
-rw-r--r--src/librustc_mir_build/thir/pattern/check_match.rs (renamed from src/librustc_mir_build/hair/pattern/check_match.rs)0
-rw-r--r--src/librustc_mir_build/thir/pattern/const_to_pat.rs (renamed from src/librustc_mir_build/hair/pattern/const_to_pat.rs)0
-rw-r--r--src/librustc_mir_build/thir/pattern/mod.rs (renamed from src/librustc_mir_build/hair/pattern/mod.rs)16
-rw-r--r--src/librustc_mir_build/thir/util.rs (renamed from src/librustc_mir_build/hair/util.rs)0
-rw-r--r--src/librustc_parse/Cargo.toml3
-rw-r--r--src/librustc_parse/lib.rs188
-rw-r--r--src/librustc_parse/parser/diagnostics.rs1
-rw-r--r--src/librustc_parse/parser/expr.rs2
-rw-r--r--src/librustc_parse/parser/mod.rs15
-rw-r--r--src/librustc_parse/parser/nonterminal.rs163
-rw-r--r--src/librustc_parse/parser/path.rs2
-rw-r--r--src/librustc_parse/parser/stmt.rs4
-rw-r--r--src/librustc_parse/parser/ty.rs4
-rw-r--r--src/librustc_passes/Cargo.toml2
-rw-r--r--src/librustc_passes/layout_test.rs6
-rw-r--r--src/librustc_privacy/Cargo.toml2
-rw-r--r--src/librustc_privacy/lib.rs2
-rw-r--r--src/librustc_query_system/Cargo.toml2
-rw-r--r--src/librustc_resolve/Cargo.toml2
-rw-r--r--src/librustc_resolve/late.rs37
-rw-r--r--src/librustc_resolve/late/diagnostics.rs195
-rw-r--r--src/librustc_resolve/macros.rs2
-rw-r--r--src/librustc_save_analysis/Cargo.toml2
-rw-r--r--src/librustc_session/Cargo.toml2
-rw-r--r--src/librustc_session/config.rs2
-rw-r--r--src/librustc_session/filesearch.rs32
-rw-r--r--src/librustc_session/lint/builtin.rs4
-rw-r--r--src/librustc_session/options.rs2
-rw-r--r--src/librustc_session/parse.rs5
-rw-r--r--src/librustc_session/session.rs10
-rw-r--r--src/librustc_span/Cargo.toml2
-rw-r--r--src/librustc_span/hygiene.rs4
-rw-r--r--src/librustc_span/symbol.rs1
-rw-r--r--src/librustc_symbol_mangling/Cargo.toml2
-rw-r--r--src/librustc_symbol_mangling/v0.rs6
-rw-r--r--src/librustc_target/Cargo.toml2
-rw-r--r--src/librustc_target/spec/thumbv4t_none_eabi.rs2
-rw-r--r--src/librustc_trait_selection/Cargo.toml2
-rw-r--r--src/librustc_trait_selection/traits/auto_trait.rs32
-rw-r--r--src/librustc_traits/Cargo.toml2
-rw-r--r--src/librustc_ty/Cargo.toml2
-rw-r--r--src/librustc_ty/instance.rs2
-rw-r--r--src/librustc_ty/ty.rs5
-rw-r--r--src/librustc_typeck/Cargo.toml2
-rw-r--r--src/librustc_typeck/check/coercion.rs2
-rw-r--r--src/librustc_typeck/check/method/suggest.rs5
-rw-r--r--src/librustc_typeck/check/op.rs6
-rw-r--r--src/librustc_typeck/check/pat.rs2
-rw-r--r--src/librustc_typeck/collect.rs5
-rw-r--r--src/librustc_typeck/variance/constraints.rs1
-rw-r--r--src/librustdoc/clean/auto_trait.rs13
-rw-r--r--src/librustdoc/clean/mod.rs23
-rw-r--r--src/librustdoc/clean/simplify.rs13
-rw-r--r--src/librustdoc/clean/types.rs7
-rw-r--r--src/librustdoc/config.rs23
-rw-r--r--src/librustdoc/core.rs8
-rw-r--r--src/librustdoc/docfs.rs61
-rw-r--r--src/librustdoc/error.rs56
-rw-r--r--src/librustdoc/formats/cache.rs488
-rw-r--r--src/librustdoc/formats/item_type.rs (renamed from src/librustdoc/html/item_type.rs)2
-rw-r--r--src/librustdoc/formats/mod.rs44
-rw-r--r--src/librustdoc/formats/renderer.rs106
-rw-r--r--src/librustdoc/html/format.rs20
-rw-r--r--src/librustdoc/html/mod.rs9
-rw-r--r--src/librustdoc/html/render/cache.rs500
-rw-r--r--src/librustdoc/html/render/mod.rs (renamed from src/librustdoc/html/render.rs)923
-rw-r--r--src/librustdoc/html/sources.rs3
-rw-r--r--src/librustdoc/html/static/themes/ayu.css5
-rw-r--r--src/librustdoc/json/mod.rs47
-rw-r--r--src/librustdoc/lib.rs59
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs66
-rw-r--r--src/rustllvm/CoverageMappingWrapper.cpp66
-rw-r--r--src/test/assembly/asm/aarch64-modifiers.rs1
-rw-r--r--src/test/assembly/asm/aarch64-types.rs1
-rw-r--r--src/test/assembly/asm/arm-modifiers.rs1
-rw-r--r--src/test/assembly/asm/arm-types.rs1
-rw-r--r--src/test/assembly/asm/hexagon-types.rs1
-rw-r--r--src/test/assembly/asm/nvptx-types.rs1
-rw-r--r--src/test/assembly/asm/riscv-modifiers.rs1
-rw-r--r--src/test/assembly/asm/riscv-types.rs1
-rw-r--r--src/test/codegen/abi-efiapi.rs8
-rw-r--r--src/test/codegen/avr/avr-func-addrspace.rs1
-rw-r--r--src/test/codegen/naked-functions.rs4
-rw-r--r--src/test/debuginfo/function-arguments-naked.rs40
-rw-r--r--src/test/mir-opt/address-of.rs4
-rw-r--r--src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir (renamed from src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir)0
-rw-r--r--src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir (renamed from src/test/mir-opt/address-of/rustc.borrow_and_cast.SimplifyCfg-initial.after.mir)0
-rw-r--r--src/test/mir-opt/array-index-is-temporary.rs2
-rw-r--r--src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.32bit (renamed from src/test/mir-opt/array-index-is-temporary/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.64bit (renamed from src/test/mir-opt/array-index-is-temporary/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir (renamed from src/test/mir-opt/basic_assignment/rustc.main.SimplifyCfg-initial.after.mir)0
-rw-r--r--src/test/mir-opt/basic_assignment.rs2
-rw-r--r--src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir (renamed from src/test/mir-opt/box_expr/rustc.main.ElaborateDrops.before.mir)0
-rw-r--r--src/test/mir-opt/box_expr.rs2
-rw-r--r--src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir (renamed from src/test/mir-opt/byte_slice/rustc.main.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/byte_slice.rs2
-rw-r--r--src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.32bit (renamed from src/test/mir-opt/combine_array_len/32bit/rustc.norm2.InstCombine.diff)0
-rw-r--r--src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.64bit (renamed from src/test/mir-opt/combine_array_len/64bit/rustc.norm2.InstCombine.diff)0
-rw-r--r--src/test/mir-opt/combine_array_len.rs2
-rw-r--r--src/test/mir-opt/const-promotion-extern-static.rs8
-rw-r--r--src/test/mir-opt/const_allocation.main.ConstProp.after.mir.32bit (renamed from src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir)0
-rw-r--r--src/test/mir-opt/const_allocation.main.ConstProp.after.mir.64bit (renamed from src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir)0
-rw-r--r--src/test/mir-opt/const_allocation.rs2
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit (renamed from src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir)0
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit (renamed from src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir)0
-rw-r--r--src/test/mir-opt/const_allocation2.rs2
-rw-r--r--src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.32bit (renamed from src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir)0
-rw-r--r--src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.64bit (renamed from src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir)0
-rw-r--r--src/test/mir-opt/const_allocation3.rs2
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir (renamed from src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir)0
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff (renamed from src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff)0
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir (renamed from src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir)0
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff (renamed from src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff)0
-rw-r--r--src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/aggregate/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/aggregate.rs2
-rw-r--r--src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.32bit (renamed from src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.64bit (renamed from src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/array_index.rs2
-rw-r--r--src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/bad_op_div_by_zero.rs2
-rw-r--r--src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs2
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.32bit (renamed from src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.64bit (renamed from src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs2
-rw-r--r--src/test/mir-opt/const_prop/boolean_identities.rs2
-rw-r--r--src/test/mir-opt/const_prop/boolean_identities.test.ConstProp.diff (renamed from src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/boxes.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/boxes/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/boxes.rs2
-rw-r--r--src/test/mir-opt/const_prop/cast.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/cast/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/cast.rs2
-rw-r--r--src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/checked_add/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/checked_add.rs2
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/const_prop_fails_gracefully/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs2
-rw-r--r--src/test/mir-opt/const_prop/control-flow-simplification.rs4
-rw-r--r--src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff (renamed from src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir (renamed from src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.PreCodegen.before.mir)0
-rw-r--r--src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit (renamed from src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit (renamed from src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/discriminant.rs2
-rw-r--r--src/test/mir-opt/const_prop/indirect.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/indirect/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/indirect.rs2
-rw-r--r--src/test/mir-opt/const_prop/issue-66971.rs2
-rw-r--r--src/test/mir-opt/const_prop/issue-67019.rs2
-rw-r--r--src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/issue-66971/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/issue-67019/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/mult_by_zero.rs2
-rw-r--r--src/test/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff (renamed from src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable.rs2
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate.rs2
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs2
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs2
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_no_prop.rs2
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/mutable_variable_unprop_assign/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs2
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit (renamed from src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit (renamed from src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.32bit (renamed from src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.SimplifyLocals.after.mir)0
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.64bit (renamed from src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.SimplifyLocals.after.mir)0
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.rs4
-rw-r--r--src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/read_immutable_static/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/read_immutable_static.rs2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/ref_deref/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff (renamed from src/test/mir-opt/const_prop/ref_deref/rustc.main.PromoteTemps.diff)0
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.rs4
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/ref_deref_project/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff (renamed from src/test/mir-opt/const_prop/ref_deref_project/rustc.main.PromoteTemps.diff)0
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.rs4
-rw-r--r--src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/reify_fn_ptr/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/reify_fn_ptr.rs2
-rw-r--r--src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.32bit (renamed from src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.64bit (renamed from src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/repeat.rs2
-rw-r--r--src/test/mir-opt/const_prop/return_place.add.ConstProp.diff (renamed from src/test/mir-opt/const_prop/return_place/rustc.add.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/return_place.add.PreCodegen.before.mir (renamed from src/test/mir-opt/const_prop/return_place/rustc.add.PreCodegen.before.mir)0
-rw-r--r--src/test/mir-opt/const_prop/return_place.rs4
-rw-r--r--src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/scalar_literal_propagation.rs2
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.32bit (renamed from src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.64bit (renamed from src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/slice_len.rs2
-rw-r--r--src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff (renamed from src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff)0
-rw-r--r--src/test/mir-opt/const_prop/switch_int.rs4
-rw-r--r--src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff (renamed from src/test/mir-opt/const_prop/tuple_literal_propagation/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop/tuple_literal_propagation.rs2
-rw-r--r--src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff (renamed from src/test/mir-opt/const_prop_miscompile/rustc.bar.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff (renamed from src/test/mir-opt/const_prop_miscompile/rustc.foo.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/const_prop_miscompile.rs4
-rw-r--r--src/test/mir-opt/copy_propagation.rs2
-rw-r--r--src/test/mir-opt/copy_propagation.test.CopyPropagation.diff (renamed from src/test/mir-opt/copy_propagation/rustc.test.CopyPropagation.diff)0
-rw-r--r--src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff (renamed from src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff)0
-rw-r--r--src/test/mir-opt/copy_propagation_arg.bar.CopyPropagation.diff (renamed from src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff)0
-rw-r--r--src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff (renamed from src/test/mir-opt/copy_propagation_arg/rustc.baz.CopyPropagation.diff)0
-rw-r--r--src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff (renamed from src/test/mir-opt/copy_propagation_arg/rustc.foo.CopyPropagation.diff)0
-rw-r--r--src/test/mir-opt/copy_propagation_arg.rs8
-rw-r--r--src/test/mir-opt/deaggregator_test.bar.Deaggregator.diff (renamed from src/test/mir-opt/deaggregator_test/rustc.bar.Deaggregator.diff)0
-rw-r--r--src/test/mir-opt/deaggregator_test.rs2
-rw-r--r--src/test/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff (renamed from src/test/mir-opt/deaggregator_test_enum/rustc.bar.Deaggregator.diff)0
-rw-r--r--src/test/mir-opt/deaggregator_test_enum.rs2
-rw-r--r--src/test/mir-opt/deaggregator_test_enum_2.rs2
-rw-r--r--src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff (renamed from src/test/mir-opt/deaggregator_test_enum_2/rustc.test1.Deaggregator.diff)0
-rw-r--r--src/test/mir-opt/deaggregator_test_multiple.rs2
-rw-r--r--src/test/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff (renamed from src/test/mir-opt/deaggregator_test_multiple/rustc.test.Deaggregator.diff)0
-rw-r--r--src/test/mir-opt/exponential-or.rs2
-rw-r--r--src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir (renamed from src/test/mir-opt/exponential-or/rustc.match_tuple.SimplifyCfg-initial.after.mir)0
-rw-r--r--src/test/mir-opt/fn-ptr-shim.rs2
-rw-r--r--src/test/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir (renamed from src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir)0
-rw-r--r--src/test/mir-opt/generator-drop-cleanup.rs2
-rw-r--r--src/test/mir-opt/generator-storage-dead-unwind.rs2
-rw-r--r--src/test/mir-opt/generator-tiny.rs2
-rw-r--r--src/test/mir-opt/generator_drop_cleanup.main-{{closure}}.generator_drop.0.mir (renamed from src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir)0
-rw-r--r--src/test/mir-opt/generator_storage_dead_unwind.main-{{closure}}.StateTransform.before.mir (renamed from src/test/mir-opt/generator-storage-dead-unwind/rustc.main-{{closure}}.StateTransform.before.mir)0
-rw-r--r--src/test/mir-opt/generator_tiny.main-{{closure}}.generator_resume.0.mir (renamed from src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir)0
-rw-r--r--src/test/mir-opt/graphviz.main.mir_map.0.dot (renamed from src/test/mir-opt/graphviz/rustc.main.mir_map.0.dot)0
-rw-r--r--src/test/mir-opt/graphviz.rs2
-rw-r--r--src/test/mir-opt/inline/inline-any-operand.rs2
-rw-r--r--src/test/mir-opt/inline/inline-closure-borrows-arg.rs2
-rw-r--r--src/test/mir-opt/inline/inline-closure-captures.rs2
-rw-r--r--src/test/mir-opt/inline/inline-closure.rs2
-rw-r--r--src/test/mir-opt/inline/inline-into-box-place.rs2
-rw-r--r--src/test/mir-opt/inline/inline-retag.rs2
-rw-r--r--src/test/mir-opt/inline/inline-specialization.rs2
-rw-r--r--src/test/mir-opt/inline/inline-trait-method.rs2
-rw-r--r--src/test/mir-opt/inline/inline-trait-method_2.rs2
-rw-r--r--src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir (renamed from src/test/mir-opt/inline/inline-any-operand/rustc.bar.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir (renamed from src/test/mir-opt/inline/inline-closure/rustc.foo.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir (renamed from src/test/mir-opt/inline/inline-closure-borrows-arg/rustc.foo.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir (renamed from src/test/mir-opt/inline/inline-closure-captures/rustc.foo.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.32bit (renamed from src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff)0
-rw-r--r--src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.64bit (renamed from src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff)0
-rw-r--r--src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir (renamed from src/test/mir-opt/inline/inline-retag/rustc.bar.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/inline_specialization.main.Inline.diff (renamed from src/test/mir-opt/inline/inline-specialization/rustc.main.Inline.diff)0
-rw-r--r--src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir (renamed from src/test/mir-opt/inline/inline-trait-method/rustc.test.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir (renamed from src/test/mir-opt/inline/inline-trait-method_2/rustc.test2.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs8
-rw-r--r--src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir (renamed from src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.a.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir (renamed from src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.b.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir (renamed from src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.c.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir (renamed from src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.d.Inline.after.mir)0
-rw-r--r--src/test/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff (renamed from src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff)10
-rw-r--r--src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff (renamed from src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff)10
-rw-r--r--src/test/mir-opt/instrument_coverage.rs4
-rw-r--r--src/test/mir-opt/issue-38669.rs2
-rw-r--r--src/test/mir-opt/issue-41110.rs4
-rw-r--r--src/test/mir-opt/issue-41697.rs2
-rw-r--r--src/test/mir-opt/issue-41888.rs2
-rw-r--r--src/test/mir-opt/issue-49232.rs2
-rw-r--r--src/test/mir-opt/issue-62289.rs2
-rw-r--r--src/test/mir-opt/issue-72181-1.rs4
-rw-r--r--src/test/mir-opt/issue-72181.rs6
-rw-r--r--src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir25
-rw-r--r--src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir37
-rw-r--r--src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir93
-rw-r--r--src/test/mir-opt/issue-73223.rs4
-rw-r--r--src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir (renamed from src/test/mir-opt/issue-38669/rustc.main.SimplifyCfg-initial.after.mir)0
-rw-r--r--src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir (renamed from src/test/mir-opt/issue-41110/rustc.main.ElaborateDrops.after.mir)0
-rw-r--r--src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir (renamed from src/test/mir-opt/issue-41110/rustc.test.ElaborateDrops.after.mir)0
-rw-r--r--src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir.32bit (renamed from src/test/mir-opt/issue-41697/32bit/rustc.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir)0
-rw-r--r--src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir.64bit (renamed from src/test/mir-opt/issue-41697/64bit/rustc.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir)0
-rw-r--r--src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir (renamed from src/test/mir-opt/issue-41888/rustc.main.ElaborateDrops.after.mir)0
-rw-r--r--src/test/mir-opt/issue_49232.main.mir_map.0.mir (renamed from src/test/mir-opt/issue-49232/rustc.main.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir (renamed from src/test/mir-opt/issue-62289/rustc.test.ElaborateDrops.before.mir)0
-rw-r--r--src/test/mir-opt/issue_72181.bar.mir_map.0.mir.32bit (renamed from src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/issue_72181.bar.mir_map.0.mir.64bit (renamed from src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/issue_72181.foo.mir_map.0.mir.32bit (renamed from src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/issue_72181.foo.mir_map.0.mir.64bit (renamed from src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/issue_72181.main.mir_map.0.mir.32bit (renamed from src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/issue_72181.main.mir_map.0.mir.64bit (renamed from src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/issue_72181_1.f.mir_map.0.mir (renamed from src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/issue_72181_1.main.mir_map.0.mir (renamed from src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit (renamed from src/test/mir-opt/issue-73223/32bit/rustc.main.PreCodegen.diff)0
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit (renamed from src/test/mir-opt/issue-73223/64bit/rustc.main.PreCodegen.diff)0
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit (renamed from src/test/mir-opt/issue-73223/32bit/rustc.main.SimplifyArmIdentity.diff)0
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit (renamed from src/test/mir-opt/issue-73223/64bit/rustc.main.SimplifyArmIdentity.diff)0
-rw-r--r--src/test/mir-opt/loop_test.main.SimplifyCfg-qualify-consts.after.mir (renamed from src/test/mir-opt/loop_test/rustc.main.SimplifyCfg-qualify-consts.after.mir)0
-rw-r--r--src/test/mir-opt/loop_test.rs2
-rw-r--r--src/test/mir-opt/match-arm-scopes.rs2
-rw-r--r--src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff (renamed from src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff)0
-rw-r--r--src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir (renamed from src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir)0
-rw-r--r--src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir (renamed from src/test/mir-opt/match_false_edges/rustc.full_tested_match2.PromoteTemps.before.mir)0
-rw-r--r--src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir (renamed from src/test/mir-opt/match_false_edges/rustc.main.PromoteTemps.before.mir)0
-rw-r--r--src/test/mir-opt/match_false_edges.rs6
-rw-r--r--src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir (renamed from src/test/mir-opt/match_test/rustc.main.SimplifyCfg-initial.after.mir)0
-rw-r--r--src/test/mir-opt/match_test.rs2
-rw-r--r--src/test/mir-opt/nll/named-lifetimes-basic.rs2
-rw-r--r--src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir (renamed from src/test/mir-opt/nll/named-lifetimes-basic/rustc.use_x.nll.0.mir)0
-rw-r--r--src/test/mir-opt/nll/region-subtyping-basic.rs2
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.32bit (renamed from src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir)0
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.64bit (renamed from src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir)0
-rw-r--r--src/test/mir-opt/no-drop-for-inactive-variant.rs2
-rw-r--r--src/test/mir-opt/no-spurious-drop-after-call.rs2
-rw-r--r--src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir (renamed from src/test/mir-opt/no-drop-for-inactive-variant/rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir (renamed from src/test/mir-opt/no-spurious-drop-after-call/rustc.main.ElaborateDrops.before.mir)0
-rw-r--r--src/test/mir-opt/nrvo-simple.rs2
-rw-r--r--src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff (renamed from src/test/mir-opt/nrvo-simple/rustc.nrvo.RenameReturnPlace.diff)0
-rw-r--r--src/test/mir-opt/packed-struct-drop-aligned.rs2
-rw-r--r--src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.32bit (renamed from src/test/mir-opt/packed-struct-drop-aligned/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.64bit (renamed from src/test/mir-opt/packed-struct-drop-aligned/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/remove-never-const.rs2
-rw-r--r--src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff (renamed from src/test/mir-opt/remove_fake_borrows/rustc.match_guard.CleanupNonCodegenStatements.diff)0
-rw-r--r--src/test/mir-opt/remove_fake_borrows.rs2
-rw-r--r--src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir (renamed from src/test/mir-opt/remove-never-const/rustc.no_codegen.PreCodegen.after.mir)0
-rw-r--r--src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir (renamed from src/test/mir-opt/retag/rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir)0
-rw-r--r--src/test/mir-opt/retag.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir (renamed from src/test/mir-opt/retag/rustc.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir (renamed from src/test/mir-opt/retag/rustc.main.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/retag.rs10
-rw-r--r--src/test/mir-opt/retag.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir (renamed from src/test/mir-opt/retag/rustc.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/retag.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir (renamed from src/test/mir-opt/retag/rustc.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir)0
-rw-r--r--src/test/mir-opt/simple-match.rs2
-rw-r--r--src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.32bit (renamed from src/test/mir-opt/simple-match/32bit/rustc.match_bool.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.64bit (renamed from src/test/mir-opt/simple-match/64bit/rustc.match_bool.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/simplify-arm-identity.rs2
-rw-r--r--src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff70
-rw-r--r--src/test/mir-opt/simplify-arm.rs12
-rw-r--r--src/test/mir-opt/simplify-locals-fixedpoint.rs2
-rw-r--r--src/test/mir-opt/simplify-locals-removes-unused-consts.rs2
-rw-r--r--src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs2
-rw-r--r--src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff (renamed from src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff)0
-rw-r--r--src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff (renamed from src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff)0
-rw-r--r--src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff (renamed from src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff)0
-rw-r--r--src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff (renamed from src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff)0
-rw-r--r--src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff (renamed from src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff)0
-rw-r--r--src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff (renamed from src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff)0
-rw-r--r--src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit (renamed from src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff)0
-rw-r--r--src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit (renamed from src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff)0
-rw-r--r--src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff (renamed from src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-early-opt.diff)0
-rw-r--r--src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff (renamed from src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-initial.diff)0
-rw-r--r--src/test/mir-opt/simplify_cfg.rs4
-rw-r--r--src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff (renamed from src/test/mir-opt/simplify_if/rustc.main.SimplifyBranches-after-const-prop.diff)0
-rw-r--r--src/test/mir-opt/simplify_if.rs2
-rw-r--r--src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff (renamed from src/test/mir-opt/simplify-locals-fixedpoint/rustc.foo.SimplifyLocals.diff)0
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff (renamed from src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff)0
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit (renamed from src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff)0
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit (renamed from src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff)0
-rw-r--r--src/test/mir-opt/simplify_match.main.ConstProp.diff (renamed from src/test/mir-opt/simplify_match/rustc.main.ConstProp.diff)0
-rw-r--r--src/test/mir-opt/simplify_match.rs2
-rw-r--r--src/test/mir-opt/simplify_try.rs6
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff (renamed from src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyArmIdentity.diff)0
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir (renamed from src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyBranchSame.after.mir)0
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir (renamed from src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyLocals.after.mir)0
-rw-r--r--src/test/mir-opt/simplify_try_if_let.rs2
-rw-r--r--src/test/mir-opt/simplify_try_if_let.{{impl}}-append.SimplifyArmIdentity.diff (renamed from src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff)0
-rw-r--r--src/test/mir-opt/slice-drop-shim.rs2
-rw-r--r--src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir.32bit (renamed from src/test/mir-opt/slice-drop-shim/32bit/rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir)0
-rw-r--r--src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir.64bit (renamed from src/test/mir-opt/slice-drop-shim/64bit/rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir)0
-rw-r--r--src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir (renamed from src/test/mir-opt/storage_live_dead_in_statics/rustc.XXX.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/storage_live_dead_in_statics.rs2
-rw-r--r--src/test/mir-opt/storage_ranges.main.nll.0.mir (renamed from src/test/mir-opt/storage_ranges/rustc.main.nll.0.mir)0
-rw-r--r--src/test/mir-opt/storage_ranges.rs2
-rw-r--r--src/test/mir-opt/tls-access.rs2
-rw-r--r--src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir (renamed from src/test/mir-opt/tls-access/rustc.main.SimplifyCfg-final.after.mir)0
-rw-r--r--src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir (renamed from src/test/mir-opt/uniform_array_move_out/rustc.move_out_by_subslice.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir (renamed from src/test/mir-opt/uniform_array_move_out/rustc.move_out_from_end.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/uniform_array_move_out.rs4
-rw-r--r--src/test/mir-opt/uninhabited-enum.rs4
-rw-r--r--src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir (renamed from src/test/mir-opt/uninhabited-enum/rustc.process_never.SimplifyLocals.after.mir)0
-rw-r--r--src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir (renamed from src/test/mir-opt/uninhabited-enum/rustc.process_void.SimplifyLocals.after.mir)0
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir (renamed from src/test/mir-opt/uninhabited_enum_branching/rustc.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir)0
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff (renamed from src/test/mir-opt/uninhabited_enum_branching/rustc.main.UninhabitedEnumBranching.diff)0
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching.rs4
-rw-r--r--src/test/mir-opt/unreachable.main.UnreachablePropagation.diff (renamed from src/test/mir-opt/unreachable/rustc.main.UnreachablePropagation.diff)0
-rw-r--r--src/test/mir-opt/unreachable.rs2
-rw-r--r--src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff (renamed from src/test/mir-opt/unreachable_asm/rustc.main.UnreachablePropagation.diff)0
-rw-r--r--src/test/mir-opt/unreachable_asm.rs2
-rw-r--r--src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff (renamed from src/test/mir-opt/unreachable_asm_2/rustc.main.UnreachablePropagation.diff)0
-rw-r--r--src/test/mir-opt/unreachable_asm_2.rs2
-rw-r--r--src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff (renamed from src/test/mir-opt/unreachable_diverging/rustc.main.UnreachablePropagation.diff)0
-rw-r--r--src/test/mir-opt/unreachable_diverging.rs2
-rw-r--r--src/test/mir-opt/unusual-item-types.rs8
-rw-r--r--src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.32bit (renamed from src/test/mir-opt/unusual-item-types/32bit/rustc.E-V-{{constant}}.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.64bit (renamed from src/test/mir-opt/unusual-item-types/64bit/rustc.E-V-{{constant}}.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.32bit (renamed from src/test/mir-opt/unusual-item-types/32bit/rustc.Test-X-{{constructor}}.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.64bit (renamed from src/test/mir-opt/unusual-item-types/64bit/rustc.Test-X-{{constructor}}.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir.32bit (renamed from src/test/mir-opt/unusual-item-types/32bit/rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir)0
-rw-r--r--src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir.64bit (renamed from src/test/mir-opt/unusual-item-types/64bit/rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir)0
-rw-r--r--src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.32bit (renamed from src/test/mir-opt/unusual-item-types/32bit/rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.64bit (renamed from src/test/mir-opt/unusual-item-types/64bit/rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir)0
-rw-r--r--src/test/mir-opt/while-storage.rs2
-rw-r--r--src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir (renamed from src/test/mir-opt/while-storage/rustc.while_loop.PreCodegen.after.mir)0
-rw-r--r--src/test/pretty/block-comment-wchar.pp2
-rw-r--r--src/test/pretty/issue-74745.rs5
-rw-r--r--src/test/run-make-fulldeps/exit-code/lint-failure.rs2
-rw-r--r--src/test/run-make-fulldeps/mingw-export-call-convention/Makefile9
-rw-r--r--src/test/run-make-fulldeps/mingw-export-call-convention/foo.rs4
-rw-r--r--src/test/run-make-fulldeps/tools.mk1
-rw-r--r--src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs2
-rw-r--r--src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr4
-rw-r--r--src/test/rustdoc-ui/intra-doc-alias-ice.rs2
-rw-r--r--src/test/rustdoc-ui/intra-doc-alias-ice.stderr4
-rw-r--r--src/test/rustdoc-ui/intra-link-span-ice-55723.rs2
-rw-r--r--src/test/rustdoc-ui/intra-link-span-ice-55723.stderr4
-rw-r--r--src/test/rustdoc-ui/intra-links-ambiguity.rs2
-rw-r--r--src/test/rustdoc-ui/intra-links-ambiguity.stderr4
-rw-r--r--src/test/rustdoc-ui/intra-links-anchors.rs2
-rw-r--r--src/test/rustdoc-ui/intra-links-anchors.stderr4
-rw-r--r--src/test/rustdoc-ui/intra-links-private.private.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-links-private.public.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-links-warning-crlf.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-links-warning.stderr2
-rw-r--r--src/test/rustdoc-ui/issue-74134.private.stderr2
-rw-r--r--src/test/rustdoc-ui/issue-74134.public.stderr2
-rw-r--r--src/test/rustdoc-ui/lint-group.stderr2
-rw-r--r--src/test/rustdoc-ui/reference-link-has-one-warning.stderr2
-rw-r--r--src/test/rustdoc/const-generics/const-impl.rs4
-rw-r--r--src/test/rustdoc/intra-doc-crate/additional_doc.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/auxiliary/hidden.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/auxiliary/module.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/basic.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/hidden.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/macro.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/module.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/submodule-inner.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/submodule-outer.rs2
-rw-r--r--src/test/rustdoc/intra-doc-crate/traits.rs2
-rw-r--r--src/test/rustdoc/intra-doc-link-mod-ambiguity.rs2
-rw-r--r--src/test/rustdoc/intra-link-extern-crate.rs2
-rw-r--r--src/test/rustdoc/intra-link-in-bodies.rs2
-rw-r--r--src/test/rustdoc/intra-link-libstd-re-export.rs2
-rw-r--r--src/test/rustdoc/intra-link-prim-methods-external-core.rs2
-rw-r--r--src/test/rustdoc/intra-link-prim-methods-local.rs2
-rw-r--r--src/test/rustdoc/intra-link-prim-methods.rs2
-rw-r--r--src/test/rustdoc/intra-link-prim-precedence.rs2
-rw-r--r--src/test/rustdoc/intra-link-private.rs2
-rw-r--r--src/test/rustdoc/intra-link-proc-macro.rs2
-rw-r--r--src/test/rustdoc/intra-links-external-traits.rs2
-rw-r--r--src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs18
-rw-r--r--src/test/rustdoc/through-proc-macro.rs2
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-multi-true.rs8
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr8
-rw-r--r--src/test/ui/const-generics/coerce_unsized_array.rs11
-rw-r--r--src/test/ui/const-generics/nested-type.rs18
-rw-r--r--src/test/ui/const-generics/nested-type.stderr159
-rw-r--r--src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs14
-rw-r--r--src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr20
-rw-r--r--src/test/ui/consts/const-size_of_val-align_of_val.rs45
-rw-r--r--src/test/ui/consts/const-typeid-of-rpass.rs1
-rw-r--r--src/test/ui/consts/const-typeid-of.rs8
-rw-r--r--src/test/ui/consts/const-typeid-of.stderr10
-rw-r--r--src/test/ui/consts/const-unwrap.rs14
-rw-r--r--src/test/ui/consts/const-unwrap.stderr20
-rw-r--r--src/test/ui/consts/const_constructor/const-construct-call.rs2
-rw-r--r--src/test/ui/consts/const_in_pattern/warn_corner_cases.rs2
-rw-r--r--src/test/ui/consts/issue-73976-monomorphic.rs1
-rw-r--r--src/test/ui/consts/issue-73976-polymorphic.rs11
-rw-r--r--src/test/ui/consts/issue-73976-polymorphic.stderr16
-rw-r--r--src/test/ui/deprecation/atomic_initializers.fixed2
-rw-r--r--src/test/ui/deprecation/atomic_initializers.rs2
-rw-r--r--src/test/ui/deprecation/atomic_initializers.stderr4
-rw-r--r--src/test/ui/deprecation/deprecation-in-future.rs2
-rw-r--r--src/test/ui/deprecation/deprecation-in-future.stderr2
-rw-r--r--src/test/ui/deprecation/deprecation-lint-2.rs2
-rw-r--r--src/test/ui/deprecation/deprecation-lint-2.stderr2
-rw-r--r--src/test/ui/deprecation/deprecation-lint-3.rs2
-rw-r--r--src/test/ui/deprecation/deprecation-lint-3.stderr2
-rw-r--r--src/test/ui/deprecation/deprecation-lint-nested.rs12
-rw-r--r--src/test/ui/deprecation/deprecation-lint-nested.stderr12
-rw-r--r--src/test/ui/deprecation/deprecation-lint.rs250
-rw-r--r--src/test/ui/deprecation/deprecation-lint.stderr316
-rw-r--r--src/test/ui/deprecation/rustc_deprecation-in-future.rs2
-rw-r--r--src/test/ui/deprecation/rustc_deprecation-in-future.stderr2
-rw-r--r--src/test/ui/deprecation/suggestion.stderr4
-rw-r--r--src/test/ui/generator/issue-52398.rs4
-rw-r--r--src/test/ui/generator/issue-52398.stderr24
-rw-r--r--src/test/ui/generator/issue-57084.rs2
-rw-r--r--src/test/ui/generator/issue-57084.stderr16
-rw-r--r--src/test/ui/generator/match-bindings.rs2
-rw-r--r--src/test/ui/generator/match-bindings.stderr17
-rw-r--r--src/test/ui/generator/reborrow-mut-upvar.rs2
-rw-r--r--src/test/ui/generator/reborrow-mut-upvar.stderr17
-rw-r--r--src/test/ui/generator/too-live-local-in-immovable-gen.rs2
-rw-r--r--src/test/ui/generator/too-live-local-in-immovable-gen.stderr17
-rw-r--r--src/test/ui/generator/yield-in-args-rev.rs2
-rw-r--r--src/test/ui/generator/yield-in-args-rev.stderr14
-rw-r--r--src/test/ui/generator/yield-in-box.rs2
-rw-r--r--src/test/ui/generator/yield-in-box.stderr17
-rw-r--r--src/test/ui/generator/yield-in-initializer.rs2
-rw-r--r--src/test/ui/generator/yield-in-initializer.stderr17
-rw-r--r--src/test/ui/generator/yield-subtype.rs2
-rw-r--r--src/test/ui/generator/yield-subtype.stderr14
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs (renamed from src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs)0
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr (renamed from src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr)52
-rw-r--r--src/test/ui/issues/issue-1460.rs2
-rw-r--r--src/test/ui/issues/issue-1460.stderr11
-rw-r--r--src/test/ui/issues/issue-16256.rs2
-rw-r--r--src/test/ui/issues/issue-16256.stderr11
-rw-r--r--src/test/ui/issues/issue-17337.rs2
-rw-r--r--src/test/ui/issues/issue-17337.stderr2
-rw-r--r--src/test/ui/issues/issue-37131.rs1
-rw-r--r--src/test/ui/issues/issue-49851/compiler-builtins-error.rs1
-rw-r--r--src/test/ui/issues/issue-50993.rs1
-rw-r--r--src/test/ui/issues/issue-72574-1.rs2
-rw-r--r--src/test/ui/issues/issue-72574-1.stderr22
-rw-r--r--src/test/ui/issues/issue-72574-2.rs2
-rw-r--r--src/test/ui/issues/issue-72574-2.stderr20
-rw-r--r--src/test/ui/issues/issue-74539.rs12
-rw-r--r--src/test/ui/issues/issue-74539.stderr21
-rw-r--r--src/test/ui/issues/issue-74614.rs1
-rw-r--r--src/test/ui/lint/auxiliary/external_extern_fn.rs2
-rw-r--r--src/test/ui/lint/clashing-extern-fn.rs173
-rw-r--r--src/test/ui/lint/clashing-extern-fn.stderr122
-rw-r--r--src/test/ui/lint/issue-74883-unused-paren-baren-yield.rs33
-rw-r--r--src/test/ui/lint/issue-74883-unused-paren-baren-yield.stderr62
-rw-r--r--src/test/ui/lint/lint-nonstandard-style-unicode-1.rs2
-rw-r--r--src/test/ui/lint/lint-nonstandard-style-unicode-2.rs2
-rw-r--r--src/test/ui/lint/lint-output-format-2.rs4
-rw-r--r--src/test/ui/lint/lint-output-format-2.stderr4
-rw-r--r--src/test/ui/lint/lint-stability-deprecated.rs224
-rw-r--r--src/test/ui/lint/lint-stability-deprecated.stderr320
-rw-r--r--src/test/ui/lint/lint-stability-fields-deprecated.rs124
-rw-r--r--src/test/ui/lint/lint-stability-fields-deprecated.stderr124
-rw-r--r--src/test/ui/lint/lint-stability2.rs2
-rw-r--r--src/test/ui/lint/lint-stability2.stderr2
-rw-r--r--src/test/ui/lint/lint-stability3.rs2
-rw-r--r--src/test/ui/lint/lint-stability3.stderr2
-rw-r--r--src/test/ui/liveness/liveness-upvars.rs18
-rw-r--r--src/test/ui/macros/macro-deprecation.rs4
-rw-r--r--src/test/ui/macros/macro-deprecation.stderr4
-rw-r--r--src/test/ui/macros/macro-stability.rs4
-rw-r--r--src/test/ui/macros/macro-stability.stderr4
-rw-r--r--src/test/ui/nll/capture-mut-ref.fixed2
-rw-r--r--src/test/ui/nll/capture-mut-ref.rs2
-rw-r--r--src/test/ui/nll/issue-48623-generator.rs2
-rw-r--r--src/test/ui/nll/issue-48623-generator.stderr11
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs2
-rw-r--r--src/test/ui/pattern/const-pat-ice.stderr2
-rw-r--r--src/test/ui/pattern/issue-74539.rs15
-rw-r--r--src/test/ui/pattern/issue-74539.stderr32
-rw-r--r--src/test/ui/pattern/issue-74702.rs7
-rw-r--r--src/test/ui/pattern/issue-74702.stderr34
-rw-r--r--src/test/ui/pattern/issue-74954.rs7
-rw-r--r--src/test/ui/polymorphization/issue-74636.rs16
-rw-r--r--src/test/ui/proc-macro/attributes-on-definitions.rs2
-rw-r--r--src/test/ui/proc-macro/attributes-on-definitions.stderr2
-rw-r--r--src/test/ui/proc-macro/crt-static.rs2
-rw-r--r--src/test/ui/statics/static-promotion.rs34
-rw-r--r--src/test/ui/suggestions/issue-61226.fixed6
-rw-r--r--src/test/ui/suggestions/issue-61226.rs3
-rw-r--r--src/test/ui/suggestions/issue-61226.stderr6
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-method.fixed5
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-method.rs3
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-method.stderr10
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-path-2.fixed6
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-path-2.rs3
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr10
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-variant.fixed5
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-variant.rs1
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-variant.stderr2
-rw-r--r--src/test/ui/test-attrs/test-runner-hides-buried-main.rs4
-rw-r--r--src/test/ui/type/ascription/issue-47666.fixed4
-rw-r--r--src/test/ui/type/ascription/issue-47666.rs5
-rw-r--r--src/test/ui/type/ascription/issue-47666.stderr34
-rw-r--r--src/test/ui/type/ascription/issue-54516.fixed7
-rw-r--r--src/test/ui/type/ascription/issue-54516.rs3
-rw-r--r--src/test/ui/type/ascription/issue-54516.stderr22
-rw-r--r--src/test/ui/type/ascription/issue-60933.fixed5
-rw-r--r--src/test/ui/type/ascription/issue-60933.rs5
-rw-r--r--src/test/ui/type/ascription/issue-60933.stderr24
-rw-r--r--src/test/ui/type/type-ascription-with-fn-call.fixed9
-rw-r--r--src/test/ui/type/type-ascription-with-fn-call.rs1
-rw-r--r--src/test/ui/type/type-ascription-with-fn-call.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs1
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr4
-rw-r--r--src/test/ui/unused/unused-closure.rs40
-rw-r--r--src/test/ui/unused/unused-closure.stderr75
-rw-r--r--src/test/ui/unused/unused-mut-warning-captured-var.fixed2
-rw-r--r--src/test/ui/unused/unused-mut-warning-captured-var.rs2
-rw-r--r--src/test/ui/weird-exprs.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs2
-rw-r--r--src/tools/clippy/tests/ui/formatting.rs2
-rw-r--r--src/tools/compiletest/Cargo.toml3
-rw-r--r--src/tools/compiletest/src/header.rs12
-rw-r--r--src/tools/compiletest/src/runtest.rs101
-rw-r--r--src/tools/error_index_generator/main.rs4
m---------src/tools/miri43
-rw-r--r--src/tools/tidy/src/deps.rs13
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/unstable-book-gen/src/main.rs8
764 files changed, 7300 insertions, 5413 deletions
diff --git a/src/README.md b/src/README.md
index b69a92a7237..2f8e9da179a 100644
--- a/src/README.md
+++ b/src/README.md
@@ -1,6 +1,6 @@
 This directory contains the source code of the rust project, including:
 - `rustc` and its tests
-- `libstd`
+- The bootstrapping build system
 - Various submodules for tools, like rustdoc, rls, etc.
 
 For more information on how various parts of the compiler work, see the [rustc dev guide].
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index d6649d0521c..4dd71ebade1 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -171,7 +171,9 @@ fn main() {
         // note: everything below here is unreachable. do not put code that
         // should run on success, after this block.
     }
-    println!("\nDid not run successfully: {}\n{:?}\n-------------", status, cmd);
+    if verbose > 0 {
+        println!("\nDid not run successfully: {}\n{:?}\n-------------", status, cmd);
+    }
 
     if let Some(mut on_fail) = on_fail {
         on_fail.status().expect("Could not run the on_fail command");
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index c1e56347ab1..144e146685f 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -232,7 +232,7 @@ impl StepDescription {
                 }
 
                 if !attempted_run {
-                    panic!("Error: no rules matched {}.", path.display());
+                    panic!("error: no rules matched {}", path.display());
                 }
             }
         }
@@ -501,16 +501,7 @@ impl<'a> Builder<'a> {
             _ => return None,
         };
 
-        let builder = Builder {
-            build,
-            top_stage: build.config.stage.unwrap_or(2),
-            kind,
-            cache: Cache::new(),
-            stack: RefCell::new(Vec::new()),
-            time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
-            paths: vec![],
-        };
-
+        let builder = Self::new_internal(build, kind, vec![]);
         let builder = &builder;
         let mut should_run = ShouldRun::new(builder);
         for desc in Builder::get_step_descriptions(builder.kind) {
@@ -535,6 +526,32 @@ impl<'a> Builder<'a> {
         Some(help)
     }
 
+    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,
+            kind,
+            cache: Cache::new(),
+            stack: RefCell::new(Vec::new()),
+            time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
+            paths,
+        }
+    }
+
     pub fn new(build: &Build) -> Builder<'_> {
         let (kind, paths) = match build.config.cmd {
             Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
@@ -550,15 +567,20 @@ impl<'a> Builder<'a> {
             Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(),
         };
 
-        Builder {
-            build,
-            top_stage: build.config.stage.unwrap_or(2),
-            kind,
-            cache: Cache::new(),
-            stack: RefCell::new(Vec::new()),
-            time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
-            paths: paths.to_owned(),
+        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
     }
 
     pub fn execute_cli(&self) {
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 6684ca82c27..111971534ba 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -2,8 +2,6 @@ use super::*;
 use crate::config::{Config, TargetSelection};
 use std::thread;
 
-use pretty_assertions::assert_eq;
-
 fn configure(host: &[&str], target: &[&str]) -> Config {
     let mut config = Config::default_opts();
     // don't save toolstates
@@ -35,463 +33,562 @@ fn first<A, B>(v: Vec<(A, B)>) -> Vec<A> {
     v.into_iter().map(|(a, _)| a).collect::<Vec<_>>()
 }
 
-#[test]
-fn dist_baseline() {
-    let build = Build::new(configure(&[], &[]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-
-    assert_eq!(first(builder.cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
-    assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-    // Make sure rustdoc is only built once.
-    assert_eq!(
-        first(builder.cache.all::<tool::Rustdoc>()),
-        &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
-    );
-}
-
-#[test]
-fn dist_with_targets() {
-    let build = Build::new(configure(&[], &["B"]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-}
-
-#[test]
-fn dist_with_hosts() {
-    let build = Build::new(configure(&["B"], &[]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[
-            dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
-            dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-}
-
-#[test]
-fn dist_only_cross_host() {
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let mut build = Build::new(configure(&["B"], &[]));
-    build.config.docs = false;
-    build.config.extended = true;
-    build.hosts = vec![b];
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[dist::Rustc { compiler: Compiler { host: b, stage: 2 } },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<compile::Rustc>()),
-        &[
-            compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
-        ]
-    );
-}
-
-#[test]
-fn dist_with_targets_and_hosts() {
-    let build = Build::new(configure(&["B"], &["C"]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let c = TargetSelection::from_user("C");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[
-            dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
-            dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-}
-
-#[test]
-fn dist_with_target_flag() {
-    let mut config = configure(&["B"], &["C"]);
-    config.skip_only_host_steps = true; // as-if --target=C was passed
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let c = TargetSelection::from_user("C");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[]);
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[]);
-}
-
-#[test]
-fn dist_with_same_targets_and_hosts() {
-    let build = Build::new(configure(&["B"], &["B"]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[
-            dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
-            dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-    assert_eq!(
-        first(builder.cache.all::<compile::Std>()),
-        &[
-            compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<compile::Assemble>()),
-        &[
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
-            compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-}
-
-#[test]
-fn build_default() {
-    let build = Build::new(configure(&["B"], &["C"]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let c = TargetSelection::from_user("C");
-
-    assert_eq!(
-        first(builder.cache.all::<compile::Std>()),
-        &[
-            compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
-        ]
-    );
-    assert!(!builder.cache.all::<compile::Assemble>().is_empty());
-    assert_eq!(
-        first(builder.cache.all::<compile::Rustc>()),
-        &[
-            compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: a },
-            compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
-            compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: b },
-            compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: b },
-        ]
-    );
-}
-
-#[test]
-fn build_with_target_flag() {
-    let mut config = configure(&["B"], &["C"]);
-    config.skip_only_host_steps = true;
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let c = TargetSelection::from_user("C");
-
-    assert_eq!(
-        first(builder.cache.all::<compile::Std>()),
-        &[
-            compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<compile::Assemble>()),
-        &[
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
-            compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<compile::Rustc>()),
-        &[
-            compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
-        ]
-    );
-}
-
-#[test]
-fn test_with_no_doc_stage0() {
-    let mut config = configure(&[], &[]);
-    config.stage = Some(0);
-    config.cmd = Subcommand::Test {
-        paths: vec!["library/std".into()],
-        test_args: vec![],
-        rustc_args: vec![],
-        fail_fast: true,
-        doc_tests: DocTests::No,
-        bless: false,
-        compare_mode: None,
-        rustfix_coverage: false,
-        pass: None,
-    };
-
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-
-    let host = TargetSelection::from_user("A");
-
-    builder
-        .run_step_descriptions(&[StepDescription::from::<test::Crate>()], &["library/std".into()]);
-
-    // Ensure we don't build any compiler artifacts.
-    assert!(!builder.cache.contains::<compile::Rustc>());
-    assert_eq!(
-        first(builder.cache.all::<test::Crate>()),
-        &[test::Crate {
-            compiler: Compiler { host, stage: 0 },
-            target: host,
-            mode: Mode::Std,
-            test_kind: test::TestKind::Test,
-            krate: INTERNER.intern_str("std"),
-        },]
-    );
-}
-
-#[test]
-fn test_exclude() {
-    let mut config = configure(&[], &[]);
-    config.exclude = vec!["src/tools/tidy".into()];
-    config.cmd = Subcommand::Test {
-        paths: Vec::new(),
-        test_args: Vec::new(),
-        rustc_args: Vec::new(),
-        fail_fast: true,
-        doc_tests: DocTests::No,
-        bless: false,
-        compare_mode: None,
-        rustfix_coverage: false,
-        pass: None,
-    };
-
-    let build = Build::new(config);
-    let builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
-
-    // Ensure we have really excluded tidy
-    assert!(!builder.cache.contains::<test::Tidy>());
-
-    // Ensure other tests are not affected.
-    assert!(builder.cache.contains::<test::RustdocUi>());
-}
-
-#[test]
-fn doc_default() {
-    let mut config = configure(&[], &[]);
-    config.compiler_docs = true;
-    config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
-    let a = TargetSelection::from_user("A");
-
-    // error_index_generator uses stage 1 to share rustdoc artifacts with the
-    // rustdoc tool.
-    assert_eq!(
-        first(builder.cache.all::<doc::ErrorIndex>()),
-        &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<tool::ErrorIndex>()),
-        &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
-    );
-    // This is actually stage 1, but Rustdoc::run swaps out the compiler with
-    // stage minus 1 if --stage is not 0. Very confusing!
-    assert_eq!(
-        first(builder.cache.all::<tool::Rustdoc>()),
-        &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
-    );
+mod defaults {
+    use super::{configure, first};
+    use crate::builder::*;
+    use crate::Config;
+    use pretty_assertions::assert_eq;
+
+    #[test]
+    fn build_default() {
+        let build = Build::new(configure(&[], &[]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+
+        let a = TargetSelection::from_user("A");
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[
+                compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+            ]
+        );
+        assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+        // Make sure rustdoc is only built once.
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            // Recall that rustdoc stages are off-by-one
+            // - this is the compiler it's _linked_ to, not built with.
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } }],
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Rustc>()),
+            &[compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },]
+        );
+    }
+
+    #[test]
+    fn build_stage_0() {
+        let config = Config { stage: Some(0), ..configure(&[], &[]) };
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+
+        let a = TargetSelection::from_user("A");
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },]
+        );
+        assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            // This is the beta rustdoc.
+            // Add an assert here to make sure this is the only rustdoc built.
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } }],
+        );
+        assert!(builder.cache.all::<compile::Rustc>().is_empty());
+    }
+
+    #[test]
+    fn doc_default() {
+        let mut config = configure(&[], &[]);
+        config.compiler_docs = true;
+        config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
+        let a = TargetSelection::from_user("A");
+
+        // error_index_generator uses stage 0 to share rustdoc artifacts with the
+        // rustdoc tool.
+        assert_eq!(
+            first(builder.cache.all::<doc::ErrorIndex>()),
+            &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 0 }, target: a },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<tool::ErrorIndex>()),
+            &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 0 } }]
+        );
+        // docs should be built with the beta compiler, not with the stage0 artifacts.
+        // recall that rustdoc is off-by-one: `stage` is the compiler rustdoc is _linked_ to,
+        // not the one it was built by.
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },]
+        );
+    }
 }
 
-//FIXME(mark-i-m): reinstate this test when things are fixed...
-//#[test]
-#[allow(dead_code)]
-fn test_docs() {
-    // Behavior of `x.py test` doing various documentation tests.
-    let mut config = configure(&[], &[]);
-    config.cmd = Subcommand::Test {
-        paths: vec![],
-        test_args: vec![],
-        rustc_args: vec![],
-        fail_fast: true,
-        doc_tests: DocTests::Yes,
-        bless: false,
-        compare_mode: None,
-        rustfix_coverage: false,
-        pass: None,
-    };
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
-    let a = TargetSelection::from_user("A");
-
-    // error_index_generator uses stage 1 to share rustdoc artifacts with the
-    // rustdoc tool.
-    assert_eq!(
-        first(builder.cache.all::<doc::ErrorIndex>()),
-        &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<tool::ErrorIndex>()),
-        &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
-    );
-    // Unfortunately rustdoc is built twice. Once from stage1 for compiletest
-    // (and other things), and once from stage0 for std crates. Ideally it
-    // would only be built once. If someone wants to fix this, it might be
-    // worth investigating if it would be possible to test std from stage1.
-    // Note that the stages here are +1 than what they actually are because
-    // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is
-    // not 0.
-    assert_eq!(
-        first(builder.cache.all::<tool::Rustdoc>()),
-        &[
-            tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
-            tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },
-        ]
-    );
+mod dist {
+    use super::{first, Config};
+    use crate::builder::*;
+    use pretty_assertions::assert_eq;
+
+    fn configure(host: &[&str], target: &[&str]) -> Config {
+        Config { stage: Some(2), ..super::configure(host, target) }
+    }
+
+    #[test]
+    fn dist_baseline() {
+        let build = Build::new(configure(&[], &[]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+
+        assert_eq!(first(builder.cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
+        assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+        // Make sure rustdoc is only built once.
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
+        );
+    }
+
+    #[test]
+    fn dist_with_targets() {
+        let build = Build::new(configure(&[], &["B"]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+    }
+
+    #[test]
+    fn dist_with_hosts() {
+        let build = Build::new(configure(&["B"], &[]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[
+                dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
+                dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+    }
+
+    #[test]
+    fn dist_only_cross_host() {
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let mut build = Build::new(configure(&["B"], &[]));
+        build.config.docs = false;
+        build.config.extended = true;
+        build.hosts = vec![b];
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[dist::Rustc { compiler: Compiler { host: b, stage: 2 } },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Rustc>()),
+            &[
+                compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
+            ]
+        );
+    }
+
+    #[test]
+    fn dist_with_targets_and_hosts() {
+        let build = Build::new(configure(&["B"], &["C"]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let c = TargetSelection::from_user("C");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[
+                dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
+                dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+    }
+
+    #[test]
+    fn dist_with_target_flag() {
+        let mut config = configure(&["B"], &["C"]);
+        config.skip_only_host_steps = true; // as-if --target=C was passed
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let c = TargetSelection::from_user("C");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[]);
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[]);
+    }
+
+    #[test]
+    fn dist_with_same_targets_and_hosts() {
+        let build = Build::new(configure(&["B"], &["B"]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[
+                dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
+                dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[
+                compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Assemble>()),
+            &[
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
+                compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+    }
+
+    #[test]
+    fn build_all() {
+        let build = Build::new(configure(&["B"], &["C"]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(
+            &Builder::get_step_descriptions(Kind::Build),
+            &["src/rustc".into(), "library/std".into()],
+        );
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let c = TargetSelection::from_user("C");
+
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[
+                compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
+            ]
+        );
+        assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+        assert_eq!(
+            first(builder.cache.all::<compile::Rustc>()),
+            &[
+                compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: a },
+                compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
+                compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: b },
+                compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: b },
+            ]
+        );
+    }
+
+    #[test]
+    fn build_with_target_flag() {
+        let mut config = configure(&["B"], &["C"]);
+        config.skip_only_host_steps = true;
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let c = TargetSelection::from_user("C");
+
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[
+                compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Assemble>()),
+            &[
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
+                compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Rustc>()),
+            &[
+                compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
+            ]
+        );
+    }
+
+    #[test]
+    fn test_with_no_doc_stage0() {
+        let mut config = configure(&[], &[]);
+        config.stage = Some(0);
+        config.cmd = Subcommand::Test {
+            paths: vec!["library/std".into()],
+            test_args: vec![],
+            rustc_args: vec![],
+            fail_fast: true,
+            doc_tests: DocTests::No,
+            bless: false,
+            compare_mode: None,
+            rustfix_coverage: false,
+            pass: None,
+        };
+
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+
+        let host = TargetSelection::from_user("A");
+
+        builder.run_step_descriptions(
+            &[StepDescription::from::<test::Crate>()],
+            &["library/std".into()],
+        );
+
+        // Ensure we don't build any compiler artifacts.
+        assert!(!builder.cache.contains::<compile::Rustc>());
+        assert_eq!(
+            first(builder.cache.all::<test::Crate>()),
+            &[test::Crate {
+                compiler: Compiler { host, stage: 0 },
+                target: host,
+                mode: Mode::Std,
+                test_kind: test::TestKind::Test,
+                krate: INTERNER.intern_str("std"),
+            },]
+        );
+    }
+
+    #[test]
+    fn test_exclude() {
+        let mut config = configure(&[], &[]);
+        config.exclude = vec!["src/tools/tidy".into()];
+        config.cmd = Subcommand::Test {
+            paths: Vec::new(),
+            test_args: Vec::new(),
+            rustc_args: Vec::new(),
+            fail_fast: true,
+            doc_tests: DocTests::No,
+            bless: false,
+            compare_mode: None,
+            rustfix_coverage: false,
+            pass: None,
+        };
+
+        let build = Build::new(config);
+        let builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
+
+        // Ensure we have really excluded tidy
+        assert!(!builder.cache.contains::<test::Tidy>());
+
+        // Ensure other tests are not affected.
+        assert!(builder.cache.contains::<test::RustdocUi>());
+    }
+
+    #[test]
+    fn doc_ci() {
+        let mut config = configure(&[], &[]);
+        config.compiler_docs = true;
+        config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
+        let a = TargetSelection::from_user("A");
+
+        // error_index_generator uses stage 1 to share rustdoc artifacts with the
+        // rustdoc tool.
+        assert_eq!(
+            first(builder.cache.all::<doc::ErrorIndex>()),
+            &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<tool::ErrorIndex>()),
+            &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
+        );
+        // This is actually stage 1, but Rustdoc::run swaps out the compiler with
+        // stage minus 1 if --stage is not 0. Very confusing!
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
+        );
+    }
+
+    #[test]
+    fn test_docs() {
+        // Behavior of `x.py test` doing various documentation tests.
+        let mut config = configure(&[], &[]);
+        config.cmd = Subcommand::Test {
+            paths: vec![],
+            test_args: vec![],
+            rustc_args: vec![],
+            fail_fast: true,
+            doc_tests: DocTests::Yes,
+            bless: false,
+            compare_mode: None,
+            rustfix_coverage: false,
+            pass: None,
+        };
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
+        let a = TargetSelection::from_user("A");
+
+        // error_index_generator uses stage 1 to share rustdoc artifacts with the
+        // rustdoc tool.
+        assert_eq!(
+            first(builder.cache.all::<doc::ErrorIndex>()),
+            &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<tool::ErrorIndex>()),
+            &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
+        );
+        // Unfortunately rustdoc is built twice. Once from stage1 for compiletest
+        // (and other things), and once from stage0 for std crates. Ideally it
+        // would only be built once. If someone wants to fix this, it might be
+        // worth investigating if it would be possible to test std from stage1.
+        // Note that the stages here are +1 than what they actually are because
+        // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is
+        // not 0.
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            &[
+                tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
+                tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },
+            ]
+        );
+    }
 }
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index e3d1e005373..373e240cb8e 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -446,10 +446,10 @@ pub struct Rustc {
 impl Step for Rustc {
     type Output = ();
     const ONLY_HOSTS: bool = true;
-    const DEFAULT: bool = true;
+    const DEFAULT: bool = false;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.all_krates("rustc-main")
+        run.path("src/rustc")
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index d71f3170420..d64ca95d243 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -734,7 +734,7 @@ impl Config {
 
         let with_defaults = |debuginfo_level_specific: Option<u32>| {
             debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {
-                2
+                1
             } else {
                 0
             })
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 7f10d7895a5..a4a1d5193b9 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1016,7 +1016,17 @@ impl Step for Src {
         let src_files = ["Cargo.lock"];
         // This is the reduced set of paths which will become the rust-src component
         // (essentially libstd and all of its path dependencies).
-        copy_src_dirs(builder, &builder.src, &["library"], &[], &dst_src);
+        copy_src_dirs(
+            builder,
+            &builder.src,
+            &["library"],
+            &[
+                // not needed and contains symlinks which rustup currently
+                // chokes on when unpacking.
+                "library/backtrace/crates",
+            ],
+            &dst_src,
+        );
         for file in src_files.iter() {
             builder.copy(&builder.src.join(file), &dst_src.join(file));
         }
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index b43108ccaf9..a1b5ca2ea2f 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -460,7 +460,7 @@ impl Step for Std {
         // open the corresponding rendered docs.
         for path in builder.paths.iter().map(components_simplified) {
             if path.get(0) == Some(&"library") {
-                let requested_crate = &path[1][3..];
+                let requested_crate = &path[1];
                 if krates.contains(&requested_crate) {
                     let index = out.join(requested_crate).join("index.html");
                     open(builder, &index);
@@ -693,6 +693,7 @@ impl Step for UnstableBookGen {
         builder.create_dir(&out);
         builder.remove_dir(&out);
         let mut cmd = builder.tool_cmd(Tool::UnstableBookGen);
+        cmd.arg(builder.src.join("library"));
         cmd.arg(builder.src.join("src"));
         cmd.arg(out);
 
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index a298b299667..56e4f0467cc 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -425,7 +425,7 @@ Arguments:
     This subcommand accepts a number of paths to tools to build and run. For
     example:
 
-        ./x.py run src/tool/expand-yaml-anchors
+        ./x.py run src/tools/expand-yaml-anchors
 
     At least a tool needs to be called.",
                 );
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index e5b9f27c258..1564cfb0619 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -9,8 +9,8 @@ endif
 BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py
 
 all:
-	$(Q)$(BOOTSTRAP) build $(BOOTSTRAP_ARGS)
-	$(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS)
+	$(Q)$(BOOTSTRAP) build --stage 2 $(BOOTSTRAP_ARGS)
+	$(Q)$(BOOTSTRAP) doc --stage 2 $(BOOTSTRAP_ARGS)
 
 help:
 	$(Q)echo 'Welcome to the rustbuild build system!'
@@ -31,17 +31,17 @@ rustc-stage2:
 
 docs: doc
 doc:
-	$(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS)
+	$(Q)$(BOOTSTRAP) doc --stage 2 $(BOOTSTRAP_ARGS)
 nomicon:
-	$(Q)$(BOOTSTRAP) doc src/doc/nomicon $(BOOTSTRAP_ARGS)
+	$(Q)$(BOOTSTRAP) doc --stage 2 src/doc/nomicon $(BOOTSTRAP_ARGS)
 book:
-	$(Q)$(BOOTSTRAP) doc src/doc/book $(BOOTSTRAP_ARGS)
+	$(Q)$(BOOTSTRAP) doc --stage 2 src/doc/book $(BOOTSTRAP_ARGS)
 standalone-docs:
-	$(Q)$(BOOTSTRAP) doc src/doc $(BOOTSTRAP_ARGS)
+	$(Q)$(BOOTSTRAP) doc --stage 2 src/doc $(BOOTSTRAP_ARGS)
 check:
-	$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
+	$(Q)$(BOOTSTRAP) test --stage 2 $(BOOTSTRAP_ARGS)
 check-aux:
-	$(Q)$(BOOTSTRAP) test \
+	$(Q)$(BOOTSTRAP) test --stage 2 \
 		src/tools/cargo \
 		src/tools/cargotest \
 		$(BOOTSTRAP_ARGS)
@@ -51,18 +51,18 @@ dist:
 	$(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
 distcheck:
 	$(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
-	$(Q)$(BOOTSTRAP) test distcheck $(BOOTSTRAP_ARGS)
+	$(Q)$(BOOTSTRAP) test --stage 2 distcheck $(BOOTSTRAP_ARGS)
 install:
 	$(Q)$(BOOTSTRAP) install $(BOOTSTRAP_ARGS)
 tidy:
-	$(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS)
+	$(Q)$(BOOTSTRAP) test --stage 2 src/tools/tidy $(BOOTSTRAP_ARGS)
 prepare:
-	$(Q)$(BOOTSTRAP) build nonexistent/path/to/trigger/cargo/metadata
+	$(Q)$(BOOTSTRAP) build --stage 2 nonexistent/path/to/trigger/cargo/metadata
 
 check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu:
-	$(Q)$(BOOTSTRAP) test --target arm-linux-androideabi
+	$(Q)$(BOOTSTRAP) test --stage 2 --target arm-linux-androideabi
 check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu:
-	$(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-musl
+	$(Q)$(BOOTSTRAP) test --stage 2 --target x86_64-unknown-linux-musl
 
 TESTS_IN_2 := \
 	src/test/ui \
@@ -70,18 +70,18 @@ TESTS_IN_2 := \
 	src/tools/linkchecker
 
 ci-subset-1:
-	$(Q)$(BOOTSTRAP) test $(TESTS_IN_2:%=--exclude %)
+	$(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_2:%=--exclude %)
 ci-subset-2:
-	$(Q)$(BOOTSTRAP) test $(TESTS_IN_2)
+	$(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_2)
 
 TESTS_IN_MINGW_2 := \
 	src/test/ui \
 	src/test/compile-fail
 
 ci-mingw-subset-1:
-	$(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2:%=--exclude %)
+	$(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %)
 ci-mingw-subset-2:
-	$(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2)
+	$(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2)
 
 
 .PHONY: dist
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index addc51faa5e..bb5b9296c0a 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -106,19 +106,18 @@ impl Step for Linkcheck {
     ///
     /// This tool in `src/tools` will verify the validity of all our links in the
     /// documentation to ensure we don't have a bunch of dead ones.
-    fn run(self, _builder: &Builder<'_>) {
-        // FIXME(mark-i-m): uncomment this after we fix the links...
-        // let host = self.host;
+    fn run(self, builder: &Builder<'_>) {
+        let host = self.host;
 
-        // builder.info(&format!("Linkcheck ({})", host));
+        builder.info(&format!("Linkcheck ({})", host));
 
-        // builder.default_doc(None);
+        builder.default_doc(None);
 
-        // let _time = util::timeit(&builder);
-        // try_run(
-        //     builder,
-        //     builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")),
-        // );
+        let _time = util::timeit(&builder);
+        try_run(
+            builder,
+            builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")),
+        );
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -394,7 +393,7 @@ impl Step for Miri {
             cargo.arg("--").arg("miri").arg("setup");
 
             // Tell `cargo miri setup` where to find the sources.
-            cargo.env("XARGO_RUST_SRC", builder.src.join("src"));
+            cargo.env("XARGO_RUST_SRC", builder.src.join("library"));
             // Tell it where to find Miri.
             cargo.env("MIRI", &miri);
             // Debug things.
@@ -1159,13 +1158,19 @@ impl Step for Compiletest {
             cmd.arg("--quiet");
         }
 
+        let mut llvm_components_passed = false;
+        let mut copts_passed = false;
         if builder.config.llvm_enabled() {
             let llvm_config = builder.ensure(native::Llvm { target: builder.config.build });
             if !builder.config.dry_run {
                 let llvm_version = output(Command::new(&llvm_config).arg("--version"));
+                let llvm_components = output(Command::new(&llvm_config).arg("--components"));
                 // Remove trailing newline from llvm-config output.
-                let llvm_version = llvm_version.trim_end();
-                cmd.arg("--llvm-version").arg(llvm_version);
+                cmd.arg("--llvm-version")
+                    .arg(llvm_version.trim())
+                    .arg("--llvm-components")
+                    .arg(llvm_components.trim());
+                llvm_components_passed = true;
             }
             if !builder.is_rust_llvm(target) {
                 cmd.arg("--system-llvm");
@@ -1183,15 +1188,13 @@ impl Step for Compiletest {
             // Only pass correct values for these flags for the `run-make` suite as it
             // requires that a C++ compiler was configured which isn't always the case.
             if !builder.config.dry_run && suite == "run-make-fulldeps" {
-                let llvm_components = output(Command::new(&llvm_config).arg("--components"));
                 cmd.arg("--cc")
                     .arg(builder.cc(target))
                     .arg("--cxx")
                     .arg(builder.cxx(target).unwrap())
                     .arg("--cflags")
-                    .arg(builder.cflags(target, GitRepo::Rustc).join(" "))
-                    .arg("--llvm-components")
-                    .arg(llvm_components.trim());
+                    .arg(builder.cflags(target, GitRepo::Rustc).join(" "));
+                copts_passed = true;
                 if let Some(ar) = builder.ar(target) {
                     cmd.arg("--ar").arg(ar);
                 }
@@ -1221,15 +1224,11 @@ impl Step for Compiletest {
             }
         }
 
-        if suite != "run-make-fulldeps" {
-            cmd.arg("--cc")
-                .arg("")
-                .arg("--cxx")
-                .arg("")
-                .arg("--cflags")
-                .arg("")
-                .arg("--llvm-components")
-                .arg("");
+        if !llvm_components_passed {
+            cmd.arg("--llvm-components").arg("");
+        }
+        if !copts_passed {
+            cmd.arg("--cc").arg("").arg("--cxx").arg("").arg("--cflags").arg("");
         }
 
         if builder.remote_tested(target) {
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index 06e284c763c..2185b0d30db 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -36,7 +36,7 @@ jobs:
       # Note that the compiler is compiled to target 10.8 here because the Xcode
       # version that we're using, 8.2, cannot compile LLVM for OSX 10.7.
       x86_64-apple:
-        SCRIPT: ./x.py test
+        SCRIPT: ./x.py --stage 2 test
         INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
         RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
         MACOSX_DEPLOYMENT_TARGET: 10.8
diff --git a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
index 114ac832cf5..b6cf60a5e15 100644
--- a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
+++ b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
@@ -23,4 +23,4 @@ ENV RUST_CONFIGURE_ARGS \
  --enable-sanitizers \
  --enable-profiler \
  --enable-compiler-docs
-ENV SCRIPT python3 ../x.py test
+ENV SCRIPT python3 ../x.py --stage 2 test
diff --git a/src/ci/docker/host-x86_64/arm-android/Dockerfile b/src/ci/docker/host-x86_64/arm-android/Dockerfile
index aa9335c473b..add2647fa1e 100644
--- a/src/ci/docker/host-x86_64/arm-android/Dockerfile
+++ b/src/ci/docker/host-x86_64/arm-android/Dockerfile
@@ -31,7 +31,7 @@ ENV TARGETS=arm-linux-androideabi
 
 ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14
 
-ENV SCRIPT python3 ../x.py test --target $TARGETS
+ENV SCRIPT python3 ../x.py --stage 2 test --target $TARGETS
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
index 71071761f05..1f3092c5513 100644
--- a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
@@ -78,6 +78,6 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --qemu-armhf-rootfs=/tmp/rootfs
-ENV SCRIPT python3 ../x.py test --target arm-unknown-linux-gnueabihf
+ENV SCRIPT python3 ../x.py --stage 2 test --target arm-unknown-linux-gnueabihf
 
 ENV NO_CHANGE_USER=1
diff --git a/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile b/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile
index 3fa65511e94..a4d9f53ebab 100644
--- a/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile
+++ b/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile
@@ -33,7 +33,7 @@ ENV EMCC_CFLAGS=-O1
 # Emscripten installation is user-specific
 ENV NO_CHANGE_USER=1
 
-ENV SCRIPT python3 ../x.py test --target $TARGETS
+ENV SCRIPT python3 ../x.py --stage 2 test --target $TARGETS
 
 # This is almost identical to the wasm32-unknown-emscripten target, so
 # running with assertions again is not useful
diff --git a/src/ci/docker/host-x86_64/disabled/dist-armv7-android/Dockerfile b/src/ci/docker/host-x86_64/disabled/dist-armv7-android/Dockerfile
index 7227c41ccca..f986c38ea02 100644
--- a/src/ci/docker/host-x86_64/disabled/dist-armv7-android/Dockerfile
+++ b/src/ci/docker/host-x86_64/disabled/dist-armv7-android/Dockerfile
@@ -33,7 +33,7 @@ ENV RUST_CONFIGURE_ARGS \
 # build to finish we use --warn-unresolved-symbols. Note that the missing
 # symbols does not affect std, only the compiler (llvm) and cargo (openssl).
 ENV SCRIPT \
-  python3 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
+  python3 ../x.py --stage 2 build src/llvm --host $HOSTS --target $HOSTS && \
   (export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
     rm /android/ndk/arm && \
     ln -s /android/ndk/arm-14 /android/ndk/arm && \
diff --git a/src/ci/docker/host-x86_64/disabled/dist-i686-android/Dockerfile b/src/ci/docker/host-x86_64/disabled/dist-i686-android/Dockerfile
index b74dcefa351..4dfbc725607 100644
--- a/src/ci/docker/host-x86_64/disabled/dist-i686-android/Dockerfile
+++ b/src/ci/docker/host-x86_64/disabled/dist-i686-android/Dockerfile
@@ -33,7 +33,7 @@ ENV RUST_CONFIGURE_ARGS \
 # build to finish we use --warn-unresolved-symbols. Note that the missing
 # symbols does not affect std, only the compiler (llvm) and cargo (openssl).
 ENV SCRIPT \
-  python3 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
+  python3 ../x.py --stage 2 build src/llvm --host $HOSTS --target $HOSTS && \
   (export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
     rm /android/ndk/x86 && \
     ln -s /android/ndk/x86-14 /android/ndk/x86 && \
diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile
index a938899636a..e3c35000eb8 100644
--- a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile
@@ -97,6 +97,6 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs
-ENV SCRIPT python3 ../x.py test --target riscv64gc-unknown-linux-gnu
+ENV SCRIPT python3 ../x.py --stage 2 test --target riscv64gc-unknown-linux-gnu
 
 ENV NO_CHANGE_USER=1
diff --git a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
index 996fffeb871..162d7a1345c 100644
--- a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
@@ -46,5 +46,5 @@ ENV CFLAGS_i586_unknown_linux_musl=-Wa,-mrelax-relocations=no
 ENV TARGETS=i586-unknown-linux-gnu,i686-unknown-linux-musl
 
 ENV SCRIPT \
-      python3 ../x.py test --target $TARGETS && \
+      python3 ../x.py --stage 2 test --target $TARGETS && \
       python3 ../x.py dist --target $TARGETS,i586-unknown-linux-musl
diff --git a/src/ci/docker/host-x86_64/dist-i686-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-freebsd/Dockerfile
index 7978bb70869..14af9b9efe8 100644
--- a/src/ci/docker/host-x86_64/dist-i686-freebsd/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-i686-freebsd/Dockerfile
@@ -29,5 +29,5 @@ ENV \
 
 ENV HOSTS=i686-unknown-freebsd
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
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 ac228cfe01d..fdd777e824b 100644
--- a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile
@@ -192,7 +192,7 @@ ENV RUST_CONFIGURE_ARGS \
       --disable-docs
 
 ENV SCRIPT \
-      python3 ../x.py test --target $RUN_MAKE_TARGETS src/test/run-make && \
+      python3 ../x.py --stage 2 test --target $RUN_MAKE_TARGETS src/test/run-make && \
       python3 ../x.py dist --target $TARGETS
 
 # sccache
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
index c82031690ab..c6db200f866 100755
--- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
@@ -4,15 +4,15 @@
 
 set -ex
 
-# Originally from https://releases.llvm.org/9.0.0/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz
-curl https://ci-mirrors.rust-lang.org/rustc/clang%2Bllvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \
+# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz
+curl https://ci-mirrors.rust-lang.org/rustc/clang%2Bllvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \
   tar xJf -
-export PATH=`pwd`/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH
+export PATH=`pwd`/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04/bin:$PATH
 
-git clone https://github.com/CraneStation/wasi-libc
+git clone https://github.com/WebAssembly/wasi-libc
 
 cd wasi-libc
-git reset --hard 9efc2f428358564fe64c374d762d0bfce1d92507
+git reset --hard 215adc8ac9f91eb055311acc72683fd2eb1ae15a
 make -j$(nproc) INSTALL_DIR=/wasm32-wasi install
 
 cd ..
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
index 12170a36614..2372c0dad0a 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
@@ -29,5 +29,5 @@ ENV \
 
 ENV HOSTS=x86_64-unknown-freebsd
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
index c026506b106..ab6515cd1fa 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
@@ -33,7 +33,6 @@ ENV HOSTS=x86_64-unknown-linux-musl
 ENV RUST_CONFIGURE_ARGS \
       --musl-root-x86_64=/usr/local/x86_64-linux-musl \
       --enable-extended \
-      --disable-docs \
       --enable-lld \
       --set target.x86_64-unknown-linux-musl.crt-static=false \
       --build $HOSTS
diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
index 436215839f7..6a596b3465f 100644
--- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
@@ -20,7 +20,7 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
-ENV SCRIPT python3 ../x.py test
+ENV SCRIPT python3 ../x.py --stage 2 test
 
 # FIXME(#59637) takes too long on CI right now
 ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
index 34a76f39668..9d319017d79 100644
--- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
@@ -22,7 +22,7 @@ RUN sh /scripts/sccache.sh
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
 # Exclude some tests that are unlikely to be platform specific, to speed up
 # this slow job.
-ENV SCRIPT python3 ../x.py test \
+ENV SCRIPT python3 ../x.py --stage 2 test \
   --exclude src/bootstrap \
   --exclude src/test/rustdoc-js \
   --exclude src/tools/error_index_generator \
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 0c59b95ea21..b902eda87bc 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -22,10 +22,10 @@ RUN sh /scripts/sccache.sh
 COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
 
 ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
-ENV SCRIPT python3 ../x.py test src/tools/expand-yaml-anchors && \
+ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
            python3 ../x.py build --stage 0 src/tools/build-manifest && \
            python3 ../x.py test --stage 0 src/tools/compiletest && \
-           python3 ../x.py test src/tools/tidy && \
+           python3 ../x.py test --stage 2 src/tools/tidy && \
            python3 ../x.py doc --stage 0 library/std && \
            /scripts/validate-toolstate.sh
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index b7276f60867..c55a284e137 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -40,7 +40,7 @@ ENV RUST_CONFIGURE_ARGS \
 ENV NO_DEBUG_ASSERTIONS=1
 
 ENV WASM_TARGETS=wasm32-unknown-unknown
-ENV WASM_SCRIPT python3 /checkout/x.py test --target $WASM_TARGETS \
+ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --target $WASM_TARGETS \
   src/test/run-make \
   src/test/ui \
   src/test/compile-fail \
@@ -49,13 +49,13 @@ ENV WASM_SCRIPT python3 /checkout/x.py test --target $WASM_TARGETS \
   library/core
 
 ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
-ENV NVPTX_SCRIPT python3 /checkout/x.py test --target $NVPTX_TARGETS \
+ENV NVPTX_SCRIPT python3 /checkout/x.py --stage 2 test --target $NVPTX_TARGETS \
   src/test/run-make \
   src/test/assembly
 
 ENV MUSL_TARGETS=x86_64-unknown-linux-musl \
     CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc \
     CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++
-ENV MUSL_SCRIPT python3 /checkout/x.py test --target $MUSL_TARGETS
+ENV MUSL_SCRIPT python3 /checkout/x.py --stage 2 test --target $MUSL_TARGETS
 
 ENV SCRIPT $WASM_SCRIPT && $NVPTX_SCRIPT && $MUSL_SCRIPT
diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile
index a40ccb6bfd5..e00177b4a67 100644
--- a/src/ci/docker/host-x86_64/wasm32/Dockerfile
+++ b/src/ci/docker/host-x86_64/wasm32/Dockerfile
@@ -52,7 +52,7 @@ ENV NO_CHANGE_USER=1
 
 # FIXME: Re-enable these tests once https://github.com/rust-lang/cargo/pull/7476
 # is picked up by CI
-ENV SCRIPT python3 ../x.py test --target $TARGETS \
+ENV SCRIPT python3 ../x.py test --stage 2 --target $TARGETS \
     --exclude library/core \
     --exclude library/alloc \
     --exclude library/proc_macro \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
index c5e41b8a75a..c1cb20b631d 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
@@ -40,5 +40,5 @@ ENV RUST_CONFIGURE_ARGS \
       --set target.x86_64-unknown-linux-gnu.cxx=clang++
 
 ENV SCRIPT \
-  python3 ../x.py build && \
-  python3 ../x.py test src/test/run-make-fulldeps --test-args clang
+  python3 ../x.py --stage 2 build && \
+  python3 ../x.py --stage 2 test src/test/run-make-fulldeps --test-args clang
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
index cc07a591cc1..68e89a7bade 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
@@ -19,10 +19,10 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.ignore-git=false
-ENV SCRIPT python3 ../x.py test distcheck
+ENV SCRIPT python3 ../x.py --stage 2 test distcheck
 ENV DIST_SRC 1
 
-# The purpose of this builder is to test that we can `./x.py test` successfully
+# The purpose of this builder is to test that we can `./x.py --stage 2 test` successfully
 # from a tarball, not to test LLVM/rustc's own set of assertions. These cause a
 # significant hit to CI compile time (over a half hour as observed in #61185),
 # so disable assertions for this builder.
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-full-bootstrap/Dockerfile
index de7ee6950b5..8648e5ed7a4 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-full-bootstrap/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-full-bootstrap/Dockerfile
@@ -21,7 +21,7 @@ RUN sh /scripts/sccache.sh
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --enable-full-bootstrap
-ENV SCRIPT python3 ../x.py build
+ENV SCRIPT python3 ../x.py --stage 2 build
 
 # In general this just slows down the build and we're just a smoke test that
 # a full bootstrap works in general, so there's not much need to take this
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-8/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-8/Dockerfile
index 1d9cad149d9..5c971c73c97 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-8/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-8/Dockerfile
@@ -30,7 +30,7 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-llvm-link-shared \
       --set rust.thin-lto-import-instr-limit=10
 
-ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && \
+ENV SCRIPT python2.7 ../x.py --stage 2 test --exclude src/tools/tidy && \
            # Run the `mir-opt` tests again but this time for a 32-bit target.
            # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
            # both 32-bit and 64-bit outputs updated by the PR author, before
@@ -43,7 +43,7 @@ ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && \
            # This also requires `--pass=build` because we can't execute the tests
            # on the `x86_64` host when they're built as `armv5te` binaries.
            # (we're only interested in the MIR output, so this doesn't matter)
-           python2.7 ../x.py test src/test/mir-opt --pass=build \
+           python2.7 ../x.py --stage 2 test src/test/mir-opt --pass=build \
                                   --target=armv5te-unknown-linux-gnueabi && \
            # Run the UI test suite again, but in `--pass=check` mode
            #
@@ -53,9 +53,9 @@ ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && \
            # FIXME: We ideally want to test this in 32-bit mode, but currently
            # (due to the LLVM problems mentioned above) that isn't readily
            # possible.
-           python2.7 ../x.py test src/test/ui --pass=check && \
+           python2.7 ../x.py --stage 2 test src/test/ui --pass=check && \
            # Run tidy at the very end, after all the other tests.
-           python2.7 ../x.py test src/tools/tidy
+           python2.7 ../x.py --stage 2 test src/tools/tidy
 
 # The purpose of this container isn't to test with debug assertions and
 # this is run on all PRs, so let's get speedier builds by disabling these extra
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
index 096f67e13d1..fa769cac9c1 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
@@ -21,4 +21,4 @@ RUN sh /scripts/sccache.sh
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \
   --disable-optimize-tests \
   --set rust.test-compare-mode
-ENV SCRIPT python3 ../x.py test
+ENV SCRIPT python3 ../x.py --stage 2 test
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
index b4b23a245e0..49a8e5e88a0 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
@@ -7,7 +7,7 @@ X_PY="$1"
 # Try to test all the tools and store the build/test success in the TOOLSTATE_FILE
 
 set +e
-python3 "$X_PY" test --no-fail-fast \
+python3 "$X_PY" test --stage 2 --no-fail-fast \
     src/doc/book \
     src/doc/nomicon \
     src/doc/reference \
@@ -22,5 +22,5 @@ set -e
 
 # debugging: print out the saved toolstates
 cat /tmp/toolstate/toolstates.json
-python3 "$X_PY" test check-tools
-python3 "$X_PY" test src/tools/clippy
+python3 "$X_PY" test --stage 2 check-tools
+python3 "$X_PY" test --stage 2 src/tools/clippy
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
index af6e1318062..f8bacf79ac0 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
@@ -23,4 +23,4 @@ ENV RUST_CONFIGURE_ARGS \
  --enable-sanitizers \
  --enable-profiler \
  --enable-compiler-docs
-ENV SCRIPT python3 ../x.py test
+ENV SCRIPT python3 ../x.py --stage 2 test
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 0aeb6a04e5f..8a6973bcdd6 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -84,6 +84,9 @@ x--expand-yaml-anchors--remove:
     os: windows-latest-xl
     <<: *base-job
 
+  - &job-aarch64-linux
+    os: [self-hosted, ARM64, linux]
+
   - &step
     if: success() && !env.SKIP_JOB
 
@@ -471,7 +474,7 @@ jobs:
 
           - name: x86_64-msvc-cargo
             env:
-              SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
+              SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo
               RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld
               VCVARS_BAT: vcvars64.bat
               # FIXME(#59637)
@@ -586,6 +589,13 @@ jobs:
     strategy:
       matrix:
         include:
+          #############################
+          #   Linux/Docker builders   #
+          #############################
+
+          - name: aarch64-gnu
+            <<: *job-aarch64-linux
+
           ####################
           #  macOS Builders  #
           ####################
@@ -613,7 +623,7 @@ jobs:
 
           - name: x86_64-apple
             env:
-              SCRIPT: ./x.py test
+              SCRIPT: ./x.py --stage 2 test
               RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
               RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
               MACOSX_DEPLOYMENT_TARGET: 10.8
diff --git a/src/ci/scripts/symlink-build-dir.sh b/src/ci/scripts/symlink-build-dir.sh
index 50178b9c33e..28d8aa3b6e7 100755
--- a/src/ci/scripts/symlink-build-dir.sh
+++ b/src/ci/scripts/symlink-build-dir.sh
@@ -12,7 +12,7 @@ source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 if isWindows && isAzurePipelines; then
     cmd //c "mkdir c:\\MORE_SPACE"
     cmd //c "mklink /J build c:\\MORE_SPACE"
-elif isLinux && isGitHubActions; then
+elif isLinux && isGitHubActions && ! isSelfHostedGitHubActions; then
     sudo mkdir -p /mnt/more-space
     sudo chown -R "$(whoami):" /mnt/more-space
 
diff --git a/src/ci/shared.sh b/src/ci/shared.sh
index 206065d7072..8222758ed6d 100644
--- a/src/ci/shared.sh
+++ b/src/ci/shared.sh
@@ -38,6 +38,11 @@ function isGitHubActions {
     [[ "${GITHUB_ACTIONS-false}" = "true" ]]
 }
 
+
+function isSelfHostedGitHubActions {
+    [[ "${RUST_GHA_SELF_HOSTED-false}" = "true" ]]
+}
+
 function isMacOS {
     [[ "${OSTYPE}" = "darwin"* ]]
 }
diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md
index beb2556872d..d1d6bc1c1fe 100644
--- a/src/doc/rustdoc/src/lints.md
+++ b/src/doc/rustdoc/src/lints.md
@@ -11,7 +11,7 @@ can use them like any other lints by doing this:
 
 Here is the list of the lints provided by `rustdoc`:
 
-## intra_doc_link_resolution_failure
+## broken_intra_doc_links
 
 This lint **warns by default** and is **nightly-only**. This lint detects when
 an intra-doc link fails to get resolved. For example:
diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
index 47ac986c224..38351131527 100644
--- a/src/doc/unstable-book/src/language-features/plugin.md
+++ b/src/doc/unstable-book/src/language-features/plugin.md
@@ -35,7 +35,7 @@ of a library.
 Plugins can extend [Rust's lint
 infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with
 additional checks for code style, safety, etc. Now let's write a plugin
-[`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs)
+[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs)
 that warns about any item named `lintme`.
 
 ```rust,ignore
@@ -45,42 +45,40 @@ that warns about any item named `lintme`.
 extern crate rustc_ast;
 
 // Load rustc as a plugin to get macros
-#[macro_use]
-extern crate rustc;
 extern crate rustc_driver;
+#[macro_use]
+extern crate rustc_lint;
+#[macro_use]
+extern crate rustc_session;
 
-use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
-                  EarlyLintPassObject, LintArray};
 use rustc_driver::plugin::Registry;
+use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
 use rustc_ast::ast;
-
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT]);
 
 impl EarlyLintPass for Pass {
     fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
-        if it.ident.as_str() == "lintme" {
-            cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
+        if it.ident.name.as_str() == "lintme" {
+            cx.lint(TEST_LINT, |lint| {
+                lint.build("item is named 'lintme'").set_span(it.span).emit()
+            });
         }
     }
 }
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_early_lint_pass(box Pass as EarlyLintPassObject);
+    reg.lint_store.register_lints(&[&TEST_LINT]);
+    reg.lint_store.register_early_pass(|| box Pass);
 }
 ```
 
 Then code like
 
 ```rust,ignore
+#![feature(plugin)]
 #![plugin(lint_plugin_test)]
 
 fn lintme() { }
@@ -107,7 +105,7 @@ The components of a lint plugin are:
 
 Lint passes are syntax traversals, but they run at a late stage of compilation
 where type information is available. `rustc`'s [built-in
-lints](https://github.com/rust-lang/rust/blob/master/src/librustc/lint/builtin.rs)
+lints](https://github.com/rust-lang/rust/blob/master/src/librustc_session/lint/builtin.rs)
 mostly use the same infrastructure as lint plugins, and provide examples of how
 to access type information.
 
diff --git a/src/etc/test-float-parse/runtests.py b/src/etc/test-float-parse/runtests.py
index 7106078f897..218552a4597 100644
--- a/src/etc/test-float-parse/runtests.py
+++ b/src/etc/test-float-parse/runtests.py
@@ -193,11 +193,12 @@ def interact(proc, queue):
 
 def main():
     global MAILBOX
-    tests = [os.path.splitext(f)[0] for f in glob('*.rs')
-                                    if not f.startswith('_')]
-    listed = sys.argv[1:]
-    if listed:
-        tests = [test for test in tests if test in listed]
+    all_tests = [os.path.splitext(f)[0] for f in glob('*.rs') if not f.startswith('_')]
+    args = sys.argv[1:]
+    if args:
+        tests = [test for test in all_tests if test in args]
+    else
+        tests = all_tests
     if not tests:
         print("Error: No tests to run")
         sys.exit(1)
diff --git a/src/librustc_ast/Cargo.toml b/src/librustc_ast/Cargo.toml
index 6bd65fd5f96..a36f49bd414 100644
--- a/src/librustc_ast/Cargo.toml
+++ b/src/librustc_ast/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_serialize = { path = "../librustc_serialize" }
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 scoped-tls = "1.0"
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs
index 173ea5e48d6..e1c94ddf782 100644
--- a/src/librustc_ast/token.rs
+++ b/src/librustc_ast/token.rs
@@ -673,62 +673,6 @@ impl Token {
 
         Some(Token::new(kind, self.span.to(joint.span)))
     }
-
-    // See comments in `Nonterminal::to_tokenstream` for why we care about
-    // *probably* equal here rather than actual equality
-    crate fn probably_equal_for_proc_macro(&self, other: &Token) -> bool {
-        if mem::discriminant(&self.kind) != mem::discriminant(&other.kind) {
-            return false;
-        }
-        match (&self.kind, &other.kind) {
-            (&Eq, &Eq)
-            | (&Lt, &Lt)
-            | (&Le, &Le)
-            | (&EqEq, &EqEq)
-            | (&Ne, &Ne)
-            | (&Ge, &Ge)
-            | (&Gt, &Gt)
-            | (&AndAnd, &AndAnd)
-            | (&OrOr, &OrOr)
-            | (&Not, &Not)
-            | (&Tilde, &Tilde)
-            | (&At, &At)
-            | (&Dot, &Dot)
-            | (&DotDot, &DotDot)
-            | (&DotDotDot, &DotDotDot)
-            | (&DotDotEq, &DotDotEq)
-            | (&Comma, &Comma)
-            | (&Semi, &Semi)
-            | (&Colon, &Colon)
-            | (&ModSep, &ModSep)
-            | (&RArrow, &RArrow)
-            | (&LArrow, &LArrow)
-            | (&FatArrow, &FatArrow)
-            | (&Pound, &Pound)
-            | (&Dollar, &Dollar)
-            | (&Question, &Question)
-            | (&Whitespace, &Whitespace)
-            | (&Comment, &Comment)
-            | (&Eof, &Eof) => true,
-
-            (&BinOp(a), &BinOp(b)) | (&BinOpEq(a), &BinOpEq(b)) => a == b,
-
-            (&OpenDelim(a), &OpenDelim(b)) | (&CloseDelim(a), &CloseDelim(b)) => a == b,
-
-            (&DocComment(a), &DocComment(b)) | (&Shebang(a), &Shebang(b)) => a == b,
-
-            (&Literal(a), &Literal(b)) => a == b,
-
-            (&Lifetime(a), &Lifetime(b)) => a == b,
-            (&Ident(a, b), &Ident(c, d)) => {
-                b == d && (a == c || a == kw::DollarCrate || c == kw::DollarCrate)
-            }
-
-            (&Interpolated(..), &Interpolated(..)) => false,
-
-            _ => panic!("forgot to add a token?"),
-        }
-    }
 }
 
 impl PartialEq<TokenKind> for Token {
@@ -760,6 +704,67 @@ pub enum Nonterminal {
 #[cfg(target_arch = "x86_64")]
 rustc_data_structures::static_assert_size!(Nonterminal, 40);
 
+#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
+pub enum NonterminalKind {
+    Item,
+    Block,
+    Stmt,
+    Pat,
+    Expr,
+    Ty,
+    Ident,
+    Lifetime,
+    Literal,
+    Meta,
+    Path,
+    Vis,
+    TT,
+}
+
+impl NonterminalKind {
+    pub fn from_symbol(symbol: Symbol) -> Option<NonterminalKind> {
+        Some(match symbol {
+            sym::item => NonterminalKind::Item,
+            sym::block => NonterminalKind::Block,
+            sym::stmt => NonterminalKind::Stmt,
+            sym::pat => NonterminalKind::Pat,
+            sym::expr => NonterminalKind::Expr,
+            sym::ty => NonterminalKind::Ty,
+            sym::ident => NonterminalKind::Ident,
+            sym::lifetime => NonterminalKind::Lifetime,
+            sym::literal => NonterminalKind::Literal,
+            sym::meta => NonterminalKind::Meta,
+            sym::path => NonterminalKind::Path,
+            sym::vis => NonterminalKind::Vis,
+            sym::tt => NonterminalKind::TT,
+            _ => return None,
+        })
+    }
+    fn symbol(self) -> Symbol {
+        match self {
+            NonterminalKind::Item => sym::item,
+            NonterminalKind::Block => sym::block,
+            NonterminalKind::Stmt => sym::stmt,
+            NonterminalKind::Pat => sym::pat,
+            NonterminalKind::Expr => sym::expr,
+            NonterminalKind::Ty => sym::ty,
+            NonterminalKind::Ident => sym::ident,
+            NonterminalKind::Lifetime => sym::lifetime,
+            NonterminalKind::Literal => sym::literal,
+            NonterminalKind::Meta => sym::meta,
+            NonterminalKind::Path => sym::path,
+            NonterminalKind::Vis => sym::vis,
+            NonterminalKind::TT => sym::tt,
+        }
+    }
+}
+
+impl fmt::Display for NonterminalKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.symbol())
+    }
+}
+
 impl Nonterminal {
     fn span(&self) -> Span {
         match self {
diff --git a/src/librustc_ast/tokenstream.rs b/src/librustc_ast/tokenstream.rs
index 15ae12ebf10..9d0199078fa 100644
--- a/src/librustc_ast/tokenstream.rs
+++ b/src/librustc_ast/tokenstream.rs
@@ -21,8 +21,6 @@ use rustc_macros::HashStable_Generic;
 use rustc_span::{Span, DUMMY_SP};
 use smallvec::{smallvec, SmallVec};
 
-use log::debug;
-
 use std::{iter, mem};
 
 /// When the main rust parser encounters a syntax-extension invocation, it
@@ -68,23 +66,6 @@ impl TokenTree {
         }
     }
 
-    // See comments in `Nonterminal::to_tokenstream` for why we care about
-    // *probably* equal here rather than actual equality
-    //
-    // This is otherwise the same as `eq_unspanned`, only recursing with a
-    // different method.
-    pub fn probably_equal_for_proc_macro(&self, other: &TokenTree) -> bool {
-        match (self, other) {
-            (TokenTree::Token(token), TokenTree::Token(token2)) => {
-                token.probably_equal_for_proc_macro(token2)
-            }
-            (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
-                delim == delim2 && tts.probably_equal_for_proc_macro(&tts2)
-            }
-            _ => false,
-        }
-    }
-
     /// Retrieves the TokenTree's span.
     pub fn span(&self) -> Span {
         match self {
@@ -307,112 +288,6 @@ impl TokenStream {
         t1.next().is_none() && t2.next().is_none()
     }
 
-    // See comments in `Nonterminal::to_tokenstream` for why we care about
-    // *probably* equal here rather than actual equality
-    //
-    // This is otherwise the same as `eq_unspanned`, only recursing with a
-    // different method.
-    pub fn probably_equal_for_proc_macro(&self, other: &TokenStream) -> bool {
-        // When checking for `probably_eq`, we ignore certain tokens that aren't
-        // preserved in the AST. Because they are not preserved, the pretty
-        // printer arbitrarily adds or removes them when printing as token
-        // streams, making a comparison between a token stream generated from an
-        // AST and a token stream which was parsed into an AST more reliable.
-        fn semantic_tree(tree: &TokenTree) -> bool {
-            if let TokenTree::Token(token) = tree {
-                if let
-                    // The pretty printer tends to add trailing commas to
-                    // everything, and in particular, after struct fields.
-                    | token::Comma
-                    // The pretty printer emits `NoDelim` as whitespace.
-                    | token::OpenDelim(DelimToken::NoDelim)
-                    | token::CloseDelim(DelimToken::NoDelim)
-                    // The pretty printer collapses many semicolons into one.
-                    | token::Semi
-                    // The pretty printer collapses whitespace arbitrarily and can
-                    // introduce whitespace from `NoDelim`.
-                    | token::Whitespace
-                    // The pretty printer can turn `$crate` into `::crate_name`
-                    | token::ModSep = token.kind {
-                    return false;
-                }
-            }
-            true
-        }
-
-        // When comparing two `TokenStream`s, we ignore the `IsJoint` information.
-        //
-        // However, `rustc_parse::lexer::tokentrees::TokenStreamBuilder` will
-        // use `Token.glue` on adjacent tokens with the proper `IsJoint`.
-        // Since we are ignoreing `IsJoint`, a 'glued' token (e.g. `BinOp(Shr)`)
-        // and its 'split'/'unglued' compoenents (e.g. `Gt, Gt`) are equivalent
-        // when determining if two `TokenStream`s are 'probably equal'.
-        //
-        // Therefore, we use `break_two_token_op` to convert all tokens
-        // to the 'unglued' form (if it exists). This ensures that two
-        // `TokenStream`s which differ only in how their tokens are glued
-        // will be considered 'probably equal', which allows us to keep spans.
-        //
-        // This is important when the original `TokenStream` contained
-        // extra spaces (e.g. `f :: < Vec < _ > > ( ) ;'). These extra spaces
-        // will be omitted when we pretty-print, which can cause the original
-        // and reparsed `TokenStream`s to differ in the assignment of `IsJoint`,
-        // leading to some tokens being 'glued' together in one stream but not
-        // the other. See #68489 for more details.
-        fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
-            // In almost all cases, we should have either zero or one levels
-            // of 'unglueing'. However, in some unusual cases, we may need
-            // to iterate breaking tokens mutliple times. For example:
-            // '[BinOpEq(Shr)] => [Gt, Ge] -> [Gt, Gt, Eq]'
-            let mut token_trees: SmallVec<[_; 2]>;
-            if let TokenTree::Token(token) = &tree {
-                let mut out = SmallVec::<[_; 2]>::new();
-                out.push(token.clone());
-                // Iterate to fixpoint:
-                // * We start off with 'out' containing our initial token, and `temp` empty
-                // * If we are able to break any tokens in `out`, then `out` will have
-                //   at least one more element than 'temp', so we will try to break tokens
-                //   again.
-                // * If we cannot break any tokens in 'out', we are done
-                loop {
-                    let mut temp = SmallVec::<[_; 2]>::new();
-                    let mut changed = false;
-
-                    for token in out.into_iter() {
-                        if let Some((first, second)) = token.kind.break_two_token_op() {
-                            temp.push(Token::new(first, DUMMY_SP));
-                            temp.push(Token::new(second, DUMMY_SP));
-                            changed = true;
-                        } else {
-                            temp.push(token);
-                        }
-                    }
-                    out = temp;
-                    if !changed {
-                        break;
-                    }
-                }
-                token_trees = out.into_iter().map(TokenTree::Token).collect();
-                if token_trees.len() != 1 {
-                    debug!("break_tokens: broke {:?} to {:?}", tree, token_trees);
-                }
-            } else {
-                token_trees = SmallVec::new();
-                token_trees.push(tree);
-            }
-            token_trees.into_iter()
-        }
-
-        let mut t1 = self.trees().filter(semantic_tree).flat_map(break_tokens);
-        let mut t2 = other.trees().filter(semantic_tree).flat_map(break_tokens);
-        for (t1, t2) in t1.by_ref().zip(t2.by_ref()) {
-            if !t1.probably_equal_for_proc_macro(&t2) {
-                return false;
-            }
-        }
-        t1.next().is_none() && t2.next().is_none()
-    }
-
     pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
         TokenStream(Lrc::new(
             self.0
diff --git a/src/librustc_ast_lowering/Cargo.toml b/src/librustc_ast_lowering/Cargo.toml
index d71eb4fcd5c..bf7e69a31ab 100644
--- a/src/librustc_ast_lowering/Cargo.toml
+++ b/src/librustc_ast_lowering/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_arena = { path = "../librustc_arena" }
-log = { version = "0.4", features = ["release_max_level_info", "std"] }
+tracing = "0.1"
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index dd5e658102f..5414e584290 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -17,9 +17,9 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
 use rustc_target::spec::abi;
 
-use log::debug;
 use smallvec::{smallvec, SmallVec};
 use std::collections::BTreeSet;
+use tracing::debug;
 
 pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
     pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>,
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 1c70eef3bf5..9df7ad2a9ac 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -64,10 +64,10 @@ use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 
-use log::{debug, trace};
 use smallvec::{smallvec, SmallVec};
 use std::collections::BTreeMap;
 use std::mem;
+use tracing::{debug, trace};
 
 macro_rules! arena_vec {
     ($this:expr; $($x:expr),*) => ({
diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs
index 55c1f802663..171856e7e63 100644
--- a/src/librustc_ast_lowering/pat.rs
+++ b/src/librustc_ast_lowering/pat.rs
@@ -112,7 +112,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // Found a sub-tuple pattern `$binding_mode $ident @ ..`.
                 // This is not allowed as a sub-tuple pattern
                 PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => {
-                    rest = Some((idx, pat.span));
                     let sp = pat.span;
                     self.diagnostic()
                         .struct_span_err(
@@ -128,7 +127,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             Applicability::MaybeIncorrect,
                         )
                         .emit();
-                    break;
                 }
                 _ => {}
             }
diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs
index e5ce51f8d2d..2541d6824fe 100644
--- a/src/librustc_ast_lowering/path.rs
+++ b/src/librustc_ast_lowering/path.rs
@@ -12,8 +12,8 @@ use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
-use log::debug;
 use smallvec::smallvec;
+use tracing::debug;
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     crate fn lower_qpath(
diff --git a/src/librustc_ast_passes/Cargo.toml b/src/librustc_ast_passes/Cargo.toml
index e4d1d79abb2..6db9bce3164 100644
--- a/src/librustc_ast_passes/Cargo.toml
+++ b/src/librustc_ast_passes/Cargo.toml
@@ -10,7 +10,7 @@ path = "lib.rs"
 
 [dependencies]
 itertools = "0.8"
-log = "0.4"
+tracing = "0.1"
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index b424c8afb34..2fe208c3ce6 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -10,7 +10,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
-use log::debug;
+use tracing::debug;
 
 macro_rules! gate_feature_fn {
     ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
diff --git a/src/librustc_ast_pretty/Cargo.toml b/src/librustc_ast_pretty/Cargo.toml
index 6c076d2c5b8..d26205c791d 100644
--- a/src/librustc_ast_pretty/Cargo.toml
+++ b/src/librustc_ast_pretty/Cargo.toml
@@ -10,7 +10,7 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-log = "0.4"
+tracing = "0.1"
 rustc_span = { path = "../librustc_span" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc_ast_pretty/pp.rs b/src/librustc_ast_pretty/pp.rs
index 4bb806a923e..ca7f127ced6 100644
--- a/src/librustc_ast_pretty/pp.rs
+++ b/src/librustc_ast_pretty/pp.rs
@@ -132,10 +132,10 @@
 //! methods called `Printer::scan_*`, and the 'PRINT' process is the
 //! method called `Printer::print`.
 
-use log::debug;
 use std::borrow::Cow;
 use std::collections::VecDeque;
 use std::fmt;
+use tracing::debug;
 
 /// How to break. Described in more detail in the module docs.
 #[derive(Clone, Copy, PartialEq)]
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index b0edb1ca41d..4b228629ad7 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -450,7 +450,9 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     fn print_comment(&mut self, cmnt: &comments::Comment) {
         match cmnt.style {
             comments::Mixed => {
-                self.zerobreak();
+                if !self.is_beginning_of_line() {
+                    self.zerobreak();
+                }
                 if let Some((last, lines)) = cmnt.lines.split_last() {
                     self.ibox(0);
 
diff --git a/src/librustc_builtin_macros/Cargo.toml b/src/librustc_builtin_macros/Cargo.toml
index fdb6c359052..c612781153e 100644
--- a/src/librustc_builtin_macros/Cargo.toml
+++ b/src/librustc_builtin_macros/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_parse_format = { path = "../librustc_parse_format" }
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml
index bedefcc30ed..ec4dfabdcc2 100644
--- a/src/librustc_codegen_llvm/Cargo.toml
+++ b/src/librustc_codegen_llvm/Cargo.toml
@@ -15,7 +15,7 @@ bitflags = "1.0"
 flate2 = "1.0"
 libc = "0.2"
 measureme = "0.7.1"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_middle = { path = "../librustc_middle" }
 rustc-demangle = "0.1"
 rustc_attr = { path = "../librustc_attr" }
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index 75b4f2e3ca5..afdc8dc6187 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -172,7 +172,12 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
             }
         }
 
-        if cx.use_dll_storage_attrs && tcx.is_dllimport_foreign_item(instance_def_id) {
+        // MinGW: For backward compatibility we rely on the linker to decide whether it
+        // should use dllimport for functions.
+        if cx.use_dll_storage_attrs
+            && tcx.is_dllimport_foreign_item(instance_def_id)
+            && tcx.sess.target.target.target_env != "gnu"
+        {
             unsafe {
                 llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
             }
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 3e9e5d9c8c1..1288870f55f 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -287,7 +287,7 @@ impl CodegenCx<'ll, 'tcx> {
             // argument validation.
             debug_assert!(
                 !(self.tcx.sess.opts.cg.linker_plugin_lto.enabled()
-                    && self.tcx.sess.target.target.options.is_like_msvc
+                    && self.tcx.sess.target.target.options.is_like_windows
                     && self.tcx.sess.opts.cg.prefer_dynamic)
             );
 
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 33a3cdbfa9b..26707fdf839 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -217,7 +217,16 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
         // attributes in LLVM IR as well as native dependencies (in C these
         // correspond to `__declspec(dllimport)`).
         //
-        // Whenever a dynamic library is built by MSVC it must have its public
+        // LD (BFD) in MinGW mode can often correctly guess `dllexport` but
+        // relying on that can result in issues like #50176.
+        // LLD won't support that and expects symbols with proper attributes.
+        // Because of that we make MinGW target emit dllexport just like MSVC.
+        // When it comes to dllimport we use it for constants but for functions
+        // rely on the linker to do the right thing. Opposed to dllexport this
+        // task is easy for them (both LD and LLD) and allows us to easily use
+        // symbols from static libraries in shared libraries.
+        //
+        // Whenever a dynamic library is built on Windows it must have its public
         // interface specified by functions tagged with `dllexport` or otherwise
         // they're not available to be linked against. This poses a few problems
         // for the compiler, some of which are somewhat fundamental, but we use
@@ -254,8 +263,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
         // this effect) by marking very little as `dllimport` and praying the
         // linker will take care of everything. Fixing this problem will likely
         // require adding a few attributes to Rust itself (feature gated at the
-        // start) and then strongly recommending static linkage on MSVC!
-        let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc;
+        // start) and then strongly recommending static linkage on Windows!
+        let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_windows;
 
         let check_overflow = tcx.sess.overflow_checks();
 
diff --git a/src/librustc_codegen_llvm/coverageinfo/mapgen.rs b/src/librustc_codegen_llvm/coverageinfo/mapgen.rs
index 7f48b1d864c..4d9747a43f2 100644
--- a/src/librustc_codegen_llvm/coverageinfo/mapgen.rs
+++ b/src/librustc_codegen_llvm/coverageinfo/mapgen.rs
@@ -1,23 +1,15 @@
-use crate::llvm;
-
 use crate::common::CodegenCx;
 use crate::coverageinfo;
+use crate::llvm;
 
+use llvm::coverageinfo::CounterMappingRegion;
 use log::debug;
-use rustc_codegen_ssa::coverageinfo::map::*;
-use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, MiscMethods};
+use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression, Region};
+use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_llvm::RustString;
-use rustc_middle::ty::Instance;
-use rustc_middle::{bug, mir};
 
-use std::collections::BTreeMap;
 use std::ffi::CString;
-use std::path::PathBuf;
-
-// FIXME(richkadel): Complete all variations of generating and exporting the coverage map to LLVM.
-// The current implementation is an initial foundation with basic capabilities (Counters, but not
-// CounterExpressions, etc.).
 
 /// Generates and exports the Coverage Map.
 ///
@@ -32,174 +24,123 @@ use std::path::PathBuf;
 /// undocumented details in Clang's implementation (that may or may not be important) were also
 /// replicated for Rust's Coverage Map.
 pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
-    let mut coverage_writer = CoverageMappingWriter::new(cx);
-
     let function_coverage_map = cx.coverage_context().take_function_coverage_map();
+    if function_coverage_map.is_empty() {
+        // This module has no functions with coverage instrumentation
+        return;
+    }
+
+    let mut mapgen = CoverageMapGenerator::new();
 
     // Encode coverage mappings and generate function records
     let mut function_records = Vec::<&'ll llvm::Value>::new();
     let coverage_mappings_buffer = llvm::build_byte_buffer(|coverage_mappings_buffer| {
         for (instance, function_coverage) in function_coverage_map.into_iter() {
-            if let Some(function_record) = coverage_writer.write_function_mappings_and_record(
-                instance,
-                function_coverage,
-                coverage_mappings_buffer,
-            ) {
-                function_records.push(function_record);
-            }
+            debug!("Generate coverage map for: {:?}", instance);
+
+            let mangled_function_name = cx.tcx.symbol_name(instance).to_string();
+            let function_source_hash = function_coverage.source_hash();
+            let (expressions, counter_regions) =
+                function_coverage.get_expressions_and_counter_regions();
+
+            let old_len = coverage_mappings_buffer.len();
+            mapgen.write_coverage_mappings(expressions, counter_regions, coverage_mappings_buffer);
+            let mapping_data_size = coverage_mappings_buffer.len() - old_len;
+            debug_assert!(
+                mapping_data_size > 0,
+                "Every `FunctionCoverage` should have at least one counter"
+            );
+
+            let function_record = mapgen.make_function_record(
+                cx,
+                mangled_function_name,
+                function_source_hash,
+                mapping_data_size,
+            );
+            function_records.push(function_record);
         }
     });
 
-    // Encode all filenames covered in this module, ordered by `file_id`
+    // Encode all filenames referenced by counters/expressions in this module
     let filenames_buffer = llvm::build_byte_buffer(|filenames_buffer| {
-        coverageinfo::write_filenames_section_to_buffer(
-            &coverage_writer.filenames,
-            filenames_buffer,
-        );
+        coverageinfo::write_filenames_section_to_buffer(&mapgen.filenames, filenames_buffer);
     });
 
-    if coverage_mappings_buffer.len() > 0 {
-        // Generate the LLVM IR representation of the coverage map and store it in a well-known
-        // global constant.
-        coverage_writer.write_coverage_map(
-            function_records,
-            filenames_buffer,
-            coverage_mappings_buffer,
-        );
-    }
+    // Generate the LLVM IR representation of the coverage map and store it in a well-known global
+    mapgen.save_generated_coverage_map(
+        cx,
+        function_records,
+        filenames_buffer,
+        coverage_mappings_buffer,
+    );
 }
 
-struct CoverageMappingWriter<'a, 'll, 'tcx> {
-    cx: &'a CodegenCx<'ll, 'tcx>,
+struct CoverageMapGenerator {
     filenames: Vec<CString>,
     filename_to_index: FxHashMap<CString, u32>,
 }
 
-impl<'a, 'll, 'tcx> CoverageMappingWriter<'a, 'll, 'tcx> {
-    fn new(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
-        Self { cx, filenames: Vec::new(), filename_to_index: FxHashMap::<CString, u32>::default() }
+impl CoverageMapGenerator {
+    fn new() -> Self {
+        Self { filenames: Vec::new(), filename_to_index: FxHashMap::default() }
     }
 
-    /// For the given function, get the coverage region data, stream it to the given buffer, and
-    /// then generate and return a new function record.
-    fn write_function_mappings_and_record(
+    /// Using the `expressions` and `counter_regions` collected for the current function, generate
+    /// the `mapping_regions` and `virtual_file_mapping`, and capture any new filenames. Then use
+    /// LLVM APIs to encode the `virtual_file_mapping`, `expressions`, and `mapping_regions` into
+    /// the given `coverage_mappings` byte buffer, compliant with the LLVM Coverage Mapping format.
+    fn write_coverage_mappings(
         &mut self,
-        instance: Instance<'tcx>,
-        mut function_coverage: FunctionCoverage,
+        expressions: Vec<CounterExpression>,
+        counter_regions: impl Iterator<Item = (Counter, &'a Region)>,
         coverage_mappings_buffer: &RustString,
-    ) -> Option<&'ll llvm::Value> {
-        let cx = self.cx;
-        let coverageinfo: &mir::CoverageInfo = cx.tcx.coverageinfo(instance.def_id());
-        debug!(
-            "Generate coverage map for: {:?}, num_counters: {}, num_expressions: {}",
-            instance, coverageinfo.num_counters, coverageinfo.num_expressions
-        );
-        debug_assert!(coverageinfo.num_counters > 0);
-
-        let regions_in_file_order = function_coverage.regions_in_file_order(cx.sess().source_map());
-        if regions_in_file_order.len() == 0 {
-            return None;
+    ) {
+        let mut counter_regions = counter_regions.collect::<Vec<_>>();
+        if counter_regions.is_empty() {
+            return;
         }
 
-        // Stream the coverage mapping regions for the function (`instance`) to the buffer, and
-        // compute the data byte size used.
-        let old_len = coverage_mappings_buffer.len();
-        self.regions_to_mappings(regions_in_file_order, coverage_mappings_buffer);
-        let mapping_data_size = coverage_mappings_buffer.len() - old_len;
-        debug_assert!(mapping_data_size > 0);
-
-        let mangled_function_name = cx.tcx.symbol_name(instance).to_string();
-        let name_ref = coverageinfo::compute_hash(&mangled_function_name);
-        let function_source_hash = function_coverage.source_hash();
-
-        // Generate and return the function record
-        let name_ref_val = cx.const_u64(name_ref);
-        let mapping_data_size_val = cx.const_u32(mapping_data_size as u32);
-        let func_hash_val = cx.const_u64(function_source_hash);
-        Some(cx.const_struct(
-            &[name_ref_val, mapping_data_size_val, func_hash_val],
-            /*packed=*/ true,
-        ))
-    }
-
-    /// For each coverage region, extract its coverage data from the earlier coverage analysis.
-    /// Use LLVM APIs to convert the data into buffered bytes compliant with the LLVM Coverage
-    /// Mapping format.
-    fn regions_to_mappings(
-        &mut self,
-        regions_in_file_order: BTreeMap<PathBuf, BTreeMap<CoverageLoc, (usize, CoverageKind)>>,
-        coverage_mappings_buffer: &RustString,
-    ) {
         let mut virtual_file_mapping = Vec::new();
-        let mut mapping_regions = coverageinfo::SmallVectorCounterMappingRegion::new();
-        let mut expressions = coverageinfo::SmallVectorCounterExpression::new();
-
-        for (file_id, (file_path, file_coverage_regions)) in
-            regions_in_file_order.into_iter().enumerate()
-        {
-            let file_id = file_id as u32;
-            let filename = CString::new(file_path.to_string_lossy().to_string())
-                .expect("null error converting filename to C string");
-            debug!("  file_id: {} = '{:?}'", file_id, filename);
-            let filenames_index = match self.filename_to_index.get(&filename) {
-                Some(index) => *index,
-                None => {
-                    let index = self.filenames.len() as u32;
-                    self.filenames.push(filename.clone());
-                    self.filename_to_index.insert(filename, index);
-                    index
+        let mut mapping_regions = Vec::new();
+        let mut current_file_path = None;
+        let mut current_file_id = 0;
+
+        // Convert the list of (Counter, Region) pairs to an array of `CounterMappingRegion`, sorted
+        // by filename and position. Capture any new files to compute the `CounterMappingRegion`s
+        // `file_id` (indexing files referenced by the current function), and construct the
+        // function-specific `virtual_file_mapping` from `file_id` to its index in the module's
+        // `filenames` array.
+        counter_regions.sort_unstable_by_key(|(_counter, region)| *region);
+        for (counter, region) in counter_regions {
+            let (file_path, start_line, start_col, end_line, end_col) = region.file_start_and_end();
+            let same_file = current_file_path.as_ref().map_or(false, |p| p == file_path);
+            if !same_file {
+                if current_file_path.is_some() {
+                    current_file_id += 1;
                 }
-            };
-            virtual_file_mapping.push(filenames_index);
-
-            let mut mapping_indexes = vec![0 as u32; file_coverage_regions.len()];
-            for (mapping_index, (region_id, _)) in file_coverage_regions.values().enumerate() {
-                mapping_indexes[*region_id] = mapping_index as u32;
-            }
-
-            for (region_loc, (region_id, region_kind)) in file_coverage_regions.into_iter() {
-                let mapping_index = mapping_indexes[region_id];
-                match region_kind {
-                    CoverageKind::Counter => {
-                        debug!(
-                            "  Counter {}, file_id: {}, region_loc: {}",
-                            mapping_index, file_id, region_loc
-                        );
-                        mapping_regions.push_from(
-                            mapping_index,
-                            file_id,
-                            region_loc.start_line,
-                            region_loc.start_col,
-                            region_loc.end_line,
-                            region_loc.end_col,
-                        );
-                    }
-                    CoverageKind::CounterExpression(lhs, op, rhs) => {
-                        debug!(
-                            "  CounterExpression {} = {} {:?} {}, file_id: {}, region_loc: {:?}",
-                            mapping_index, lhs, op, rhs, file_id, region_loc,
-                        );
-                        mapping_regions.push_from(
-                            mapping_index,
-                            file_id,
-                            region_loc.start_line,
-                            region_loc.start_col,
-                            region_loc.end_line,
-                            region_loc.end_col,
-                        );
-                        expressions.push_from(op, lhs, rhs);
-                    }
-                    CoverageKind::Unreachable => {
-                        debug!(
-                            "  Unreachable region, file_id: {}, region_loc: {:?}",
-                            file_id, region_loc,
-                        );
-                        bug!("Unreachable region not expected and not yet handled!")
-                        // FIXME(richkadel): implement and call
-                        //   mapping_regions.push_from(...) for unreachable regions
+                current_file_path = Some(file_path.clone());
+                let filename = CString::new(file_path.to_string_lossy().to_string())
+                    .expect("null error converting filename to C string");
+                debug!("  file_id: {} = '{:?}'", current_file_id, filename);
+                let filenames_index = match self.filename_to_index.get(&filename) {
+                    Some(index) => *index,
+                    None => {
+                        let index = self.filenames.len() as u32;
+                        self.filenames.push(filename.clone());
+                        self.filename_to_index.insert(filename.clone(), index);
+                        index
                     }
-                }
+                };
+                virtual_file_mapping.push(filenames_index);
             }
+            mapping_regions.push(CounterMappingRegion::code_region(
+                counter,
+                current_file_id,
+                start_line,
+                start_col,
+                end_line,
+                end_col,
+            ));
         }
 
         // Encode and append the current function's coverage mapping data
@@ -211,14 +152,35 @@ impl<'a, 'll, 'tcx> CoverageMappingWriter<'a, 'll, 'tcx> {
         );
     }
 
-    fn write_coverage_map(
+    /// Generate and return the function record `Value`
+    fn make_function_record(
+        &mut self,
+        cx: &CodegenCx<'ll, 'tcx>,
+        mangled_function_name: String,
+        function_source_hash: u64,
+        mapping_data_size: usize,
+    ) -> &'ll llvm::Value {
+        let name_ref = coverageinfo::compute_hash(&mangled_function_name);
+        let name_ref_val = cx.const_u64(name_ref);
+        let mapping_data_size_val = cx.const_u32(mapping_data_size as u32);
+        let func_hash_val = cx.const_u64(function_source_hash);
+        cx.const_struct(
+            &[name_ref_val, mapping_data_size_val, func_hash_val],
+            /*packed=*/ true,
+        )
+    }
+
+    /// Combine the filenames and coverage mappings buffers, construct coverage map header and the
+    /// array of function records, and combine everything into the complete coverage map. Save the
+    /// coverage map data into the LLVM IR as a static global using a specific, well-known section
+    /// and name.
+    fn save_generated_coverage_map(
         self,
+        cx: &CodegenCx<'ll, 'tcx>,
         function_records: Vec<&'ll llvm::Value>,
         filenames_buffer: Vec<u8>,
         mut coverage_mappings_buffer: Vec<u8>,
     ) {
-        let cx = self.cx;
-
         // Concatenate the encoded filenames and encoded coverage mappings, and add additional zero
         // bytes as-needed to ensure 8-byte alignment.
         let mut coverage_size = coverage_mappings_buffer.len();
diff --git a/src/librustc_codegen_llvm/coverageinfo/mod.rs b/src/librustc_codegen_llvm/coverageinfo/mod.rs
index 76894bcd6c1..9d2090eae8f 100644
--- a/src/librustc_codegen_llvm/coverageinfo/mod.rs
+++ b/src/librustc_codegen_llvm/coverageinfo/mod.rs
@@ -4,8 +4,9 @@ use crate::builder::Builder;
 use crate::common::CodegenCx;
 
 use libc::c_uint;
+use llvm::coverageinfo::CounterMappingRegion;
 use log::debug;
-use rustc_codegen_ssa::coverageinfo::map::*;
+use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, ExprKind, FunctionCoverage};
 use rustc_codegen_ssa::traits::{
     BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, StaticMethods,
 };
@@ -23,7 +24,7 @@ const COVMAP_VAR_ALIGN_BYTES: usize = 8;
 /// A context object for maintaining all state needed by the coverageinfo module.
 pub struct CrateCoverageContext<'tcx> {
     // Coverage region data for each instrumented function identified by DefId.
-    pub(crate) function_coverage_map: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverage>>,
+    pub(crate) function_coverage_map: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>>>,
 }
 
 impl<'tcx> CrateCoverageContext<'tcx> {
@@ -31,7 +32,7 @@ impl<'tcx> CrateCoverageContext<'tcx> {
         Self { function_coverage_map: Default::default() }
     }
 
-    pub fn take_function_coverage_map(&self) -> FxHashMap<Instance<'tcx>, FunctionCoverage> {
+    pub fn take_function_coverage_map(&self) -> FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>> {
         self.function_coverage_map.replace(FxHashMap::default())
     }
 }
@@ -47,44 +48,49 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         &mut self,
         instance: Instance<'tcx>,
         function_source_hash: u64,
-        index: u32,
+        id: u32,
         start_byte_pos: u32,
         end_byte_pos: u32,
     ) {
         debug!(
-            "adding counter to coverage_regions: instance={:?}, function_source_hash={}, index={}, byte range {}..{}",
-            instance, function_source_hash, index, start_byte_pos, end_byte_pos,
+            "adding counter to coverage_regions: instance={:?}, function_source_hash={}, id={}, \
+             byte range {}..{}",
+            instance, function_source_hash, id, start_byte_pos, end_byte_pos,
         );
         let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
         coverage_regions
             .entry(instance)
-            .or_insert_with(|| {
-                FunctionCoverage::with_coverageinfo(self.tcx.coverageinfo(instance.def_id()))
-            })
-            .add_counter(function_source_hash, index, start_byte_pos, end_byte_pos);
+            .or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
+            .add_counter(function_source_hash, id, start_byte_pos, end_byte_pos);
     }
 
     fn add_counter_expression_region(
         &mut self,
         instance: Instance<'tcx>,
-        index: u32,
+        id_descending_from_max: u32,
         lhs: u32,
-        op: CounterOp,
+        op: ExprKind,
         rhs: u32,
         start_byte_pos: u32,
         end_byte_pos: u32,
     ) {
         debug!(
-            "adding counter expression to coverage_regions: instance={:?}, index={}, {} {:?} {}, byte range {}..{}",
-            instance, index, lhs, op, rhs, start_byte_pos, end_byte_pos,
+            "adding counter expression to coverage_regions: instance={:?}, id={}, {} {:?} {}, \
+             byte range {}..{}",
+            instance, id_descending_from_max, lhs, op, rhs, start_byte_pos, end_byte_pos,
         );
         let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
         coverage_regions
             .entry(instance)
-            .or_insert_with(|| {
-                FunctionCoverage::with_coverageinfo(self.tcx.coverageinfo(instance.def_id()))
-            })
-            .add_counter_expression(index, lhs, op, rhs, start_byte_pos, end_byte_pos);
+            .or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
+            .add_counter_expression(
+                id_descending_from_max,
+                lhs,
+                op,
+                rhs,
+                start_byte_pos,
+                end_byte_pos,
+            );
     }
 
     fn add_unreachable_region(
@@ -100,108 +106,8 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         let mut coverage_regions = self.coverage_context().function_coverage_map.borrow_mut();
         coverage_regions
             .entry(instance)
-            .or_insert_with(|| {
-                FunctionCoverage::with_coverageinfo(self.tcx.coverageinfo(instance.def_id()))
-            })
-            .add_unreachable(start_byte_pos, end_byte_pos);
-    }
-}
-
-/// This struct wraps an opaque reference to the C++ template instantiation of
-/// `llvm::SmallVector<coverage::CounterExpression>`. Each `coverage::CounterExpression` object is
-/// constructed from primative-typed arguments, and pushed to the `SmallVector`, in the C++
-/// implementation of `LLVMRustCoverageSmallVectorCounterExpressionAdd()` (see
-/// `src/rustllvm/CoverageMappingWrapper.cpp`).
-pub struct SmallVectorCounterExpression<'a> {
-    pub raw: &'a mut llvm::coverageinfo::SmallVectorCounterExpression<'a>,
-}
-
-impl SmallVectorCounterExpression<'a> {
-    pub fn new() -> Self {
-        SmallVectorCounterExpression {
-            raw: unsafe { llvm::LLVMRustCoverageSmallVectorCounterExpressionCreate() },
-        }
-    }
-
-    pub fn as_ptr(&self) -> *const llvm::coverageinfo::SmallVectorCounterExpression<'a> {
-        self.raw
-    }
-
-    pub fn push_from(
-        &mut self,
-        kind: rustc_codegen_ssa::coverageinfo::CounterOp,
-        left_index: u32,
-        right_index: u32,
-    ) {
-        unsafe {
-            llvm::LLVMRustCoverageSmallVectorCounterExpressionAdd(
-                &mut *(self.raw as *mut _),
-                kind,
-                left_index,
-                right_index,
-            )
-        }
-    }
-}
-
-impl Drop for SmallVectorCounterExpression<'a> {
-    fn drop(&mut self) {
-        unsafe {
-            llvm::LLVMRustCoverageSmallVectorCounterExpressionDispose(&mut *(self.raw as *mut _));
-        }
-    }
-}
-
-/// This struct wraps an opaque reference to the C++ template instantiation of
-/// `llvm::SmallVector<coverage::CounterMappingRegion>`. Each `coverage::CounterMappingRegion`
-/// object is constructed from primative-typed arguments, and pushed to the `SmallVector`, in the
-/// C++ implementation of `LLVMRustCoverageSmallVectorCounterMappingRegionAdd()` (see
-/// `src/rustllvm/CoverageMappingWrapper.cpp`).
-pub struct SmallVectorCounterMappingRegion<'a> {
-    pub raw: &'a mut llvm::coverageinfo::SmallVectorCounterMappingRegion<'a>,
-}
-
-impl SmallVectorCounterMappingRegion<'a> {
-    pub fn new() -> Self {
-        SmallVectorCounterMappingRegion {
-            raw: unsafe { llvm::LLVMRustCoverageSmallVectorCounterMappingRegionCreate() },
-        }
-    }
-
-    pub fn as_ptr(&self) -> *const llvm::coverageinfo::SmallVectorCounterMappingRegion<'a> {
-        self.raw
-    }
-
-    pub fn push_from(
-        &mut self,
-        index: u32,
-        file_id: u32,
-        line_start: u32,
-        column_start: u32,
-        line_end: u32,
-        column_end: u32,
-    ) {
-        unsafe {
-            llvm::LLVMRustCoverageSmallVectorCounterMappingRegionAdd(
-                &mut *(self.raw as *mut _),
-                index,
-                file_id,
-                line_start,
-                column_start,
-                line_end,
-                column_end,
-            )
-        }
-    }
-}
-
-impl Drop for SmallVectorCounterMappingRegion<'a> {
-    fn drop(&mut self) {
-        unsafe {
-            llvm::LLVMRustCoverageSmallVectorCounterMappingRegionDispose(
-                &mut *(self.raw as *mut _),
-            );
-        }
+            .or_insert_with(|| FunctionCoverage::new(self.tcx, instance))
+            .add_unreachable_region(start_byte_pos, end_byte_pos);
     }
 }
 
@@ -218,8 +124,8 @@ pub(crate) fn write_filenames_section_to_buffer(filenames: &Vec<CString>, buffer
 
 pub(crate) fn write_mapping_to_buffer(
     virtual_file_mapping: Vec<u32>,
-    expressions: SmallVectorCounterExpression<'_>,
-    mapping_regions: SmallVectorCounterMappingRegion<'_>,
+    expressions: Vec<CounterExpression>,
+    mut mapping_regions: Vec<CounterMappingRegion>,
     buffer: &RustString,
 ) {
     unsafe {
@@ -227,7 +133,9 @@ pub(crate) fn write_mapping_to_buffer(
             virtual_file_mapping.as_ptr(),
             virtual_file_mapping.len() as c_uint,
             expressions.as_ptr(),
-            mapping_regions.as_ptr(),
+            expressions.len() as c_uint,
+            mapping_regions.as_mut_ptr(),
+            mapping_regions.len() as c_uint,
             buffer,
         );
     }
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 11b1c95c58b..728af7b0a8c 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -13,7 +13,7 @@ use rustc_ast::ast;
 use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
 use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
-use rustc_codegen_ssa::coverageinfo::CounterOp;
+use rustc_codegen_ssa::coverageinfo::ExprKind;
 use rustc_codegen_ssa::glue;
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
@@ -90,64 +90,69 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         args: &Vec<Operand<'tcx>>,
         caller_instance: ty::Instance<'tcx>,
     ) -> bool {
+        let mut is_codegen_intrinsic = true;
+        // Set `is_codegen_intrinsic` to `false` to bypass `codegen_intrinsic_call()`.
+
         if self.tcx.sess.opts.debugging_opts.instrument_coverage {
-            // Add the coverage information from the MIR to the Codegen context. Some coverage
-            // intrinsics are used only to pass along the coverage information (returns `false`
-            // for `is_codegen_intrinsic()`), but `count_code_region` is also converted into an
-            // LLVM intrinsic to increment a coverage counter.
-            match intrinsic {
-                sym::count_code_region => {
-                    use coverage::count_code_region_args::*;
-                    self.add_counter_region(
-                        caller_instance,
-                        op_to_u64(&args[FUNCTION_SOURCE_HASH]),
-                        op_to_u32(&args[COUNTER_INDEX]),
-                        op_to_u32(&args[START_BYTE_POS]),
-                        op_to_u32(&args[END_BYTE_POS]),
-                    );
-                    return true; // Also inject the counter increment in the backend
-                }
-                sym::coverage_counter_add | sym::coverage_counter_subtract => {
-                    use coverage::coverage_counter_expression_args::*;
-                    self.add_counter_expression_region(
-                        caller_instance,
-                        op_to_u32(&args[COUNTER_EXPRESSION_INDEX]),
-                        op_to_u32(&args[LEFT_INDEX]),
-                        if intrinsic == sym::coverage_counter_add {
-                            CounterOp::Add
-                        } else {
-                            CounterOp::Subtract
-                        },
-                        op_to_u32(&args[RIGHT_INDEX]),
-                        op_to_u32(&args[START_BYTE_POS]),
-                        op_to_u32(&args[END_BYTE_POS]),
-                    );
-                    return false; // Does not inject backend code
+            // If the intrinsic is from the local MIR, add the coverage information to the Codegen
+            // context, to be encoded into the local crate's coverage map.
+            if caller_instance.def_id().is_local() {
+                // FIXME(richkadel): Make sure to add coverage analysis tests on a crate with
+                // external crate dependencies, where:
+                //   1. Both binary and dependent crates are compiled with `-Zinstrument-coverage`
+                //   2. Only binary is compiled with `-Zinstrument-coverage`
+                //   3. Only dependent crates are compiled with `-Zinstrument-coverage`
+                match intrinsic {
+                    sym::count_code_region => {
+                        use coverage::count_code_region_args::*;
+                        self.add_counter_region(
+                            caller_instance,
+                            op_to_u64(&args[FUNCTION_SOURCE_HASH]),
+                            op_to_u32(&args[COUNTER_ID]),
+                            op_to_u32(&args[START_BYTE_POS]),
+                            op_to_u32(&args[END_BYTE_POS]),
+                        );
+                    }
+                    sym::coverage_counter_add | sym::coverage_counter_subtract => {
+                        use coverage::coverage_counter_expression_args::*;
+                        self.add_counter_expression_region(
+                            caller_instance,
+                            op_to_u32(&args[EXPRESSION_ID]),
+                            op_to_u32(&args[LEFT_ID]),
+                            if intrinsic == sym::coverage_counter_add {
+                                ExprKind::Add
+                            } else {
+                                ExprKind::Subtract
+                            },
+                            op_to_u32(&args[RIGHT_ID]),
+                            op_to_u32(&args[START_BYTE_POS]),
+                            op_to_u32(&args[END_BYTE_POS]),
+                        );
+                    }
+                    sym::coverage_unreachable => {
+                        use coverage::coverage_unreachable_args::*;
+                        self.add_unreachable_region(
+                            caller_instance,
+                            op_to_u32(&args[START_BYTE_POS]),
+                            op_to_u32(&args[END_BYTE_POS]),
+                        );
+                    }
+                    _ => {}
                 }
-                sym::coverage_unreachable => {
-                    use coverage::coverage_unreachable_args::*;
-                    self.add_unreachable_region(
-                        caller_instance,
-                        op_to_u32(&args[START_BYTE_POS]),
-                        op_to_u32(&args[END_BYTE_POS]),
-                    );
-                    return false; // Does not inject backend code
+            }
+
+            // Only the `count_code_region` coverage intrinsic is translated into an actual LLVM
+            // intrinsic call (local or not); otherwise, set `is_codegen_intrinsic` to `false`.
+            match intrinsic {
+                sym::coverage_counter_add
+                | sym::coverage_counter_subtract
+                | sym::coverage_unreachable => {
+                    is_codegen_intrinsic = false;
                 }
                 _ => {}
             }
-        } else {
-            // NOT self.tcx.sess.opts.debugging_opts.instrument_coverage
-            if intrinsic == sym::count_code_region {
-                // An external crate may have been pre-compiled with coverage instrumentation, and
-                // some references from the current crate to the external crate might carry along
-                // the call terminators to coverage intrinsics, like `count_code_region` (for
-                // example, when instantiating a generic function). If the current crate has
-                // `instrument_coverage` disabled, the `count_code_region` call terminators should
-                // be ignored.
-                return false; // Do not inject coverage counters inlined from external crates
-            }
         }
-        true // Unhandled intrinsics should be passed to `codegen_intrinsic_call()`
+        is_codegen_intrinsic
     }
 
     fn codegen_intrinsic_call(
@@ -219,7 +224,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                 let num_counters = self.const_u32(coverageinfo.num_counters);
                 use coverage::count_code_region_args::*;
                 let hash = args[FUNCTION_SOURCE_HASH].immediate();
-                let index = args[COUNTER_INDEX].immediate();
+                let index = args[COUNTER_ID].immediate();
                 debug!(
                     "translating Rust intrinsic `count_code_region()` to LLVM intrinsic: \
                     instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})",
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 9784beaa079..eb7dc827f93 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -1,7 +1,7 @@
 #![allow(non_camel_case_types)]
 #![allow(non_upper_case_globals)]
 
-use super::coverageinfo::{SmallVectorCounterExpression, SmallVectorCounterMappingRegion};
+use rustc_codegen_ssa::coverageinfo::map as coverage_map;
 
 use super::debuginfo::{
     DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
@@ -653,13 +653,152 @@ pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
 pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
 
 pub mod coverageinfo {
-    use super::InvariantOpaque;
+    use super::coverage_map;
 
+    /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L205-L221)
+    #[derive(Copy, Clone, Debug)]
     #[repr(C)]
-    pub struct SmallVectorCounterExpression<'a>(InvariantOpaque<'a>);
+    pub enum RegionKind {
+        /// A CodeRegion associates some code with a counter
+        CodeRegion = 0,
+
+        /// An ExpansionRegion represents a file expansion region that associates
+        /// a source range with the expansion of a virtual source file, such as
+        /// for a macro instantiation or #include file.
+        ExpansionRegion = 1,
+
+        /// A SkippedRegion represents a source range with code that was skipped
+        /// by a preprocessor or similar means.
+        SkippedRegion = 2,
+
+        /// A GapRegion is like a CodeRegion, but its count is only set as the
+        /// line execution count when its the only region in the line.
+        GapRegion = 3,
+    }
 
+    /// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the
+    /// coverage map, in accordance with the
+    /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/llvmorg-8.0.0/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
+    /// The struct composes fields representing the `Counter` type and value(s) (injected counter
+    /// ID, or expression type and operands), the source file (an indirect index into a "filenames
+    /// array", encoded separately), and source location (start and end positions of the represented
+    /// code region).
+    ///
+    /// Aligns with [llvm::coverage::CounterMappingRegion](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L223-L226)
+    /// Important: The Rust struct layout (order and types of fields) must match its C++
+    /// counterpart.
+    #[derive(Copy, Clone, Debug)]
     #[repr(C)]
-    pub struct SmallVectorCounterMappingRegion<'a>(InvariantOpaque<'a>);
+    pub struct CounterMappingRegion {
+        /// The counter type and type-dependent counter data, if any.
+        counter: coverage_map::Counter,
+
+        /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the
+        /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes
+        /// that, in turn, are used to look up the filename for this region.
+        file_id: u32,
+
+        /// If the `RegionKind` is an `ExpansionRegion`, the `expanded_file_id` can be used to find
+        /// the mapping regions created as a result of macro expansion, by checking if their file id
+        /// matches the expanded file id.
+        expanded_file_id: u32,
+
+        /// 1-based starting line of the mapping region.
+        start_line: u32,
+
+        /// 1-based starting column of the mapping region.
+        start_col: u32,
+
+        /// 1-based ending line of the mapping region.
+        end_line: u32,
+
+        /// 1-based ending column of the mapping region. If the high bit is set, the current
+        /// mapping region is a gap area.
+        end_col: u32,
+
+        kind: RegionKind,
+    }
+
+    impl CounterMappingRegion {
+        pub fn code_region(
+            counter: coverage_map::Counter,
+            file_id: u32,
+            start_line: u32,
+            start_col: u32,
+            end_line: u32,
+            end_col: u32,
+        ) -> Self {
+            Self {
+                counter,
+                file_id,
+                expanded_file_id: 0,
+                start_line,
+                start_col,
+                end_line,
+                end_col,
+                kind: RegionKind::CodeRegion,
+            }
+        }
+
+        pub fn expansion_region(
+            file_id: u32,
+            expanded_file_id: u32,
+            start_line: u32,
+            start_col: u32,
+            end_line: u32,
+            end_col: u32,
+        ) -> Self {
+            Self {
+                counter: coverage_map::Counter::zero(),
+                file_id,
+                expanded_file_id,
+                start_line,
+                start_col,
+                end_line,
+                end_col,
+                kind: RegionKind::ExpansionRegion,
+            }
+        }
+
+        pub fn skipped_region(
+            file_id: u32,
+            start_line: u32,
+            start_col: u32,
+            end_line: u32,
+            end_col: u32,
+        ) -> Self {
+            Self {
+                counter: coverage_map::Counter::zero(),
+                file_id,
+                expanded_file_id: 0,
+                start_line,
+                start_col,
+                end_line,
+                end_col,
+                kind: RegionKind::SkippedRegion,
+            }
+        }
+
+        pub fn gap_region(
+            counter: coverage_map::Counter,
+            file_id: u32,
+            start_line: u32,
+            start_col: u32,
+            end_line: u32,
+            end_col: u32,
+        ) -> Self {
+            Self {
+                counter,
+                file_id,
+                expanded_file_id: 0,
+                start_line,
+                start_col,
+                end_line,
+                end_col: ((1 as u32) << 31) | end_col,
+                kind: RegionKind::GapRegion,
+            }
+        }
+    }
 }
 
 pub mod debuginfo {
@@ -1645,33 +1784,6 @@ extern "C" {
         ConstraintsLen: size_t,
     ) -> bool;
 
-    pub fn LLVMRustCoverageSmallVectorCounterExpressionCreate()
-    -> &'a mut SmallVectorCounterExpression<'a>;
-    pub fn LLVMRustCoverageSmallVectorCounterExpressionDispose(
-        Container: &'a mut SmallVectorCounterExpression<'a>,
-    );
-    pub fn LLVMRustCoverageSmallVectorCounterExpressionAdd(
-        Container: &mut SmallVectorCounterExpression<'a>,
-        Kind: rustc_codegen_ssa::coverageinfo::CounterOp,
-        LeftIndex: c_uint,
-        RightIndex: c_uint,
-    );
-
-    pub fn LLVMRustCoverageSmallVectorCounterMappingRegionCreate()
-    -> &'a mut SmallVectorCounterMappingRegion<'a>;
-    pub fn LLVMRustCoverageSmallVectorCounterMappingRegionDispose(
-        Container: &'a mut SmallVectorCounterMappingRegion<'a>,
-    );
-    pub fn LLVMRustCoverageSmallVectorCounterMappingRegionAdd(
-        Container: &mut SmallVectorCounterMappingRegion<'a>,
-        Index: c_uint,
-        FileID: c_uint,
-        LineStart: c_uint,
-        ColumnStart: c_uint,
-        LineEnd: c_uint,
-        ColumnEnd: c_uint,
-    );
-
     #[allow(improper_ctypes)]
     pub fn LLVMRustCoverageWriteFilenamesSectionToBuffer(
         Filenames: *const *const c_char,
@@ -1683,8 +1795,10 @@ extern "C" {
     pub fn LLVMRustCoverageWriteMappingToBuffer(
         VirtualFileMappingIDs: *const c_uint,
         NumVirtualFileMappingIDs: c_uint,
-        Expressions: *const SmallVectorCounterExpression<'_>,
-        MappingRegions: *const SmallVectorCounterMappingRegion<'_>,
+        Expressions: *const coverage_map::CounterExpression,
+        NumExpressions: c_uint,
+        MappingRegions: *mut coverageinfo::CounterMappingRegion,
+        NumMappingRegions: c_uint,
         BufferOut: &RustString,
     );
 
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index e100e0095c9..8fa0de37648 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -14,7 +14,7 @@ bitflags = "1.2.1"
 cc = "1.0.1"
 num_cpus = "1.0"
 memmap = "0.7"
-log = "0.4.5"
+log = { package = "tracing", version = "0.1" }
 libc = "0.2.50"
 jobserver = "0.1.11"
 tempfile = "3.1"
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index d1ae9e37269..f9a782af24c 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -523,8 +523,9 @@ impl<'a> Linker for GccLinker<'a> {
             return;
         }
 
+        let is_windows = self.sess.target.target.options.is_like_windows;
         let mut arg = OsString::new();
-        let path = tmpdir.join("list");
+        let path = tmpdir.join(if is_windows { "list.def" } else { "list" });
 
         debug!("EXPORTED SYMBOLS:");
 
@@ -540,6 +541,21 @@ impl<'a> Linker for GccLinker<'a> {
             if let Err(e) = res {
                 self.sess.fatal(&format!("failed to write lib.def file: {}", e));
             }
+        } else if is_windows {
+            let res: io::Result<()> = try {
+                let mut f = BufWriter::new(File::create(&path)?);
+
+                // .def file similar to MSVC one but without LIBRARY section
+                // because LD doesn't like when it's empty
+                writeln!(f, "EXPORTS")?;
+                for symbol in self.info.exports[&crate_type].iter() {
+                    debug!("  _{}", symbol);
+                    writeln!(f, "  {}", symbol)?;
+                }
+            };
+            if let Err(e) = res {
+                self.sess.fatal(&format!("failed to write list.def file: {}", e));
+            }
         } else {
             // Write an LD version script
             let res: io::Result<()> = try {
@@ -573,7 +589,10 @@ impl<'a> Linker for GccLinker<'a> {
             if !self.is_ld {
                 arg.push("-Wl,")
             }
-            arg.push("--version-script=");
+            // Both LD and LLD accept export list in *.def file form, there are no flags required
+            if !is_windows {
+                arg.push("--version-script=")
+            }
         }
 
         arg.push(&path);
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 23e0b9344ec..b0fae566a5a 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -1846,11 +1846,11 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
     // something is wrong with commandline arg validation.
     assert!(
         !(tcx.sess.opts.cg.linker_plugin_lto.enabled()
-            && tcx.sess.target.target.options.is_like_msvc
+            && tcx.sess.target.target.options.is_like_windows
             && tcx.sess.opts.cg.prefer_dynamic)
     );
 
-    tcx.sess.target.target.options.is_like_msvc &&
+    tcx.sess.target.target.options.is_like_windows &&
         tcx.sess.crate_types().iter().any(|ct| *ct == CrateType::Rlib) &&
     // ThinLTO can't handle this workaround in all cases, so we don't
     // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing
diff --git a/src/librustc_codegen_ssa/coverageinfo/ffi.rs b/src/librustc_codegen_ssa/coverageinfo/ffi.rs
new file mode 100644
index 00000000000..5b04f994994
--- /dev/null
+++ b/src/librustc_codegen_ssa/coverageinfo/ffi.rs
@@ -0,0 +1,67 @@
+use super::map::{CounterValueReference, MappedExpressionIndex};
+
+/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L91)
+#[derive(Copy, Clone, Debug)]
+#[repr(C)]
+enum CounterKind {
+    Zero = 0,
+    CounterValueReference = 1,
+    Expression = 2,
+}
+
+/// A reference to an instance of an abstract "counter" that will yield a value in a coverage
+/// report. Note that `id` has different interpretations, depending on the `kind`:
+///   * For `CounterKind::Zero`, `id` is assumed to be `0`
+///   * For `CounterKind::CounterValueReference`,  `id` matches the `counter_id` of the injected
+///     instrumentation counter (the `index` argument to the LLVM intrinsic
+///     `instrprof.increment()`)
+///   * For `CounterKind::Expression`, `id` is the index into the coverage map's array of
+///     counter expressions.
+/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L98-L99)
+/// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart.
+#[derive(Copy, Clone, Debug)]
+#[repr(C)]
+pub struct Counter {
+    // Important: The layout (order and types of fields) must match its C++ counterpart.
+    kind: CounterKind,
+    id: u32,
+}
+
+impl Counter {
+    pub fn zero() -> Self {
+        Self { kind: CounterKind::Zero, id: 0 }
+    }
+
+    pub fn counter_value_reference(counter_id: CounterValueReference) -> Self {
+        Self { kind: CounterKind::CounterValueReference, id: counter_id.into() }
+    }
+
+    pub fn expression(mapped_expression_index: MappedExpressionIndex) -> Self {
+        Self { kind: CounterKind::Expression, id: mapped_expression_index.into() }
+    }
+}
+
+/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L146)
+#[derive(Copy, Clone, Debug)]
+#[repr(C)]
+pub enum ExprKind {
+    Subtract = 0,
+    Add = 1,
+}
+
+/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147-L148)
+/// Important: The Rust struct layout (order and types of fields) must match its C++
+/// counterpart.
+#[derive(Copy, Clone, Debug)]
+#[repr(C)]
+pub struct CounterExpression {
+    kind: ExprKind,
+    lhs: Counter,
+    rhs: Counter,
+}
+
+impl CounterExpression {
+    pub fn new(lhs: Counter, kind: ExprKind, rhs: Counter) -> Self {
+        Self { kind, lhs, rhs }
+    }
+}
diff --git a/src/librustc_codegen_ssa/coverageinfo/map.rs b/src/librustc_codegen_ssa/coverageinfo/map.rs
index a8ffef8bc5b..72138065a90 100644
--- a/src/librustc_codegen_ssa/coverageinfo/map.rs
+++ b/src/librustc_codegen_ssa/coverageinfo/map.rs
@@ -1,289 +1,364 @@
-use rustc_data_structures::sync::Lrc;
-use rustc_middle::mir;
-use rustc_span::source_map::{Pos, SourceFile, SourceMap};
-use rustc_span::{BytePos, FileName, RealFileName};
+pub use super::ffi::*;
+
+use rustc_index::vec::IndexVec;
+use rustc_middle::ty::Instance;
+use rustc_middle::ty::TyCtxt;
+use rustc_span::source_map::{Pos, SourceMap};
+use rustc_span::{BytePos, FileName, Loc, RealFileName};
 
 use std::cmp::{Ord, Ordering};
-use std::collections::BTreeMap;
 use std::fmt;
 use std::path::PathBuf;
 
-#[derive(Copy, Clone, Debug)]
-#[repr(C)]
-pub enum CounterOp {
-    // Note the order (and therefore the default values) is important. With the attribute
-    // `#[repr(C)]`, this enum matches the layout of the LLVM enum defined for the nested enum,
-    // `llvm::coverage::CounterExpression::ExprKind`, as shown in the following source snippet:
-    // https://github.com/rust-lang/llvm-project/blob/f208b70fbc4dee78067b3c5bd6cb92aa3ba58a1e/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L146
-    Subtract,
-    Add,
-}
-
-#[derive(Copy, Clone, Debug)]
-pub enum CoverageKind {
-    Counter,
-    CounterExpression(u32, CounterOp, u32),
-    Unreachable,
+rustc_index::newtype_index! {
+    pub struct ExpressionOperandId {
+        DEBUG_FORMAT = "ExpressionOperandId({})",
+        MAX = 0xFFFF_FFFF,
+    }
 }
 
-#[derive(Clone, Debug)]
-pub struct CoverageRegion {
-    pub kind: CoverageKind,
-    pub start_byte_pos: u32,
-    pub end_byte_pos: u32,
+rustc_index::newtype_index! {
+    pub struct CounterValueReference {
+        DEBUG_FORMAT = "CounterValueReference({})",
+        MAX = 0xFFFF_FFFF,
+    }
 }
 
-impl CoverageRegion {
-    pub fn source_loc(&self, source_map: &SourceMap) -> Option<(Lrc<SourceFile>, CoverageLoc)> {
-        let (start_file, start_line, start_col) =
-            lookup_file_line_col(source_map, BytePos::from_u32(self.start_byte_pos));
-        let (end_file, end_line, end_col) =
-            lookup_file_line_col(source_map, BytePos::from_u32(self.end_byte_pos));
-        let start_file_path = match &start_file.name {
-            FileName::Real(RealFileName::Named(path)) => path,
-            _ => {
-                bug!("start_file_path should be a RealFileName, but it was: {:?}", start_file.name)
-            }
-        };
-        let end_file_path = match &end_file.name {
-            FileName::Real(RealFileName::Named(path)) => path,
-            _ => bug!("end_file_path should be a RealFileName, but it was: {:?}", end_file.name),
-        };
-        if start_file_path == end_file_path {
-            Some((start_file, CoverageLoc { start_line, start_col, end_line, end_col }))
-        } else {
-            None
-            // FIXME(richkadel): There seems to be a problem computing the file location in
-            // some cases. I need to investigate this more. When I generate and show coverage
-            // for the example binary in the crates.io crate `json5format`, I had a couple of
-            // notable problems:
-            //
-            //   1. I saw a lot of coverage spans in `llvm-cov show` highlighting regions in
-            //      various comments (not corresponding to rustdoc code), indicating a possible
-            //      problem with the byte_pos-to-source-map implementation.
-            //
-            //   2. And (perhaps not related) when I build the aforementioned example binary with:
-            //      `RUST_FLAGS="-Zinstrument-coverage" cargo build --example formatjson5`
-            //      and then run that binary with
-            //      `LLVM_PROFILE_FILE="formatjson5.profraw" ./target/debug/examples/formatjson5 \
-            //      some.json5` for some reason the binary generates *TWO* `.profraw` files. One
-            //      named `default.profraw` and the other named `formatjson5.profraw` (the expected
-            //      name, in this case).
-            //
-            // If the byte range conversion is wrong, fix it. But if it
-            // is right, then it is possible for the start and end to be in different files.
-            // Can I do something other than ignore coverages that span multiple files?
-            //
-            // If I can resolve this, remove the "Option<>" result type wrapper
-            // `regions_in_file_order()` accordingly.
-        }
+rustc_index::newtype_index! {
+    pub struct InjectedExpressionIndex {
+        DEBUG_FORMAT = "InjectedExpressionIndex({})",
+        MAX = 0xFFFF_FFFF,
     }
 }
 
-impl Default for CoverageRegion {
-    fn default() -> Self {
-        Self {
-            // The default kind (Unreachable) is a placeholder that will be overwritten before
-            // backend codegen.
-            kind: CoverageKind::Unreachable,
-            start_byte_pos: 0,
-            end_byte_pos: 0,
-        }
+rustc_index::newtype_index! {
+    pub struct MappedExpressionIndex {
+        DEBUG_FORMAT = "MappedExpressionIndex({})",
+        MAX = 0xFFFF_FFFF,
     }
 }
 
-/// A source code region used with coverage information.
-#[derive(Debug, Eq, PartialEq)]
-pub struct CoverageLoc {
-    /// The (1-based) line number of the region start.
-    pub start_line: u32,
-    /// The (1-based) column number of the region start.
-    pub start_col: u32,
-    /// The (1-based) line number of the region end.
-    pub end_line: u32,
-    /// The (1-based) column number of the region end.
-    pub end_col: u32,
+#[derive(Clone, Debug)]
+pub struct Region {
+    start: Loc,
+    end: Loc,
 }
 
-impl Ord for CoverageLoc {
+impl Ord for Region {
     fn cmp(&self, other: &Self) -> Ordering {
-        (self.start_line, &self.start_col, &self.end_line, &self.end_col).cmp(&(
-            other.start_line,
-            &other.start_col,
-            &other.end_line,
-            &other.end_col,
-        ))
+        (&self.start.file.name, &self.start.line, &self.start.col, &self.end.line, &self.end.col)
+            .cmp(&(
+                &other.start.file.name,
+                &other.start.line,
+                &other.start.col,
+                &other.end.line,
+                &other.end.col,
+            ))
     }
 }
 
-impl PartialOrd for CoverageLoc {
+impl PartialOrd for Region {
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         Some(self.cmp(other))
     }
 }
 
-impl fmt::Display for CoverageLoc {
+impl PartialEq for Region {
+    fn eq(&self, other: &Self) -> bool {
+        self.start.file.name == other.start.file.name
+            && self.start.line == other.start.line
+            && self.start.col == other.start.col
+            && self.end.line == other.end.line
+            && self.end.col == other.end.col
+    }
+}
+
+impl Eq for Region {}
+
+impl fmt::Display for Region {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Customize debug format, and repeat the file name, so generated location strings are
-        // "clickable" in many IDEs.
-        write!(f, "{}:{} - {}:{}", self.start_line, self.start_col, self.end_line, self.end_col)
+        let (file_path, start_line, start_col, end_line, end_col) = self.file_start_and_end();
+        write!(f, "{:?}:{}:{} - {}:{}", file_path, start_line, start_col, end_line, end_col)
     }
 }
 
-fn lookup_file_line_col(source_map: &SourceMap, byte_pos: BytePos) -> (Lrc<SourceFile>, u32, u32) {
-    let found = source_map
-        .lookup_line(byte_pos)
-        .expect("should find coverage region byte position in source");
-    let file = found.sf;
-    let line_pos = file.line_begin_pos(byte_pos);
+impl Region {
+    pub fn new(source_map: &SourceMap, start_byte_pos: u32, end_byte_pos: u32) -> Self {
+        let start = source_map.lookup_char_pos(BytePos::from_u32(start_byte_pos));
+        let end = source_map.lookup_char_pos(BytePos::from_u32(end_byte_pos));
+        assert_eq!(
+            start.file.name, end.file.name,
+            "Region start ({} -> {:?}) and end ({} -> {:?}) don't come from the same source file!",
+            start_byte_pos, start, end_byte_pos, end
+        );
+        Self { start, end }
+    }
 
-    // Use 1-based indexing.
-    let line = (found.line + 1) as u32;
-    let col = (byte_pos - line_pos).to_u32() + 1;
+    pub fn file_start_and_end<'a>(&'a self) -> (&'a PathBuf, u32, u32, u32, u32) {
+        let start = &self.start;
+        let end = &self.end;
+        match &start.file.name {
+            FileName::Real(RealFileName::Named(path)) => (
+                path,
+                start.line as u32,
+                start.col.to_u32() + 1,
+                end.line as u32,
+                end.col.to_u32() + 1,
+            ),
+            _ => {
+                bug!("start.file.name should be a RealFileName, but it was: {:?}", start.file.name)
+            }
+        }
+    }
+}
 
-    (file, line, col)
+#[derive(Clone, Debug)]
+pub struct ExpressionRegion {
+    lhs: ExpressionOperandId,
+    op: ExprKind,
+    rhs: ExpressionOperandId,
+    region: Region,
 }
 
+// FIXME(richkadel): There seems to be a problem computing the file location in
+// some cases. I need to investigate this more. When I generate and show coverage
+// for the example binary in the crates.io crate `json5format`, I had a couple of
+// notable problems:
+//
+//   1. I saw a lot of coverage spans in `llvm-cov show` highlighting regions in
+//      various comments (not corresponding to rustdoc code), indicating a possible
+//      problem with the byte_pos-to-source-map implementation.
+//
+//   2. And (perhaps not related) when I build the aforementioned example binary with:
+//      `RUST_FLAGS="-Zinstrument-coverage" cargo build --example formatjson5`
+//      and then run that binary with
+//      `LLVM_PROFILE_FILE="formatjson5.profraw" ./target/debug/examples/formatjson5 \
+//      some.json5` for some reason the binary generates *TWO* `.profraw` files. One
+//      named `default.profraw` and the other named `formatjson5.profraw` (the expected
+//      name, in this case).
+//
+//   3. I think that if I eliminate regions within a function, their region_ids,
+//      referenced in expressions, will be wrong? I think the ids are implied by their
+//      array position in the final coverage map output (IIRC).
+//
+//   4. I suspect a problem (if not the only problem) is the SourceMap is wrong for some
+//      region start/end byte positions. Just like I couldn't get the function hash at
+//      intrinsic codegen time for external crate functions, I think the SourceMap I
+//      have here only applies to the local crate, and I know I have coverages that
+//      reference external crates.
+//
+//          I still don't know if I fixed the hash problem correctly. If external crates
+//          implement the function, can't I use the coverage counters already compiled
+//          into those external crates? (Maybe not for generics and/or maybe not for
+//          macros... not sure. But I need to understand this better.)
+//
+// If the byte range conversion is wrong, fix it. But if it
+// is right, then it is possible for the start and end to be in different files.
+// Can I do something other than ignore coverages that span multiple files?
+//
+// If I can resolve this, remove the "Option<>" result type wrapper
+// `regions_in_file_order()` accordingly.
+
 /// Collects all of the coverage regions associated with (a) injected counters, (b) counter
 /// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero),
-/// for a given Function. Counters and counter expressions are indexed because they can be operands
-/// in an expression. This struct also stores the `function_source_hash`, computed during
-/// instrumentation and forwarded with counters.
+/// for a given Function. Counters and counter expressions have non-overlapping `id`s because they
+/// can both be operands in an expression. This struct also stores the `function_source_hash`,
+/// computed during instrumentation, and forwarded with counters.
 ///
-/// Note, it's important to distinguish the `unreachable` region type from what LLVM's refers to as
-/// a "gap region" (or "gap area"). A gap region is a code region within a counted region (either
-/// counter or expression), but the line or lines in the gap region are not executable (such as
-/// lines with only whitespace or comments). According to LLVM Code Coverage Mapping documentation,
-/// "A count for a gap area is only used as the line execution count if there are no other regions
-/// on a line."
-pub struct FunctionCoverage {
+/// Note, it may be important to understand LLVM's definitions of `unreachable` regions versus "gap
+/// regions" (or "gap areas"). A gap region is a code region within a counted region (either counter
+/// or expression), but the line or lines in the gap region are not executable (such as lines with
+/// only whitespace or comments). According to LLVM Code Coverage Mapping documentation, "A count
+/// for a gap area is only used as the line execution count if there are no other regions on a
+/// line."
+pub struct FunctionCoverage<'a> {
+    source_map: &'a SourceMap,
     source_hash: u64,
-    counters: Vec<CoverageRegion>,
-    expressions: Vec<CoverageRegion>,
-    unreachable: Vec<CoverageRegion>,
-    translated: bool,
+    counters: IndexVec<CounterValueReference, Option<Region>>,
+    expressions: IndexVec<InjectedExpressionIndex, Option<ExpressionRegion>>,
+    unreachable_regions: Vec<Region>,
 }
 
-impl FunctionCoverage {
-    pub fn with_coverageinfo<'tcx>(coverageinfo: &'tcx mir::CoverageInfo) -> Self {
+impl<'a> FunctionCoverage<'a> {
+    pub fn new<'tcx: 'a>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self {
+        let coverageinfo = tcx.coverageinfo(instance.def_id());
         Self {
+            source_map: tcx.sess.source_map(),
             source_hash: 0, // will be set with the first `add_counter()`
-            counters: vec![CoverageRegion::default(); coverageinfo.num_counters as usize],
-            expressions: vec![CoverageRegion::default(); coverageinfo.num_expressions as usize],
-            unreachable: Vec::new(),
-            translated: false,
+            counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize),
+            expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize),
+            unreachable_regions: Vec::new(),
         }
     }
 
-    /// Adds a code region to be counted by an injected counter intrinsic. Return a counter ID
-    /// for the call.
+    /// Adds a code region to be counted by an injected counter intrinsic.
+    /// The source_hash (computed during coverage instrumentation) should also be provided, and
+    /// should be the same for all counters in a given function.
     pub fn add_counter(
         &mut self,
         source_hash: u64,
-        index: u32,
+        id: u32,
         start_byte_pos: u32,
         end_byte_pos: u32,
     ) {
-        self.source_hash = source_hash;
-        self.counters[index as usize] =
-            CoverageRegion { kind: CoverageKind::Counter, start_byte_pos, end_byte_pos };
+        if self.source_hash == 0 {
+            self.source_hash = source_hash;
+        } else {
+            debug_assert_eq!(source_hash, self.source_hash);
+        }
+        self.counters[CounterValueReference::from(id)]
+            .replace(Region::new(self.source_map, start_byte_pos, end_byte_pos))
+            .expect_none("add_counter called with duplicate `id`");
     }
 
+    /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
+    /// expressions. Expression IDs start from `u32::MAX` and go down, so the range of expression
+    /// IDs will not overlap with the range of counter IDs. Counters and expressions can be added in
+    /// any order, and expressions can still be assigned contiguous (though descending) IDs, without
+    /// knowing what the last counter ID will be.
+    ///
+    /// When storing the expression data in the `expressions` vector in the `FunctionCoverage`
+    /// struct, its vector index is computed, from the given expression ID, by subtracting from
+    /// `u32::MAX`.
+    ///
+    /// Since the expression operands (`lhs` and `rhs`) can reference either counters or
+    /// expressions, an operand that references an expression also uses its original ID, descending
+    /// from `u32::MAX`. Theses operands are translated only during code generation, after all
+    /// counters and expressions have been added.
     pub fn add_counter_expression(
         &mut self,
-        translated_index: u32,
+        id_descending_from_max: u32,
         lhs: u32,
-        op: CounterOp,
+        op: ExprKind,
         rhs: u32,
         start_byte_pos: u32,
         end_byte_pos: u32,
     ) {
-        let index = u32::MAX - translated_index;
-        // Counter expressions start with "translated indexes", descending from `u32::MAX`, so
-        // the range of expression indexes is disjoint from the range of counter indexes. This way,
-        // both counters and expressions can be operands in other expressions.
-        //
-        // Once all counters have been added, the final "region index" for an expression is
-        // `counters.len() + expression_index` (where `expression_index` is its index in
-        // `self.expressions`), and the expression operands (`lhs` and `rhs`) can be converted to
-        // final "region index" references by the same conversion, after subtracting from
-        // `u32::MAX`.
-        self.expressions[index as usize] = CoverageRegion {
-            kind: CoverageKind::CounterExpression(lhs, op, rhs),
-            start_byte_pos,
-            end_byte_pos,
-        };
+        let expression_id = ExpressionOperandId::from(id_descending_from_max);
+        let lhs = ExpressionOperandId::from(lhs);
+        let rhs = ExpressionOperandId::from(rhs);
+
+        let expression_index = self.expression_index(expression_id);
+        self.expressions[expression_index]
+            .replace(ExpressionRegion {
+                lhs,
+                op,
+                rhs,
+                region: Region::new(self.source_map, start_byte_pos, end_byte_pos),
+            })
+            .expect_none("add_counter_expression called with duplicate `id_descending_from_max`");
     }
 
-    pub fn add_unreachable(&mut self, start_byte_pos: u32, end_byte_pos: u32) {
-        self.unreachable.push(CoverageRegion {
-            kind: CoverageKind::Unreachable,
-            start_byte_pos,
-            end_byte_pos,
-        });
+    /// Add a region that will be marked as "unreachable", with a constant "zero counter".
+    pub fn add_unreachable_region(&mut self, start_byte_pos: u32, end_byte_pos: u32) {
+        self.unreachable_regions.push(Region::new(self.source_map, start_byte_pos, end_byte_pos));
     }
 
+    /// Return the source hash, generated from the HIR node structure, and used to indicate whether
+    /// or not the source code structure changed between different compilations.
     pub fn source_hash(&self) -> u64 {
         self.source_hash
     }
 
-    fn regions(&'a mut self) -> impl Iterator<Item = &'a CoverageRegion> {
+    /// Generate an array of CounterExpressions, and an iterator over all `Counter`s and their
+    /// associated `Regions` (from which the LLVM-specific `CoverageMapGenerator` will create
+    /// `CounterMappingRegion`s.
+    pub fn get_expressions_and_counter_regions(
+        &'a self,
+    ) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'a Region)>) {
         assert!(self.source_hash != 0);
-        self.ensure_expressions_translated();
-        self.counters.iter().chain(self.expressions.iter().chain(self.unreachable.iter()))
+
+        let counter_regions = self.counter_regions();
+        let (counter_expressions, expression_regions) = self.expressions_with_regions();
+        let unreachable_regions = self.unreachable_regions();
+
+        let counter_regions =
+            counter_regions.chain(expression_regions.into_iter().chain(unreachable_regions));
+        (counter_expressions, counter_regions)
     }
 
-    pub fn regions_in_file_order(
-        &'a mut self,
-        source_map: &SourceMap,
-    ) -> BTreeMap<PathBuf, BTreeMap<CoverageLoc, (usize, CoverageKind)>> {
-        let mut regions_in_file_order = BTreeMap::new();
-        for (region_id, region) in self.regions().enumerate() {
-            if let Some((source_file, region_loc)) = region.source_loc(source_map) {
-                // FIXME(richkadel): `region.source_loc()` sometimes fails with two different
-                // filenames for the start and end byte position. This seems wrong, but for
-                // now, if encountered, the region is skipped. If resolved, convert the result
-                // to a non-option value so regions are never skipped.
-                let real_file_path = match &(*source_file).name {
-                    FileName::Real(RealFileName::Named(path)) => path.clone(),
-                    _ => bug!("coverage mapping expected only real, named files"),
-                };
-                let file_coverage_regions =
-                    regions_in_file_order.entry(real_file_path).or_insert_with(|| BTreeMap::new());
-                file_coverage_regions.insert(region_loc, (region_id, region.kind));
-            }
-        }
-        regions_in_file_order
+    fn counter_regions(&'a self) -> impl Iterator<Item = (Counter, &'a Region)> {
+        self.counters.iter_enumerated().filter_map(|(index, entry)| {
+            // Option::map() will return None to filter out missing counters. This may happen
+            // if, for example, a MIR-instrumented counter is removed during an optimization.
+            entry.as_ref().map(|region| {
+                (Counter::counter_value_reference(index as CounterValueReference), region)
+            })
+        })
     }
 
-    /// A one-time translation of expression operands is needed, for any operands referencing
-    /// other CounterExpressions. CounterExpression operands get an initial operand ID that is
-    /// computed by the simple translation: `u32::max - expression_index` because, when created,
-    /// the total number of Counters is not yet known. This function recomputes region indexes
-    /// for expressions so they start with the next region index after the last counter index.
-    fn ensure_expressions_translated(&mut self) {
-        if !self.translated {
-            self.translated = true;
-            let start = self.counters.len() as u32;
-            assert!(
-                (start as u64 + self.expressions.len() as u64) < u32::MAX as u64,
-                "the number of counters and counter expressions in a single function exceeds {}",
-                u32::MAX
-            );
-            for region in self.expressions.iter_mut() {
-                match region.kind {
-                    CoverageKind::CounterExpression(lhs, op, rhs) => {
-                        let lhs = to_region_index(start, lhs);
-                        let rhs = to_region_index(start, rhs);
-                        region.kind = CoverageKind::CounterExpression(lhs, op, rhs);
-                    }
-                    _ => bug!("expressions must only contain CounterExpression kinds"),
+    fn expressions_with_regions(
+        &'a self,
+    ) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'a Region)>) {
+        let mut counter_expressions = Vec::with_capacity(self.expressions.len());
+        let mut expression_regions = Vec::with_capacity(self.expressions.len());
+        let mut new_indexes =
+            IndexVec::from_elem_n(MappedExpressionIndex::from(u32::MAX), self.expressions.len());
+        // Note, the initial value shouldn't matter since every index in use in `self.expressions`
+        // will be set, and after that, `new_indexes` will only be accessed using those same
+        // indexes.
+
+        // Note that an `ExpressionRegion`s at any given index can include other expressions as
+        // operands, but expression operands can only come from the subset of expressions having
+        // `expression_index`s lower than the referencing `ExpressionRegion`. Therefore, it is
+        // reasonable to look up the new index of an expression operand while the `new_indexes`
+        // vector is only complete up to the current `ExpressionIndex`.
+        let id_to_counter =
+            |new_indexes: &IndexVec<InjectedExpressionIndex, MappedExpressionIndex>,
+             id: ExpressionOperandId| {
+                if id.index() < self.counters.len() {
+                    let index = CounterValueReference::from(id.index());
+                    self.counters
+                        .get(index)
+                        .unwrap() // pre-validated
+                        .as_ref()
+                        .map(|_| Counter::counter_value_reference(index))
+                } else {
+                    let index = self.expression_index(id);
+                    self.expressions
+                        .get(index)
+                        .expect("expression id is out of range")
+                        .as_ref()
+                        .map(|_| Counter::expression(new_indexes[index]))
                 }
+            };
+
+        for (original_index, expression_region) in
+            self.expressions.iter_enumerated().filter_map(|(original_index, entry)| {
+                // Option::map() will return None to filter out missing expressions. This may happen
+                // if, for example, a MIR-instrumented expression is removed during an optimization.
+                entry.as_ref().map(|region| (original_index, region))
+            })
+        {
+            let region = &expression_region.region;
+            let ExpressionRegion { lhs, op, rhs, .. } = *expression_region;
+
+            if let Some(Some((lhs_counter, rhs_counter))) =
+                id_to_counter(&new_indexes, lhs).map(|lhs_counter| {
+                    id_to_counter(&new_indexes, rhs).map(|rhs_counter| (lhs_counter, rhs_counter))
+                })
+            {
+                // Both operands exist. `Expression` operands exist in `self.expressions` and have
+                // been assigned a `new_index`.
+                let mapped_expression_index =
+                    MappedExpressionIndex::from(counter_expressions.len());
+                counter_expressions.push(CounterExpression::new(lhs_counter, op, rhs_counter));
+                new_indexes[original_index] = mapped_expression_index;
+                expression_regions.push((Counter::expression(mapped_expression_index), region));
             }
         }
+        (counter_expressions, expression_regions.into_iter())
+    }
+
+    fn unreachable_regions(&'a self) -> impl Iterator<Item = (Counter, &'a Region)> {
+        self.unreachable_regions.iter().map(|region| (Counter::zero(), region))
     }
-}
 
-fn to_region_index(start: u32, index: u32) -> u32 {
-    if index < start { index } else { start + (u32::MAX - index) }
+    fn expression_index(
+        &self,
+        id_descending_from_max: ExpressionOperandId,
+    ) -> InjectedExpressionIndex {
+        debug_assert!(id_descending_from_max.index() >= self.counters.len());
+        InjectedExpressionIndex::from(u32::MAX - u32::from(id_descending_from_max))
+    }
 }
diff --git a/src/librustc_codegen_ssa/coverageinfo/mod.rs b/src/librustc_codegen_ssa/coverageinfo/mod.rs
index 304f8e19da4..1f0ffd289b1 100644
--- a/src/librustc_codegen_ssa/coverageinfo/mod.rs
+++ b/src/librustc_codegen_ssa/coverageinfo/mod.rs
@@ -1,3 +1,4 @@
+pub mod ffi;
 pub mod map;
 
-pub use map::CounterOp;
+pub use map::ExprKind;
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index bdd73c08313..85260d30a3d 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -1,5 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(bool_to_option)]
+#![feature(option_expect_none)]
 #![feature(box_patterns)]
 #![feature(try_blocks)]
 #![feature(in_band_lifetimes)]
@@ -7,6 +8,8 @@
 #![feature(or_patterns)]
 #![feature(trusted_len)]
 #![feature(associated_type_bounds)]
+#![feature(const_fn)] // for rustc_index::newtype_index
+#![feature(const_panic)] // for rustc_index::newtype_index
 #![recursion_limit = "256"]
 
 //! This crate contains codegen code that is used by all codegen backends (LLVM and others).
diff --git a/src/librustc_codegen_ssa/traits/coverageinfo.rs b/src/librustc_codegen_ssa/traits/coverageinfo.rs
index 1b9faa42484..db1d86c974e 100644
--- a/src/librustc_codegen_ssa/traits/coverageinfo.rs
+++ b/src/librustc_codegen_ssa/traits/coverageinfo.rs
@@ -1,5 +1,5 @@
 use super::BackendTypes;
-use crate::coverageinfo::CounterOp;
+use crate::coverageinfo::ExprKind;
 use rustc_middle::ty::Instance;
 
 pub trait CoverageInfoMethods: BackendTypes {
@@ -21,7 +21,7 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
         instance: Instance<'tcx>,
         index: u32,
         lhs: u32,
-        op: CounterOp,
+        op: ExprKind,
         rhs: u32,
         start_byte_pos: u32,
         end_byte_pos: u32,
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 1c2fb90b2d8..811d1e49626 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
 [dependencies]
 ena = "0.14"
 indexmap = "1"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
 lazy_static = "1"
 once_cell = { version = "1", features = ["parking_lot"] }
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 75d65920766..6474a69b216 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -12,8 +12,8 @@ crate-type = ["dylib"]
 [dependencies]
 lazy_static = "1.0"
 libc = "0.2"
-log = "0.4"
-env_logger = { version = "0.7", default-features = false }
+log = { package = "tracing", version = "0.1.18", features = ["release_max_level_info"]  }
+tracing-subscriber = { version = "0.2.10", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 rustc_middle = { path = "../librustc_middle" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index ab4eac9440b..7af640c109e 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -1224,9 +1224,26 @@ pub fn install_ice_hook() {
 }
 
 /// This allows tools to enable rust logging without having to magically match rustc's
-/// log crate version
+/// log crate version.
 pub fn init_rustc_env_logger() {
-    env_logger::init_from_env("RUSTC_LOG");
+    init_env_logger("RUSTC_LOG")
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// log crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
+/// other than `RUSTC_LOG`.
+pub fn init_env_logger(env: &str) {
+    // Don't register a dispatcher if there's no filter to print anything
+    match std::env::var(env) {
+        Err(_) => return,
+        Ok(s) if s.is_empty() => return,
+        Ok(_) => {}
+    }
+    let builder = tracing_subscriber::FmtSubscriber::builder();
+
+    let builder = builder.with_env_filter(tracing_subscriber::EnvFilter::from_env(env));
+
+    builder.init()
 }
 
 pub fn main() -> ! {
diff --git a/src/librustc_error_codes/error_codes/E0720.md b/src/librustc_error_codes/error_codes/E0720.md
index 410aa4f4609..40dfa484d3f 100644
--- a/src/librustc_error_codes/error_codes/E0720.md
+++ b/src/librustc_error_codes/error_codes/E0720.md
@@ -1,11 +1,13 @@
 An `impl Trait` type expands to a recursive type.
 
-An `impl Trait` type must be expandable to a concrete type that contains no
-`impl Trait` types. For example the following example tries to create an
-`impl Trait` type `T` that is equal to `[T, T]`:
+Erroneous code example:
 
 ```compile_fail,E0720
 fn make_recursive_type() -> impl Sized {
     [make_recursive_type(), make_recursive_type()]
 }
 ```
+
+An `impl Trait` type must be expandable to a concrete type that contains no
+`impl Trait` types. For example the previous example tries to create an
+`impl Trait` type `T` that is equal to `[T, T]`.
diff --git a/src/librustc_error_codes/error_codes/E0728.md b/src/librustc_error_codes/error_codes/E0728.md
index 1afbedab0ca..f4968a4f00e 100644
--- a/src/librustc_error_codes/error_codes/E0728.md
+++ b/src/librustc_error_codes/error_codes/E0728.md
@@ -1,6 +1,6 @@
-[`await`] has been used outside [`async`] function or block.
+[`await`] has been used outside [`async`] function or [`async`] block.
 
-Erroneous code examples:
+Erroneous code example:
 
 ```edition2018,compile_fail,E0728
 # use std::pin::Pin;
@@ -33,7 +33,7 @@ fn foo() {
 
 [`await`] is used to suspend the current computation until the given
 future is ready to produce a value. So it is legal only within
-an [`async`] context, like an `async fn` or an `async` block.
+an [`async`] context, like an `async` function or an `async` block.
 
 ```edition2018
 # use std::pin::Pin;
diff --git a/src/librustc_error_codes/error_codes/E0730.md b/src/librustc_error_codes/error_codes/E0730.md
index c2a71ca5669..016b3f38aa3 100644
--- a/src/librustc_error_codes/error_codes/E0730.md
+++ b/src/librustc_error_codes/error_codes/E0730.md
@@ -1,6 +1,6 @@
 An array without a fixed length was pattern-matched.
 
-Example of erroneous code:
+Erroneous code example:
 
 ```compile_fail,E0730
 #![feature(const_generics)]
@@ -14,14 +14,28 @@ fn is_123<const N: usize>(x: [u32; N]) -> bool {
 }
 ```
 
-Ensure that the pattern is consistent with the size of the matched
-array. Additional elements can be matched with `..`:
+To fix this error, you have two solutions:
+ 1. Use an array with a fixed length.
+ 2. Use a slice.
 
+Example with an array with a fixed length:
+
+```
+fn is_123(x: [u32; 3]) -> bool { // We use an array with a fixed size
+    match x {
+        [1, 2, ..] => true, // ok!
+        _ => false
+    }
+}
 ```
-let r = &[1, 2, 3, 4];
-match r {
-    &[a, b, ..] => { // ok!
-        println!("a={}, b={}", a, b);
+
+Example with a slice:
+
+```
+fn is_123(x: &[u32]) -> bool { // We use a slice
+    match x {
+        [1, 2, ..] => true, // ok!
+        _ => false
     }
 }
 ```
diff --git a/src/librustc_error_codes/error_codes/E0733.md b/src/librustc_error_codes/error_codes/E0733.md
index 0bda7a7d682..051b75148e5 100644
--- a/src/librustc_error_codes/error_codes/E0733.md
+++ b/src/librustc_error_codes/error_codes/E0733.md
@@ -1,4 +1,6 @@
-Recursion in an `async fn` requires boxing. For example, this will not compile:
+An [`async`] function used recursion without boxing.
+
+Erroneous code example:
 
 ```edition2018,compile_fail,E0733
 async fn foo(n: usize) {
@@ -8,8 +10,8 @@ async fn foo(n: usize) {
 }
 ```
 
-To achieve async recursion, the `async fn` needs to be desugared
-such that the `Future` is explicit in the return type:
+To perform async recursion, the `async fn` needs to be desugared such that the
+`Future` is explicit in the return type:
 
 ```edition2018,compile_fail,E0720
 use std::future::Future;
@@ -36,5 +38,7 @@ fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
 }
 ```
 
-The `Box<...>` ensures that the result is of known size,
-and the pin is required to keep it in the same place in memory.
+The `Box<...>` ensures that the result is of known size, and the pin is
+required to keep it in the same place in memory.
+
+[`async`]: https://doc.rust-lang.org/std/keyword.async.html
diff --git a/src/librustc_error_codes/error_codes/E0734.md b/src/librustc_error_codes/error_codes/E0734.md
index 7506c8e693e..4b8e89a7060 100644
--- a/src/librustc_error_codes/error_codes/E0734.md
+++ b/src/librustc_error_codes/error_codes/E0734.md
@@ -1,6 +1,6 @@
 A stability attribute has been used outside of the standard library.
 
-Erroneous code examples:
+Erroneous code example:
 
 ```compile_fail,E0734
 #[rustc_deprecated(since = "b", reason = "text")] // invalid
diff --git a/src/librustc_error_codes/error_codes/E0740.md b/src/librustc_error_codes/error_codes/E0740.md
index 37776785189..6240099a99f 100644
--- a/src/librustc_error_codes/error_codes/E0740.md
+++ b/src/librustc_error_codes/error_codes/E0740.md
@@ -1,4 +1,4 @@
-A `union` cannot have fields with destructors.
+A `union` was declared with fields with destructors.
 
 Erroneous code example:
 
@@ -14,3 +14,5 @@ impl Drop for A {
     fn drop(&mut self) { println!("A"); }
 }
 ```
+
+A `union` cannot have fields with destructors.
diff --git a/src/librustc_error_codes/error_codes/E0741.md b/src/librustc_error_codes/error_codes/E0741.md
index 0a8650282a3..91379bfe05c 100644
--- a/src/librustc_error_codes/error_codes/E0741.md
+++ b/src/librustc_error_codes/error_codes/E0741.md
@@ -1,5 +1,6 @@
-Only structural-match types (that is, types that derive `PartialEq` and `Eq`)
-may be used as the types of const generic parameters.
+A non-structural-match type was used as the type of a const generic parameter.
+
+Erroneous code example:
 
 ```compile_fail,E0741
 #![feature(const_generics)]
@@ -9,12 +10,15 @@ struct A;
 struct B<const X: A>; // error!
 ```
 
-To fix this example, we derive `PartialEq` and `Eq`.
+Only structural-match types (that is, types that derive `PartialEq` and `Eq`)
+may be used as the types of const generic parameters.
+
+To fix the previous code example, we derive `PartialEq` and `Eq`:
 
 ```
 #![feature(const_generics)]
 
-#[derive(PartialEq, Eq)]
+#[derive(PartialEq, Eq)] // We derive both traits here.
 struct A;
 
 struct B<const X: A>; // ok!
diff --git a/src/librustc_error_codes/error_codes/E0743.md b/src/librustc_error_codes/error_codes/E0743.md
index 1780fe59cbd..ddd3136df0c 100644
--- a/src/librustc_error_codes/error_codes/E0743.md
+++ b/src/librustc_error_codes/error_codes/E0743.md
@@ -8,10 +8,9 @@ Erroneous code example:
 fn foo2(x: u8, y: &...) {} // error!
 ```
 
-Only foreign functions can use the C-variadic type (`...`).
-In such functions, `...` may only occur non-nested.
-That is, `y: &'a ...` is not allowed.
+Only foreign functions can use the C-variadic type (`...`). In such functions,
+`...` may only occur non-nested. That is, `y: &'a ...` is not allowed.
 
-A C-variadic type is used to give an undefined number
-of parameters to a given function (like `printf` in C).
-The equivalent in Rust would be to use macros directly.
+A C-variadic type is used to give an undefined number of parameters to a given
+function (like `printf` in C). The equivalent in Rust would be to use macros
+directly (like `println!` for example).
diff --git a/src/librustc_error_codes/error_codes/E0744.md b/src/librustc_error_codes/error_codes/E0744.md
index 56b947a8282..14cff3613e0 100644
--- a/src/librustc_error_codes/error_codes/E0744.md
+++ b/src/librustc_error_codes/error_codes/E0744.md
@@ -1,7 +1,6 @@
-Control-flow expressions are not allowed inside a const context.
+A control-flow expression was used inside a const context.
 
-At the moment, `if` and `match`, as well as the looping constructs `for`,
-`while`, and `loop`, are forbidden inside a `const`, `static`, or `const fn`.
+Erroneous code example:
 
 ```compile_fail,E0744
 const _: i32 = {
@@ -13,6 +12,9 @@ const _: i32 = {
 };
 ```
 
+At the moment, `if` and `match`, as well as the looping constructs `for`,
+`while`, and `loop`, are forbidden inside a `const`, `static`, or `const fn`.
+
 This will be allowed at some point in the future, but the implementation is not
 yet complete. See the tracking issue for [conditionals] or [loops] in a const
 context for the current status.
diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml
index 7f72161aff8..d0f04c3fe76 100644
--- a/src/librustc_errors/Cargo.toml
+++ b/src/librustc_errors/Cargo.toml
@@ -10,7 +10,7 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_serialize = { path = "../librustc_serialize" }
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_expand/Cargo.toml b/src/librustc_expand/Cargo.toml
index ef617acfe13..bdf039c36ab 100644
--- a/src/librustc_expand/Cargo.toml
+++ b/src/librustc_expand/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
 
 [dependencies]
 rustc_serialize = { path = "../librustc_serialize" }
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_span = { path = "../librustc_span" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_ast_passes = { path = "../librustc_ast_passes" }
diff --git a/src/librustc_expand/mbe.rs b/src/librustc_expand/mbe.rs
index a728261d711..6f2daaa81c0 100644
--- a/src/librustc_expand/mbe.rs
+++ b/src/librustc_expand/mbe.rs
@@ -9,7 +9,7 @@ crate mod macro_rules;
 crate mod quoted;
 crate mod transcribe;
 
-use rustc_ast::token::{self, Token, TokenKind};
+use rustc_ast::token::{self, NonterminalKind, Token, TokenKind};
 use rustc_ast::tokenstream::DelimSpan;
 
 use rustc_span::symbol::Ident;
@@ -84,7 +84,7 @@ enum TokenTree {
     /// e.g., `$var`
     MetaVar(Span, Ident),
     /// e.g., `$var:expr`. This is only used in the left hand side of MBE macros.
-    MetaVarDecl(Span, Ident /* name to bind */, Ident /* kind of nonterminal */),
+    MetaVarDecl(Span, Ident /* name to bind */, Option<NonterminalKind>),
 }
 
 impl TokenTree {
diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs
index 3c15a81c67f..d2fe7fe10a8 100644
--- a/src/librustc_expand/mbe/macro_parser.rs
+++ b/src/librustc_expand/mbe/macro_parser.rs
@@ -76,15 +76,11 @@ use TokenTreeOrTokenTreeSlice::*;
 
 use crate::mbe::{self, TokenTree};
 
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, DocComment, Nonterminal, Token};
-use rustc_ast_pretty::pprust;
-use rustc_parse::parser::{FollowedByType, Parser, PathStyle};
+use rustc_parse::parser::Parser;
 use rustc_session::parse::ParseSess;
-use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol};
+use rustc_span::symbol::MacroRulesNormalizedIdent;
 
-use rustc_errors::PResult;
-use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
 
 use rustc_data_structures::fx::FxHashMap;
@@ -382,7 +378,7 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
                     n_rec(sess, next_m, res.by_ref(), ret_val)?;
                 }
             }
-            TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => {
+            TokenTree::MetaVarDecl(span, _, None) => {
                 if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
                     return Err((span, "missing fragment specifier".to_string()));
                 }
@@ -565,7 +561,7 @@ fn inner_parse_loop<'root, 'tt>(
                 }
 
                 // We need to match a metavar (but the identifier is invalid)... this is an error
-                TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => {
+                TokenTree::MetaVarDecl(span, _, None) => {
                     if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
                         return Error(span, "missing fragment specifier".to_string());
                     }
@@ -573,10 +569,10 @@ fn inner_parse_loop<'root, 'tt>(
 
                 // We need to match a metavar with a valid ident... call out to the black-box
                 // parser by adding an item to `bb_items`.
-                TokenTree::MetaVarDecl(_, _, id) => {
+                TokenTree::MetaVarDecl(_, _, Some(kind)) => {
                     // Built-in nonterminals never start with these tokens,
                     // so we can eliminate them from consideration.
-                    if may_begin_with(token, id.name) {
+                    if Parser::nonterminal_may_begin_with(kind, token) {
                         bb_items.push(item);
                     }
                 }
@@ -706,7 +702,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
             let nts = bb_items
                 .iter()
                 .map(|item| match item.top_elts.get_tt(item.idx) {
-                    TokenTree::MetaVarDecl(_, bind, name) => format!("{} ('{}')", name, bind),
+                    TokenTree::MetaVarDecl(_, bind, Some(kind)) => format!("{} ('{}')", kind, bind),
                     _ => panic!(),
                 })
                 .collect::<Vec<String>>()
@@ -736,10 +732,17 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
             assert_eq!(bb_items.len(), 1);
 
             let mut item = bb_items.pop().unwrap();
-            if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) {
+            if let TokenTree::MetaVarDecl(span, _, Some(kind)) = item.top_elts.get_tt(item.idx) {
                 let match_cur = item.match_cur;
-                let nt = match parse_nt(parser.to_mut(), span, ident.name) {
-                    Err(()) => return ErrorReported,
+                let nt = match parser.to_mut().parse_nonterminal(kind) {
+                    Err(mut err) => {
+                        err.span_label(
+                            span,
+                            format!("while parsing argument for this `{}` macro fragment", kind),
+                        )
+                        .emit();
+                        return ErrorReported;
+                    }
                     Ok(nt) => nt,
                 };
                 item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt)));
@@ -754,178 +757,3 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
         assert!(!cur_items.is_empty());
     }
 }
-
-/// The token is an identifier, but not `_`.
-/// We prohibit passing `_` to macros expecting `ident` for now.
-fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
-    token.ident().filter(|(ident, _)| ident.name != kw::Underscore)
-}
-
-/// Checks whether a non-terminal may begin with a particular token.
-///
-/// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
-/// token. Be conservative (return true) if not sure.
-fn may_begin_with(token: &Token, name: Symbol) -> bool {
-    /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
-    fn may_be_ident(nt: &token::Nonterminal) -> bool {
-        match *nt {
-            token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_) => false,
-            _ => true,
-        }
-    }
-
-    match name {
-        sym::expr => {
-            token.can_begin_expr()
-            // This exception is here for backwards compatibility.
-            && !token.is_keyword(kw::Let)
-        }
-        sym::ty => token.can_begin_type(),
-        sym::ident => get_macro_ident(token).is_some(),
-        sym::literal => token.can_begin_literal_maybe_minus(),
-        sym::vis => match token.kind {
-            // The follow-set of :vis + "priv" keyword + interpolated
-            token::Comma | token::Ident(..) | token::Interpolated(..) => true,
-            _ => token.can_begin_type(),
-        },
-        sym::block => match token.kind {
-            token::OpenDelim(token::Brace) => true,
-            token::Interpolated(ref nt) => match **nt {
-                token::NtItem(_)
-                | token::NtPat(_)
-                | token::NtTy(_)
-                | token::NtIdent(..)
-                | token::NtMeta(_)
-                | token::NtPath(_)
-                | token::NtVis(_) => false, // none of these may start with '{'.
-                _ => true,
-            },
-            _ => false,
-        },
-        sym::path | sym::meta => match token.kind {
-            token::ModSep | token::Ident(..) => true,
-            token::Interpolated(ref nt) => match **nt {
-                token::NtPath(_) | token::NtMeta(_) => true,
-                _ => may_be_ident(&nt),
-            },
-            _ => false,
-        },
-        sym::pat => match token.kind {
-            token::Ident(..) |               // box, ref, mut, and other identifiers (can stricten)
-            token::OpenDelim(token::Paren) |    // tuple pattern
-            token::OpenDelim(token::Bracket) |  // slice pattern
-            token::BinOp(token::And) |          // reference
-            token::BinOp(token::Minus) |        // negative literal
-            token::AndAnd |                     // double reference
-            token::Literal(..) |                // literal
-            token::DotDot |                     // range pattern (future compat)
-            token::DotDotDot |                  // range pattern (future compat)
-            token::ModSep |                     // path
-            token::Lt |                         // path (UFCS constant)
-            token::BinOp(token::Shl) => true,   // path (double UFCS)
-            token::Interpolated(ref nt) => may_be_ident(nt),
-            _ => false,
-        },
-        sym::lifetime => match token.kind {
-            token::Lifetime(_) => true,
-            token::Interpolated(ref nt) => match **nt {
-                token::NtLifetime(_) | token::NtTT(_) => true,
-                _ => false,
-            },
-            _ => false,
-        },
-        _ => match token.kind {
-            token::CloseDelim(_) => false,
-            _ => true,
-        },
-    }
-}
-
-/// A call to the "black-box" parser to parse some Rust non-terminal.
-///
-/// # Parameters
-///
-/// - `p`: the "black-box" parser to use
-/// - `sp`: the `Span` we want to parse
-/// - `name`: the name of the metavar _matcher_ we want to match (e.g., `tt`, `ident`, `block`,
-///   etc...)
-///
-/// # Returns
-///
-/// The parsed non-terminal.
-fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Result<Nonterminal, ()> {
-    // FIXME(Centril): Consider moving this to `parser.rs` to make
-    // the visibilities of the methods used below `pub(super)` at most.
-    if name == sym::tt {
-        return Ok(token::NtTT(p.parse_token_tree()));
-    }
-    parse_nt_inner(p, sp, name).map_err(|mut err| {
-        err.span_label(sp, format!("while parsing argument for this `{}` macro fragment", name))
-            .emit()
-    })
-}
-
-fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> {
-    // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
-    // needs to have them force-captured here.
-    // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
-    // which requires having captured tokens available. Since we cannot determine
-    // in advance whether or not a proc-macro will be (transitively) invoked,
-    // we always capture tokens for any `Nonterminal` which needs them.
-    Ok(match name {
-        sym::item => match p.collect_tokens(|this| this.parse_item())? {
-            (Some(mut item), tokens) => {
-                // If we captured tokens during parsing (due to outer attributes),
-                // use those.
-                if item.tokens.is_none() {
-                    item.tokens = Some(tokens);
-                }
-                token::NtItem(item)
-            }
-            (None, _) => return Err(p.struct_span_err(p.token.span, "expected an item keyword")),
-        },
-        sym::block => token::NtBlock(p.parse_block()?),
-        sym::stmt => match p.parse_stmt()? {
-            Some(s) => token::NtStmt(s),
-            None => return Err(p.struct_span_err(p.token.span, "expected a statement")),
-        },
-        sym::pat => token::NtPat(p.parse_pat(None)?),
-        sym::expr => {
-            let (mut expr, tokens) = p.collect_tokens(|this| this.parse_expr())?;
-            // If we captured tokens during parsing (due to outer attributes),
-            // use those.
-            if expr.tokens.is_none() {
-                expr.tokens = Some(tokens);
-            }
-            token::NtExpr(expr)
-        }
-        sym::literal => token::NtLiteral(p.parse_literal_maybe_minus()?),
-        sym::ty => token::NtTy(p.parse_ty()?),
-        // this could be handled like a token, since it is one
-        sym::ident => {
-            if let Some((ident, is_raw)) = get_macro_ident(&p.token) {
-                p.bump();
-                token::NtIdent(ident, is_raw)
-            } else {
-                let token_str = pprust::token_to_string(&p.token);
-                let msg = &format!("expected ident, found {}", &token_str);
-                return Err(p.struct_span_err(p.token.span, msg));
-            }
-        }
-        sym::path => token::NtPath(p.parse_path(PathStyle::Type)?),
-        sym::meta => token::NtMeta(P(p.parse_attr_item()?)),
-        sym::vis => token::NtVis(p.parse_visibility(FollowedByType::Yes)?),
-        sym::lifetime => {
-            if p.check_lifetime() {
-                token::NtLifetime(p.expect_lifetime().ident)
-            } else {
-                let token_str = pprust::token_to_string(&p.token);
-                let msg = &format!("expected a lifetime, found `{}`", &token_str);
-                return Err(p.struct_span_err(p.token.span, msg));
-            }
-        }
-        // this is not supposed to happen, since it has been checked
-        // when compiling the macro.
-        _ => p.span_bug(sp, "invalid fragment specifier"),
-    })
-}
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index 36b323df697..74d4023b410 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -9,7 +9,7 @@ use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq};
 use crate::mbe::transcribe::transcribe;
 
 use rustc_ast::ast;
-use rustc_ast::token::{self, NtTT, Token, TokenKind::*};
+use rustc_ast::token::{self, NonterminalKind, NtTT, Token, TokenKind::*};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, TransparencyError};
@@ -21,7 +21,7 @@ use rustc_parse::parser::Parser;
 use rustc_session::parse::ParseSess;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::Transparency;
-use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent};
 use rustc_span::Span;
 
 use log::debug;
@@ -29,10 +29,6 @@ use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 use std::{mem, slice};
 
-const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
-                                        `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
-                                        `literal`, `path`, `meta`, `tt`, `item` and `vis`";
-
 crate struct ParserAnyMacro<'a> {
     parser: Parser<'a>,
 
@@ -403,7 +399,7 @@ pub fn compile_declarative_macro(
     let diag = &sess.span_diagnostic;
     let lhs_nm = Ident::new(sym::lhs, def.span);
     let rhs_nm = Ident::new(sym::rhs, def.span);
-    let tt_spec = Ident::new(sym::tt, def.span);
+    let tt_spec = Some(NonterminalKind::TT);
 
     // Parse the macro_rules! invocation
     let (macro_rules, body) = match &def.kind {
@@ -571,7 +567,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
             TokenTree::Sequence(span, ref seq) => {
                 if seq.separator.is_none()
                     && seq.tts.iter().all(|seq_tt| match *seq_tt {
-                        TokenTree::MetaVarDecl(_, _, id) => id.name == sym::vis,
+                        TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis)) => true,
                         TokenTree::Sequence(_, ref sub_seq) => {
                             sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore
                                 || sub_seq.kleene.op == mbe::KleeneOp::ZeroOrOne
@@ -890,21 +886,7 @@ fn check_matcher_core(
         // of NT tokens that might end the sequence `... token`.
         match *token {
             TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
-                let can_be_followed_by_any;
-                if let Err(bad_frag) = has_legal_fragment_specifier(sess, features, attrs, token) {
-                    let msg = format!("invalid fragment specifier `{}`", bad_frag);
-                    sess.span_diagnostic
-                        .struct_span_err(token.span(), &msg)
-                        .help(VALID_FRAGMENT_NAMES_MSG)
-                        .emit();
-                    // (This eliminates false positives and duplicates
-                    // from error messages.)
-                    can_be_followed_by_any = true;
-                } else {
-                    can_be_followed_by_any = token_can_be_followed_by_any(token);
-                }
-
-                if can_be_followed_by_any {
+                if token_can_be_followed_by_any(token) {
                     // don't need to track tokens that work with any,
                     last.replace_with_irrelevant();
                     // ... and don't need to check tokens that can be
@@ -967,19 +949,10 @@ fn check_matcher_core(
 
         // Now `last` holds the complete set of NT tokens that could
         // end the sequence before SUFFIX. Check that every one works with `suffix`.
-        'each_last: for token in &last.tokens {
-            if let TokenTree::MetaVarDecl(_, name, frag_spec) = *token {
+        for token in &last.tokens {
+            if let TokenTree::MetaVarDecl(_, name, Some(kind)) = *token {
                 for next_token in &suffix_first.tokens {
-                    match is_in_follow(next_token, frag_spec.name) {
-                        IsInFollow::Invalid(msg, help) => {
-                            sess.span_diagnostic
-                                .struct_span_err(next_token.span(), &msg)
-                                .help(help)
-                                .emit();
-                            // don't bother reporting every source of
-                            // conflict for a particular element of `last`.
-                            continue 'each_last;
-                        }
+                    match is_in_follow(next_token, kind) {
                         IsInFollow::Yes => {}
                         IsInFollow::No(possible) => {
                             let may_be = if last.tokens.len() == 1 && suffix_first.tokens.len() == 1
@@ -996,22 +969,19 @@ fn check_matcher_core(
                                     "`${name}:{frag}` {may_be} followed by `{next}`, which \
                                      is not allowed for `{frag}` fragments",
                                     name = name,
-                                    frag = frag_spec,
+                                    frag = kind,
                                     next = quoted_tt_to_string(next_token),
                                     may_be = may_be
                                 ),
                             );
-                            err.span_label(
-                                sp,
-                                format!("not allowed after `{}` fragments", frag_spec),
-                            );
+                            err.span_label(sp, format!("not allowed after `{}` fragments", kind));
                             let msg = "allowed there are: ";
                             match possible {
                                 &[] => {}
                                 &[t] => {
                                     err.note(&format!(
                                         "only {} is allowed after `{}` fragments",
-                                        t, frag_spec,
+                                        t, kind,
                                     ));
                                 }
                                 ts => {
@@ -1038,8 +1008,8 @@ fn check_matcher_core(
 }
 
 fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool {
-    if let mbe::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok {
-        frag_can_be_followed_by_any(frag_spec.name)
+    if let mbe::TokenTree::MetaVarDecl(_, _, Some(kind)) = *tok {
+        frag_can_be_followed_by_any(kind)
     } else {
         // (Non NT's can always be followed by anything in matchers.)
         true
@@ -1054,26 +1024,23 @@ fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool {
 /// specifier which consumes at most one token tree can be followed by
 /// a fragment specifier (indeed, these fragments can be followed by
 /// ANYTHING without fear of future compatibility hazards).
-fn frag_can_be_followed_by_any(frag: Symbol) -> bool {
-    match frag {
-        sym::item     | // always terminated by `}` or `;`
-        sym::block    | // exactly one token tree
-        sym::ident    | // exactly one token tree
-        sym::literal  | // exactly one token tree
-        sym::meta     | // exactly one token tree
-        sym::lifetime | // exactly one token tree
-        sym::tt =>   // exactly one token tree
-            true,
-
-        _ =>
-            false,
+fn frag_can_be_followed_by_any(kind: NonterminalKind) -> bool {
+    match kind {
+        NonterminalKind::Item           // always terminated by `}` or `;`
+        | NonterminalKind::Block        // exactly one token tree
+        | NonterminalKind::Ident        // exactly one token tree
+        | NonterminalKind::Literal      // exactly one token tree
+        | NonterminalKind::Meta         // exactly one token tree
+        | NonterminalKind::Lifetime     // exactly one token tree
+        | NonterminalKind::TT => true,  // exactly one token tree
+
+        _ => false,
     }
 }
 
 enum IsInFollow {
     Yes,
     No(&'static [&'static str]),
-    Invalid(String, &'static str),
 }
 
 /// Returns `true` if `frag` can legally be followed by the token `tok`. For
@@ -1084,7 +1051,7 @@ enum IsInFollow {
 /// break macros that were relying on that binary operator as a
 /// separator.
 // when changing this do not forget to update doc/book/macros.md!
-fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
+fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
     use mbe::TokenTree;
 
     if let TokenTree::Token(Token { kind: token::CloseDelim(_), .. }) = *tok {
@@ -1092,18 +1059,18 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
         // iow, we always require that `(` and `)` match, etc.
         IsInFollow::Yes
     } else {
-        match frag {
-            sym::item => {
+        match kind {
+            NonterminalKind::Item => {
                 // since items *must* be followed by either a `;` or a `}`, we can
                 // accept anything after them
                 IsInFollow::Yes
             }
-            sym::block => {
+            NonterminalKind::Block => {
                 // anything can follow block, the braces provide an easy boundary to
                 // maintain
                 IsInFollow::Yes
             }
-            sym::stmt | sym::expr => {
+            NonterminalKind::Stmt | NonterminalKind::Expr => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1113,7 +1080,7 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            sym::pat => {
+            NonterminalKind::Pat => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1124,7 +1091,7 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            sym::path | sym::ty => {
+            NonterminalKind::Path | NonterminalKind::Ty => {
                 const TOKENS: &[&str] = &[
                     "`{`", "`[`", "`=>`", "`,`", "`>`", "`=`", "`:`", "`;`", "`|`", "`as`",
                     "`where`",
@@ -1146,26 +1113,24 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
                         }
                         _ => IsInFollow::No(TOKENS),
                     },
-                    TokenTree::MetaVarDecl(_, _, frag) if frag.name == sym::block => {
-                        IsInFollow::Yes
-                    }
+                    TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Block)) => IsInFollow::Yes,
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            sym::ident | sym::lifetime => {
+            NonterminalKind::Ident | NonterminalKind::Lifetime => {
                 // being a single token, idents and lifetimes are harmless
                 IsInFollow::Yes
             }
-            sym::literal => {
+            NonterminalKind::Literal => {
                 // literals may be of a single token, or two tokens (negative numbers)
                 IsInFollow::Yes
             }
-            sym::meta | sym::tt => {
+            NonterminalKind::Meta | NonterminalKind::TT => {
                 // being either a single token or a delimited sequence, tt is
                 // harmless
                 IsInFollow::Yes
             }
-            sym::vis => {
+            NonterminalKind::Vis => {
                 // Explicitly disallow `priv`, on the off chance it comes back.
                 const TOKENS: &[&str] = &["`,`", "an ident", "a type"];
                 match tok {
@@ -1180,78 +1145,24 @@ fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow {
                             }
                         }
                     },
-                    TokenTree::MetaVarDecl(_, _, frag)
-                        if frag.name == sym::ident
-                            || frag.name == sym::ty
-                            || frag.name == sym::path =>
-                    {
-                        IsInFollow::Yes
-                    }
+                    TokenTree::MetaVarDecl(
+                        _,
+                        _,
+                        Some(NonterminalKind::Ident | NonterminalKind::Ty | NonterminalKind::Path),
+                    ) => IsInFollow::Yes,
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            kw::Invalid => IsInFollow::Yes,
-            _ => IsInFollow::Invalid(
-                format!("invalid fragment specifier `{}`", frag),
-                VALID_FRAGMENT_NAMES_MSG,
-            ),
         }
     }
 }
 
-fn has_legal_fragment_specifier(
-    sess: &ParseSess,
-    features: &Features,
-    attrs: &[ast::Attribute],
-    tok: &mbe::TokenTree,
-) -> Result<(), String> {
-    debug!("has_legal_fragment_specifier({:?})", tok);
-    if let mbe::TokenTree::MetaVarDecl(_, _, ref frag_spec) = *tok {
-        let frag_span = tok.span();
-        if !is_legal_fragment_specifier(sess, features, attrs, frag_spec.name, frag_span) {
-            return Err(frag_spec.to_string());
-        }
-    }
-    Ok(())
-}
-
-fn is_legal_fragment_specifier(
-    _sess: &ParseSess,
-    _features: &Features,
-    _attrs: &[ast::Attribute],
-    frag_name: Symbol,
-    _frag_span: Span,
-) -> bool {
-    /*
-     * If new fragment specifiers are invented in nightly, `_sess`,
-     * `_features`, `_attrs`, and `_frag_span` will be useful here
-     * for checking against feature gates. See past versions of
-     * this function.
-     */
-    match frag_name {
-        sym::item
-        | sym::block
-        | sym::stmt
-        | sym::expr
-        | sym::pat
-        | sym::lifetime
-        | sym::path
-        | sym::ty
-        | sym::ident
-        | sym::meta
-        | sym::tt
-        | sym::vis
-        | sym::literal
-        | kw::Invalid => true,
-        _ => false,
-    }
-}
-
 fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
     match *tt {
         mbe::TokenTree::Token(ref token) => pprust::token_to_string(&token),
         mbe::TokenTree::MetaVar(_, name) => format!("${}", name),
-        mbe::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind),
+        mbe::TokenTree::MetaVarDecl(_, name, Some(kind)) => format!("${}:{}", name, kind),
+        mbe::TokenTree::MetaVarDecl(_, name, None) => format!("${}:", name),
         _ => panic!(
             "unexpected mbe::TokenTree::{{Sequence or Delimited}} \
              in follow set checker"
diff --git a/src/librustc_expand/mbe/quoted.rs b/src/librustc_expand/mbe/quoted.rs
index 09306f26ee0..774cc84afde 100644
--- a/src/librustc_expand/mbe/quoted.rs
+++ b/src/librustc_expand/mbe/quoted.rs
@@ -12,6 +12,10 @@ use rustc_span::Span;
 
 use rustc_data_structures::sync::Lrc;
 
+const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
+                                        `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
+                                        `literal`, `path`, `meta`, `tt`, `item` and `vis`";
+
 /// Takes a `tokenstream::TokenStream` and returns a `Vec<self::TokenTree>`. Specifically, this
 /// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a
 /// collection of `TokenTree` for use in parsing a macro.
@@ -55,9 +59,21 @@ pub(super) fn parse(
                     Some(tokenstream::TokenTree::Token(Token { kind: token::Colon, span })) => {
                         match trees.next() {
                             Some(tokenstream::TokenTree::Token(token)) => match token.ident() {
-                                Some((kind, _)) => {
+                                Some((frag, _)) => {
                                     let span = token.span.with_lo(start_sp.lo());
-                                    result.push(TokenTree::MetaVarDecl(span, ident, kind));
+                                    let kind = token::NonterminalKind::from_symbol(frag.name)
+                                        .unwrap_or_else(|| {
+                                            let msg = format!(
+                                                "invalid fragment specifier `{}`",
+                                                frag.name
+                                            );
+                                            sess.span_diagnostic
+                                                .struct_span_err(span, &msg)
+                                                .help(VALID_FRAGMENT_NAMES_MSG)
+                                                .emit();
+                                            token::NonterminalKind::Ident
+                                        });
+                                    result.push(TokenTree::MetaVarDecl(span, ident, Some(kind)));
                                     continue;
                                 }
                                 _ => token.span,
@@ -71,7 +87,7 @@ pub(super) fn parse(
                     // Macros loaded from other crates have dummy node ids.
                     sess.missing_fragment_specifiers.borrow_mut().insert(span, node_id);
                 }
-                result.push(TokenTree::MetaVarDecl(span, ident, Ident::invalid()));
+                result.push(TokenTree::MetaVarDecl(span, ident, None));
             }
 
             // Not a metavar or no matchers allowed, so just return the tree
diff --git a/src/librustc_hir/Cargo.toml b/src/librustc_hir/Cargo.toml
index 1b91d769c70..4a404e176e1 100644
--- a/src/librustc_hir/Cargo.toml
+++ b/src/librustc_hir/Cargo.toml
@@ -18,5 +18,5 @@ rustc_span = { path = "../librustc_span" }
 rustc_serialize = { path = "../librustc_serialize" }
 rustc_ast = { path = "../librustc_ast" }
 lazy_static = "1"
-log = { version = "0.4", features = ["release_max_level_info", "std"] }
+log = { package = "tracing", version = "0.1" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml
index 7b3030fa1d9..60a87078d63 100644
--- a/src/librustc_incremental/Cargo.toml
+++ b/src/librustc_incremental/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_graphviz = { path = "../librustc_graphviz" }
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rand = "0.7"
 rustc_middle = { path = "../librustc_middle" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_infer/Cargo.toml b/src/librustc_infer/Cargo.toml
index 06fc7ecf95f..9d56fa223a9 100644
--- a/src/librustc_infer/Cargo.toml
+++ b/src/librustc_infer/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_graphviz = { path = "../librustc_graphviz" }
-log = { version = "0.4", features = ["release_max_level_info", "std"] }
+log = { package = "tracing", version = "0.1" }
 rustc_middle = { path = "../librustc_middle" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs
index 5b4d91de3ca..133c4bf2db5 100644
--- a/src/librustc_infer/infer/combine.rs
+++ b/src/librustc_infer/infer/combine.rs
@@ -166,7 +166,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
                 return self.unify_const_variable(!a_is_expected, vid, a);
             }
             (ty::ConstKind::Unevaluated(..), _) if self.tcx.lazy_normalization() => {
-                // FIXME(#59490): Need to remove the leak check to accomodate
+                // FIXME(#59490): Need to remove the leak check to accommodate
                 // escaping bound variables here.
                 if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
                     relation.const_equate_obligation(a, b);
@@ -174,7 +174,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
                 return Ok(b);
             }
             (_, ty::ConstKind::Unevaluated(..)) if self.tcx.lazy_normalization() => {
-                // FIXME(#59490): Need to remove the leak check to accomodate
+                // FIXME(#59490): Need to remove the leak check to accommodate
                 // escaping bound variables here.
                 if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
                     relation.const_equate_obligation(a, b);
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 4fa6d9d2394..0125e0f48e8 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -195,7 +195,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             }
         }
         if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
-            // Provide a more targetted error code and description.
+            // Provide a more targeted error code and description.
             err.code(rustc_errors::error_code!(E0772));
             err.set_primary_message(&format!(
                 "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index 112dc7037f5..5c7edc10dd5 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 libc = "0.2"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rayon = { version = "0.3.0", package = "rustc-rayon" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_ast = { path = "../librustc_ast" }
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index f1b9fafc781..125a020de37 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -2,7 +2,7 @@ use crate::interface::{Compiler, Result};
 use crate::proc_macro_decls;
 use crate::util;
 
-use log::{info, log_enabled, warn};
+use log::{info, warn};
 use once_cell::sync::Lazy;
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::{self, ast, visit};
@@ -1015,10 +1015,7 @@ pub fn start_codegen<'tcx>(
     tcx: TyCtxt<'tcx>,
     outputs: &OutputFilenames,
 ) -> Box<dyn Any> {
-    if log_enabled!(::log::Level::Info) {
-        println!("Pre-codegen");
-        tcx.print_debug_stats();
-    }
+    info!("Pre-codegen\n{:?}", tcx.debug_stats());
 
     let (metadata, need_metadata_module) = encode_and_write_metadata(tcx, outputs);
 
@@ -1026,10 +1023,7 @@ pub fn start_codegen<'tcx>(
         codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
     });
 
-    if log_enabled!(::log::Level::Info) {
-        println!("Post-codegen");
-        tcx.print_debug_stats();
-    }
+    info!("Post-codegen\n{:?}", tcx.debug_stats());
 
     if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
         if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, outputs) {
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index 58c15257326..3ba1566023d 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -9,7 +9,7 @@ name = "rustc_lint"
 path = "lib.rs"
 
 [dependencies]
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 unicode-security = "0.0.5"
 rustc_middle = { path = "../librustc_middle" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index a45817beea1..e32c8fbee68 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -20,7 +20,9 @@
 //! If you define a new `LateLintPass`, you will also need to add it to the
 //! `late_lint_methods!` invocation in `lib.rs`.
 
-use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use crate::{
+    types::CItemKind, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
+};
 use rustc_ast::ast::{self, Expr};
 use rustc_ast::attr::{self, HasAttrs};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
@@ -36,14 +38,14 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind};
 use rustc_hir::{HirId, HirIdSet, Node};
 use rustc_middle::lint::LintDiagnosticBuilder;
-use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::subst::{GenericArgKind, Subst};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::lint::FutureIncompatibleInfo;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Span};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{LayoutOf, VariantIdx};
 use rustc_trait_selection::traits::misc::can_type_implement_copy;
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
@@ -2144,7 +2146,13 @@ impl ClashingExternDeclarations {
     /// Checks whether two types are structurally the same enough that the declarations shouldn't
     /// clash. We need this so we don't emit a lint when two modules both declare an extern struct,
     /// with the same members (as the declarations shouldn't clash).
-    fn structurally_same_type<'tcx>(cx: &LateContext<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+    fn structurally_same_type<'tcx>(
+        cx: &LateContext<'tcx>,
+        a: Ty<'tcx>,
+        b: Ty<'tcx>,
+        ckind: CItemKind,
+    ) -> bool {
+        debug!("structurally_same_type(cx, a = {:?}, b = {:?})", a, b);
         let tcx = cx.tcx;
         if a == b || rustc_middle::ty::TyS::same_type(a, b) {
             // All nominally-same types are structurally same, too.
@@ -2155,47 +2163,77 @@ impl ClashingExternDeclarations {
             let a_kind = &a.kind;
             let b_kind = &b.kind;
 
+            let compare_layouts = |a, b| -> bool {
+                let a_layout = &cx.layout_of(a).unwrap().layout.abi;
+                let b_layout = &cx.layout_of(b).unwrap().layout.abi;
+                debug!("{:?} == {:?} = {}", a_layout, b_layout, a_layout == b_layout);
+                a_layout == b_layout
+            };
+
+            #[allow(rustc::usage_of_ty_tykind)]
+            let is_primitive_or_pointer =
+                |kind: &ty::TyKind<'_>| kind.is_primitive() || matches!(kind, RawPtr(..));
+
             match (a_kind, b_kind) {
-                (Adt(..), Adt(..)) => {
-                    // Adts are pretty straightforward: just compare the layouts.
-                    use rustc_target::abi::LayoutOf;
-                    let a_layout = cx.layout_of(a).unwrap().layout;
-                    let b_layout = cx.layout_of(b).unwrap().layout;
-                    a_layout == b_layout
+                (Adt(_, a_substs), Adt(_, b_substs)) => {
+                    let a = a.subst(cx.tcx, a_substs);
+                    let b = b.subst(cx.tcx, b_substs);
+                    debug!("Comparing {:?} and {:?}", a, b);
+
+                    if let (Adt(a_def, ..), Adt(b_def, ..)) = (&a.kind, &b.kind) {
+                        // Grab a flattened representation of all fields.
+                        let a_fields = a_def.variants.iter().flat_map(|v| v.fields.iter());
+                        let b_fields = b_def.variants.iter().flat_map(|v| v.fields.iter());
+                        compare_layouts(a, b)
+                            && a_fields.eq_by(
+                                b_fields,
+                                |&ty::FieldDef { did: a_did, .. },
+                                 &ty::FieldDef { did: b_did, .. }| {
+                                    Self::structurally_same_type(
+                                        cx,
+                                        tcx.type_of(a_did),
+                                        tcx.type_of(b_did),
+                                        ckind,
+                                    )
+                                },
+                            )
+                    } else {
+                        unreachable!()
+                    }
                 }
                 (Array(a_ty, a_const), Array(b_ty, b_const)) => {
                     // For arrays, we also check the constness of the type.
                     a_const.val == b_const.val
-                        && Self::structurally_same_type(cx, a_const.ty, b_const.ty)
-                        && Self::structurally_same_type(cx, a_ty, b_ty)
+                        && Self::structurally_same_type(cx, a_const.ty, b_const.ty, ckind)
+                        && Self::structurally_same_type(cx, a_ty, b_ty, ckind)
                 }
-                (Slice(a_ty), Slice(b_ty)) => Self::structurally_same_type(cx, a_ty, b_ty),
+                (Slice(a_ty), Slice(b_ty)) => Self::structurally_same_type(cx, a_ty, b_ty, ckind),
                 (RawPtr(a_tymut), RawPtr(b_tymut)) => {
-                    a_tymut.mutbl == a_tymut.mutbl
-                        && Self::structurally_same_type(cx, &a_tymut.ty, &b_tymut.ty)
+                    a_tymut.mutbl == b_tymut.mutbl
+                        && Self::structurally_same_type(cx, &a_tymut.ty, &b_tymut.ty, ckind)
                 }
                 (Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
                     // For structural sameness, we don't need the region to be same.
-                    a_mut == b_mut && Self::structurally_same_type(cx, a_ty, b_ty)
+                    a_mut == b_mut && Self::structurally_same_type(cx, a_ty, b_ty, ckind)
                 }
                 (FnDef(..), FnDef(..)) => {
-                    // As we don't compare regions, skip_binder is fine.
                     let a_poly_sig = a.fn_sig(tcx);
                     let b_poly_sig = b.fn_sig(tcx);
 
+                    // As we don't compare regions, skip_binder is fine.
                     let a_sig = a_poly_sig.skip_binder();
                     let b_sig = b_poly_sig.skip_binder();
 
                     (a_sig.abi, a_sig.unsafety, a_sig.c_variadic)
                         == (b_sig.abi, b_sig.unsafety, b_sig.c_variadic)
                         && a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
-                            Self::structurally_same_type(cx, a, b)
+                            Self::structurally_same_type(cx, a, b, ckind)
                         })
-                        && Self::structurally_same_type(cx, a_sig.output(), b_sig.output())
+                        && Self::structurally_same_type(cx, a_sig.output(), b_sig.output(), ckind)
                 }
                 (Tuple(a_substs), Tuple(b_substs)) => {
                     a_substs.types().eq_by(b_substs.types(), |a_ty, b_ty| {
-                        Self::structurally_same_type(cx, a_ty, b_ty)
+                        Self::structurally_same_type(cx, a_ty, b_ty, ckind)
                     })
                 }
                 // For these, it's not quite as easy to define structural-sameness quite so easily.
@@ -2208,9 +2246,27 @@ impl ClashingExternDeclarations {
                 | (GeneratorWitness(..), GeneratorWitness(..))
                 | (Projection(..), Projection(..))
                 | (Opaque(..), Opaque(..)) => false,
+
                 // These definitely should have been caught above.
                 (Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
-                _ => false,
+
+                // An Adt and a primitive type. This can be FFI-safe is the ADT is an enum with a
+                // non-null field.
+                (Adt(..), other_kind) | (other_kind, Adt(..))
+                    if is_primitive_or_pointer(other_kind) =>
+                {
+                    let (primitive, adt) =
+                        if is_primitive_or_pointer(&a.kind) { (a, b) } else { (b, a) };
+                    if let Some(ty) = crate::types::repr_nullable_ptr(cx, adt, ckind) {
+                        ty == primitive
+                    } else {
+                        compare_layouts(a, b)
+                    }
+                }
+                // Otherwise, just compare the layouts. This may fail to lint for some
+                // incompatible types, but at the very least, will stop reads into
+                // uninitialised memory.
+                _ => compare_layouts(a, b),
             }
         }
     }
@@ -2231,7 +2287,12 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
                     existing_hid, existing_decl_ty, this_fi.hir_id, this_decl_ty
                 );
                 // Check that the declarations match.
-                if !Self::structurally_same_type(cx, existing_decl_ty, this_decl_ty) {
+                if !Self::structurally_same_type(
+                    cx,
+                    existing_decl_ty,
+                    this_decl_ty,
+                    CItemKind::Declaration,
+                ) {
                     let orig_fi = tcx.hir().expect_foreign_item(existing_hid);
                     let orig = Self::name_of_extern_decl(tcx, orig_fi);
 
diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs
index 84f5ea7bcda..31d30a264a5 100644
--- a/src/librustc_lint/context.rs
+++ b/src/librustc_lint/context.rs
@@ -573,7 +573,7 @@ pub trait LintContext: Sized {
                     }
                 }
                 BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
-                    stability::deprecation_suggestion(&mut db, suggestion, span)
+                    stability::deprecation_suggestion(&mut db, "macro", suggestion, span)
                 }
                 BuiltinLintDiagnostics::UnusedDocComment(span) => {
                     db.span_label(span, "rustdoc does not generate documentation for macro invocations");
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index ab30d545edf..15a9affbff7 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -61,8 +61,8 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::{
-    BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
-    INTRA_DOC_LINK_RESOLUTION_FAILURE, INVALID_CODEBLOCK_ATTRIBUTES, MISSING_DOC_CODE_EXAMPLES,
+    BARE_TRAIT_OBJECTS, BROKEN_INTRA_DOC_LINKS, ELIDED_LIFETIMES_IN_PATHS,
+    EXPLICIT_OUTLIVES_REQUIREMENTS, INVALID_CODEBLOCK_ATTRIBUTES, MISSING_DOC_CODE_EXAMPLES,
     PRIVATE_DOC_TESTS,
 };
 use rustc_span::symbol::{Ident, Symbol};
@@ -303,7 +303,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
 
     add_lint_group!(
         "rustdoc",
-        INTRA_DOC_LINK_RESOLUTION_FAILURE,
+        BROKEN_INTRA_DOC_LINKS,
         INVALID_CODEBLOCK_ATTRIBUTES,
         MISSING_DOC_CODE_EXAMPLES,
         PRIVATE_DOC_TESTS
@@ -318,6 +318,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
     store.register_renamed("async_idents", "keyword_idents");
     store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
     store.register_renamed("redundant_semicolon", "redundant_semicolons");
+    store.register_renamed("intra_doc_link_resolution_failure", "broken_intra_doc_links");
     store.register_removed("unknown_features", "replaced by an error");
     store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
     store.register_removed("negate_unsigned", "cast a signed value instead");
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 1affc9457b8..de750010ed1 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -15,8 +15,9 @@ use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable};
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi::Abi;
 use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants};
-use rustc_target::spec::abi::Abi;
+use rustc_target::spec::abi::Abi as SpecAbi;
 
 use log::debug;
 use std::cmp;
@@ -509,14 +510,15 @@ declare_lint! {
 
 declare_lint_pass!(ImproperCTypesDefinitions => [IMPROPER_CTYPES_DEFINITIONS]);
 
-enum ImproperCTypesMode {
-    Declarations,
-    Definitions,
+#[derive(Clone, Copy)]
+crate enum CItemKind {
+    Declaration,
+    Definition,
 }
 
 struct ImproperCTypesVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    mode: ImproperCTypesMode,
+    mode: CItemKind,
 }
 
 enum FfiResult<'tcx> {
@@ -525,54 +527,94 @@ enum FfiResult<'tcx> {
     FfiUnsafe { ty: Ty<'tcx>, reason: String, help: Option<String> },
 }
 
-impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
-    /// Is type known to be non-null?
-    fn ty_is_known_nonnull(&self, ty: Ty<'tcx>) -> bool {
-        match ty.kind {
-            ty::FnPtr(_) => true,
-            ty::Ref(..) => true,
-            ty::Adt(def, _)
-                if def.is_box() && matches!(self.mode, ImproperCTypesMode::Definitions) =>
-            {
-                true
-            }
-            ty::Adt(def, substs) if def.repr.transparent() && !def.is_union() => {
-                let guaranteed_nonnull_optimization = self
-                    .cx
-                    .tcx
-                    .get_attrs(def.did)
-                    .iter()
-                    .any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed));
-
-                if guaranteed_nonnull_optimization {
-                    return true;
-                }
+/// Is type known to be non-null?
+fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
+    let tcx = cx.tcx;
+    match ty.kind {
+        ty::FnPtr(_) => true,
+        ty::Ref(..) => true,
+        ty::Adt(def, _) if def.is_box() && matches!(mode, CItemKind::Definition) => true,
+        ty::Adt(def, substs) if def.repr.transparent() && !def.is_union() => {
+            let guaranteed_nonnull_optimization = tcx
+                .get_attrs(def.did)
+                .iter()
+                .any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed));
 
-                for variant in &def.variants {
-                    if let Some(field) = variant.transparent_newtype_field(self.cx.tcx) {
-                        if self.ty_is_known_nonnull(field.ty(self.cx.tcx, substs)) {
-                            return true;
-                        }
+            if guaranteed_nonnull_optimization {
+                return true;
+            }
+            for variant in &def.variants {
+                if let Some(field) = variant.transparent_newtype_field(tcx) {
+                    if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) {
+                        return true;
                     }
                 }
-
-                false
             }
-            _ => false,
+
+            false
         }
+        _ => false,
     }
+}
+/// Given a non-null scalar (or transparent) type `ty`, return the nullable version of that type.
+/// If the type passed in was not scalar, returns None.
+fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+    let tcx = cx.tcx;
+    Some(match ty.kind {
+        ty::Adt(field_def, field_substs) => {
+            let inner_field_ty = {
+                let first_non_zst_ty =
+                    field_def.variants.iter().filter_map(|v| v.transparent_newtype_field(tcx));
+                debug_assert_eq!(
+                    first_non_zst_ty.clone().count(),
+                    1,
+                    "Wrong number of fields for transparent type"
+                );
+                first_non_zst_ty
+                    .last()
+                    .expect("No non-zst fields in transparent type.")
+                    .ty(tcx, field_substs)
+            };
+            return get_nullable_type(cx, inner_field_ty);
+        }
+        ty::Int(ty) => tcx.mk_mach_int(ty),
+        ty::Uint(ty) => tcx.mk_mach_uint(ty),
+        ty::RawPtr(ty_mut) => tcx.mk_ptr(ty_mut),
+        // As these types are always non-null, the nullable equivalent of
+        // Option<T> of these types are their raw pointer counterparts.
+        ty::Ref(_region, ty, mutbl) => tcx.mk_ptr(ty::TypeAndMut { ty, mutbl }),
+        ty::FnPtr(..) => {
+            // There is no nullable equivalent for Rust's function pointers -- you
+            // must use an Option<fn(..) -> _> to represent it.
+            ty
+        }
 
-    /// Check if this enum can be safely exported based on the "nullable pointer optimization".
-    /// Currently restricted to function pointers, boxes, references, `core::num::NonZero*`,
-    /// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes.
-    fn is_repr_nullable_ptr(
-        &self,
-        ty: Ty<'tcx>,
-        ty_def: &'tcx ty::AdtDef,
-        substs: SubstsRef<'tcx>,
-    ) -> bool {
+        // We should only ever reach this case if ty_is_known_nonnull is extended
+        // to other types.
+        ref unhandled => {
+            debug!(
+                "get_nullable_type: Unhandled scalar kind: {:?} while checking {:?}",
+                unhandled, ty
+            );
+            return None;
+        }
+    })
+}
+
+/// Check if this enum can be safely exported based on the "nullable pointer optimization". If it
+/// can, return the the type that `ty` can be safely converted to, otherwise return `None`.
+/// Currently restricted to function pointers, boxes, references, `core::num::NonZero*`,
+/// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes.
+/// FIXME: This duplicates code in codegen.
+crate fn repr_nullable_ptr<'tcx>(
+    cx: &LateContext<'tcx>,
+    ty: Ty<'tcx>,
+    ckind: CItemKind,
+) -> Option<Ty<'tcx>> {
+    debug!("is_repr_nullable_ptr(cx, ty = {:?})", ty);
+    if let ty::Adt(ty_def, substs) = ty.kind {
         if ty_def.variants.len() != 2 {
-            return false;
+            return None;
         }
 
         let get_variant_fields = |index| &ty_def.variants[VariantIdx::new(index)].fields;
@@ -582,30 +624,42 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         } else if variant_fields[1].is_empty() {
             &variant_fields[0]
         } else {
-            return false;
+            return None;
         };
 
         if fields.len() != 1 {
-            return false;
+            return None;
         }
 
-        let field_ty = fields[0].ty(self.cx.tcx, substs);
-        if !self.ty_is_known_nonnull(field_ty) {
-            return false;
+        let field_ty = fields[0].ty(cx.tcx, substs);
+        if !ty_is_known_nonnull(cx, field_ty, ckind) {
+            return None;
         }
 
-        // At this point, the field's type is known to be nonnull and the parent enum is
-        // Option-like. If the computed size for the field and the enum are different, the non-null
-        // optimization isn't being applied (and we've got a problem somewhere).
-        let compute_size_skeleton =
-            |t| SizeSkeleton::compute(t, self.cx.tcx, self.cx.param_env).unwrap();
+        // At this point, the field's type is known to be nonnull and the parent enum is Option-like.
+        // If the computed size for the field and the enum are different, the nonnull optimization isn't
+        // being applied (and we've got a problem somewhere).
+        let compute_size_skeleton = |t| SizeSkeleton::compute(t, cx.tcx, cx.param_env).unwrap();
         if !compute_size_skeleton(ty).same_size(compute_size_skeleton(field_ty)) {
             bug!("improper_ctypes: Option nonnull optimization not applied?");
         }
 
-        true
+        // Return the nullable type this Option-like enum can be safely represented with.
+        let field_ty_abi = &cx.layout_of(field_ty).unwrap().abi;
+        if let Abi::Scalar(field_ty_scalar) = field_ty_abi {
+            match (field_ty_scalar.valid_range.start(), field_ty_scalar.valid_range.end()) {
+                (0, _) => unreachable!("Non-null optimisation extended to a non-zero value."),
+                (1, _) => {
+                    return Some(get_nullable_type(cx, field_ty).unwrap());
+                }
+                (start, end) => unreachable!("Unhandled start and end range: ({}, {})", start, end),
+            };
+        }
     }
+    None
+}
 
+impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     /// Check if the type is array and emit an unsafe type lint.
     fn check_for_array_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
         if let ty::Array(..) = ty.kind {
@@ -686,7 +740,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> FfiResult<'tcx> {
         use FfiResult::*;
 
-        let cx = self.cx.tcx;
+        let tcx = self.cx.tcx;
 
         // Protect against infinite recursion, for example
         // `struct S(*mut S);`.
@@ -697,9 +751,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         }
 
         match ty.kind {
-            ty::Adt(def, _)
-                if def.is_box() && matches!(self.mode, ImproperCTypesMode::Definitions) =>
-            {
+            ty::Adt(def, _) if def.is_box() && matches!(self.mode, CItemKind::Definition) => {
                 FfiSafe
             }
 
@@ -753,7 +805,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                         // discriminant.
                         if !def.repr.c() && !def.repr.transparent() && def.repr.int.is_none() {
                             // Special-case types like `Option<extern fn()>`.
-                            if !self.is_repr_nullable_ptr(ty, def, substs) {
+                            if repr_nullable_ptr(self.cx, ty, self.mode).is_none() {
                                 return FfiUnsafe {
                                     ty,
                                     reason: "enum has no representation hint".into(),
@@ -836,7 +888,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
             ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _)
                 if {
-                    matches!(self.mode, ImproperCTypesMode::Definitions)
+                    matches!(self.mode, CItemKind::Definition)
                         && ty.is_sized(self.cx.tcx.at(DUMMY_SP), self.cx.param_env)
                 } =>
             {
@@ -862,7 +914,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                     };
                 }
 
-                let sig = cx.erase_late_bound_regions(&sig);
+                let sig = tcx.erase_late_bound_regions(&sig);
                 if !sig.output().is_unit() {
                     let r = self.check_type_for_ffi(cache, sig.output());
                     match r {
@@ -894,9 +946,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
             // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
             //  so they are currently ignored for the purposes of this lint.
-            ty::Param(..) | ty::Projection(..)
-                if matches!(self.mode, ImproperCTypesMode::Definitions) =>
-            {
+            ty::Param(..) | ty::Projection(..) if matches!(self.mode, CItemKind::Definition) => {
                 FfiSafe
             }
 
@@ -921,14 +971,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         help: Option<&str>,
     ) {
         let lint = match self.mode {
-            ImproperCTypesMode::Declarations => IMPROPER_CTYPES,
-            ImproperCTypesMode::Definitions => IMPROPER_CTYPES_DEFINITIONS,
+            CItemKind::Declaration => IMPROPER_CTYPES,
+            CItemKind::Definition => IMPROPER_CTYPES_DEFINITIONS,
         };
 
         self.cx.struct_span_lint(lint, sp, |lint| {
             let item_description = match self.mode {
-                ImproperCTypesMode::Declarations => "block",
-                ImproperCTypesMode::Definitions => "fn",
+                CItemKind::Declaration => "block",
+                CItemKind::Definition => "fn",
             };
             let mut diag = lint.build(&format!(
                 "`extern` {} uses type `{}`, which is not FFI-safe",
@@ -1052,8 +1102,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         self.check_type_for_ffi_and_report_errors(span, ty, true, false);
     }
 
-    fn is_internal_abi(&self, abi: Abi) -> bool {
-        if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
+    fn is_internal_abi(&self, abi: SpecAbi) -> bool {
+        if let SpecAbi::Rust
+        | SpecAbi::RustCall
+        | SpecAbi::RustIntrinsic
+        | SpecAbi::PlatformIntrinsic = abi
+        {
             true
         } else {
             false
@@ -1063,7 +1117,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
 impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
     fn check_foreign_item(&mut self, cx: &LateContext<'_>, it: &hir::ForeignItem<'_>) {
-        let mut vis = ImproperCTypesVisitor { cx, mode: ImproperCTypesMode::Declarations };
+        let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Declaration };
         let abi = cx.tcx.hir().get_foreign_abi(it.hir_id);
 
         if !vis.is_internal_abi(abi) {
@@ -1098,7 +1152,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
             _ => return,
         };
 
-        let mut vis = ImproperCTypesVisitor { cx, mode: ImproperCTypesMode::Definitions };
+        let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Definition };
         if !vis.is_internal_abi(abi) {
             vis.check_foreign_fn(hir_id, decl);
         }
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index dcb44ab6444..a33f9206035 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -203,6 +203,28 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                     // Otherwise, we don't lint, to avoid false positives.
                     _ => false,
                 },
+                ty::Closure(..) => {
+                    cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
+                        let mut err = lint.build(&format!(
+                            "unused {}closure{}{} that must be used",
+                            descr_pre, plural_suffix, descr_post,
+                        ));
+                        err.note("closures are lazy and do nothing unless called");
+                        err.emit();
+                    });
+                    true
+                }
+                ty::Generator(..) => {
+                    cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
+                        let mut err = lint.build(&format!(
+                            "unused {}generator{}{} that must be used",
+                            descr_pre, plural_suffix, descr_post,
+                        ));
+                        err.note("generators are lazy and do nothing unless resumed");
+                        err.emit();
+                    });
+                    true
+                }
                 _ => false,
             }
         }
@@ -400,7 +422,7 @@ trait UnusedDelimLint {
         lhs_needs_parens
             || (followed_by_block
                 && match inner.kind {
-                    ExprKind::Ret(_) | ExprKind::Break(..) => true,
+                    ExprKind::Ret(_) | ExprKind::Break(..) | ExprKind::Yield(..) => true,
                     _ => parser::contains_exterior_struct_lit(&inner),
                 })
     }
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index 7bbe7567d29..2c0e2aa39fd 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
 [dependencies]
 flate2 = "1.0"
 libc = "0.2"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 memmap = "0.7"
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_middle = { path = "../librustc_middle" }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 724b4123fab..9bc6c054e4d 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -13,7 +13,7 @@ use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def_id::{CrateNum, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
 use rustc_index::vec::IndexVec;
-use rustc_middle::middle::cstore::{CrateSource, DepKind, ExternCrate};
+use rustc_middle::middle::cstore::{CrateDepKind, CrateSource, ExternCrate};
 use rustc_middle::middle::cstore::{ExternCrateSource, MetadataLoaderDyn};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{self, CrateType, ExternLocation};
@@ -26,7 +26,7 @@ use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 
-use log::{debug, info, log_enabled};
+use log::{debug, info};
 use proc_macro::bridge::client::ProcMacro;
 use std::path::Path;
 use std::{cmp, env, fs};
@@ -82,24 +82,36 @@ impl std::ops::Deref for CrateMetadataRef<'_> {
     }
 }
 
-fn dump_crates(cstore: &CStore) {
-    info!("resolved crates:");
-    cstore.iter_crate_data(|cnum, data| {
-        info!("  name: {}", data.name());
-        info!("  cnum: {}", cnum);
-        info!("  hash: {}", data.hash());
-        info!("  reqd: {:?}", data.dep_kind());
-        let CrateSource { dylib, rlib, rmeta } = data.source();
-        if let Some(dylib) = dylib {
-            info!("  dylib: {}", dylib.0.display());
-        }
-        if let Some(rlib) = rlib {
-            info!("   rlib: {}", rlib.0.display());
-        }
-        if let Some(rmeta) = rmeta {
-            info!("   rmeta: {}", rmeta.0.display());
-        }
-    });
+struct CrateDump<'a>(&'a CStore);
+
+impl<'a> std::fmt::Debug for CrateDump<'a> {
+    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        writeln!(fmt, "resolved crates:")?;
+        // `iter_crate_data` does not allow returning values. Thus we use a mutable variable here
+        // that aggregates the value (and any errors that could happen).
+        let mut res = Ok(());
+        self.0.iter_crate_data(|cnum, data| {
+            res = res.and(
+                try {
+                    writeln!(fmt, "  name: {}", data.name())?;
+                    writeln!(fmt, "  cnum: {}", cnum)?;
+                    writeln!(fmt, "  hash: {}", data.hash())?;
+                    writeln!(fmt, "  reqd: {:?}", data.dep_kind())?;
+                    let CrateSource { dylib, rlib, rmeta } = data.source();
+                    if let Some(dylib) = dylib {
+                        writeln!(fmt, "  dylib: {}", dylib.0.display())?;
+                    }
+                    if let Some(rlib) = rlib {
+                        writeln!(fmt, "   rlib: {}", rlib.0.display())?;
+                    }
+                    if let Some(rmeta) = rmeta {
+                        writeln!(fmt, "   rmeta: {}", rmeta.0.display())?;
+                    }
+                },
+            );
+        });
+        res
+    }
 }
 
 impl CStore {
@@ -236,9 +248,9 @@ impl<'a> CrateLoader<'a> {
                 // Only use `--extern crate_name=path` here, not `--extern crate_name`.
                 if let Some(mut files) = entry.files() {
                     if files.any(|l| {
-                        let l = fs::canonicalize(l).ok();
-                        source.dylib.as_ref().map(|p| &p.0) == l.as_ref()
-                            || source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
+                        let l = fs::canonicalize(l).unwrap_or(l.clone().into());
+                        source.dylib.as_ref().map(|p| &p.0) == Some(&l)
+                            || source.rlib.as_ref().map(|p| &p.0) == Some(&l)
                     }) {
                         ret = Some(cnum);
                     }
@@ -294,7 +306,7 @@ impl<'a> CrateLoader<'a> {
         host_lib: Option<Library>,
         root: Option<&CratePaths>,
         lib: Library,
-        dep_kind: DepKind,
+        dep_kind: CrateDepKind,
         name: Symbol,
     ) -> Result<CrateNum, CrateError> {
         let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate");
@@ -425,7 +437,7 @@ impl<'a> CrateLoader<'a> {
         &'b mut self,
         name: Symbol,
         span: Span,
-        dep_kind: DepKind,
+        dep_kind: CrateDepKind,
         dep: Option<(&'b CratePaths, &'b CrateDep)>,
     ) -> CrateNum {
         if dep.is_none() {
@@ -438,7 +450,7 @@ impl<'a> CrateLoader<'a> {
     fn maybe_resolve_crate<'b>(
         &'b mut self,
         name: Symbol,
-        mut dep_kind: DepKind,
+        mut dep_kind: CrateDepKind,
         dep: Option<(&'b CratePaths, &'b CrateDep)>,
     ) -> Result<CrateNum, CrateError> {
         info!("resolving crate `{}`", name);
@@ -475,7 +487,7 @@ impl<'a> CrateLoader<'a> {
             match self.load(&mut locator)? {
                 Some(res) => (res, None),
                 None => {
-                    dep_kind = DepKind::MacrosOnly;
+                    dep_kind = CrateDepKind::MacrosOnly;
                     match self.load_proc_macro(&mut locator, path_kind)? {
                         Some(res) => res,
                         None => return Err(locator.into_error()),
@@ -488,7 +500,7 @@ impl<'a> CrateLoader<'a> {
             (LoadResult::Previous(cnum), None) => {
                 let data = self.cstore.get_crate_data(cnum);
                 if data.is_proc_macro_crate() {
-                    dep_kind = DepKind::MacrosOnly;
+                    dep_kind = CrateDepKind::MacrosOnly;
                 }
                 data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind));
                 Ok(cnum)
@@ -548,7 +560,7 @@ impl<'a> CrateLoader<'a> {
         crate_root: &CrateRoot<'_>,
         metadata: &MetadataBlob,
         krate: CrateNum,
-        dep_kind: DepKind,
+        dep_kind: CrateDepKind,
     ) -> Result<CrateNumMap, CrateError> {
         debug!("resolving deps of external crate");
         if crate_root.is_proc_macro_crate() {
@@ -567,7 +579,7 @@ impl<'a> CrateLoader<'a> {
                 dep.name, dep.hash, dep.extra_filename
             );
             let dep_kind = match dep_kind {
-                DepKind::MacrosOnly => DepKind::MacrosOnly,
+                CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly,
                 _ => dep.kind,
             };
             let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?;
@@ -634,7 +646,7 @@ impl<'a> CrateLoader<'a> {
                 self.inject_dependency_if(cnum, "a panic runtime", &|data| {
                     data.needs_panic_runtime()
                 });
-                runtime_found = runtime_found || data.dep_kind() == DepKind::Explicit;
+                runtime_found = runtime_found || data.dep_kind() == CrateDepKind::Explicit;
             }
         });
 
@@ -663,7 +675,7 @@ impl<'a> CrateLoader<'a> {
         };
         info!("panic runtime not found -- loading {}", name);
 
-        let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None);
+        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
         let data = self.cstore.get_crate_data(cnum);
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
@@ -693,7 +705,7 @@ impl<'a> CrateLoader<'a> {
             info!("loading profiler");
 
             let name = sym::profiler_builtins;
-            let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None);
+            let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
             let data = self.cstore.get_crate_data(cnum);
 
             // Sanity check the loaded crate to ensure it is indeed a profiler runtime
@@ -864,9 +876,7 @@ impl<'a> CrateLoader<'a> {
         self.inject_allocator_crate(krate);
         self.inject_panic_runtime(krate);
 
-        if log_enabled!(log::Level::Info) {
-            dump_crates(&self.cstore);
-        }
+        info!("{:?}", CrateDump(&self.cstore));
 
         self.report_unused_deps(krate);
     }
@@ -891,9 +901,9 @@ impl<'a> CrateLoader<'a> {
                     None => item.ident.name,
                 };
                 let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) {
-                    DepKind::MacrosOnly
+                    CrateDepKind::MacrosOnly
                 } else {
-                    DepKind::Explicit
+                    CrateDepKind::Explicit
                 };
 
                 let cnum = self.resolve_crate(name, item.span, dep_kind, None);
@@ -915,7 +925,7 @@ impl<'a> CrateLoader<'a> {
     }
 
     pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum {
-        let cnum = self.resolve_crate(name, span, DepKind::Explicit, None);
+        let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, None);
 
         self.update_extern_crate(
             cnum,
@@ -932,6 +942,6 @@ impl<'a> CrateLoader<'a> {
     }
 
     pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
-        self.maybe_resolve_crate(name, DepKind::Explicit, None).ok()
+        self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok()
     }
 }
diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs
index aa5fafcc614..bb5ae4d0557 100644
--- a/src/librustc_metadata/dependency_format.rs
+++ b/src/librustc_metadata/dependency_format.rs
@@ -56,7 +56,7 @@ use crate::creader::CStore;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::CrateNum;
 use rustc_middle::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
-use rustc_middle::middle::cstore::{self, DepKind};
+use rustc_middle::middle::cstore::{self, CrateDepKind};
 use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::CrateType;
@@ -188,7 +188,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
         let src = tcx.used_crate_source(cnum);
         if src.dylib.is_none()
             && !formats.contains_key(&cnum)
-            && tcx.dep_kind(cnum) == DepKind::Explicit
+            && tcx.dep_kind(cnum) == CrateDepKind::Explicit
         {
             assert!(src.rlib.is_some() || src.rmeta.is_some());
             log::info!("adding staticlib: {}", tcx.crate_name(cnum));
@@ -284,7 +284,7 @@ fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> {
     let last_crate = tcx.crates().len();
     let mut ret = (1..last_crate + 1)
         .map(|cnum| {
-            if tcx.dep_kind(CrateNum::new(cnum)) == DepKind::Explicit {
+            if tcx.dep_kind(CrateNum::new(cnum)) == CrateDepKind::Explicit {
                 Linkage::Static
             } else {
                 Linkage::NotLinked
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index d4add2ab7ad..059ae340bcf 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -9,6 +9,7 @@
 #![feature(proc_macro_internals)]
 #![feature(min_specialization)]
 #![feature(stmt_expr_attributes)]
+#![feature(try_blocks)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
 
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 371ec4cd911..8828b318d1e 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -426,20 +426,17 @@ impl<'a> CrateLocator<'a> {
             info!("lib candidate: {}", spf.path.display());
 
             let (rlibs, rmetas, dylibs) = candidates.entry(hash.to_string()).or_default();
-            fs::canonicalize(&spf.path)
-                .map(|p| {
-                    if seen_paths.contains(&p) {
-                        return FileDoesntMatch;
-                    };
-                    seen_paths.insert(p.clone());
-                    match found_kind {
-                        CrateFlavor::Rlib => rlibs.insert(p, kind),
-                        CrateFlavor::Rmeta => rmetas.insert(p, kind),
-                        CrateFlavor::Dylib => dylibs.insert(p, kind),
-                    };
-                    FileMatches
-                })
-                .unwrap_or(FileDoesntMatch)
+            let path = fs::canonicalize(&spf.path).unwrap_or_else(|_| spf.path.clone());
+            if seen_paths.contains(&path) {
+                return FileDoesntMatch;
+            };
+            seen_paths.insert(path.clone());
+            match found_kind {
+                CrateFlavor::Rlib => rlibs.insert(path, kind),
+                CrateFlavor::Rmeta => rmetas.insert(path, kind),
+                CrateFlavor::Dylib => dylibs.insert(path, kind),
+            };
+            FileMatches
         });
         self.rejected_via_kind.extend(staticlibs);
 
@@ -688,12 +685,13 @@ impl<'a> CrateLocator<'a> {
                     && file.ends_with(&self.target.options.dll_suffix)
             {
                 // Make sure there's at most one rlib and at most one dylib.
+                let loc = fs::canonicalize(&loc).unwrap_or_else(|_| loc.clone());
                 if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
-                    rlibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
+                    rlibs.insert(loc, PathKind::ExternFlag);
                 } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
-                    rmetas.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
+                    rmetas.insert(loc, PathKind::ExternFlag);
                 } else {
-                    dylibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
+                    dylibs.insert(loc, PathKind::ExternFlag);
                 }
             } else {
                 self.rejected_via_filename
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index b7f5921438f..3c045df45da 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -100,7 +100,7 @@ crate struct CrateMetadata {
     /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
     dependencies: Lock<Vec<CrateNum>>,
     /// How to link (or not link) this crate to the currently compiled crate.
-    dep_kind: Lock<DepKind>,
+    dep_kind: Lock<CrateDepKind>,
     /// Filesystem location of this crate.
     source: CrateSource,
     /// Whether or not this crate should be consider a private dependency
@@ -780,7 +780,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
     fn get_variant(
         &self,
-        tcx: TyCtxt<'tcx>,
         kind: &EntryKind,
         index: DefIndex,
         parent_did: DefId,
@@ -805,7 +804,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         let ctor_did = data.ctor.map(|index| self.local_def_id(index));
 
         ty::VariantDef::new(
-            tcx,
             self.item_ident(index, sess),
             variant_did,
             ctor_did,
@@ -826,6 +824,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             adt_kind,
             parent_did,
             false,
+            data.is_non_exhaustive,
         )
     }
 
@@ -847,10 +846,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 .get(self, item_id)
                 .unwrap_or(Lazy::empty())
                 .decode(self)
-                .map(|index| self.get_variant(tcx, &self.kind(index), index, did, tcx.sess))
+                .map(|index| self.get_variant(&self.kind(index), index, did, tcx.sess))
                 .collect()
         } else {
-            std::iter::once(self.get_variant(tcx, &kind, item_id, did, tcx.sess)).collect()
+            std::iter::once(self.get_variant(&kind, item_id, did, tcx.sess)).collect()
         };
 
         tcx.alloc_adt_def(did, adt_kind, variants, repr)
@@ -1670,7 +1669,7 @@ impl CrateMetadata {
         raw_proc_macros: Option<&'static [ProcMacro]>,
         cnum: CrateNum,
         cnum_map: CrateNumMap,
-        dep_kind: DepKind,
+        dep_kind: CrateDepKind,
         source: CrateSource,
         private_dep: bool,
         host_hash: Option<Svh>,
@@ -1728,11 +1727,11 @@ impl CrateMetadata {
         &self.source
     }
 
-    crate fn dep_kind(&self) -> DepKind {
+    crate fn dep_kind(&self) -> CrateDepKind {
         *self.dep_kind.lock()
     }
 
-    crate fn update_dep_kind(&self, f: impl FnOnce(DepKind) -> DepKind) {
+    crate fn update_dep_kind(&self, f: impl FnOnce(CrateDepKind) -> CrateDepKind) {
         self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind))
     }
 
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index dc8d14a44f8..352b8bff7e2 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -267,7 +267,7 @@ impl<'a, 'tcx> SpecializedEncoder<Span> for EncodeContext<'a, 'tcx> {
         // real code should never need to care about this.
         //
         // 2. Using `Span::def_site` or `Span::mixed_site` will not
-        // include any hygiene information associated with the defintion
+        // include any hygiene information associated with the definition
         // site. This means that a proc-macro cannot emit a `$crate`
         // identifier which resolves to one of its dependencies,
         // which also should never come up in practice.
@@ -738,6 +738,7 @@ impl EncodeContext<'a, 'tcx> {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
             ctor: variant.ctor_def_id.map(|did| did.index),
+            is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
         let enum_id = tcx.hir().as_local_hir_id(def.did.expect_local());
@@ -782,6 +783,7 @@ impl EncodeContext<'a, 'tcx> {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
             ctor: Some(def_id.index),
+            is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
         // Variant constructors have the same visibility as the parent enums, unless marked as
@@ -886,6 +888,7 @@ impl EncodeContext<'a, 'tcx> {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
             ctor: Some(def_id.index),
+            is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
         let struct_id = tcx.hir().as_local_hir_id(adt_def.did.expect_local());
@@ -1235,6 +1238,7 @@ impl EncodeContext<'a, 'tcx> {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     ctor,
+                    is_non_exhaustive: variant.is_field_list_non_exhaustive(),
                 }), adt_def.repr)
             }
             hir::ItemKind::Union(..) => {
@@ -1245,6 +1249,7 @@ impl EncodeContext<'a, 'tcx> {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     ctor: None,
+                    is_non_exhaustive: variant.is_field_list_non_exhaustive(),
                 }), adt_def.repr)
             }
             hir::ItemKind::Impl { defaultness, .. } => {
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 55ef66f1939..12d2f50363c 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -11,7 +11,7 @@ use rustc_hir::def_id::{DefId, DefIndex};
 use rustc_hir::lang_items;
 use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
 use rustc_middle::hir::exports::Export;
-use rustc_middle::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLib};
+use rustc_middle::middle::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc_middle::mir;
 use rustc_middle::ty::{self, ReprOptions, Ty};
@@ -226,7 +226,7 @@ crate struct CrateDep {
     pub name: Symbol,
     pub hash: Svh,
     pub host_hash: Option<Svh>,
-    pub kind: DepKind,
+    pub kind: CrateDepKind,
     pub extra_filename: String,
 }
 
@@ -346,6 +346,7 @@ struct VariantData {
     discr: ty::VariantDiscr,
     /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
     ctor: Option<DefIndex>,
+    is_non_exhaustive: bool,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_middle/Cargo.toml b/src/librustc_middle/Cargo.toml
index 02d82c67933..678fcfe6539 100644
--- a/src/librustc_middle/Cargo.toml
+++ b/src/librustc_middle/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
 rustc_arena = { path = "../librustc_arena" }
 bitflags = "1.2.1"
 scoped-tls = "1.0"
-log = { version = "0.4", features = ["release_max_level_info", "std"] }
+log = { package = "tracing", version = "0.1" }
 rustc-rayon-core = "0.3.0"
 polonius-engine = "0.12.0"
 rustc_apfloat = { path = "../librustc_apfloat" }
diff --git a/src/librustc_middle/middle/cstore.rs b/src/librustc_middle/middle/cstore.rs
index 97e877df966..0a34c06adf0 100644
--- a/src/librustc_middle/middle/cstore.rs
+++ b/src/librustc_middle/middle/cstore.rs
@@ -40,7 +40,7 @@ impl CrateSource {
 
 #[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
 #[derive(HashStable)]
-pub enum DepKind {
+pub enum CrateDepKind {
     /// A dependency that is only used for its macros.
     MacrosOnly,
     /// A dependency that is always injected into the dependency list and so
@@ -51,11 +51,11 @@ pub enum DepKind {
     Explicit,
 }
 
-impl DepKind {
+impl CrateDepKind {
     pub fn macros_only(self) -> bool {
         match self {
-            DepKind::MacrosOnly => true,
-            DepKind::Implicit | DepKind::Explicit => false,
+            CrateDepKind::MacrosOnly => true,
+            CrateDepKind::Implicit | CrateDepKind::Explicit => false,
         }
     }
 }
diff --git a/src/librustc_middle/middle/stability.rs b/src/librustc_middle/middle/stability.rs
index 5f7ff54fd31..b913d7dd4ad 100644
--- a/src/librustc_middle/middle/stability.rs
+++ b/src/librustc_middle/middle/stability.rs
@@ -166,29 +166,31 @@ pub fn deprecation_in_effect(is_since_rustc_version: bool, since: Option<&str>)
 
 pub fn deprecation_suggestion(
     diag: &mut DiagnosticBuilder<'_>,
+    kind: &str,
     suggestion: Option<Symbol>,
     span: Span,
 ) {
     if let Some(suggestion) = suggestion {
         diag.span_suggestion(
             span,
-            "replace the use of the deprecated item",
+            &format!("replace the use of the deprecated {}", kind),
             suggestion.to_string(),
             Applicability::MachineApplicable,
         );
     }
 }
 
-pub fn deprecation_message(depr: &Deprecation, path: &str) -> (String, &'static Lint) {
+pub fn deprecation_message(depr: &Deprecation, kind: &str, path: &str) -> (String, &'static Lint) {
     let (message, lint) = if deprecation_in_effect(
         depr.is_since_rustc_version,
         depr.since.map(Symbol::as_str).as_deref(),
     ) {
-        (format!("use of deprecated item '{}'", path), DEPRECATED)
+        (format!("use of deprecated {} `{}`", kind, path), DEPRECATED)
     } else {
         (
             format!(
-                "use of item '{}' that will be deprecated in future version {}",
+                "use of {} `{}` that will be deprecated in future version {}",
+                kind,
                 path,
                 depr.since.unwrap()
             ),
@@ -224,6 +226,7 @@ fn late_report_deprecation(
     lint: &'static Lint,
     span: Span,
     hir_id: HirId,
+    def_id: DefId,
 ) {
     if span.in_derive_expansion() {
         return;
@@ -232,7 +235,8 @@ fn late_report_deprecation(
     tcx.struct_span_lint_hir(lint, hir_id, span, |lint| {
         let mut diag = lint.build(message);
         if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
-            deprecation_suggestion(&mut diag, suggestion, span);
+            let kind = tcx.def_kind(def_id).descr(def_id);
+            deprecation_suggestion(&mut diag, kind, suggestion, span);
         }
         diag.emit()
     });
@@ -304,8 +308,9 @@ impl<'tcx> TyCtxt<'tcx> {
                 // #[rustc_deprecated] however wants to emit down the whole
                 // hierarchy.
                 if !skip || depr_entry.attr.is_since_rustc_version {
-                    let (message, lint) =
-                        deprecation_message(&depr_entry.attr, &self.def_path_str(def_id));
+                    let path = &self.def_path_str(def_id);
+                    let kind = self.def_kind(def_id).descr(def_id);
+                    let (message, lint) = deprecation_message(&depr_entry.attr, kind, path);
                     late_report_deprecation(
                         self,
                         &message,
@@ -313,6 +318,7 @@ impl<'tcx> TyCtxt<'tcx> {
                         lint,
                         span,
                         id,
+                        def_id,
                     );
                 }
             };
diff --git a/src/librustc_middle/mir/coverage/mod.rs b/src/librustc_middle/mir/coverage/mod.rs
index 1e06dadfa24..82365ef6a73 100644
--- a/src/librustc_middle/mir/coverage/mod.rs
+++ b/src/librustc_middle/mir/coverage/mod.rs
@@ -3,7 +3,7 @@
 /// Positional arguments to `libcore::count_code_region()`
 pub mod count_code_region_args {
     pub const FUNCTION_SOURCE_HASH: usize = 0;
-    pub const COUNTER_INDEX: usize = 1;
+    pub const COUNTER_ID: usize = 1;
     pub const START_BYTE_POS: usize = 2;
     pub const END_BYTE_POS: usize = 3;
 }
@@ -11,9 +11,9 @@ pub mod count_code_region_args {
 /// Positional arguments to `libcore::coverage_counter_add()` and
 /// `libcore::coverage_counter_subtract()`
 pub mod coverage_counter_expression_args {
-    pub const COUNTER_EXPRESSION_INDEX: usize = 0;
-    pub const LEFT_INDEX: usize = 1;
-    pub const RIGHT_INDEX: usize = 2;
+    pub const EXPRESSION_ID: usize = 0;
+    pub const LEFT_ID: usize = 1;
+    pub const RIGHT_ID: usize = 2;
     pub const START_BYTE_POS: usize = 3;
     pub const END_BYTE_POS: usize = 4;
 }
diff --git a/src/librustc_middle/mir/interpret/queries.rs b/src/librustc_middle/mir/interpret/queries.rs
index d7c0be05859..442e7f6b0f4 100644
--- a/src/librustc_middle/mir/interpret/queries.rs
+++ b/src/librustc_middle/mir/interpret/queries.rs
@@ -18,7 +18,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let substs = InternalSubsts::identity_for_item(self, def_id);
         let instance = ty::Instance::new(def_id, substs);
         let cid = GlobalId { instance, promoted: None };
-        let param_env = self.param_env(def_id).with_reveal_all();
+        let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
         self.const_eval_global_id(param_env, cid, None)
     }
 
diff --git a/src/librustc_middle/mir/interpret/value.rs b/src/librustc_middle/mir/interpret/value.rs
index 9de2d17457a..2c76f0b5ad0 100644
--- a/src/librustc_middle/mir/interpret/value.rs
+++ b/src/librustc_middle/mir/interpret/value.rs
@@ -78,7 +78,7 @@ impl<'tcx> ConstValue<'tcx> {
         param_env: ParamEnv<'tcx>,
         ty: Ty<'tcx>,
     ) -> Option<u128> {
-        let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
+        let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
         self.try_to_bits(size)
     }
 
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index f857af28622..862c046358b 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -864,11 +864,17 @@ rustc_queries! {
         /// type-checking etc, and it does not normalize specializable
         /// associated types. This is almost always what you want,
         /// unless you are doing MIR optimizations, in which case you
-        /// might want to use `reveal_all()` method to change modes.
         query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> {
             desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) }
         }
 
+        /// Like `param_env`, but returns the `ParamEnv in `Reveal::All` mode.
+        /// Prefer this over `tcx.param_env(def_id).with_reveal_all_normalized(tcx)`,
+        /// as this method is more efficient.
+        query param_env_reveal_all_normalized(def_id: DefId) -> ty::ParamEnv<'tcx> {
+            desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) }
+        }
+
         /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
         /// `ty.is_copy()`, etc, since that will prune the environment where possible.
         query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
@@ -1180,7 +1186,7 @@ rustc_queries! {
     }
 
     Other {
-        query dep_kind(_: CrateNum) -> DepKind {
+        query dep_kind(_: CrateNum) -> CrateDepKind {
             eval_always
             desc { "fetching what a dependency looks like" }
         }
@@ -1527,5 +1533,9 @@ rustc_queries! {
                 ty::Instance::new(key.value.0.to_def_id(), key.value.2),
             }
         }
+
+        query normalize_opaque_types(key: &'tcx ty::List<ty::Predicate<'tcx>>) -> &'tcx ty::List<ty::Predicate<'tcx>> {
+            desc { "normalizing opaque types in {:?}", key }
+        }
     }
 }
diff --git a/src/librustc_middle/ty/consts.rs b/src/librustc_middle/ty/consts.rs
index f3a863c3fce..c0b5693dc59 100644
--- a/src/librustc_middle/ty/consts.rs
+++ b/src/librustc_middle/ty/consts.rs
@@ -158,7 +158,7 @@ impl<'tcx> Const<'tcx> {
         ty: Ty<'tcx>,
     ) -> Option<u128> {
         assert_eq!(self.ty, ty);
-        let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
+        let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
         // if `ty` does not depend on generic parameters, use an empty param_env
         self.val.eval(tcx, param_env).try_to_bits(size)
     }
diff --git a/src/librustc_middle/ty/consts/kind.rs b/src/librustc_middle/ty/consts/kind.rs
index 75287ff7dac..e8a1e714a8f 100644
--- a/src/librustc_middle/ty/consts/kind.rs
+++ b/src/librustc_middle/ty/consts/kind.rs
@@ -96,12 +96,16 @@ impl<'tcx> ConstKind<'tcx> {
         if let ConstKind::Unevaluated(def, substs, promoted) = self {
             use crate::mir::interpret::ErrorHandled;
 
-            let param_env_and_substs = param_env.with_reveal_all().and(substs);
-
             // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
             // also does later, but we want to do it before checking for
             // inference variables.
-            let param_env_and_substs = tcx.erase_regions(&param_env_and_substs);
+            // Note that we erase regions *before* calling `with_reveal_all_normalized`,
+            // so that we don't try to invoke this query with
+            // any region variables.
+            let param_env_and_substs = tcx
+                .erase_regions(&param_env)
+                .with_reveal_all_normalized(tcx)
+                .and(tcx.erase_regions(&substs));
 
             // HACK(eddyb) when the query key would contain inference variables,
             // attempt using identity substs and `ParamEnv` instead, that will succeed
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index eeb58a0c55a..775d755444d 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -352,7 +352,7 @@ pub struct TypeckResults<'tcx> {
     pat_binding_modes: ItemLocalMap<BindingMode>,
 
     /// Stores the types which were implicitly dereferenced in pattern binding modes
-    /// for later usage in HAIR lowering. For example,
+    /// for later usage in THIR lowering. For example,
     ///
     /// ```
     /// match &&Some(5i32) {
@@ -1831,7 +1831,7 @@ pub mod tls {
 }
 
 macro_rules! sty_debug_print {
-    ($ctxt: expr, $($variant: ident),*) => {{
+    ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
         // Curious inner module to allow variant names to be used as
         // variable names.
         #[allow(non_snake_case)]
@@ -1848,7 +1848,7 @@ macro_rules! sty_debug_print {
                 all_infer: usize,
             }
 
-            pub fn go(tcx: TyCtxt<'_>) {
+            pub fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result {
                 let mut total = DebugStat {
                     total: 0,
                     lt_infer: 0,
@@ -1878,8 +1878,8 @@ macro_rules! sty_debug_print {
                     if ct { total.ct_infer += 1; variant.ct_infer += 1 }
                     if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 }
                 }
-                println!("Ty interner             total           ty lt ct all");
-                $(println!("    {:18}: {uses:6} {usespc:4.1}%, \
+                writeln!(fmt, "Ty interner             total           ty lt ct all")?;
+                $(writeln!(fmt, "    {:18}: {uses:6} {usespc:4.1}%, \
                             {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
                     stringify!($variant),
                     uses = $variant.total,
@@ -1887,9 +1887,9 @@ macro_rules! sty_debug_print {
                     ty = $variant.ty_infer as f64 * 100.0  / total.total as f64,
                     lt = $variant.lt_infer as f64 * 100.0  / total.total as f64,
                     ct = $variant.ct_infer as f64 * 100.0  / total.total as f64,
-                    all = $variant.all_infer as f64 * 100.0  / total.total as f64);
+                    all = $variant.all_infer as f64 * 100.0  / total.total as f64)?;
                 )*
-                println!("                  total {uses:6}        \
+                writeln!(fmt, "                  total {uses:6}        \
                           {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
                     uses = total.total,
                     ty = total.ty_infer as f64 * 100.0  / total.total as f64,
@@ -1899,41 +1899,56 @@ macro_rules! sty_debug_print {
             }
         }
 
-        inner::go($ctxt)
+        inner::go($fmt, $ctxt)
     }}
 }
 
 impl<'tcx> TyCtxt<'tcx> {
-    pub fn print_debug_stats(self) {
-        sty_debug_print!(
-            self,
-            Adt,
-            Array,
-            Slice,
-            RawPtr,
-            Ref,
-            FnDef,
-            FnPtr,
-            Placeholder,
-            Generator,
-            GeneratorWitness,
-            Dynamic,
-            Closure,
-            Tuple,
-            Bound,
-            Param,
-            Infer,
-            Projection,
-            Opaque,
-            Foreign
-        );
-
-        println!("InternalSubsts interner: #{}", self.interners.substs.len());
-        println!("Region interner: #{}", self.interners.region.len());
-        println!("Stability interner: #{}", self.stability_interner.len());
-        println!("Const Stability interner: #{}", self.const_stability_interner.len());
-        println!("Allocation interner: #{}", self.allocation_interner.len());
-        println!("Layout interner: #{}", self.layout_interner.len());
+    pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx {
+        struct DebugStats<'tcx>(TyCtxt<'tcx>);
+
+        impl std::fmt::Debug for DebugStats<'tcx> {
+            fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+                sty_debug_print!(
+                    fmt,
+                    self.0,
+                    Adt,
+                    Array,
+                    Slice,
+                    RawPtr,
+                    Ref,
+                    FnDef,
+                    FnPtr,
+                    Placeholder,
+                    Generator,
+                    GeneratorWitness,
+                    Dynamic,
+                    Closure,
+                    Tuple,
+                    Bound,
+                    Param,
+                    Infer,
+                    Projection,
+                    Opaque,
+                    Foreign
+                )?;
+
+                writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?;
+                writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?;
+                writeln!(fmt, "Stability interner: #{}", self.0.stability_interner.len())?;
+                writeln!(
+                    fmt,
+                    "Const Stability interner: #{}",
+                    self.0.const_stability_interner.len()
+                )?;
+                writeln!(fmt, "Allocation interner: #{}", self.0.allocation_interner.len())?;
+                writeln!(fmt, "Layout interner: #{}", self.0.layout_interner.len())?;
+
+                Ok(())
+            }
+        }
+
+        DebugStats(self)
     }
 }
 
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index 215f44819b5..143d3c4e1e9 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -1903,7 +1903,7 @@ impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
     /// Computes the layout of a type. Note that this implicitly
     /// executes in "reveal all" mode.
     fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        let param_env = self.param_env.with_reveal_all();
+        let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
         let ty = self.tcx.normalize_erasing_regions(param_env, ty);
         let layout = self.tcx.layout_raw(param_env.and(ty))?;
         let layout = TyAndLayout { ty, layout };
@@ -1927,7 +1927,7 @@ impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
     /// Computes the layout of a type. Note that this implicitly
     /// executes in "reveal all" mode.
     fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        let param_env = self.param_env.with_reveal_all();
+        let param_env = self.param_env.with_reveal_all_normalized(*self.tcx);
         let ty = self.tcx.normalize_erasing_regions(param_env, ty);
         let layout = self.tcx.layout_raw(param_env.and(ty))?;
         let layout = TyAndLayout { ty, layout };
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index d1c6d3be5f4..bd45f866abc 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -1,5 +1,5 @@
 // ignore-tidy-filelength
-pub use self::fold::{TypeFoldable, TypeVisitor};
+pub use self::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 pub use self::AssocItemContainer::*;
 pub use self::BorrowKind::*;
 pub use self::IntVarValue::*;
@@ -1874,9 +1874,15 @@ impl<'tcx> ParamEnv<'tcx> {
     /// the desired behavior during codegen and certain other special
     /// contexts; normally though we want to use `Reveal::UserFacing`,
     /// which is the default.
-    pub fn with_reveal_all(mut self) -> Self {
-        self.packed_data |= 1;
-        self
+    /// All opaque types in the caller_bounds of the `ParamEnv`
+    /// will be normalized to their underlying types.
+    /// See PR #65989 and issue #65918 for more details
+    pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
+        if self.packed_data & 1 == 1 {
+            return self;
+        }
+
+        ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All, self.def_id)
     }
 
     /// Returns this same environment but with no caller bounds.
@@ -2046,7 +2052,6 @@ impl<'tcx> VariantDef {
     /// If someone speeds up attribute loading to not be a performance concern, they can
     /// remove this hack and use the constructor `DefId` everywhere.
     pub fn new(
-        tcx: TyCtxt<'tcx>,
         ident: Ident,
         variant_did: Option<DefId>,
         ctor_def_id: Option<DefId>,
@@ -2056,6 +2061,7 @@ impl<'tcx> VariantDef {
         adt_kind: AdtKind,
         parent_did: DefId,
         recovered: bool,
+        is_field_list_non_exhaustive: bool,
     ) -> Self {
         debug!(
             "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?},
@@ -2064,14 +2070,8 @@ impl<'tcx> VariantDef {
         );
 
         let mut flags = VariantFlags::NO_VARIANT_FLAGS;
-        if adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive) {
-            debug!("found non-exhaustive field list for {:?}", parent_did);
-            flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
-        } else if let Some(variant_did) = variant_did {
-            if tcx.has_attr(variant_did, sym::non_exhaustive) {
-                debug!("found non-exhaustive field list for {:?}", variant_did);
-                flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
-            }
+        if is_field_list_non_exhaustive {
+            flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
         }
 
         VariantDef {
@@ -3122,6 +3122,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
     context::provide(providers);
     erase_regions::provide(providers);
     layout::provide(providers);
+    util::provide(providers);
     super::util::bug::provide(providers);
     *providers = ty::query::Providers {
         trait_impls_of: trait_def::trait_impls_of_provider,
diff --git a/src/librustc_middle/ty/query/keys.rs b/src/librustc_middle/ty/query/keys.rs
index cb2b7a662cb..3f7a20bba2b 100644
--- a/src/librustc_middle/ty/query/keys.rs
+++ b/src/librustc_middle/ty/query/keys.rs
@@ -270,6 +270,17 @@ impl<'tcx> Key for Ty<'tcx> {
     }
 }
 
+impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
+    type CacheSelector = DefaultCacheSelector;
+
+    fn query_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, _: TyCtxt<'_>) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl<'tcx> Key for ty::ParamEnv<'tcx> {
     type CacheSelector = DefaultCacheSelector;
 
diff --git a/src/librustc_middle/ty/query/mod.rs b/src/librustc_middle/ty/query/mod.rs
index 2f7a9aee536..b39c0b5190a 100644
--- a/src/librustc_middle/ty/query/mod.rs
+++ b/src/librustc_middle/ty/query/mod.rs
@@ -1,10 +1,10 @@
-use crate::dep_graph::{self, DepNode, DepNodeParams};
+use crate::dep_graph::{self, DepKind, DepNode, DepNodeParams};
 use crate::hir::exports::Export;
 use crate::hir::map;
 use crate::infer::canonical::{self, Canonical};
 use crate::lint::LintLevelMap;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::cstore::{CrateSource, DepKind};
+use crate::middle::cstore::{CrateDepKind, CrateSource};
 use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
 use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use crate::middle::lib_features::LibFeatures;
@@ -161,7 +161,7 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool
     // hit the cache instead of having to go through `force_from_dep_node`.
     // This assertion makes sure, we actually keep applying the solution above.
     debug_assert!(
-        dep_node.kind != crate::dep_graph::DepKind::codegen_unit,
+        dep_node.kind != DepKind::codegen_unit,
         "calling force_from_dep_node() on DepKind::codegen_unit"
     );
 
@@ -172,14 +172,14 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool
     rustc_dep_node_force!([dep_node, tcx]
         // These are inputs that are expected to be pre-allocated and that
         // should therefore always be red or green already.
-        crate::dep_graph::DepKind::CrateMetadata |
+        DepKind::CrateMetadata |
 
         // These are anonymous nodes.
-        crate::dep_graph::DepKind::TraitSelect |
+        DepKind::TraitSelect |
 
         // We don't have enough information to reconstruct the query key of
         // these.
-        crate::dep_graph::DepKind::CompileCodegenUnit => {
+        DepKind::CompileCodegenUnit => {
             bug!("force_from_dep_node: encountered {:?}", dep_node)
         }
     );
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index df8fa4d73dd..310ab4f7235 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -202,6 +202,16 @@ pub enum TyKind<'tcx> {
     Error(DelaySpanBugEmitted),
 }
 
+impl TyKind<'tcx> {
+    #[inline]
+    pub fn is_primitive(&self) -> bool {
+        match self {
+            Bool | Char | Int(_) | Uint(_) | Float(_) => true,
+            _ => false,
+        }
+    }
+}
+
 /// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
 /// except through `tcx.err*()`.
 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
@@ -1766,10 +1776,7 @@ impl<'tcx> TyS<'tcx> {
 
     #[inline]
     pub fn is_primitive(&self) -> bool {
-        match self.kind {
-            Bool | Char | Int(_) | Uint(_) | Float(_) => true,
-            _ => false,
-        }
+        self.kind.is_primitive()
     }
 
     #[inline]
diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs
index adba45facc9..07221082048 100644
--- a/src/librustc_middle/ty/util.rs
+++ b/src/librustc_middle/ty/util.rs
@@ -3,11 +3,12 @@
 use crate::ich::NodeIdHashingMode;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir::interpret::{sign_extend, truncate};
+use crate::ty::fold::TypeFolder;
 use crate::ty::layout::IntegerExt;
 use crate::ty::query::TyCtxtAt;
 use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use crate::ty::TyKind::*;
-use crate::ty::{self, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, DefIdTree, GenericParamDefKind, List, Ty, TyCtxt, TypeFoldable};
 use rustc_apfloat::Float as _;
 use rustc_ast::ast;
 use rustc_attr::{self as attr, SignedInt, UnsignedInt};
@@ -557,82 +558,84 @@ impl<'tcx> TyCtxt<'tcx> {
         def_id: DefId,
         substs: SubstsRef<'tcx>,
     ) -> Result<Ty<'tcx>, Ty<'tcx>> {
-        use crate::ty::fold::TypeFolder;
-
-        struct OpaqueTypeExpander<'tcx> {
-            // Contains the DefIds of the opaque types that are currently being
-            // expanded. When we expand an opaque type we insert the DefId of
-            // that type, and when we finish expanding that type we remove the
-            // its DefId.
-            seen_opaque_tys: FxHashSet<DefId>,
-            // Cache of all expansions we've seen so far. This is a critical
-            // optimization for some large types produced by async fn trees.
-            expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>,
-            primary_def_id: DefId,
-            found_recursion: bool,
-            tcx: TyCtxt<'tcx>,
-        }
-
-        impl<'tcx> OpaqueTypeExpander<'tcx> {
-            fn expand_opaque_ty(
-                &mut self,
-                def_id: DefId,
-                substs: SubstsRef<'tcx>,
-            ) -> Option<Ty<'tcx>> {
-                if self.found_recursion {
-                    return None;
-                }
-                let substs = substs.fold_with(self);
-                if self.seen_opaque_tys.insert(def_id) {
-                    let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
-                        Some(expanded_ty) => expanded_ty,
-                        None => {
-                            let generic_ty = self.tcx.type_of(def_id);
-                            let concrete_ty = generic_ty.subst(self.tcx, substs);
-                            let expanded_ty = self.fold_ty(concrete_ty);
-                            self.expanded_cache.insert((def_id, substs), expanded_ty);
-                            expanded_ty
-                        }
-                    };
-                    self.seen_opaque_tys.remove(&def_id);
-                    Some(expanded_ty)
-                } else {
-                    // If another opaque type that we contain is recursive, then it
-                    // will report the error, so we don't have to.
-                    self.found_recursion = def_id == self.primary_def_id;
-                    None
-                }
-            }
-        }
-
-        impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
-            fn tcx(&self) -> TyCtxt<'tcx> {
-                self.tcx
-            }
-
-            fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::Opaque(def_id, substs) = t.kind {
-                    self.expand_opaque_ty(def_id, substs).unwrap_or(t)
-                } else if t.has_opaque_types() {
-                    t.super_fold_with(self)
-                } else {
-                    t
-                }
-            }
-        }
-
         let mut visitor = OpaqueTypeExpander {
             seen_opaque_tys: FxHashSet::default(),
             expanded_cache: FxHashMap::default(),
-            primary_def_id: def_id,
+            primary_def_id: Some(def_id),
             found_recursion: false,
+            check_recursion: true,
             tcx: self,
         };
+
         let expanded_type = visitor.expand_opaque_ty(def_id, substs).unwrap();
         if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
     }
 }
 
+struct OpaqueTypeExpander<'tcx> {
+    // Contains the DefIds of the opaque types that are currently being
+    // expanded. When we expand an opaque type we insert the DefId of
+    // that type, and when we finish expanding that type we remove the
+    // its DefId.
+    seen_opaque_tys: FxHashSet<DefId>,
+    // Cache of all expansions we've seen so far. This is a critical
+    // optimization for some large types produced by async fn trees.
+    expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>,
+    primary_def_id: Option<DefId>,
+    found_recursion: bool,
+    /// Whether or not to check for recursive opaque types.
+    /// This is `true` when we're explicitly checking for opaque type
+    /// recursion, and 'false' otherwise to avoid unnecessary work.
+    check_recursion: bool,
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> OpaqueTypeExpander<'tcx> {
+    fn expand_opaque_ty(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> {
+        if self.found_recursion {
+            return None;
+        }
+        let substs = substs.fold_with(self);
+        if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
+            let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
+                Some(expanded_ty) => expanded_ty,
+                None => {
+                    let generic_ty = self.tcx.type_of(def_id);
+                    let concrete_ty = generic_ty.subst(self.tcx, substs);
+                    let expanded_ty = self.fold_ty(concrete_ty);
+                    self.expanded_cache.insert((def_id, substs), expanded_ty);
+                    expanded_ty
+                }
+            };
+            if self.check_recursion {
+                self.seen_opaque_tys.remove(&def_id);
+            }
+            Some(expanded_ty)
+        } else {
+            // If another opaque type that we contain is recursive, then it
+            // will report the error, so we don't have to.
+            self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
+            None
+        }
+    }
+}
+
+impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        if let ty::Opaque(def_id, substs) = t.kind {
+            self.expand_opaque_ty(def_id, substs).unwrap_or(t)
+        } else if t.has_opaque_types() {
+            t.super_fold_with(self)
+        } else {
+            t
+        }
+    }
+}
+
 impl<'tcx> ty::TyS<'tcx> {
     /// Returns the maximum value for the given numeric type (including `char`s)
     /// or returns `None` if the type is not numeric.
@@ -1142,3 +1145,24 @@ pub fn needs_drop_components(
 
 #[derive(Copy, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
 pub struct AlwaysRequiresDrop;
+
+/// Normalizes all opaque types in the given value, replacing them
+/// with their underlying types.
+pub fn normalize_opaque_types(
+    tcx: TyCtxt<'tcx>,
+    val: &'tcx List<ty::Predicate<'tcx>>,
+) -> &'tcx List<ty::Predicate<'tcx>> {
+    let mut visitor = OpaqueTypeExpander {
+        seen_opaque_tys: FxHashSet::default(),
+        expanded_cache: FxHashMap::default(),
+        primary_def_id: None,
+        found_recursion: false,
+        check_recursion: false,
+        tcx,
+    };
+    val.fold_with(&mut visitor)
+}
+
+pub fn provide(providers: &mut ty::query::Providers) {
+    *providers = ty::query::Providers { normalize_opaque_types, ..*providers }
+}
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index aebce78e401..f05c47e0ed6 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
 either = "1.5.0"
 rustc_graphviz = { path = "../librustc_graphviz" }
 itertools = "0.8"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 log_settings = "0.1.1"
 polonius-engine = "0.12.0"
 rustc_middle = { path = "../librustc_middle" }
diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs
index 6453630bb92..0dac8b64910 100644
--- a/src/librustc_mir/const_eval/machine.rs
+++ b/src/librustc_mir/const_eval/machine.rs
@@ -56,7 +56,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
         self.copy_op(place.into(), dest)?;
 
         self.return_to_block(ret.map(|r| r.1))?;
-        self.dump_place(*dest);
+        trace!("{:?}", self.dump_place(*dest));
         Ok(true)
     }
 
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 60cf21552e9..78f149f6451 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -8,11 +8,14 @@ use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
 use rustc_middle::mir::CastKind;
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
-use rustc_middle::ty::{self, Ty, TypeAndMut, TypeFoldable};
+use rustc_middle::ty::{self, Ty, TypeAndMut};
 use rustc_span::symbol::sym;
 use rustc_target::abi::{Integer, LayoutOf, Variants};
 
-use super::{truncate, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy};
+use super::{
+    truncate, util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy,
+    PlaceTy,
+};
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub fn cast(
@@ -47,9 +50,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 match src.layout.ty.kind {
                     ty::FnDef(def_id, substs) => {
                         // All reifications must be monomorphic, bail out otherwise.
-                        if src.layout.ty.needs_subst() {
-                            throw_inval!(TooGeneric);
-                        }
+                        ensure_monomorphic_enough(*self.tcx, src.layout.ty)?;
 
                         if self.tcx.has_attr(def_id, sym::rustc_args_required_const) {
                             span_bug!(
@@ -89,9 +90,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 match src.layout.ty.kind {
                     ty::Closure(def_id, substs) => {
                         // All reifications must be monomorphic, bail out otherwise.
-                        if src.layout.ty.needs_subst() {
-                            throw_inval!(TooGeneric);
-                        }
+                        ensure_monomorphic_enough(*self.tcx, src.layout.ty)?;
 
                         let instance = ty::Instance::resolve_closure(
                             *self.tcx,
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 3d3d756cffe..1e9be097815 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -1,5 +1,4 @@
 use std::cell::Cell;
-use std::fmt::Write;
 use std::mem;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -719,6 +718,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
         );
 
+        if unwinding && self.frame_idx() == 0 {
+            throw_ub_format!("unwinding past the topmost frame of the stack");
+        }
+
         ::log_settings::settings().indentation -= 1;
         let frame =
             self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
@@ -728,7 +731,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             if let Some(return_place) = frame.return_place {
                 let op = self.access_local(&frame, mir::RETURN_PLACE, None)?;
                 self.copy_op_transmute(op, return_place)?;
-                self.dump_place(*return_place);
+                trace!("{:?}", self.dump_place(*return_place));
             } else {
                 throw_ub!(Unreachable);
             }
@@ -819,13 +822,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx> {
         // FIXME: should we tell the user that there was a local which was never written to?
         if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
-            trace!("deallocating local");
             // All locals have a backing allocation, even if the allocation is empty
             // due to the local having ZST type.
             let ptr = ptr.assert_ptr();
-            if log_enabled!(::log::Level::Trace) {
-                self.memory.dump_alloc(ptr.alloc_id);
-            }
+            trace!("deallocating local: {:?}", self.memory.dump_alloc(ptr.alloc_id));
             self.memory.deallocate_local(ptr)?;
         };
         Ok(())
@@ -881,47 +881,77 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         self.raw_const_to_mplace(val)
     }
 
-    pub fn dump_place(&self, place: Place<M::PointerTag>) {
-        // Debug output
-        if !log_enabled!(::log::Level::Trace) {
-            return;
+    #[must_use]
+    pub fn dump_place(&'a self, place: Place<M::PointerTag>) -> PlacePrinter<'a, 'mir, 'tcx, M> {
+        PlacePrinter { ecx: self, place }
+    }
+
+    #[must_use]
+    pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
+        let mut frames = Vec::new();
+        for frame in self.stack().iter().rev() {
+            let source_info = frame.current_source_info();
+            let lint_root = source_info.and_then(|source_info| {
+                match &frame.body.source_scopes[source_info.scope].local_data {
+                    mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
+                    mir::ClearCrossCrate::Clear => None,
+                }
+            });
+            let span = source_info.map_or(DUMMY_SP, |source_info| source_info.span);
+
+            frames.push(FrameInfo { span, instance: frame.instance, lint_root });
         }
-        match place {
+        trace!("generate stacktrace: {:#?}", frames);
+        frames
+    }
+}
+
+#[doc(hidden)]
+/// Helper struct for the `dump_place` function.
+pub struct PlacePrinter<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
+    ecx: &'a InterpCx<'mir, 'tcx, M>,
+    place: Place<M::PointerTag>,
+}
+
+impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
+    for PlacePrinter<'a, 'mir, 'tcx, M>
+{
+    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self.place {
             Place::Local { frame, local } => {
                 let mut allocs = Vec::new();
-                let mut msg = format!("{:?}", local);
-                if frame != self.frame_idx() {
-                    write!(msg, " ({} frames up)", self.frame_idx() - frame).unwrap();
+                write!(fmt, "{:?}", local)?;
+                if frame != self.ecx.frame_idx() {
+                    write!(fmt, " ({} frames up)", self.ecx.frame_idx() - frame)?;
                 }
-                write!(msg, ":").unwrap();
+                write!(fmt, ":")?;
 
-                match self.stack()[frame].locals[local].value {
-                    LocalValue::Dead => write!(msg, " is dead").unwrap(),
-                    LocalValue::Uninitialized => write!(msg, " is uninitialized").unwrap(),
+                match self.ecx.stack()[frame].locals[local].value {
+                    LocalValue::Dead => write!(fmt, " is dead")?,
+                    LocalValue::Uninitialized => write!(fmt, " is uninitialized")?,
                     LocalValue::Live(Operand::Indirect(mplace)) => match mplace.ptr {
                         Scalar::Ptr(ptr) => {
                             write!(
-                                msg,
+                                fmt,
                                 " by align({}){} ref:",
                                 mplace.align.bytes(),
                                 match mplace.meta {
                                     MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
                                     MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(),
                                 }
-                            )
-                            .unwrap();
+                            )?;
                             allocs.push(ptr.alloc_id);
                         }
-                        ptr => write!(msg, " by integral ref: {:?}", ptr).unwrap(),
+                        ptr => write!(fmt, " by integral ref: {:?}", ptr)?,
                     },
                     LocalValue::Live(Operand::Immediate(Immediate::Scalar(val))) => {
-                        write!(msg, " {:?}", val).unwrap();
+                        write!(fmt, " {:?}", val)?;
                         if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr)) = val {
                             allocs.push(ptr.alloc_id);
                         }
                     }
                     LocalValue::Live(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => {
-                        write!(msg, " ({:?}, {:?})", val1, val2).unwrap();
+                        write!(fmt, " ({:?}, {:?})", val1, val2)?;
                         if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr)) = val1 {
                             allocs.push(ptr.alloc_id);
                         }
@@ -931,36 +961,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     }
                 }
 
-                trace!("{}", msg);
-                self.memory.dump_allocs(allocs);
+                write!(fmt, ": {:?}", self.ecx.memory.dump_allocs(allocs))
             }
             Place::Ptr(mplace) => match mplace.ptr {
-                Scalar::Ptr(ptr) => {
-                    trace!("by align({}) ref:", mplace.align.bytes());
-                    self.memory.dump_alloc(ptr.alloc_id);
-                }
-                ptr => trace!(" integral by ref: {:?}", ptr),
+                Scalar::Ptr(ptr) => write!(
+                    fmt,
+                    "by align({}) ref: {:?}",
+                    mplace.align.bytes(),
+                    self.ecx.memory.dump_alloc(ptr.alloc_id)
+                ),
+                ptr => write!(fmt, " integral by ref: {:?}", ptr),
             },
         }
     }
-
-    pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
-        let mut frames = Vec::new();
-        for frame in self.stack().iter().rev() {
-            let source_info = frame.current_source_info();
-            let lint_root = source_info.and_then(|source_info| {
-                match &frame.body.source_scopes[source_info.scope].local_data {
-                    mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
-                    mir::ClearCrossCrate::Clear => None,
-                }
-            });
-            let span = source_info.map_or(DUMMY_SP, |source_info| source_info.span);
-
-            frames.push(FrameInfo { span, instance: frame.instance, lint_root });
-        }
-        trace!("generate stacktrace: {:#?}", frames);
-        frames
-    }
 }
 
 impl<'ctx, 'mir, 'tcx, Tag, Extra> HashStable<StableHashingContext<'ctx>>
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 39ed3b60793..b45045716d1 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -12,11 +12,13 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::{Abi, LayoutOf as _, Primitive, Size};
 
-use super::{CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy};
+use super::{
+    util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
+};
 
 mod caller_location;
 mod type_name;
@@ -54,9 +56,7 @@ crate fn eval_nullary_intrinsic<'tcx>(
     let name = tcx.item_name(def_id);
     Ok(match name {
         sym::type_name => {
-            if tp_ty.needs_subst() {
-                throw_inval!(TooGeneric);
-            }
+            ensure_monomorphic_enough(tcx, tp_ty)?;
             let alloc = type_name::alloc_type_name(tcx, tp_ty);
             ConstValue::Slice { data: alloc, start: 0, end: alloc.len() }
         }
@@ -72,9 +72,7 @@ crate fn eval_nullary_intrinsic<'tcx>(
             ConstValue::from_machine_usize(n, &tcx)
         }
         sym::type_id => {
-            if tp_ty.needs_subst() {
-                throw_inval!(TooGeneric);
-            }
+            ensure_monomorphic_enough(tcx, tp_ty)?;
             ConstValue::from_u64(tcx.type_id_hash(tp_ty))
         }
         sym::variant_count => {
@@ -120,6 +118,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_scalar(location.ptr, dest)?;
             }
 
+            sym::min_align_of_val | sym::size_of_val => {
+                let place = self.deref_operand(args[0])?;
+                let (size, align) = self
+                    .size_and_align_of(place.meta, place.layout)?
+                    .ok_or_else(|| err_unsup_format!("`extern type` does not have known layout"))?;
+
+                let result = match intrinsic_name {
+                    sym::min_align_of_val => align.bytes(),
+                    sym::size_of_val => size.bytes(),
+                    _ => bug!(),
+                };
+
+                self.write_scalar(Scalar::from_machine_usize(result, self), dest)?;
+            }
+
             sym::min_align_of
             | sym::pref_align_of
             | sym::needs_drop
@@ -430,7 +443,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             _ => return Ok(false),
         }
 
-        self.dump_place(*dest);
+        trace!("{:?}", self.dump_place(*dest));
         self.go_to_block(ret);
         Ok(true)
     }
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index ea7a1c6cffa..a9e6e324eb2 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -667,69 +667,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         Ok(())
     }
 
-    /// Print an allocation and all allocations it points to, recursively.
-    /// This prints directly to stderr, ignoring RUSTC_LOG! It is up to the caller to
-    /// control for this.
-    pub fn dump_alloc(&self, id: AllocId) {
-        self.dump_allocs(vec![id]);
+    /// Create a lazy debug printer that prints the given allocation and all allocations it points
+    /// to, recursively.
+    #[must_use]
+    pub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'mir, 'tcx, M> {
+        self.dump_allocs(vec![id])
     }
 
-    /// Print a list of allocations and all allocations they point to, recursively.
-    /// This prints directly to stderr, ignoring RUSTC_LOG! It is up to the caller to
-    /// control for this.
-    pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
-        // Cannot be a closure because it is generic in `Tag`, `Extra`.
-        fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>(
-            tcx: TyCtxt<'tcx>,
-            allocs_to_print: &mut VecDeque<AllocId>,
-            alloc: &Allocation<Tag, Extra>,
-        ) {
-            for &(_, target_id) in alloc.relocations().values() {
-                allocs_to_print.push_back(target_id);
-            }
-            pretty::write_allocation(tcx, alloc, &mut std::io::stderr()).unwrap();
-        }
-
+    /// Create a lazy debug printer for a list of allocations and all allocations they point to,
+    /// recursively.
+    #[must_use]
+    pub fn dump_allocs<'a>(&'a self, mut allocs: Vec<AllocId>) -> DumpAllocs<'a, 'mir, 'tcx, M> {
         allocs.sort();
         allocs.dedup();
-        let mut allocs_to_print = VecDeque::from(allocs);
-        // `allocs_printed` contains all allocations that we have already printed.
-        let mut allocs_printed = FxHashSet::default();
-
-        while let Some(id) = allocs_to_print.pop_front() {
-            if !allocs_printed.insert(id) {
-                // Already printed, so skip this.
-                continue;
-            }
-
-            eprint!("{}", id);
-            match self.alloc_map.get(id) {
-                Some(&(kind, ref alloc)) => {
-                    // normal alloc
-                    eprint!(" ({}, ", kind);
-                    write_allocation_track_relocs(self.tcx, &mut allocs_to_print, alloc);
-                }
-                None => {
-                    // global alloc
-                    match self.tcx.get_global_alloc(id) {
-                        Some(GlobalAlloc::Memory(alloc)) => {
-                            eprint!(" (unchanged global, ");
-                            write_allocation_track_relocs(self.tcx, &mut allocs_to_print, alloc);
-                        }
-                        Some(GlobalAlloc::Function(func)) => {
-                            eprint!(" (fn: {})", func);
-                        }
-                        Some(GlobalAlloc::Static(did)) => {
-                            eprint!(" (static: {})", self.tcx.def_path_str(did));
-                        }
-                        None => {
-                            eprint!(" (deallocated)");
-                        }
-                    }
-                }
-            }
-            eprintln!();
-        }
+        DumpAllocs { mem: self, allocs }
     }
 
     /// Print leaked memory. Allocations reachable from `static_roots` or a `Global` allocation
@@ -760,8 +711,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         });
         let n = leaks.len();
         if n > 0 {
-            eprintln!("The following memory was leaked:");
-            self.dump_allocs(leaks);
+            eprintln!("The following memory was leaked: {:?}", self.dump_allocs(leaks));
         }
         n
     }
@@ -772,6 +722,80 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     }
 }
 
+#[doc(hidden)]
+/// There's no way to use this directly, it's just a helper struct for the `dump_alloc(s)` methods.
+pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
+    mem: &'a Memory<'mir, 'tcx, M>,
+    allocs: Vec<AllocId>,
+}
+
+impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> {
+    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        // Cannot be a closure because it is generic in `Tag`, `Extra`.
+        fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>(
+            fmt: &mut std::fmt::Formatter<'_>,
+            tcx: TyCtxt<'tcx>,
+            allocs_to_print: &mut VecDeque<AllocId>,
+            alloc: &Allocation<Tag, Extra>,
+        ) -> std::fmt::Result {
+            for &(_, target_id) in alloc.relocations().values() {
+                allocs_to_print.push_back(target_id);
+            }
+            write!(fmt, "{}", pretty::display_allocation(tcx, alloc))
+        }
+
+        let mut allocs_to_print: VecDeque<_> = self.allocs.iter().copied().collect();
+        // `allocs_printed` contains all allocations that we have already printed.
+        let mut allocs_printed = FxHashSet::default();
+
+        while let Some(id) = allocs_to_print.pop_front() {
+            if !allocs_printed.insert(id) {
+                // Already printed, so skip this.
+                continue;
+            }
+
+            write!(fmt, "{}", id)?;
+            match self.mem.alloc_map.get(id) {
+                Some(&(kind, ref alloc)) => {
+                    // normal alloc
+                    write!(fmt, " ({}, ", kind)?;
+                    write_allocation_track_relocs(
+                        &mut *fmt,
+                        self.mem.tcx,
+                        &mut allocs_to_print,
+                        alloc,
+                    )?;
+                }
+                None => {
+                    // global alloc
+                    match self.mem.tcx.get_global_alloc(id) {
+                        Some(GlobalAlloc::Memory(alloc)) => {
+                            write!(fmt, " (unchanged global, ")?;
+                            write_allocation_track_relocs(
+                                &mut *fmt,
+                                self.mem.tcx,
+                                &mut allocs_to_print,
+                                alloc,
+                            )?;
+                        }
+                        Some(GlobalAlloc::Function(func)) => {
+                            write!(fmt, " (fn: {})", func)?;
+                        }
+                        Some(GlobalAlloc::Static(did)) => {
+                            write!(fmt, " (static: {})", self.mem.tcx.def_path_str(did))?;
+                        }
+                        None => {
+                            write!(fmt, " (deallocated)")?;
+                        }
+                    }
+                }
+            }
+            writeln!(fmt)?;
+        }
+        Ok(())
+    }
+}
+
 /// Reading and writing.
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     /// Reads the given number of bytes from memory. Returns them as a slice.
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 5de9b502a37..ebb061f4851 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -12,6 +12,7 @@ mod place;
 mod step;
 mod terminator;
 mod traits;
+mod util;
 mod validity;
 mod visitor;
 
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index c5d17273225..15e341d9c4c 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -648,7 +648,7 @@ where
             place_ty = self.place_projection(place_ty, &elem)?
         }
 
-        self.dump_place(place_ty.place);
+        trace!("{:?}", self.dump_place(place_ty.place));
         // Sanity-check the type we ended up with.
         debug_assert!(mir_assign_valid_types(
             *self.tcx,
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 3d1e3eccc61..fcd26c86c47 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -271,7 +271,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
         }
 
-        self.dump_place(*dest);
+        trace!("{:?}", self.dump_place(*dest));
 
         Ok(())
     }
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index 589da04d6a3..77f4593fa16 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -1,9 +1,10 @@
 use std::convert::TryFrom;
 
 use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic, Scalar};
-use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
+use rustc_middle::ty::{self, Instance, Ty};
 use rustc_target::abi::{Align, LayoutOf, Size};
 
+use super::util::ensure_monomorphic_enough;
 use super::{FnVal, InterpCx, Machine, MemoryKind};
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
@@ -23,9 +24,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let (ty, poly_trait_ref) = self.tcx.erase_regions(&(ty, poly_trait_ref));
 
         // All vtables must be monomorphic, bail out otherwise.
-        if ty.needs_subst() || poly_trait_ref.needs_subst() {
-            throw_inval!(TooGeneric);
-        }
+        ensure_monomorphic_enough(*self.tcx, ty)?;
+        ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?;
 
         if let Some(&vtable) = self.vtables.get(&(ty, poly_trait_ref)) {
             // This means we guarantee that there are no duplicate vtables, we will
diff --git a/src/librustc_mir/interpret/util.rs b/src/librustc_mir/interpret/util.rs
new file mode 100644
index 00000000000..c0eac8a9305
--- /dev/null
+++ b/src/librustc_mir/interpret/util.rs
@@ -0,0 +1,73 @@
+use rustc_middle::mir::interpret::InterpResult;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor};
+use std::convert::TryInto;
+
+/// Returns `true` if a used generic parameter requires substitution.
+crate fn ensure_monomorphic_enough<'tcx, T>(tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx>
+where
+    T: TypeFoldable<'tcx>,
+{
+    debug!("ensure_monomorphic_enough: ty={:?}", ty);
+    if !ty.needs_subst() {
+        return Ok(());
+    }
+
+    struct UsedParamsNeedSubstVisitor<'tcx> {
+        tcx: TyCtxt<'tcx>,
+    };
+
+    impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
+        fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
+            if !c.needs_subst() {
+                return false;
+            }
+
+            match c.val {
+                ty::ConstKind::Param(..) => true,
+                _ => c.super_visit_with(self),
+            }
+        }
+
+        fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
+            if !ty.needs_subst() {
+                return false;
+            }
+
+            match ty.kind {
+                ty::Param(_) => true,
+                ty::Closure(def_id, substs)
+                | ty::Generator(def_id, substs, ..)
+                | ty::FnDef(def_id, substs) => {
+                    let unused_params = self.tcx.unused_generic_params(def_id);
+                    for (index, subst) in substs.into_iter().enumerate() {
+                        let index = index
+                            .try_into()
+                            .expect("more generic parameters than can fit into a `u32`");
+                        let is_used =
+                            unused_params.contains(index).map(|unused| !unused).unwrap_or(true);
+                        // Only recurse when generic parameters in fns, closures and generators
+                        // are used and require substitution.
+                        if is_used && subst.needs_subst() {
+                            // Just in case there are closures or generators within this subst,
+                            // recurse.
+                            if subst.super_visit_with(self) {
+                                // Only return when we find a parameter so the remaining substs
+                                // are not skipped.
+                                return true;
+                            }
+                        }
+                    }
+                    false
+                }
+                _ => ty.super_visit_with(self),
+            }
+        }
+    }
+
+    let mut vis = UsedParamsNeedSubstVisitor { tcx };
+    if ty.visit_with(&mut vis) {
+        throw_inval!(TooGeneric);
+    } else {
+        Ok(())
+    }
+}
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index bfa9bb9e0f0..6a7653b6075 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -193,7 +193,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
             );
         }
         let patch = {
-            let param_env = tcx.param_env(def_id).with_reveal_all();
+            let param_env = tcx.param_env_reveal_all_normalized(def_id);
             let mut elaborator =
                 DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, param_env };
             let dropee = tcx.mk_place_deref(dropee_ptr);
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index a1db06e6aa3..8e2fd709d66 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -328,7 +328,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     ) -> ConstPropagator<'mir, 'tcx> {
         let def_id = source.def_id();
         let substs = &InternalSubsts::identity_for_item(tcx, def_id);
-        let param_env = tcx.param_env(def_id).with_reveal_all();
+        let param_env = tcx.param_env_reveal_all_normalized(def_id);
 
         let span = tcx.def_span(def_id);
         let can_const_prop = CanConstProp::check(body);
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index d3bfd872d16..ad49090bfc5 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -25,7 +25,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
         debug!("elaborate_drops({:?} @ {:?})", src, body.span);
 
         let def_id = src.def_id();
-        let param_env = tcx.param_env(src.def_id()).with_reveal_all();
+        let param_env = tcx.param_env_reveal_all_normalized(src.def_id());
         let move_data = match MoveData::gather_moves(body, tcx, param_env) {
             Ok(move_data) => move_data,
             Err((move_data, _)) => {
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index c03be2a8fcd..92ea162e419 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -72,7 +72,7 @@ impl Inliner<'tcx> {
 
         let mut callsites = VecDeque::new();
 
-        let param_env = self.tcx.param_env(self.source.def_id()).with_reveal_all();
+        let param_env = self.tcx.param_env_reveal_all_normalized(self.source.def_id());
 
         // Only do inlining into fn bodies.
         let id = self.tcx.hir().as_local_hir_id(self.source.def_id().expect_local());
diff --git a/src/librustc_mir/transform/instrument_coverage.rs b/src/librustc_mir/transform/instrument_coverage.rs
index 9933a975e4d..fe63a67fdbb 100644
--- a/src/librustc_mir/transform/instrument_coverage.rs
+++ b/src/librustc_mir/transform/instrument_coverage.rs
@@ -7,10 +7,9 @@ use rustc_middle::hir;
 use rustc_middle::ich::StableHashingContext;
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::mir::CoverageInfo;
 use rustc_middle::mir::{
-    self, traversal, BasicBlock, BasicBlockData, Operand, Place, SourceInfo, StatementKind,
-    Terminator, TerminatorKind, START_BLOCK,
+    self, traversal, BasicBlock, BasicBlockData, CoverageInfo, Operand, Place, SourceInfo,
+    SourceScope, StatementKind, Terminator, TerminatorKind,
 };
 use rustc_middle::ty;
 use rustc_middle::ty::query::Providers;
@@ -41,14 +40,14 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, mir_def_id: DefId) -> Coverage
         tcx.require_lang_item(lang_items::CoverageCounterSubtractFnLangItem, None);
 
     // The `num_counters` argument to `llvm.instrprof.increment` is the number of injected
-    // counters, with each counter having an index from `0..num_counters-1`. MIR optimization
+    // counters, with each counter having a counter ID from `0..num_counters-1`. MIR optimization
     // may split and duplicate some BasicBlock sequences. Simply counting the calls may not
-    // not work; but computing the num_counters by adding `1` to the highest index (for a given
+    // work; but computing the num_counters by adding `1` to the highest counter_id (for a given
     // instrumented function) is valid.
     //
     // `num_expressions` is the number of counter expressions added to the MIR body. Both
     // `num_counters` and `num_expressions` are used to initialize new vectors, during backend
-    // code generate, to lookup counters and expressions by their simple u32 indexes.
+    // code generate, to lookup counters and expressions by simple u32 indexes.
     let mut num_counters: u32 = 0;
     let mut num_expressions: u32 = 0;
     for terminator in
@@ -57,27 +56,26 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, mir_def_id: DefId) -> Coverage
         if let TerminatorKind::Call { func: Operand::Constant(func), args, .. } = &terminator.kind {
             match func.literal.ty.kind {
                 FnDef(id, _) if id == count_code_region_fn => {
-                    let index_arg =
-                        args.get(count_code_region_args::COUNTER_INDEX).expect("arg found");
-                    let counter_index = mir::Operand::scalar_from_const(index_arg)
+                    let counter_id_arg =
+                        args.get(count_code_region_args::COUNTER_ID).expect("arg found");
+                    let counter_id = mir::Operand::scalar_from_const(counter_id_arg)
                         .to_u32()
-                        .expect("index arg is u32");
-                    num_counters = std::cmp::max(num_counters, counter_index + 1);
+                        .expect("counter_id arg is u32");
+                    num_counters = std::cmp::max(num_counters, counter_id + 1);
                 }
                 FnDef(id, _)
                     if id == coverage_counter_add_fn || id == coverage_counter_subtract_fn =>
                 {
-                    let index_arg = args
-                        .get(coverage_counter_expression_args::COUNTER_EXPRESSION_INDEX)
+                    let expression_id_arg = args
+                        .get(coverage_counter_expression_args::EXPRESSION_ID)
                         .expect("arg found");
-                    let translated_index = mir::Operand::scalar_from_const(index_arg)
+                    let id_descending_from_max = mir::Operand::scalar_from_const(expression_id_arg)
                         .to_u32()
-                        .expect("index arg is u32");
-                    // Counter expressions start with "translated indexes", descending from
-                    // `u32::MAX`, so the range of expression indexes is disjoint from the range of
-                    // counter indexes. This way, both counters and expressions can be operands in
-                    // other expressions.
-                    let expression_index = u32::MAX - translated_index;
+                        .expect("expression_id arg is u32");
+                    // Counter expressions are initially assigned IDs descending from `u32::MAX`, so
+                    // the range of expression IDs is disjoint from the range of counter IDs. This
+                    // way, both counters and expressions can be operands in other expressions.
+                    let expression_index = u32::MAX - id_descending_from_max;
                     num_expressions = std::cmp::max(num_expressions, expression_index + 1);
                 }
                 _ => {}
@@ -97,12 +95,10 @@ fn call_terminators(data: &'tcx BasicBlockData<'tcx>) -> Option<&'tcx Terminator
 
 impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, mir_body: &mut mir::Body<'tcx>) {
-        if tcx.sess.opts.debugging_opts.instrument_coverage {
-            // If the InstrumentCoverage pass is called on promoted MIRs, skip them.
-            // See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601
-            if src.promoted.is_none() {
-                Instrumentor::new(tcx, src, mir_body).inject_counters();
-            }
+        // If the InstrumentCoverage pass is called on promoted MIRs, skip them.
+        // See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601
+        if src.promoted.is_none() {
+            Instrumentor::new(tcx, src, mir_body).inject_counters();
         }
     }
 }
@@ -113,6 +109,12 @@ enum Op {
     Subtract,
 }
 
+struct InjectedCall<'tcx> {
+    func: Operand<'tcx>,
+    args: Vec<Operand<'tcx>>,
+    inject_at: Span,
+}
+
 struct Instrumentor<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     mir_def_id: DefId,
@@ -147,11 +149,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
     }
 
     /// Expression IDs start from u32::MAX and go down because a CounterExpression can reference
-    /// (add or subtract counts) of both Counter regions and CounterExpression regions. The indexes
-    /// of each type of region must be contiguous, but also must be unique across both sets.
-    /// The expression IDs are eventually translated into region indexes (starting after the last
-    /// counter index, for the given function), during backend code generation, by the helper method
-    /// `rustc_codegen_ssa::coverageinfo::map::FunctionCoverage::translate_expressions()`.
+    /// (add or subtract counts) of both Counter regions and CounterExpression regions. The counter
+    /// expression operand IDs must be unique across both types.
     fn next_expression(&mut self) -> u32 {
         assert!(self.num_counters < u32::MAX - self.num_expressions);
         let next = u32::MAX - self.num_expressions;
@@ -171,17 +170,25 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
     }
 
     fn inject_counters(&mut self) {
+        let mir_body = &self.mir_body;
         let body_span = self.hir_body.value.span;
-        debug!(
-            "instrumenting {:?}, span: {}",
-            self.mir_def_id,
-            self.tcx.sess.source_map().span_to_string(body_span)
-        );
+        debug!("instrumenting {:?}, span: {:?}", self.mir_def_id, body_span);
 
         // FIXME(richkadel): As a first step, counters are only injected at the top of each
         // function. The complete solution will inject counters at each conditional code branch.
-        let next_block = START_BLOCK;
-        self.inject_counter(body_span, next_block);
+        let _ignore = mir_body;
+        let id = self.next_counter();
+        let function_source_hash = self.function_source_hash();
+        let code_region = body_span;
+        let scope = rustc_middle::mir::OUTERMOST_SOURCE_SCOPE;
+        let is_cleanup = false;
+        let next_block = rustc_middle::mir::START_BLOCK;
+        self.inject_call(
+            self.make_counter(id, function_source_hash, code_region),
+            scope,
+            is_cleanup,
+            next_block,
+        );
 
         // FIXME(richkadel): The next step to implement source based coverage analysis will be
         // instrumenting branches within functions, and some regions will be counted by "counter
@@ -190,57 +197,68 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
         let fake_use = false;
         if fake_use {
             let add = false;
-            if add {
-                self.inject_counter_expression(body_span, next_block, 1, Op::Add, 2);
-            } else {
-                self.inject_counter_expression(body_span, next_block, 1, Op::Subtract, 2);
-            }
+            let lhs = 1;
+            let op = if add { Op::Add } else { Op::Subtract };
+            let rhs = 2;
+
+            let code_region = body_span;
+            let scope = rustc_middle::mir::OUTERMOST_SOURCE_SCOPE;
+            let is_cleanup = false;
+            let next_block = rustc_middle::mir::START_BLOCK;
+
+            let id = self.next_expression();
+            self.inject_call(
+                self.make_expression(id, code_region, lhs, op, rhs),
+                scope,
+                is_cleanup,
+                next_block,
+            );
         }
     }
 
-    fn inject_counter(&mut self, code_region: Span, next_block: BasicBlock) -> u32 {
-        let counter_id = self.next_counter();
-        let function_source_hash = self.function_source_hash();
-        let injection_point = code_region.shrink_to_lo();
+    fn make_counter(
+        &self,
+        id: u32,
+        function_source_hash: u64,
+        code_region: Span,
+    ) -> InjectedCall<'tcx> {
+        let inject_at = code_region.shrink_to_lo();
 
-        let count_code_region_fn = function_handle(
+        let func = function_handle(
             self.tcx,
             self.tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None),
-            injection_point,
+            inject_at,
         );
 
         let mut args = Vec::new();
 
         use count_code_region_args::*;
         debug_assert_eq!(FUNCTION_SOURCE_HASH, args.len());
-        args.push(self.const_u64(function_source_hash, injection_point));
+        args.push(self.const_u64(function_source_hash, inject_at));
 
-        debug_assert_eq!(COUNTER_INDEX, args.len());
-        args.push(self.const_u32(counter_id, injection_point));
+        debug_assert_eq!(COUNTER_ID, args.len());
+        args.push(self.const_u32(id, inject_at));
 
         debug_assert_eq!(START_BYTE_POS, args.len());
-        args.push(self.const_u32(code_region.lo().to_u32(), injection_point));
+        args.push(self.const_u32(code_region.lo().to_u32(), inject_at));
 
         debug_assert_eq!(END_BYTE_POS, args.len());
-        args.push(self.const_u32(code_region.hi().to_u32(), injection_point));
-
-        self.inject_call(count_code_region_fn, args, injection_point, next_block);
+        args.push(self.const_u32(code_region.hi().to_u32(), inject_at));
 
-        counter_id
+        InjectedCall { func, args, inject_at }
     }
 
-    fn inject_counter_expression(
-        &mut self,
+    fn make_expression(
+        &self,
+        id: u32,
         code_region: Span,
-        next_block: BasicBlock,
         lhs: u32,
         op: Op,
         rhs: u32,
-    ) -> u32 {
-        let expression_id = self.next_expression();
-        let injection_point = code_region.shrink_to_lo();
+    ) -> InjectedCall<'tcx> {
+        let inject_at = code_region.shrink_to_lo();
 
-        let count_code_region_fn = function_handle(
+        let func = function_handle(
             self.tcx,
             self.tcx.require_lang_item(
                 match op {
@@ -249,43 +267,51 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
                 },
                 None,
             ),
-            injection_point,
+            inject_at,
         );
 
         let mut args = Vec::new();
 
         use coverage_counter_expression_args::*;
-        debug_assert_eq!(COUNTER_EXPRESSION_INDEX, args.len());
-        args.push(self.const_u32(expression_id, injection_point));
+        debug_assert_eq!(EXPRESSION_ID, args.len());
+        args.push(self.const_u32(id, inject_at));
 
-        debug_assert_eq!(LEFT_INDEX, args.len());
-        args.push(self.const_u32(lhs, injection_point));
+        debug_assert_eq!(LEFT_ID, args.len());
+        args.push(self.const_u32(lhs, inject_at));
 
-        debug_assert_eq!(RIGHT_INDEX, args.len());
-        args.push(self.const_u32(rhs, injection_point));
+        debug_assert_eq!(RIGHT_ID, args.len());
+        args.push(self.const_u32(rhs, inject_at));
 
         debug_assert_eq!(START_BYTE_POS, args.len());
-        args.push(self.const_u32(code_region.lo().to_u32(), injection_point));
+        args.push(self.const_u32(code_region.lo().to_u32(), inject_at));
 
         debug_assert_eq!(END_BYTE_POS, args.len());
-        args.push(self.const_u32(code_region.hi().to_u32(), injection_point));
+        args.push(self.const_u32(code_region.hi().to_u32(), inject_at));
 
-        self.inject_call(count_code_region_fn, args, injection_point, next_block);
-
-        expression_id
+        InjectedCall { func, args, inject_at }
     }
 
     fn inject_call(
         &mut self,
-        func: Operand<'tcx>,
-        args: Vec<Operand<'tcx>>,
-        fn_span: Span,
+        call: InjectedCall<'tcx>,
+        scope: SourceScope,
+        is_cleanup: bool,
         next_block: BasicBlock,
     ) {
+        let InjectedCall { func, args, inject_at } = call;
+        debug!(
+            "  injecting {}call to {:?}({:?}) at: {:?}, scope: {:?}",
+            if is_cleanup { "cleanup " } else { "" },
+            func,
+            args,
+            inject_at,
+            scope,
+        );
+
         let mut patch = MirPatch::new(self.mir_body);
 
-        let temp = patch.new_temp(self.tcx.mk_unit(), fn_span);
-        let new_block = patch.new_block(placeholder_block(fn_span));
+        let temp = patch.new_temp(self.tcx.mk_unit(), inject_at);
+        let new_block = patch.new_block(placeholder_block(inject_at, scope, is_cleanup));
         patch.patch_terminator(
             new_block,
             TerminatorKind::Call {
@@ -295,7 +321,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
                 destination: Some((Place::from(temp), new_block)),
                 cleanup: None,
                 from_hir_call: false,
-                fn_span,
+                fn_span: inject_at,
             },
         );
 
@@ -325,15 +351,15 @@ fn function_handle<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: DefId, span: Span) -> Ope
     Operand::function_handle(tcx, fn_def_id, substs, span)
 }
 
-fn placeholder_block(span: Span) -> BasicBlockData<'tcx> {
+fn placeholder_block(span: Span, scope: SourceScope, is_cleanup: bool) -> BasicBlockData<'tcx> {
     BasicBlockData {
         statements: vec![],
         terminator: Some(Terminator {
-            source_info: SourceInfo::outermost(span),
+            source_info: SourceInfo { span, scope },
             // this gets overwritten by the counter Call
             kind: TerminatorKind::Unreachable,
         }),
-        is_cleanup: false,
+        is_cleanup,
     }
 }
 
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 283e4b289f2..26b4a696897 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -332,21 +332,25 @@ fn mir_validated(
     body.required_consts = required_consts;
 
     let promote_pass = promote_consts::PromoteTemps::default();
+    let promote: &[&dyn MirPass<'tcx>] = &[
+        // What we need to run borrowck etc.
+        &promote_pass,
+        &simplify::SimplifyCfg::new("qualify-consts"),
+    ];
+
+    let opt_coverage: &[&dyn MirPass<'tcx>] = if tcx.sess.opts.debugging_opts.instrument_coverage {
+        &[&instrument_coverage::InstrumentCoverage]
+    } else {
+        &[]
+    };
+
     run_passes(
         tcx,
         &mut body,
         InstanceDef::Item(def.to_global()),
         None,
         MirPhase::Validated,
-        &[&[
-            // What we need to run borrowck etc.
-            &promote_pass,
-            &simplify::SimplifyCfg::new("qualify-consts"),
-            // If the `instrument-coverage` option is enabled, analyze the CFG, identify each
-            // conditional branch, construct a coverage map to be passed to LLVM, and inject counters
-            // where needed.
-            &instrument_coverage::InstrumentCoverage,
-        ]],
+        &[promote, opt_coverage],
     );
 
     let promoted = promote_pass.promoted_fragments.into_inner();
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 59a8415ef96..f1a7338d11f 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -502,9 +502,47 @@ impl<'tcx> Validator<'_, 'tcx> {
     fn validate_place(&self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> {
         match place {
             PlaceRef { local, projection: [] } => self.validate_local(local),
-            PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
+            PlaceRef { local, projection: [proj_base @ .., elem] } => {
                 match *elem {
-                    ProjectionElem::Deref | ProjectionElem::Downcast(..) => {
+                    ProjectionElem::Deref => {
+                        let mut not_promotable = true;
+                        // This is a special treatment for cases like *&STATIC where STATIC is a
+                        // global static variable.
+                        // This pattern is generated only when global static variables are directly
+                        // accessed and is qualified for promotion safely.
+                        if let TempState::Defined { location, .. } = self.temps[local] {
+                            let def_stmt =
+                                self.body[location.block].statements.get(location.statement_index);
+                            if let Some(Statement {
+                                kind:
+                                    StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(c)))),
+                                ..
+                            }) = def_stmt
+                            {
+                                if let Some(did) = c.check_static_ptr(self.tcx) {
+                                    if let Some(hir::ConstContext::Static(..)) = self.const_kind {
+                                        // The `is_empty` predicate is introduced to exclude the case
+                                        // where the projection operations are [ .field, * ].
+                                        // The reason is because promotion will be illegal if field
+                                        // accesses precede the dereferencing.
+                                        // Discussion can be found at
+                                        // https://github.com/rust-lang/rust/pull/74945#discussion_r463063247
+                                        // There may be opportunity for generalization, but this needs to be
+                                        // accounted for.
+                                        if proj_base.is_empty()
+                                            && !self.tcx.is_thread_local_static(did)
+                                        {
+                                            not_promotable = false;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if not_promotable {
+                            return Err(Unpromotable);
+                        }
+                    }
+                    ProjectionElem::Downcast(..) => {
                         return Err(Unpromotable);
                     }
 
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index 491c37cbe06..9288d6e16f5 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -33,6 +33,7 @@ use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
+use smallvec::SmallVec;
 use std::borrow::Cow;
 
 pub struct SimplifyCfg {
@@ -172,9 +173,12 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
         }
     }
 
-    // Collapse a goto chain starting from `start`
-    fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
-        let mut terminator = match self.basic_blocks[*start] {
+    /// This function will return `None` if
+    /// * the block has statements
+    /// * the block has a terminator other than `goto`
+    /// * the block has no terminator (meaning some other part of the current optimization stole it)
+    fn take_terminator_if_simple_goto(&mut self, bb: BasicBlock) -> Option<Terminator<'tcx>> {
+        match self.basic_blocks[bb] {
             BasicBlockData {
                 ref statements,
                 terminator:
@@ -183,32 +187,45 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
             } if statements.is_empty() => terminator.take(),
             // if `terminator` is None, this means we are in a loop. In that
             // case, let all the loop collapse to its entry.
-            _ => return,
-        };
-
-        let target = match terminator {
-            Some(Terminator { kind: TerminatorKind::Goto { ref mut target }, .. }) => {
-                self.collapse_goto_chain(target, changed);
-                *target
-            }
-            _ => unreachable!(),
-        };
-        self.basic_blocks[*start].terminator = terminator;
-
-        debug!("collapsing goto chain from {:?} to {:?}", *start, target);
-
-        *changed |= *start != target;
+            _ => None,
+        }
+    }
 
-        if self.pred_count[*start] == 1 {
-            // This is the last reference to *start, so the pred-count to
-            // to target is moved into the current block.
-            self.pred_count[*start] = 0;
-        } else {
-            self.pred_count[target] += 1;
-            self.pred_count[*start] -= 1;
+    /// Collapse a goto chain starting from `start`
+    fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
+        // Using `SmallVec` here, because in some logs on libcore oli-obk saw many single-element
+        // goto chains. We should probably benchmark different sizes.
+        let mut terminators: SmallVec<[_; 1]> = Default::default();
+        let mut current = *start;
+        while let Some(terminator) = self.take_terminator_if_simple_goto(current) {
+            let target = match terminator {
+                Terminator { kind: TerminatorKind::Goto { target }, .. } => target,
+                _ => unreachable!(),
+            };
+            terminators.push((current, terminator));
+            current = target;
         }
+        let last = current;
+        *start = last;
+        while let Some((current, mut terminator)) = terminators.pop() {
+            let target = match terminator {
+                Terminator { kind: TerminatorKind::Goto { ref mut target }, .. } => target,
+                _ => unreachable!(),
+            };
+            *target = last;
+            debug!("collapsing goto chain from {:?} to {:?}", current, target);
 
-        *start = target;
+            if self.pred_count[current] == 1 {
+                // This is the last reference to current, so the pred-count to
+                // to target is moved into the current block.
+                self.pred_count[current] = 0;
+            } else {
+                self.pred_count[*target] += 1;
+                self.pred_count[current] -= 1;
+            }
+            *changed = true;
+            self.basic_blocks[current].terminator = Some(terminator);
+        }
     }
 
     // merge a block with 1 `goto` predecessor to its parent
diff --git a/src/librustc_mir/transform/validate.rs b/src/librustc_mir/transform/validate.rs
index e794a6949d2..b8a74f09409 100644
--- a/src/librustc_mir/transform/validate.rs
+++ b/src/librustc_mir/transform/validate.rs
@@ -189,7 +189,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // Normalize projections and things like that.
         // FIXME: We need to reveal_all, as some optimizations change types in ways
         // that require unfolding opaque types.
-        let param_env = self.param_env.with_reveal_all();
+        let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
         let src = self.tcx.normalize_erasing_regions(param_env, src);
         let dest = self.tcx.normalize_erasing_regions(param_env, dest);
 
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 990bfc064c2..25657ba98b8 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -177,6 +177,7 @@ fn dump_path(
     let mut file_path = PathBuf::new();
     file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir));
 
+    let crate_name = tcx.crate_name(source.def_id().krate);
     let item_name = tcx.def_path(source.def_id()).to_filename_friendly_no_crate();
     // All drop shims have the same DefId, so we have to add the type
     // to get unique file names.
@@ -196,8 +197,15 @@ fn dump_path(
     };
 
     let file_name = format!(
-        "rustc.{}{}{}{}.{}.{}.{}",
-        item_name, shim_disambiguator, promotion_id, pass_num, pass_name, disambiguator, extension,
+        "{}.{}{}{}{}.{}.{}.{}",
+        crate_name,
+        item_name,
+        shim_disambiguator,
+        promotion_id,
+        pass_num,
+        pass_name,
+        disambiguator,
+        extension,
     );
 
     file_path.push(&file_name);
@@ -588,7 +596,7 @@ pub fn write_allocations<'tcx>(
                         todo.push(id);
                     }
                 }
-                write_allocation(tcx, alloc, w)
+                write!(w, "{}", display_allocation(tcx, alloc))
             };
         write!(w, "\n{}", id)?;
         match tcx.get_global_alloc(id) {
@@ -640,24 +648,36 @@ pub fn write_allocations<'tcx>(
 /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control
 /// characters or characters whose value is larger than 127) with a `.`
 /// This also prints relocations adequately.
-pub fn write_allocation<Tag: Copy + Debug, Extra>(
+pub fn display_allocation<Tag: Copy + Debug, Extra>(
     tcx: TyCtxt<'tcx>,
-    alloc: &Allocation<Tag, Extra>,
-    w: &mut dyn Write,
-) -> io::Result<()> {
-    write!(w, "size: {}, align: {})", alloc.size.bytes(), alloc.align.bytes())?;
-    if alloc.size == Size::ZERO {
-        // We are done.
-        return write!(w, " {{}}");
+    alloc: &'a Allocation<Tag, Extra>,
+) -> RenderAllocation<'a, 'tcx, Tag, Extra> {
+    RenderAllocation { tcx, alloc }
+}
+
+#[doc(hidden)]
+pub struct RenderAllocation<'a, 'tcx, Tag, Extra> {
+    tcx: TyCtxt<'tcx>,
+    alloc: &'a Allocation<Tag, Extra>,
+}
+
+impl<Tag: Copy + Debug, Extra> std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> {
+    fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let RenderAllocation { tcx, alloc } = *self;
+        write!(w, "size: {}, align: {})", alloc.size.bytes(), alloc.align.bytes())?;
+        if alloc.size == Size::ZERO {
+            // We are done.
+            return write!(w, " {{}}");
+        }
+        // Write allocation bytes.
+        writeln!(w, " {{")?;
+        write_allocation_bytes(tcx, alloc, w, "    ")?;
+        write!(w, "}}")?;
+        Ok(())
     }
-    // Write allocation bytes.
-    writeln!(w, " {{")?;
-    write_allocation_bytes(tcx, alloc, w, "    ")?;
-    write!(w, "}}")?;
-    Ok(())
 }
 
-fn write_allocation_endline(w: &mut dyn Write, ascii: &str) -> io::Result<()> {
+fn write_allocation_endline(w: &mut dyn std::fmt::Write, ascii: &str) -> std::fmt::Result {
     for _ in 0..(BYTES_PER_LINE - ascii.chars().count()) {
         write!(w, "   ")?;
     }
@@ -669,12 +689,12 @@ const BYTES_PER_LINE: usize = 16;
 
 /// Prints the line start address and returns the new line start address.
 fn write_allocation_newline(
-    w: &mut dyn Write,
+    w: &mut dyn std::fmt::Write,
     mut line_start: Size,
     ascii: &str,
     pos_width: usize,
     prefix: &str,
-) -> io::Result<Size> {
+) -> Result<Size, std::fmt::Error> {
     write_allocation_endline(w, ascii)?;
     line_start += Size::from_bytes(BYTES_PER_LINE);
     write!(w, "{}0x{:02$x} │ ", prefix, line_start.bytes(), pos_width)?;
@@ -687,9 +707,9 @@ fn write_allocation_newline(
 fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
     tcx: TyCtxt<'tcx>,
     alloc: &Allocation<Tag, Extra>,
-    w: &mut dyn Write,
+    w: &mut dyn std::fmt::Write,
     prefix: &str,
-) -> io::Result<()> {
+) -> std::fmt::Result {
     let num_lines = alloc.size.bytes_usize().saturating_sub(BYTES_PER_LINE);
     // Number of chars needed to represent all line numbers.
     let pos_width = format!("{:x}", alloc.size.bytes()).len();
diff --git a/src/librustc_mir_build/Cargo.toml b/src/librustc_mir_build/Cargo.toml
index 401a5009e3c..96059fa43e5 100644
--- a/src/librustc_mir_build/Cargo.toml
+++ b/src/librustc_mir_build/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_arena = { path = "../librustc_arena" }
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_middle = { path = "../librustc_middle" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_attr = { path = "../librustc_attr" }
diff --git a/src/librustc_mir_build/build/block.rs b/src/librustc_mir_build/build/block.rs
index 2be4136ad42..d1cbf209b06 100644
--- a/src/librustc_mir_build/build/block.rs
+++ b/src/librustc_mir_build/build/block.rs
@@ -1,7 +1,7 @@
 use crate::build::matches::ArmHasGuard;
 use crate::build::ForGuard::OutsideGuard;
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
-use crate::hair::*;
+use crate::thir::*;
 use rustc_hir as hir;
 use rustc_middle::mir::*;
 use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN;
@@ -176,7 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let tail_result_is_ignored =
                 destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
             let span = match expr {
-                ExprRef::Hair(expr) => expr.span,
+                ExprRef::Thir(expr) => expr.span,
                 ExprRef::Mirror(ref expr) => expr.span,
             };
             this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored, span });
@@ -235,11 +235,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     .push_unsafe_count
                     .checked_sub(1)
                     .unwrap_or_else(|| span_bug!(span, "unsafe count underflow"));
-                if self.push_unsafe_count == 0 {
-                    Some(self.unpushed_unsafe)
-                } else {
-                    None
-                }
+                if self.push_unsafe_count == 0 { Some(self.unpushed_unsafe) } else { None }
             }
         };
 
diff --git a/src/librustc_mir_build/build/expr/as_constant.rs b/src/librustc_mir_build/build/expr/as_constant.rs
index 03ec0b48f8b..982aefcf604 100644
--- a/src/librustc_mir_build/build/expr/as_constant.rs
+++ b/src/librustc_mir_build/build/expr/as_constant.rs
@@ -1,7 +1,7 @@
 //! See docs in build/expr/mod.rs
 
 use crate::build::Builder;
-use crate::hair::*;
+use crate::thir::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
 
diff --git a/src/librustc_mir_build/build/expr/as_operand.rs b/src/librustc_mir_build/build/expr/as_operand.rs
index 5949fd1e22c..aac93f313f4 100644
--- a/src/librustc_mir_build/build/expr/as_operand.rs
+++ b/src/librustc_mir_build/build/expr/as_operand.rs
@@ -2,7 +2,7 @@
 
 use crate::build::expr::category::Category;
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
-use crate::hair::*;
+use crate::thir::*;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 
diff --git a/src/librustc_mir_build/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs
index e811d68d5a5..1e3e104c2ba 100644
--- a/src/librustc_mir_build/build/expr/as_place.rs
+++ b/src/librustc_mir_build/build/expr/as_place.rs
@@ -3,7 +3,7 @@
 use crate::build::expr::category::Category;
 use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
-use crate::hair::*;
+use crate::thir::*;
 use rustc_middle::middle::region;
 use rustc_middle::mir::AssertKind::BoundsCheck;
 use rustc_middle::mir::*;
diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs
index e2217fdfac0..9c5fddc6b77 100644
--- a/src/librustc_mir_build/build/expr/as_rvalue.rs
+++ b/src/librustc_mir_build/build/expr/as_rvalue.rs
@@ -4,7 +4,7 @@ use rustc_index::vec::Idx;
 
 use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
-use crate::hair::*;
+use crate::thir::*;
 use rustc_middle::middle::region;
 use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::*;
diff --git a/src/librustc_mir_build/build/expr/as_temp.rs b/src/librustc_mir_build/build/expr/as_temp.rs
index 901dadd6612..a9cc0cc2f24 100644
--- a/src/librustc_mir_build/build/expr/as_temp.rs
+++ b/src/librustc_mir_build/build/expr/as_temp.rs
@@ -2,7 +2,7 @@
 
 use crate::build::scope::DropKind;
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
-use crate::hair::*;
+use crate::thir::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_middle::middle::region;
@@ -67,12 +67,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 ExprKind::StaticRef { def_id, .. } => {
                     assert!(!this.hir.tcx().is_thread_local_static(def_id));
                     local_decl.internal = true;
-                    local_decl.local_info = Some(box LocalInfo::StaticRef { def_id, is_thread_local: false });
+                    local_decl.local_info =
+                        Some(box LocalInfo::StaticRef { def_id, is_thread_local: false });
                 }
                 ExprKind::ThreadLocalRef(def_id) => {
                     assert!(this.hir.tcx().is_thread_local_static(def_id));
                     local_decl.internal = true;
-                    local_decl.local_info = Some(box LocalInfo::StaticRef { def_id, is_thread_local: true });
+                    local_decl.local_info =
+                        Some(box LocalInfo::StaticRef { def_id, is_thread_local: true });
                 }
                 _ => {}
             }
diff --git a/src/librustc_mir_build/build/expr/category.rs b/src/librustc_mir_build/build/expr/category.rs
index fb4b7997b6a..9cabd186d84 100644
--- a/src/librustc_mir_build/build/expr/category.rs
+++ b/src/librustc_mir_build/build/expr/category.rs
@@ -1,4 +1,4 @@
-use crate::hair::*;
+use crate::thir::*;
 
 #[derive(Debug, PartialEq)]
 crate enum Category {
diff --git a/src/librustc_mir_build/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs
index 36f8034336b..c3f54b39a3f 100644
--- a/src/librustc_mir_build/build/expr/into.rs
+++ b/src/librustc_mir_build/build/expr/into.rs
@@ -2,7 +2,7 @@
 
 use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
-use crate::hair::*;
+use crate::thir::*;
 use rustc_ast::ast::InlineAsmOptions;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -320,23 +320,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.unit()
             }
             ExprKind::InlineAsm { template, operands, options, line_spans } => {
-                use crate::hair;
+                use crate::thir;
                 use rustc_middle::mir;
                 let operands = operands
                     .into_iter()
                     .map(|op| match op {
-                        hair::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In {
+                        thir::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In {
                             reg,
                             value: unpack!(block = this.as_local_operand(block, expr)),
                         },
-                        hair::InlineAsmOperand::Out { reg, late, expr } => {
+                        thir::InlineAsmOperand::Out { reg, late, expr } => {
                             mir::InlineAsmOperand::Out {
                                 reg,
                                 late,
                                 place: expr.map(|expr| unpack!(block = this.as_place(block, expr))),
                             }
                         }
-                        hair::InlineAsmOperand::InOut { reg, late, expr } => {
+                        thir::InlineAsmOperand::InOut { reg, late, expr } => {
                             let place = unpack!(block = this.as_place(block, expr));
                             mir::InlineAsmOperand::InOut {
                                 reg,
@@ -346,7 +346,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 out_place: Some(place),
                             }
                         }
-                        hair::InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
+                        thir::InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
                             mir::InlineAsmOperand::InOut {
                                 reg,
                                 late,
@@ -356,13 +356,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 }),
                             }
                         }
-                        hair::InlineAsmOperand::Const { expr } => mir::InlineAsmOperand::Const {
+                        thir::InlineAsmOperand::Const { expr } => mir::InlineAsmOperand::Const {
                             value: unpack!(block = this.as_local_operand(block, expr)),
                         },
-                        hair::InlineAsmOperand::SymFn { expr } => {
+                        thir::InlineAsmOperand::SymFn { expr } => {
                             mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) }
                         }
-                        hair::InlineAsmOperand::SymStatic { def_id } => {
+                        thir::InlineAsmOperand::SymStatic { def_id } => {
                             mir::InlineAsmOperand::SymStatic { def_id }
                         }
                     })
diff --git a/src/librustc_mir_build/build/expr/stmt.rs b/src/librustc_mir_build/build/expr/stmt.rs
index 49d6ce39ddf..f117689d940 100644
--- a/src/librustc_mir_build/build/expr/stmt.rs
+++ b/src/librustc_mir_build/build/expr/stmt.rs
@@ -1,11 +1,11 @@
 use crate::build::scope::BreakableTarget;
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
-use crate::hair::*;
+use crate::thir::*;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    /// Builds a block of MIR statements to evaluate the HAIR `expr`.
+    /// Builds a block of MIR statements to evaluate the THIR `expr`.
     /// If the original expression was an AST statement,
     /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
     /// span of that statement (including its semicolon, if any).
@@ -150,8 +150,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                     break;
                                 }
                             }
-                            this.block_context
-                                .push(BlockFrame::TailExpr { tail_result_is_ignored: true, span: expr.span });
+                            this.block_context.push(BlockFrame::TailExpr {
+                                tail_result_is_ignored: true,
+                                span: expr.span,
+                            });
                             return Some(expr.span);
                         }
                     }
diff --git a/src/librustc_mir_build/build/into.rs b/src/librustc_mir_build/build/into.rs
index 0baa0c833a5..7264e495b84 100644
--- a/src/librustc_mir_build/build/into.rs
+++ b/src/librustc_mir_build/build/into.rs
@@ -5,7 +5,7 @@
 //! latter `EvalInto` trait.
 
 use crate::build::{BlockAnd, Builder};
-use crate::hair::*;
+use crate::thir::*;
 use rustc_middle::mir::*;
 
 pub(in crate::build) trait EvalInto<'tcx> {
diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs
index 19948196f25..77c0fe8dda5 100644
--- a/src/librustc_mir_build/build/matches/mod.rs
+++ b/src/librustc_mir_build/build/matches/mod.rs
@@ -9,15 +9,18 @@ use crate::build::scope::DropKind;
 use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
-use crate::hair::{self, *};
-use rustc_data_structures::{fx::{FxHashMap, FxHashSet}, stack::ensure_sufficient_stack};
+use crate::thir::{self, *};
+use rustc_data_structures::{
+    fx::{FxHashMap, FxHashSet},
+    stack::ensure_sufficient_stack,
+};
 use rustc_hir::HirId;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
-use rustc_span::Span;
 use rustc_span::symbol::Symbol;
+use rustc_span::Span;
 use rustc_target::abi::VariantIdx;
 use smallvec::{smallvec, SmallVec};
 
@@ -395,7 +398,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         ..
                     },
                 ascription:
-                    hair::pattern::Ascription { user_ty: pat_ascription_ty, variance: _, user_ty_span },
+                    thir::pattern::Ascription { user_ty: pat_ascription_ty, variance: _, user_ty_span },
             } => {
                 let place =
                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
@@ -631,7 +634,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             PatKind::AscribeUserType {
                 ref subpattern,
-                ascription: hair::pattern::Ascription { ref user_ty, user_ty_span, variance: _ },
+                ascription: thir::pattern::Ascription { ref user_ty, user_ty_span, variance: _ },
             } => {
                 // This corresponds to something like
                 //
@@ -1982,16 +1985,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             source_info,
             internal: false,
             is_block_tail: None,
-            local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
-                binding_mode,
-                // hypothetically, `visit_primary_bindings` could try to unzip
-                // an outermost hir::Ty as we descend, matching up
-                // idents in pat; but complex w/ unclear UI payoff.
-                // Instead, just abandon providing diagnostic info.
-                opt_ty_info: None,
-                opt_match_place,
-                pat_span,
-            })))),
+            local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+                VarBindingForm {
+                    binding_mode,
+                    // hypothetically, `visit_primary_bindings` could try to unzip
+                    // an outermost hir::Ty as we descend, matching up
+                    // idents in pat; but complex w/ unclear UI payoff.
+                    // Instead, just abandon providing diagnostic info.
+                    opt_ty_info: None,
+                    opt_match_place,
+                    pat_span,
+                },
+            )))),
         };
         let for_arm_body = self.local_decls.push(local);
         self.var_debug_info.push(VarDebugInfo {
@@ -2009,7 +2014,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 source_info,
                 internal: false,
                 is_block_tail: None,
-                local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))),
+                local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(
+                    BindingForm::RefForGuard,
+                ))),
             });
             self.var_debug_info.push(VarDebugInfo {
                 name,
diff --git a/src/librustc_mir_build/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs
index 2917a771a2c..e584aeb9226 100644
--- a/src/librustc_mir_build/build/matches/simplify.rs
+++ b/src/librustc_mir_build/build/matches/simplify.rs
@@ -14,7 +14,7 @@
 
 use crate::build::matches::{Ascription, Binding, Candidate, MatchPair};
 use crate::build::Builder;
-use crate::hair::{self, *};
+use crate::thir::{self, *};
 use rustc_attr::{SignedInt, UnsignedInt};
 use rustc_hir::RangeEnd;
 use rustc_middle::mir::interpret::truncate;
@@ -108,7 +108,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         match *match_pair.pattern.kind {
             PatKind::AscribeUserType {
                 ref subpattern,
-                ascription: hair::pattern::Ascription { variance, user_ty, user_ty_span },
+                ascription: thir::pattern::Ascription { variance, user_ty, user_ty_span },
             } => {
                 // Apply the type ascription to the value at `match_pair.place`, which is the
                 // value being matched, taking the variance field into account.
diff --git a/src/librustc_mir_build/build/matches/test.rs b/src/librustc_mir_build/build/matches/test.rs
index 3e7bfc7d59b..158ad78a1bf 100644
--- a/src/librustc_mir_build/build/matches/test.rs
+++ b/src/librustc_mir_build/build/matches/test.rs
@@ -7,8 +7,8 @@
 
 use crate::build::matches::{Candidate, MatchPair, Test, TestKind};
 use crate::build::Builder;
-use crate::hair::pattern::compare_const_vals;
-use crate::hair::*;
+use crate::thir::pattern::compare_const_vals;
+use crate::thir::*;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::RangeEnd;
 use rustc_index::bit_set::BitSet;
@@ -443,7 +443,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 destination: Some((eq_result, eq_block)),
                 cleanup: Some(cleanup),
                 from_hir_call: false,
-                fn_span: source_info.span
+                fn_span: source_info.span,
             },
         );
 
diff --git a/src/librustc_mir_build/build/matches/util.rs b/src/librustc_mir_build/build/matches/util.rs
index 7d89a93129b..605396c5eb6 100644
--- a/src/librustc_mir_build/build/matches/util.rs
+++ b/src/librustc_mir_build/build/matches/util.rs
@@ -1,6 +1,6 @@
 use crate::build::matches::MatchPair;
 use crate::build::Builder;
-use crate::hair::*;
+use crate::thir::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty;
 use smallvec::SmallVec;
diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs
index 1e677f3d2ab..3c4587119cd 100644
--- a/src/librustc_mir_build/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -1,7 +1,7 @@
 use crate::build;
 use crate::build::scope::DropKind;
-use crate::hair::cx::Cx;
-use crate::hair::{BindingMode, LintLevel, PatKind};
+use crate::thir::cx::Cx;
+use crate::thir::{BindingMode, LintLevel, PatKind};
 use rustc_attr::{self as attr, UnwindAttr};
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
@@ -10,6 +10,7 @@ use rustc_hir::lang_items;
 use rustc_hir::{GeneratorKind, HirIdMap, Node};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::ty::subst::Subst;
@@ -293,7 +294,7 @@ struct Builder<'a, 'tcx> {
     /// see the `scope` module for more details.
     scopes: scope::Scopes<'tcx>,
 
-    /// The block-context: each time we build the code within an hair::Block,
+    /// The block-context: each time we build the code within an thir::Block,
     /// we push a frame here tracking whether we are building a statement or
     /// if we are pushing the tail expression of the block. This is used to
     /// embed information in generated temps about whether they were created
@@ -797,12 +798,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         argument_scope: region::Scope,
         ast_body: &'tcx hir::Expr<'tcx>,
     ) -> BlockAnd<()> {
+        let tcx = self.hir.tcx();
+        let attrs = tcx.codegen_fn_attrs(fn_def_id);
+        let naked = attrs.flags.contains(CodegenFnAttrFlags::NAKED);
+
         // Allocate locals for the function arguments
         for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
             let source_info =
                 SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span));
             let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
 
+            // Emit function argument debuginfo only for non-naked functions.
+            // See: https://github.com/rust-lang/rust/issues/42779
+            if naked {
+                continue;
+            }
+
             // If this is a simple binding pattern, give debuginfo a nice name.
             if let Some(arg) = arg_opt {
                 if let Some(ident) = arg.pat.simple_ident() {
@@ -815,7 +826,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        let tcx = self.hir.tcx();
         let tcx_hir = tcx.hir();
         let hir_typeck_results = self.hir.typeck_results();
 
diff --git a/src/librustc_mir_build/build/scope.rs b/src/librustc_mir_build/build/scope.rs
index b8df2709447..2a03bb78c6b 100644
--- a/src/librustc_mir_build/build/scope.rs
+++ b/src/librustc_mir_build/build/scope.rs
@@ -1,6 +1,6 @@
 /*!
 Managing the scope stack. The scopes are tied to lexical scopes, so as
-we descend the HAIR, we push a scope on the stack, build its
+we descend the THIR, we push a scope on the stack, build its
 contents, and then pop it off. Every scope is named by a
 `region::Scope`.
 
@@ -83,12 +83,12 @@ should go to.
 */
 
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
-use crate::hair::{Expr, ExprRef, LintLevel};
-use rustc_middle::middle::region;
-use rustc_middle::mir::*;
+use crate::thir::{Expr, ExprRef, LintLevel};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::GeneratorKind;
+use rustc_middle::middle::region;
+use rustc_middle::mir::*;
 use rustc_span::{Span, DUMMY_SP};
 use std::collections::hash_map::Entry;
 use std::mem;
diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs
index ed154b9dc6f..30545558933 100644
--- a/src/librustc_mir_build/lib.rs
+++ b/src/librustc_mir_build/lib.rs
@@ -17,13 +17,13 @@ extern crate log;
 extern crate rustc_middle;
 
 mod build;
-mod hair;
 mod lints;
+mod thir;
 
 use rustc_middle::ty::query::Providers;
 
 pub fn provide(providers: &mut Providers) {
-    providers.check_match = hair::pattern::check_match;
-    providers.lit_to_const = hair::constant::lit_to_const;
+    providers.check_match = thir::pattern::check_match;
+    providers.lit_to_const = thir::constant::lit_to_const;
     providers.mir_built = build::mir_built;
 }
diff --git a/src/librustc_mir_build/hair/constant.rs b/src/librustc_mir_build/thir/constant.rs
index e5af0b5bd6b..e5af0b5bd6b 100644
--- a/src/librustc_mir_build/hair/constant.rs
+++ b/src/librustc_mir_build/thir/constant.rs
diff --git a/src/librustc_mir_build/hair/cx/block.rs b/src/librustc_mir_build/thir/cx/block.rs
index a5381781d1d..980888df7fe 100644
--- a/src/librustc_mir_build/hair/cx/block.rs
+++ b/src/librustc_mir_build/thir/cx/block.rs
@@ -1,6 +1,6 @@
-use crate::hair::cx::to_ref::ToRef;
-use crate::hair::cx::Cx;
-use crate::hair::{self, *};
+use crate::thir::cx::to_ref::ToRef;
+use crate::thir::cx::Cx;
+use crate::thir::{self, *};
 
 use rustc_hir as hir;
 use rustc_middle::middle::region;
@@ -71,7 +71,7 @@ fn mirror_stmts<'a, 'tcx>(
                             ty: pattern.ty,
                             span: pattern.span,
                             kind: Box::new(PatKind::AscribeUserType {
-                                ascription: hair::pattern::Ascription {
+                                ascription: thir::pattern::Ascription {
                                     user_ty: PatTyProj::from_user_type(user_ty),
                                     user_ty_span: ty.span,
                                     variance: ty::Variance::Covariant,
diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/thir/cx/expr.rs
index 6e1d8a8fc40..ea41a66b3e4 100644
--- a/src/librustc_mir_build/hair/cx/expr.rs
+++ b/src/librustc_mir_build/thir/cx/expr.rs
@@ -1,8 +1,8 @@
-use crate::hair::cx::block;
-use crate::hair::cx::to_ref::ToRef;
-use crate::hair::cx::Cx;
-use crate::hair::util::UserAnnotatedTyHelpers;
-use crate::hair::*;
+use crate::thir::cx::block;
+use crate::thir::cx::to_ref::ToRef;
+use crate::thir::cx::Cx;
+use crate::thir::util::UserAnnotatedTyHelpers;
+use crate::thir::*;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_index::vec::Idx;
@@ -1020,7 +1020,7 @@ fn overloaded_place<'a, 'tcx>(
     // line up (this is because `*x` and `x[y]` represent places):
 
     let recv_ty = match args[0] {
-        ExprRef::Hair(e) => cx.typeck_results().expr_ty_adjusted(e),
+        ExprRef::Thir(e) => cx.typeck_results().expr_ty_adjusted(e),
         ExprRef::Mirror(ref e) => e.ty,
     };
 
diff --git a/src/librustc_mir_build/hair/cx/mod.rs b/src/librustc_mir_build/thir/cx/mod.rs
index 2694cde14fd..21736df7b07 100644
--- a/src/librustc_mir_build/hair/cx/mod.rs
+++ b/src/librustc_mir_build/thir/cx/mod.rs
@@ -1,9 +1,9 @@
 //! This module contains the functionality to convert from the wacky tcx data
-//! structures into the HAIR. The `builder` is generally ignorant of the tcx,
+//! structures into the THIR. The `builder` is generally ignorant of the tcx,
 //! etc., and instead goes through the `Cx` for most of its work.
 
-use crate::hair::util::UserAnnotatedTyHelpers;
-use crate::hair::*;
+use crate::thir::util::UserAnnotatedTyHelpers;
+use crate::thir::*;
 
 use rustc_ast::ast;
 use rustc_ast::attr;
diff --git a/src/librustc_mir_build/hair/cx/to_ref.rs b/src/librustc_mir_build/thir/cx/to_ref.rs
index 6cf8122e200..53a988ebb79 100644
--- a/src/librustc_mir_build/hair/cx/to_ref.rs
+++ b/src/librustc_mir_build/thir/cx/to_ref.rs
@@ -1,4 +1,4 @@
-use crate::hair::*;
+use crate::thir::*;
 
 use rustc_hir as hir;
 
@@ -11,7 +11,7 @@ impl<'tcx> ToRef for &'tcx hir::Expr<'tcx> {
     type Output = ExprRef<'tcx>;
 
     fn to_ref(self) -> ExprRef<'tcx> {
-        ExprRef::Hair(self)
+        ExprRef::Thir(self)
     }
 }
 
@@ -19,7 +19,7 @@ impl<'tcx> ToRef for &'tcx &'tcx hir::Expr<'tcx> {
     type Output = ExprRef<'tcx>;
 
     fn to_ref(self) -> ExprRef<'tcx> {
-        ExprRef::Hair(&**self)
+        ExprRef::Thir(&**self)
     }
 }
 
diff --git a/src/librustc_mir_build/hair/mod.rs b/src/librustc_mir_build/thir/mod.rs
index ccff510f2d4..b6ce7e0b41e 100644
--- a/src/librustc_mir_build/hair/mod.rs
+++ b/src/librustc_mir_build/thir/mod.rs
@@ -1,5 +1,5 @@
-//! The MIR is built from some high-level abstract IR
-//! (HAIR). This section defines the HAIR along with a trait for
+//! The MIR is built from some typed high-level IR
+//! (THIR). This section defines the THIR along with a trait for
 //! accessing it. The intention is to allow MIR construction to be
 //! unit-tested and separated from the Rust source and compiler data
 //! structures.
@@ -99,18 +99,18 @@ crate enum StmtKind<'tcx> {
 #[cfg(target_arch = "x86_64")]
 rustc_data_structures::static_assert_size!(Expr<'_>, 168);
 
-/// The Hair trait implementor lowers their expressions (`&'tcx H::Expr`)
+/// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
 /// into instances of this `Expr` enum. This lowering can be done
 /// basically as lazily or as eagerly as desired: every recursive
 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
 /// may in turn be another instance of this enum (boxed), or else an
 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
-/// short-lived. They are created by `Hair::to_expr`, analyzed and
+/// short-lived. They are created by `Thir::to_expr`, analyzed and
 /// converted into MIR, and then discarded.
 ///
 /// If you compare `Expr` to the full compiler AST, you will see it is
 /// a good bit simpler. In fact, a number of the more straight-forward
-/// MIR simplifications are already done in the impl of `Hair`. For
+/// MIR simplifications are already done in the impl of `Thir`. For
 /// example, method calls and overloaded operators are absent: they are
 /// expected to be converted into `Expr::Call` instances.
 #[derive(Clone, Debug)]
@@ -302,7 +302,7 @@ crate enum ExprKind<'tcx> {
 
 #[derive(Clone, Debug)]
 crate enum ExprRef<'tcx> {
-    Hair(&'tcx hir::Expr<'tcx>),
+    Thir(&'tcx hir::Expr<'tcx>),
     Mirror(Box<Expr<'tcx>>),
 }
 
@@ -342,7 +342,7 @@ crate enum LogicalOp {
 impl<'tcx> ExprRef<'tcx> {
     crate fn span(&self) -> Span {
         match self {
-            ExprRef::Hair(expr) => expr.span,
+            ExprRef::Thir(expr) => expr.span,
             ExprRef::Mirror(expr) => expr.span,
         }
     }
@@ -385,7 +385,7 @@ crate enum InlineAsmOperand<'tcx> {
 // The Mirror trait
 
 /// "Mirroring" is the process of converting from a HIR type into one
-/// of the HAIR types defined in this file. This is basically a "on
+/// of the THIR types defined in this file. This is basically a "on
 /// the fly" desugaring step that hides a lot of the messiness in the
 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
 /// `Expr<'tcx>`.
@@ -394,7 +394,7 @@ crate enum InlineAsmOperand<'tcx> {
 /// + e2`, the references to the inner expressions `e1` and `e2` are
 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
 /// mirrored. This allows a single AST node from the compiler to
-/// expand into one or more Hair nodes, which lets the Hair nodes be
+/// expand into one or more Thir nodes, which lets the Thir nodes be
 /// simpler.
 crate trait Mirror<'tcx> {
     type Output;
@@ -415,7 +415,7 @@ impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
 
     fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
         match self {
-            ExprRef::Hair(h) => h.make_mirror(hir),
+            ExprRef::Thir(h) => h.make_mirror(hir),
             ExprRef::Mirror(m) => *m,
         }
     }
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/thir/pattern/_match.rs
index 3202f7d1b1b..3202f7d1b1b 100644
--- a/src/librustc_mir_build/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/thir/pattern/_match.rs
diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/thir/pattern/check_match.rs
index 744f319205f..744f319205f 100644
--- a/src/librustc_mir_build/hair/pattern/check_match.rs
+++ b/src/librustc_mir_build/thir/pattern/check_match.rs
diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/thir/pattern/const_to_pat.rs
index 6dd7e0871b4..6dd7e0871b4 100644
--- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/thir/pattern/const_to_pat.rs
diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/thir/pattern/mod.rs
index a5c87bc963f..daff10eb194 100644
--- a/src/librustc_mir_build/hair/pattern/mod.rs
+++ b/src/librustc_mir_build/thir/pattern/mod.rs
@@ -6,7 +6,7 @@ mod const_to_pat;
 
 pub(crate) use self::check_match::check_match;
 
-use crate::hair::util::UserAnnotatedTyHelpers;
+use crate::thir::util::UserAnnotatedTyHelpers;
 
 use rustc_ast::ast;
 use rustc_errors::struct_span_err;
@@ -16,7 +16,7 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::RangeEnd;
 use rustc_index::vec::Idx;
 use rustc_middle::mir::interpret::{get_slice_bytes, sign_extend, ConstValue};
-use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
+use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
 use rustc_middle::mir::UserTypeProjection;
 use rustc_middle::mir::{BorrowKind, Field, Mutability};
 use rustc_middle::ty::subst::{GenericArg, SubstsRef};
@@ -133,7 +133,7 @@ crate enum PatKind<'tcx> {
         var: hir::HirId,
         ty: Ty<'tcx>,
         subpattern: Option<Pat<'tcx>>,
-        /// Is this the leftmost occurance of the binding, i.e., is `var` the
+        /// Is this the leftmost occurrence of the binding, i.e., is `var` the
         /// `HirId` of this pattern?
         is_primary: bool,
     },
@@ -402,7 +402,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         //
         // `vec![&&Option<i32>, &Option<i32>]`.
         //
-        // Applying the adjustments, we want to instead output `&&Some(n)` (as a HAIR pattern). So
+        // Applying the adjustments, we want to instead output `&&Some(n)` (as a THIR pattern). So
         // we wrap the unadjusted pattern in `PatKind::Deref` repeatedly, consuming the
         // adjustments in *reverse order* (last-in-first-out, so that the last `Deref` inserted
         // gets the least-dereferenced type).
@@ -776,7 +776,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
         // Use `Reveal::All` here because patterns are always monomorphic even if their function
         // isn't.
-        let param_env_reveal_all = self.param_env.with_reveal_all();
+        let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx);
         let substs = self.typeck_results.node_substs(id);
         let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
             Ok(Some(i)) => i,
@@ -834,6 +834,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     pattern
                 }
             }
+            Err(ErrorHandled::TooGeneric) => {
+                // While `Reported | Linted` cases will have diagnostics emitted already
+                // it is not true for TooGeneric case, so we need to give user more information.
+                self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
+                pat_from_kind(PatKind::Wild)
+            }
             Err(_) => {
                 self.tcx.sess.span_err(span, "could not evaluate constant pattern");
                 pat_from_kind(PatKind::Wild)
diff --git a/src/librustc_mir_build/hair/util.rs b/src/librustc_mir_build/thir/util.rs
index 7de60ddda41..7de60ddda41 100644
--- a/src/librustc_mir_build/hair/util.rs
+++ b/src/librustc_mir_build/thir/util.rs
diff --git a/src/librustc_parse/Cargo.toml b/src/librustc_parse/Cargo.toml
index 7164c678808..25144bd610d 100644
--- a/src/librustc_parse/Cargo.toml
+++ b/src/librustc_parse/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 bitflags = "1.0"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
@@ -21,3 +21,4 @@ rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rustc_ast = { path = "../librustc_ast" }
 unicode-normalization = "0.1.11"
+smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index be86b4b7c77..3319ca44da4 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -7,14 +7,16 @@
 #![feature(or_patterns)]
 
 use rustc_ast::ast;
-use rustc_ast::token::{self, Nonterminal};
+use rustc_ast::token::{self, DelimToken, Nonterminal, Token};
 use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Diagnostic, FatalError, Level, PResult};
 use rustc_session::parse::ParseSess;
-use rustc_span::{FileName, SourceFile, Span};
+use rustc_span::{symbol::kw, FileName, SourceFile, Span, DUMMY_SP};
 
+use smallvec::SmallVec;
+use std::mem;
 use std::path::Path;
 use std::str;
 
@@ -306,7 +308,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
     // modifications, including adding/removing typically non-semantic
     // tokens such as extra braces and commas, don't happen.
     if let Some(tokens) = tokens {
-        if tokens.probably_equal_for_proc_macro(&tokens_for_real) {
+        if tokenstream_probably_equal_for_proc_macro(&tokens, &tokens_for_real) {
             return tokens;
         }
         info!(
@@ -319,6 +321,186 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
     tokens_for_real
 }
 
+// See comments in `Nonterminal::to_tokenstream` for why we care about
+// *probably* equal here rather than actual equality
+//
+// This is otherwise the same as `eq_unspanned`, only recursing with a
+// different method.
+pub fn tokenstream_probably_equal_for_proc_macro(first: &TokenStream, other: &TokenStream) -> bool {
+    // When checking for `probably_eq`, we ignore certain tokens that aren't
+    // preserved in the AST. Because they are not preserved, the pretty
+    // printer arbitrarily adds or removes them when printing as token
+    // streams, making a comparison between a token stream generated from an
+    // AST and a token stream which was parsed into an AST more reliable.
+    fn semantic_tree(tree: &TokenTree) -> bool {
+        if let TokenTree::Token(token) = tree {
+            if let
+                // The pretty printer tends to add trailing commas to
+                // everything, and in particular, after struct fields.
+                | token::Comma
+                // The pretty printer emits `NoDelim` as whitespace.
+                | token::OpenDelim(DelimToken::NoDelim)
+                | token::CloseDelim(DelimToken::NoDelim)
+                // The pretty printer collapses many semicolons into one.
+                | token::Semi
+                // The pretty printer collapses whitespace arbitrarily and can
+                // introduce whitespace from `NoDelim`.
+                | token::Whitespace
+                // The pretty printer can turn `$crate` into `::crate_name`
+                | token::ModSep = token.kind {
+                return false;
+            }
+        }
+        true
+    }
+
+    // When comparing two `TokenStream`s, we ignore the `IsJoint` information.
+    //
+    // However, `rustc_parse::lexer::tokentrees::TokenStreamBuilder` will
+    // use `Token.glue` on adjacent tokens with the proper `IsJoint`.
+    // Since we are ignoreing `IsJoint`, a 'glued' token (e.g. `BinOp(Shr)`)
+    // and its 'split'/'unglued' compoenents (e.g. `Gt, Gt`) are equivalent
+    // when determining if two `TokenStream`s are 'probably equal'.
+    //
+    // Therefore, we use `break_two_token_op` to convert all tokens
+    // to the 'unglued' form (if it exists). This ensures that two
+    // `TokenStream`s which differ only in how their tokens are glued
+    // will be considered 'probably equal', which allows us to keep spans.
+    //
+    // This is important when the original `TokenStream` contained
+    // extra spaces (e.g. `f :: < Vec < _ > > ( ) ;'). These extra spaces
+    // will be omitted when we pretty-print, which can cause the original
+    // and reparsed `TokenStream`s to differ in the assignment of `IsJoint`,
+    // leading to some tokens being 'glued' together in one stream but not
+    // the other. See #68489 for more details.
+    fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
+        // In almost all cases, we should have either zero or one levels
+        // of 'unglueing'. However, in some unusual cases, we may need
+        // to iterate breaking tokens mutliple times. For example:
+        // '[BinOpEq(Shr)] => [Gt, Ge] -> [Gt, Gt, Eq]'
+        let mut token_trees: SmallVec<[_; 2]>;
+        if let TokenTree::Token(token) = &tree {
+            let mut out = SmallVec::<[_; 2]>::new();
+            out.push(token.clone());
+            // Iterate to fixpoint:
+            // * We start off with 'out' containing our initial token, and `temp` empty
+            // * If we are able to break any tokens in `out`, then `out` will have
+            //   at least one more element than 'temp', so we will try to break tokens
+            //   again.
+            // * If we cannot break any tokens in 'out', we are done
+            loop {
+                let mut temp = SmallVec::<[_; 2]>::new();
+                let mut changed = false;
+
+                for token in out.into_iter() {
+                    if let Some((first, second)) = token.kind.break_two_token_op() {
+                        temp.push(Token::new(first, DUMMY_SP));
+                        temp.push(Token::new(second, DUMMY_SP));
+                        changed = true;
+                    } else {
+                        temp.push(token);
+                    }
+                }
+                out = temp;
+                if !changed {
+                    break;
+                }
+            }
+            token_trees = out.into_iter().map(TokenTree::Token).collect();
+            if token_trees.len() != 1 {
+                debug!("break_tokens: broke {:?} to {:?}", tree, token_trees);
+            }
+        } else {
+            token_trees = SmallVec::new();
+            token_trees.push(tree);
+        }
+        token_trees.into_iter()
+    }
+
+    let mut t1 = first.trees().filter(semantic_tree).flat_map(break_tokens);
+    let mut t2 = other.trees().filter(semantic_tree).flat_map(break_tokens);
+    for (t1, t2) in t1.by_ref().zip(t2.by_ref()) {
+        if !tokentree_probably_equal_for_proc_macro(&t1, &t2) {
+            return false;
+        }
+    }
+    t1.next().is_none() && t2.next().is_none()
+}
+
+// See comments in `Nonterminal::to_tokenstream` for why we care about
+// *probably* equal here rather than actual equality
+//
+// This is otherwise the same as `eq_unspanned`, only recursing with a
+// different method.
+fn tokentree_probably_equal_for_proc_macro(first: &TokenTree, other: &TokenTree) -> bool {
+    match (first, other) {
+        (TokenTree::Token(token), TokenTree::Token(token2)) => {
+            token_probably_equal_for_proc_macro(token, token2)
+        }
+        (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
+            delim == delim2 && tokenstream_probably_equal_for_proc_macro(&tts, &tts2)
+        }
+        _ => false,
+    }
+}
+
+// See comments in `Nonterminal::to_tokenstream` for why we care about
+// *probably* equal here rather than actual equality
+fn token_probably_equal_for_proc_macro(first: &Token, other: &Token) -> bool {
+    if mem::discriminant(&first.kind) != mem::discriminant(&other.kind) {
+        return false;
+    }
+    use rustc_ast::token::TokenKind::*;
+    match (&first.kind, &other.kind) {
+        (&Eq, &Eq)
+        | (&Lt, &Lt)
+        | (&Le, &Le)
+        | (&EqEq, &EqEq)
+        | (&Ne, &Ne)
+        | (&Ge, &Ge)
+        | (&Gt, &Gt)
+        | (&AndAnd, &AndAnd)
+        | (&OrOr, &OrOr)
+        | (&Not, &Not)
+        | (&Tilde, &Tilde)
+        | (&At, &At)
+        | (&Dot, &Dot)
+        | (&DotDot, &DotDot)
+        | (&DotDotDot, &DotDotDot)
+        | (&DotDotEq, &DotDotEq)
+        | (&Comma, &Comma)
+        | (&Semi, &Semi)
+        | (&Colon, &Colon)
+        | (&ModSep, &ModSep)
+        | (&RArrow, &RArrow)
+        | (&LArrow, &LArrow)
+        | (&FatArrow, &FatArrow)
+        | (&Pound, &Pound)
+        | (&Dollar, &Dollar)
+        | (&Question, &Question)
+        | (&Whitespace, &Whitespace)
+        | (&Comment, &Comment)
+        | (&Eof, &Eof) => true,
+
+        (&BinOp(a), &BinOp(b)) | (&BinOpEq(a), &BinOpEq(b)) => a == b,
+
+        (&OpenDelim(a), &OpenDelim(b)) | (&CloseDelim(a), &CloseDelim(b)) => a == b,
+
+        (&DocComment(a), &DocComment(b)) | (&Shebang(a), &Shebang(b)) => a == b,
+
+        (&Literal(a), &Literal(b)) => a == b,
+
+        (&Lifetime(a), &Lifetime(b)) => a == b,
+        (&Ident(a, b), &Ident(c, d)) => {
+            b == d && (a == c || a == kw::DollarCrate || c == kw::DollarCrate)
+        }
+
+        (&Interpolated(..), &Interpolated(..)) => false,
+
+        _ => panic!("forgot to add a token?"),
+    }
+}
+
 fn prepend_attrs(
     sess: &ParseSess,
     attrs: &[ast::Attribute],
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 609a0c961e9..5e9411327ca 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -333,6 +333,7 @@ impl<'a> Parser<'a> {
                         Applicability::MachineApplicable
                     },
                 );
+                self.sess.type_ascription_path_suggestions.borrow_mut().insert(sp);
             } else if op_pos.line != next_pos.line && maybe_expected_semicolon {
                 err.span_suggestion(
                     sp,
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index d06b172bc14..3aec300d86d 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -1450,7 +1450,7 @@ impl<'a> Parser<'a> {
 
     /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
     /// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
-    pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
+    pub(super) fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
         maybe_whole_expr!(self);
 
         let lo = self.token.span;
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index 72866468b65..2509a979221 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -1,16 +1,17 @@
 pub mod attr;
+mod diagnostics;
 mod expr;
+mod generics;
 mod item;
+mod nonterminal;
 mod pat;
 mod path;
-mod ty;
-pub use path::PathStyle;
-mod diagnostics;
-mod generics;
 mod stmt;
-use diagnostics::Error;
+mod ty;
 
 use crate::lexer::UnmatchedBrace;
+use diagnostics::Error;
+pub use path::PathStyle;
 
 use log::debug;
 use rustc_ast::ast::DUMMY_NODE_ID;
@@ -958,7 +959,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a single token tree from the input.
-    pub fn parse_token_tree(&mut self) -> TokenTree {
+    pub(crate) fn parse_token_tree(&mut self) -> TokenTree {
         match self.token.kind {
             token::OpenDelim(..) => {
                 let frame = mem::replace(
@@ -1017,7 +1018,7 @@ impl<'a> Parser<'a> {
     /// If the following element can't be a tuple (i.e., it's a function definition), then
     /// it's not a tuple struct field), and the contents within the parentheses isn't valid,
     /// so emit a proper diagnostic.
-    pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
+    pub(crate) fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
         maybe_whole!(self, NtVis, |x| x);
 
         self.expected_tokens.push(TokenType::Keyword(kw::Crate));
diff --git a/src/librustc_parse/parser/nonterminal.rs b/src/librustc_parse/parser/nonterminal.rs
new file mode 100644
index 00000000000..12139771bbf
--- /dev/null
+++ b/src/librustc_parse/parser/nonterminal.rs
@@ -0,0 +1,163 @@
+use rustc_ast::ptr::P;
+use rustc_ast::token::{self, Nonterminal, NonterminalKind, Token};
+use rustc_ast_pretty::pprust;
+use rustc_errors::PResult;
+use rustc_span::symbol::{kw, Ident};
+
+use crate::parser::{FollowedByType, Parser, PathStyle};
+
+impl<'a> Parser<'a> {
+    /// Checks whether a non-terminal may begin with a particular token.
+    ///
+    /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
+    /// token. Be conservative (return true) if not sure.
+    pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
+        /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
+        fn may_be_ident(nt: &token::Nonterminal) -> bool {
+            match *nt {
+                token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_) => {
+                    false
+                }
+                _ => true,
+            }
+        }
+
+        match kind {
+            NonterminalKind::Expr => {
+                token.can_begin_expr()
+                // This exception is here for backwards compatibility.
+                && !token.is_keyword(kw::Let)
+            }
+            NonterminalKind::Ty => token.can_begin_type(),
+            NonterminalKind::Ident => get_macro_ident(token).is_some(),
+            NonterminalKind::Literal => token.can_begin_literal_maybe_minus(),
+            NonterminalKind::Vis => match token.kind {
+                // The follow-set of :vis + "priv" keyword + interpolated
+                token::Comma | token::Ident(..) | token::Interpolated(..) => true,
+                _ => token.can_begin_type(),
+            },
+            NonterminalKind::Block => match token.kind {
+                token::OpenDelim(token::Brace) => true,
+                token::Interpolated(ref nt) => match **nt {
+                    token::NtItem(_)
+                    | token::NtPat(_)
+                    | token::NtTy(_)
+                    | token::NtIdent(..)
+                    | token::NtMeta(_)
+                    | token::NtPath(_)
+                    | token::NtVis(_) => false, // none of these may start with '{'.
+                    _ => true,
+                },
+                _ => false,
+            },
+            NonterminalKind::Path | NonterminalKind::Meta => match token.kind {
+                token::ModSep | token::Ident(..) => true,
+                token::Interpolated(ref nt) => match **nt {
+                    token::NtPath(_) | token::NtMeta(_) => true,
+                    _ => may_be_ident(&nt),
+                },
+                _ => false,
+            },
+            NonterminalKind::Pat => match token.kind {
+                token::Ident(..) |                  // box, ref, mut, and other identifiers (can stricten)
+                token::OpenDelim(token::Paren) |    // tuple pattern
+                token::OpenDelim(token::Bracket) |  // slice pattern
+                token::BinOp(token::And) |          // reference
+                token::BinOp(token::Minus) |        // negative literal
+                token::AndAnd |                     // double reference
+                token::Literal(..) |                // literal
+                token::DotDot |                     // range pattern (future compat)
+                token::DotDotDot |                  // range pattern (future compat)
+                token::ModSep |                     // path
+                token::Lt |                         // path (UFCS constant)
+                token::BinOp(token::Shl) => true,   // path (double UFCS)
+                token::Interpolated(ref nt) => may_be_ident(nt),
+                _ => false,
+            },
+            NonterminalKind::Lifetime => match token.kind {
+                token::Lifetime(_) => true,
+                token::Interpolated(ref nt) => match **nt {
+                    token::NtLifetime(_) | token::NtTT(_) => true,
+                    _ => false,
+                },
+                _ => false,
+            },
+            NonterminalKind::TT | NonterminalKind::Item | NonterminalKind::Stmt => match token.kind
+            {
+                token::CloseDelim(_) => false,
+                _ => true,
+            },
+        }
+    }
+
+    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonterminal> {
+        // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
+        // needs to have them force-captured here.
+        // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
+        // which requires having captured tokens available. Since we cannot determine
+        // in advance whether or not a proc-macro will be (transitively) invoked,
+        // we always capture tokens for any `Nonterminal` which needs them.
+        Ok(match kind {
+            NonterminalKind::Item => match self.collect_tokens(|this| this.parse_item())? {
+                (Some(mut item), tokens) => {
+                    // If we captured tokens during parsing (due to outer attributes),
+                    // use those.
+                    if item.tokens.is_none() {
+                        item.tokens = Some(tokens);
+                    }
+                    token::NtItem(item)
+                }
+                (None, _) => {
+                    return Err(self.struct_span_err(self.token.span, "expected an item keyword"));
+                }
+            },
+            NonterminalKind::Block => token::NtBlock(self.parse_block()?),
+            NonterminalKind::Stmt => match self.parse_stmt()? {
+                Some(s) => token::NtStmt(s),
+                None => return Err(self.struct_span_err(self.token.span, "expected a statement")),
+            },
+            NonterminalKind::Pat => token::NtPat(self.parse_pat(None)?),
+            NonterminalKind::Expr => {
+                let (mut expr, tokens) = self.collect_tokens(|this| this.parse_expr())?;
+                // If we captured tokens during parsing (due to outer attributes),
+                // use those.
+                if expr.tokens.is_none() {
+                    expr.tokens = Some(tokens);
+                }
+                token::NtExpr(expr)
+            }
+            NonterminalKind::Literal => token::NtLiteral(self.parse_literal_maybe_minus()?),
+            NonterminalKind::Ty => token::NtTy(self.parse_ty()?),
+            // this could be handled like a token, since it is one
+            NonterminalKind::Ident => {
+                if let Some((ident, is_raw)) = get_macro_ident(&self.token) {
+                    self.bump();
+                    token::NtIdent(ident, is_raw)
+                } else {
+                    let token_str = pprust::token_to_string(&self.token);
+                    let msg = &format!("expected ident, found {}", &token_str);
+                    return Err(self.struct_span_err(self.token.span, msg));
+                }
+            }
+            NonterminalKind::Path => token::NtPath(self.parse_path(PathStyle::Type)?),
+            NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item()?)),
+            NonterminalKind::TT => token::NtTT(self.parse_token_tree()),
+            NonterminalKind::Vis => token::NtVis(self.parse_visibility(FollowedByType::Yes)?),
+            NonterminalKind::Lifetime => {
+                if self.check_lifetime() {
+                    token::NtLifetime(self.expect_lifetime().ident)
+                } else {
+                    let token_str = pprust::token_to_string(&self.token);
+                    let msg = &format!("expected a lifetime, found `{}`", &token_str);
+                    return Err(self.struct_span_err(self.token.span, msg));
+                }
+            }
+        })
+    }
+}
+
+/// The token is an identifier, but not `_`.
+/// We prohibit passing `_` to macros expecting `ident` for now.
+fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
+    token.ident().filter(|(ident, _)| ident.name != kw::Underscore)
+}
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index 3dcefd36257..d4e44c54b12 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -125,7 +125,7 @@ impl<'a> Parser<'a> {
     /// `a::b::C::<D>` (with disambiguator)
     /// `Fn(Args)` (without disambiguator)
     /// `Fn::(Args)` (with disambiguator)
-    pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
+    pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
         maybe_whole!(self, NtPath, |path| {
             if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
             {
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index d04920de47f..5c3a5e99873 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -21,7 +21,7 @@ use std::mem;
 impl<'a> Parser<'a> {
     /// Parses a statement. This stops just before trailing semicolons on everything but items.
     /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
-    pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> {
+    pub(super) fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> {
         Ok(self.parse_stmt_without_recovery().unwrap_or_else(|mut e| {
             e.emit();
             self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
@@ -247,7 +247,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a block. No inner attributes are allowed.
-    pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
+    pub(super) fn parse_block(&mut self) -> PResult<'a, P<Block>> {
         let (attrs, block) = self.parse_inner_attrs_and_block()?;
         if let [.., last] = &*attrs {
             self.error_on_forbidden_inner_attr(last.span, DEFAULT_INNER_ATTR_FORBIDDEN);
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index a6015504a32..cd66b917f23 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -610,13 +610,13 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn check_lifetime(&mut self) -> bool {
+    pub(super) fn check_lifetime(&mut self) -> bool {
         self.expected_tokens.push(TokenType::Lifetime);
         self.token.is_lifetime()
     }
 
     /// Parses a single lifetime `'a` or panics.
-    pub fn expect_lifetime(&mut self) -> Lifetime {
+    pub(super) fn expect_lifetime(&mut self) -> Lifetime {
         if let Some(ident) = self.token.lifetime() {
             self.bump();
             Lifetime { ident, id: ast::DUMMY_NODE_ID }
diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml
index 69048cbf24a..d9fa435e3ad 100644
--- a/src/librustc_passes/Cargo.toml
+++ b/src/librustc_passes/Cargo.toml
@@ -9,7 +9,7 @@ name = "rustc_passes"
 path = "lib.rs"
 
 [dependencies]
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_middle = { path = "../librustc_middle" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs
index 2419e696596..55a6d3f7645 100644
--- a/src/librustc_passes/layout_test.rs
+++ b/src/librustc_passes/layout_test.rs
@@ -82,8 +82,10 @@ impl LayoutTest<'tcx> {
                         }
 
                         sym::debug => {
-                            let normalized_ty =
-                                self.tcx.normalize_erasing_regions(param_env.with_reveal_all(), ty);
+                            let normalized_ty = self.tcx.normalize_erasing_regions(
+                                param_env.with_reveal_all_normalized(self.tcx),
+                                ty,
+                            );
                             self.tcx.sess.span_err(
                                 item.span,
                                 &format!("layout_of({:?}) = {:#?}", normalized_ty, *ty_layout),
diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml
index 6110d2ef7fc..6f543e71b42 100644
--- a/src/librustc_privacy/Cargo.toml
+++ b/src/librustc_privacy/Cargo.toml
@@ -17,4 +17,4 @@ rustc_typeck = { path = "../librustc_typeck" }
 rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 9c5fb4ce734..fc00050f405 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -637,7 +637,7 @@ impl EmbargoVisitor<'tcx> {
         &mut self,
         segments: &[hir::PathSegment<'_>],
     ) {
-        if let Some([module, segment]) = segments.rchunks_exact(2).next() {
+        if let [.., module, segment] = segments {
             if let Some(item) = module
                 .res
                 .and_then(|res| res.mod_def_id())
diff --git a/src/librustc_query_system/Cargo.toml b/src/librustc_query_system/Cargo.toml
index 73d50f84fe8..64af9c5f1a1 100644
--- a/src/librustc_query_system/Cargo.toml
+++ b/src/librustc_query_system/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_arena = { path = "../librustc_arena" }
-log = { version = "0.4", features = ["release_max_level_info", "std"] }
+log = { package = "tracing", version = "0.1" }
 rustc-rayon-core = "0.3.0"
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
index 6f6104c3d69..1cb49132ead 100644
--- a/src/librustc_resolve/Cargo.toml
+++ b/src/librustc_resolve/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
 
 [dependencies]
 bitflags = "1.2.1"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_arena = { path = "../librustc_arena" }
 rustc_middle = { path = "../librustc_middle" }
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index bcd2c6c1f1c..44ff4209095 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -1510,30 +1510,18 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         pat_src: PatternSource,
         bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
     ) {
-        let is_tuple_struct_pat = matches!(pat.kind, PatKind::TupleStruct(_, _));
-
         // Visit all direct subpatterns of this pattern.
         pat.walk(&mut |pat| {
             debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind);
             match pat.kind {
                 PatKind::Ident(bmode, ident, ref sub) => {
-                    if is_tuple_struct_pat && sub.as_ref().filter(|p| p.is_rest()).is_some() {
-                        // In tuple struct patterns ignore the invalid `ident @ ...`.
-                        // It will be handled as an error by the AST lowering.
-                        self.r
-                            .session
-                            .delay_span_bug(ident.span, "ident in tuple pattern is invalid");
-                    } else {
-                        // First try to resolve the identifier as some existing entity,
-                        // then fall back to a fresh binding.
-                        let has_sub = sub.is_some();
-                        let res = self
-                            .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
-                            .unwrap_or_else(|| {
-                                self.fresh_binding(ident, pat.id, pat_src, bindings)
-                            });
-                        self.r.record_partial_res(pat.id, PartialRes::new(res));
-                    }
+                    // First try to resolve the identifier as some existing entity,
+                    // then fall back to a fresh binding.
+                    let has_sub = sub.is_some();
+                    let res = self
+                        .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
+                        .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
+                    self.r.record_partial_res(pat.id, PartialRes::new(res));
                 }
                 PatKind::TupleStruct(ref path, ..) => {
                     self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct(pat.span));
@@ -2241,8 +2229,15 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     self.resolve_expr(argument, None);
                 }
             }
-            ExprKind::Type(ref type_expr, _) => {
-                self.diagnostic_metadata.current_type_ascription.push(type_expr.span);
+            ExprKind::Type(ref type_expr, ref ty) => {
+                // `ParseSess::type_ascription_path_suggestions` keeps spans of colon tokens in
+                // type ascription. Here we are trying to retrieve the span of the colon token as
+                // well, but only if it's written without spaces `expr:Ty` and therefore confusable
+                // with `expr::Ty`, only in this case it will match the span from
+                // `type_ascription_path_suggestions`.
+                self.diagnostic_metadata
+                    .current_type_ascription
+                    .push(type_expr.span.between(ty.span));
                 visit::walk_expr(self, expr);
                 self.diagnostic_metadata.current_type_ascription.pop();
             }
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index c86b4141847..ec6dbb070df 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -17,7 +17,7 @@ use rustc_hir::PrimTy;
 use rustc_session::config::nightly_options;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
 
 use log::debug;
 
@@ -223,13 +223,31 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
         if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) {
             let enum_candidates =
                 self.r.lookup_import_candidates(ident, ns, &self.parent_scope, is_enum_variant);
-            let mut enum_candidates = enum_candidates
-                .iter()
-                .map(|suggestion| import_candidate_to_enum_paths(&suggestion))
-                .collect::<Vec<_>>();
-            enum_candidates.sort();
 
             if !enum_candidates.is_empty() {
+                if let (PathSource::Type, Some(span)) =
+                    (source, self.diagnostic_metadata.current_type_ascription.last())
+                {
+                    if self
+                        .r
+                        .session
+                        .parse_sess
+                        .type_ascription_path_suggestions
+                        .borrow()
+                        .contains(span)
+                    {
+                        // Already reported this issue on the lhs of the type ascription.
+                        err.delay_as_bug();
+                        return (err, candidates);
+                    }
+                }
+
+                let mut enum_candidates = enum_candidates
+                    .iter()
+                    .map(|suggestion| import_candidate_to_enum_paths(&suggestion))
+                    .collect::<Vec<_>>();
+                enum_candidates.sort();
+
                 // Contextualize for E0412 "cannot find type", but don't belabor the point
                 // (that it's a variant) for E0573 "expected type, found variant".
                 let preamble = if res.is_none() {
@@ -484,10 +502,21 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
             match source {
                 PathSource::Expr(Some(
                     parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. },
-                )) => {
-                    path_sep(err, &parent);
-                }
-                PathSource::Expr(None) if followed_by_brace => {
+                )) if path_sep(err, &parent) => {}
+                PathSource::Expr(
+                    None
+                    | Some(Expr {
+                        kind:
+                            ExprKind::Path(..)
+                            | ExprKind::Binary(..)
+                            | ExprKind::Unary(..)
+                            | ExprKind::If(..)
+                            | ExprKind::While(..)
+                            | ExprKind::ForLoop(..)
+                            | ExprKind::Match(..),
+                        ..
+                    }),
+                ) if followed_by_brace => {
                     if let Some(sp) = closing_brace {
                         err.multipart_suggestion(
                             "surround the struct literal with parentheses",
@@ -508,11 +537,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                         );
                     }
                 }
-                PathSource::Expr(
-                    None | Some(Expr { kind: ExprKind::Call(..) | ExprKind::Path(..), .. }),
-                )
-                | PathSource::TupleStruct(_)
-                | PathSource::Pat => {
+                PathSource::Expr(_) | PathSource::TupleStruct(_) | PathSource::Pat => {
                     let span = match &source {
                         PathSource::Expr(Some(Expr {
                             span, kind: ExprKind::Call(_, _), ..
@@ -593,6 +618,24 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                 Res::Def(DefKind::Enum, def_id),
                 PathSource::TupleStruct(_) | PathSource::Expr(..),
             ) => {
+                if self
+                    .diagnostic_metadata
+                    .current_type_ascription
+                    .last()
+                    .map(|sp| {
+                        self.r
+                            .session
+                            .parse_sess
+                            .type_ascription_path_suggestions
+                            .borrow()
+                            .contains(&sp)
+                    })
+                    .unwrap_or(false)
+                {
+                    err.delay_as_bug();
+                    // We already suggested changing `:` into `::` during parsing.
+                    return false;
+                }
                 if let Some(variants) = self.collect_enum_variants(def_id) {
                     if !variants.is_empty() {
                         let msg = if variants.len() == 1 {
@@ -609,7 +652,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                         );
                     }
                 } else {
-                    err.note("did you mean to use one of the enum's variants?");
+                    err.note("you might have meant to use one of the enum's variants");
                 }
             }
             (Res::Def(DefKind::Struct, def_id), _) if ns == ValueNS => {
@@ -829,77 +872,73 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
     fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: Span) {
         let sm = self.r.session.source_map();
         let base_snippet = sm.span_to_snippet(base_span);
-        if let Some(sp) = self.diagnostic_metadata.current_type_ascription.last() {
-            let mut sp = *sp;
-            loop {
-                // Try to find the `:`; bail on first non-':' / non-whitespace.
-                sp = sm.next_point(sp);
-                if let Ok(snippet) = sm.span_to_snippet(sp.to(sm.next_point(sp))) {
-                    let line_sp = sm.lookup_char_pos(sp.hi()).line;
-                    let line_base_sp = sm.lookup_char_pos(base_span.lo()).line;
-                    if snippet == ":" {
-                        let mut show_label = true;
-                        if line_sp != line_base_sp {
-                            err.span_suggestion_short(
-                                sp,
-                                "did you mean to use `;` here instead?",
-                                ";".to_string(),
+        if let Some(&sp) = self.diagnostic_metadata.current_type_ascription.last() {
+            if let Ok(snippet) = sm.span_to_snippet(sp) {
+                let len = snippet.trim_end().len() as u32;
+                if snippet.trim() == ":" {
+                    let colon_sp =
+                        sp.with_lo(sp.lo() + BytePos(len - 1)).with_hi(sp.lo() + BytePos(len));
+                    let mut show_label = true;
+                    if sm.is_multiline(sp) {
+                        err.span_suggestion_short(
+                            colon_sp,
+                            "maybe you meant to write `;` here",
+                            ";".to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        let after_colon_sp =
+                            self.get_colon_suggestion_span(colon_sp.shrink_to_hi());
+                        if snippet.len() == 1 {
+                            // `foo:bar`
+                            err.span_suggestion(
+                                colon_sp,
+                                "maybe you meant to write a path separator here",
+                                "::".to_string(),
                                 Applicability::MaybeIncorrect,
                             );
-                        } else {
-                            let colon_sp = self.get_colon_suggestion_span(sp);
-                            let after_colon_sp =
-                                self.get_colon_suggestion_span(colon_sp.shrink_to_hi());
-                            if !sm
-                                .span_to_snippet(after_colon_sp)
-                                .map(|s| s == " ")
-                                .unwrap_or(false)
+                            show_label = false;
+                            if !self
+                                .r
+                                .session
+                                .parse_sess
+                                .type_ascription_path_suggestions
+                                .borrow_mut()
+                                .insert(colon_sp)
                             {
-                                err.span_suggestion(
-                                    colon_sp,
-                                    "maybe you meant to write a path separator here",
-                                    "::".to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                                show_label = false;
+                                err.delay_as_bug();
                             }
-                            if let Ok(base_snippet) = base_snippet {
-                                let mut sp = after_colon_sp;
-                                for _ in 0..100 {
-                                    // Try to find an assignment
-                                    sp = sm.next_point(sp);
-                                    let snippet = sm.span_to_snippet(sp.to(sm.next_point(sp)));
-                                    match snippet {
-                                        Ok(ref x) if x.as_str() == "=" => {
-                                            err.span_suggestion(
-                                                base_span,
-                                                "maybe you meant to write an assignment here",
-                                                format!("let {}", base_snippet),
-                                                Applicability::MaybeIncorrect,
-                                            );
-                                            show_label = false;
-                                            break;
-                                        }
-                                        Ok(ref x) if x.as_str() == "\n" => break,
-                                        Err(_) => break,
-                                        Ok(_) => {}
+                        }
+                        if let Ok(base_snippet) = base_snippet {
+                            let mut sp = after_colon_sp;
+                            for _ in 0..100 {
+                                // Try to find an assignment
+                                sp = sm.next_point(sp);
+                                let snippet = sm.span_to_snippet(sp.to(sm.next_point(sp)));
+                                match snippet {
+                                    Ok(ref x) if x.as_str() == "=" => {
+                                        err.span_suggestion(
+                                            base_span,
+                                            "maybe you meant to write an assignment here",
+                                            format!("let {}", base_snippet),
+                                            Applicability::MaybeIncorrect,
+                                        );
+                                        show_label = false;
+                                        break;
                                     }
+                                    Ok(ref x) if x.as_str() == "\n" => break,
+                                    Err(_) => break,
+                                    Ok(_) => {}
                                 }
                             }
                         }
-                        if show_label {
-                            err.span_label(
-                                base_span,
-                                "expecting a type here because of type ascription",
-                            );
-                        }
-                        break;
-                    } else if !snippet.trim().is_empty() {
-                        debug!("tried to find type ascription `:` token, couldn't find it");
-                        break;
                     }
-                } else {
-                    break;
+                    if show_label {
+                        err.span_label(
+                            base_span,
+                            "expecting a type here because of type ascription",
+                        );
+                    }
                 }
             }
         }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index fee7cb4836e..ccc7e16ae4c 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -1020,7 +1020,7 @@ impl<'a> Resolver<'a> {
         }
         if let Some(depr) = &ext.deprecation {
             let path = pprust::path_to_string(&path);
-            let (message, lint) = stability::deprecation_message(depr, &path);
+            let (message, lint) = stability::deprecation_message(depr, "macro", &path);
             stability::early_report_deprecation(
                 &mut self.lint_buffer,
                 &message,
diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml
index 5948c88054d..7a5ae0ace3a 100644
--- a/src/librustc_save_analysis/Cargo.toml
+++ b/src/librustc_save_analysis/Cargo.toml
@@ -9,7 +9,7 @@ name = "rustc_save_analysis"
 path = "lib.rs"
 
 [dependencies]
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_middle = { path = "../librustc_middle" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
diff --git a/src/librustc_session/Cargo.toml b/src/librustc_session/Cargo.toml
index abce7359c0e..35c227df850 100644
--- a/src/librustc_session/Cargo.toml
+++ b/src/librustc_session/Cargo.toml
@@ -11,7 +11,7 @@ path = "lib.rs"
 [dependencies]
 bitflags = "1.2.1"
 getopts = "0.2"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index 620a04b45b0..9fcdd46539c 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -1717,7 +1717,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         }
 
         // `-Z instrument-coverage` implies:
-        //   * `-Z symbol-mangling-version=v0` - to ensure consistent and reversable name mangling.
+        //   * `-Z symbol-mangling-version=v0` - to ensure consistent and reversible name mangling.
         //     Note, LLVM coverage tools can analyze coverage over multiple runs, including some
         //     changes to source code; so mangled names must be consistent across compilations.
         //   * `-C link-dead-code` - so unexecuted code is still counted as zero, rather than be
diff --git a/src/librustc_session/filesearch.rs b/src/librustc_session/filesearch.rs
index 27396c524f4..504490d938c 100644
--- a/src/librustc_session/filesearch.rs
+++ b/src/librustc_session/filesearch.rs
@@ -117,28 +117,22 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
 
 pub fn get_or_default_sysroot() -> PathBuf {
     // Follow symlinks.  If the resolved path is relative, make it absolute.
-    fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
-        path.and_then(|path| {
-            match fs::canonicalize(&path) {
-                // See comments on this target function, but the gist is that
-                // gcc chokes on verbatim paths which fs::canonicalize generates
-                // so we try to avoid those kinds of paths.
-                Ok(canon) => Some(fix_windows_verbatim_for_gcc(&canon)),
-                Err(e) => panic!("failed to get realpath: {}", e),
-            }
-        })
+    fn canonicalize(path: PathBuf) -> PathBuf {
+        let path = fs::canonicalize(&path).unwrap_or(path);
+        // See comments on this target function, but the gist is that
+        // gcc chokes on verbatim paths which fs::canonicalize generates
+        // so we try to avoid those kinds of paths.
+        fix_windows_verbatim_for_gcc(&path)
     }
 
     match env::current_exe() {
-        Ok(exe) => match canonicalize(Some(exe)) {
-            Some(mut p) => {
-                p.pop();
-                p.pop();
-                p
-            }
-            None => panic!("can't determine value for sysroot"),
-        },
-        Err(ref e) => panic!(format!("failed to get current_exe: {}", e)),
+        Ok(exe) => {
+            let mut p = canonicalize(exe);
+            p.pop();
+            p.pop();
+            p
+        }
+        Err(e) => panic!("failed to get current_exe: {}", e),
     }
 }
 
diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
index aa2a133952f..144a06a4916 100644
--- a/src/librustc_session/lint/builtin.rs
+++ b/src/librustc_session/lint/builtin.rs
@@ -398,7 +398,7 @@ declare_lint! {
 }
 
 declare_lint! {
-    pub INTRA_DOC_LINK_RESOLUTION_FAILURE,
+    pub BROKEN_INTRA_DOC_LINKS,
     Warn,
     "failures in resolving intra-doc link targets"
 }
@@ -601,7 +601,7 @@ declare_lint_pass! {
         ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
         UNSTABLE_NAME_COLLISIONS,
         IRREFUTABLE_LET_PATTERNS,
-        INTRA_DOC_LINK_RESOLUTION_FAILURE,
+        BROKEN_INTRA_DOC_LINKS,
         INVALID_CODEBLOCK_ATTRIBUTES,
         MISSING_CRATE_LEVEL_DOCS,
         MISSING_DOC_CODE_EXAMPLES,
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index 502102fa178..80164840334 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -883,7 +883,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "instrument the generated code to support LLVM source-based code coverage \
         reports (note, the compiler build config must include `profiler = true`, \
         and is mutually exclusive with `-C profile-generate`/`-C profile-use`); \
-        implies `-C link-dead-code` (unless explicitly disabled)` and
+        implies `-C link-dead-code` (unless explicitly disabled)` and \
         `-Z symbol-mangling-version=v0`; and disables/overrides some optimization \
         options (default: no)"),
     instrument_mcount: bool = (false, parse_bool, [TRACKED],
diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs
index b428315b3cd..9cdb7e966fe 100644
--- a/src/librustc_session/parse.rs
+++ b/src/librustc_session/parse.rs
@@ -63,7 +63,7 @@ impl GatedSpans {
 
 #[derive(Default)]
 pub struct SymbolGallery {
-    /// All symbols occurred and their first occurrance span.
+    /// All symbols occurred and their first occurrence span.
     pub symbols: Lock<BTreeMap<Symbol, Span>>,
 }
 
@@ -138,6 +138,8 @@ pub struct ParseSess {
     pub reached_eof: Lock<bool>,
     /// Environment variables accessed during the build and their values when they exist.
     pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>,
+    /// All the type ascriptions expressions that have had a suggestion for likely path typo.
+    pub type_ascription_path_suggestions: Lock<FxHashSet<Span>>,
 }
 
 impl ParseSess {
@@ -164,6 +166,7 @@ impl ParseSess {
             symbol_gallery: SymbolGallery::default(),
             reached_eof: Lock::new(false),
             env_depinfo: Default::default(),
+            type_ascription_path_suggestions: Default::default(),
         }
     }
 
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index 0d4298fa6f5..e9077f40859 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -1294,19 +1294,19 @@ pub fn build_session(
 // commandline argument, you can do so here.
 fn validate_commandline_args_with_session_available(sess: &Session) {
     // Since we don't know if code in an rlib will be linked to statically or
-    // dynamically downstream, rustc generates `__imp_` symbols that help the
-    // MSVC linker deal with this lack of knowledge (#27438). Unfortunately,
+    // dynamically downstream, rustc generates `__imp_` symbols that help linkers
+    // on Windows deal with this lack of knowledge (#27438). Unfortunately,
     // these manually generated symbols confuse LLD when it tries to merge
-    // bitcode during ThinLTO. Therefore we disallow dynamic linking on MSVC
+    // bitcode during ThinLTO. Therefore we disallow dynamic linking on Windows
     // when compiling for LLD ThinLTO. This way we can validly just not generate
     // the `dllimport` attributes and `__imp_` symbols in that case.
     if sess.opts.cg.linker_plugin_lto.enabled()
         && sess.opts.cg.prefer_dynamic
-        && sess.target.target.options.is_like_msvc
+        && sess.target.target.options.is_like_windows
     {
         sess.err(
             "Linker plugin based LTO is not supported together with \
-                  `-C prefer-dynamic` when targeting MSVC",
+                  `-C prefer-dynamic` when targeting Windows-like targets",
         );
     }
 
diff --git a/src/librustc_span/Cargo.toml b/src/librustc_span/Cargo.toml
index 2a7a7748725..2db417ce0e1 100644
--- a/src/librustc_span/Cargo.toml
+++ b/src/librustc_span/Cargo.toml
@@ -18,6 +18,6 @@ rustc_arena = { path = "../librustc_arena" }
 scoped-tls = "1.0"
 unicode-width = "0.1.4"
 cfg-if = "0.1.2"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 sha-1 = "0.8"
 md-5 = "0.8"
diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs
index 13bc1751831..a03ac4e1fdb 100644
--- a/src/librustc_span/hygiene.rs
+++ b/src/librustc_span/hygiene.rs
@@ -891,7 +891,7 @@ impl UseSpecializedDecodable for ExpnId {}
 
 #[derive(Default)]
 pub struct HygieneEncodeContext {
-    /// All `SyntaxContexts` for which we have writen `SyntaxContextData` into crate metadata.
+    /// All `SyntaxContexts` for which we have written `SyntaxContextData` into crate metadata.
     /// This is `None` after we finish encoding `SyntaxContexts`, to ensure
     /// that we don't accidentally try to encode any more `SyntaxContexts`
     serialized_ctxts: Lock<FxHashSet<SyntaxContext>>,
@@ -961,7 +961,7 @@ pub struct HygieneDecodeContext {
     // Maps serialized `SyntaxContext` ids to a `SyntaxContext` in the current
     // global `HygieneData`. When we deserialize a `SyntaxContext`, we need to create
     // a new id in the global `HygieneData`. This map tracks the ID we end up picking,
-    // so that multiple occurences of the same serialized id are decoded to the same
+    // so that multiple occurrences of the same serialized id are decoded to the same
     // `SyntaxContext`
     remapped_ctxts: Lock<Vec<Option<SyntaxContext>>>,
     // The same as `remapepd_ctxts`, but for `ExpnId`s
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index dadf040304d..98776a04782 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -1043,6 +1043,7 @@ symbols! {
         stop_after_dataflow,
         str,
         str_alloc,
+        string_type,
         stringify,
         struct_field_attributes,
         struct_inherit,
diff --git a/src/librustc_symbol_mangling/Cargo.toml b/src/librustc_symbol_mangling/Cargo.toml
index d670ababe9f..757d86bd95a 100644
--- a/src/librustc_symbol_mangling/Cargo.toml
+++ b/src/librustc_symbol_mangling/Cargo.toml
@@ -10,7 +10,7 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 punycode = "0.4.0"
 rustc-demangle = "0.1.16"
 
diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs
index ecf27fbf542..56ee492de87 100644
--- a/src/librustc_symbol_mangling/v0.rs
+++ b/src/librustc_symbol_mangling/v0.rs
@@ -271,7 +271,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
         let key = self.tcx.def_key(impl_def_id);
         let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
 
-        let mut param_env = self.tcx.param_env(impl_def_id).with_reveal_all();
+        let mut param_env = self.tcx.param_env_reveal_all_normalized(impl_def_id);
         if !substs.is_empty() {
             param_env = param_env.subst(self.tcx, substs);
         }
@@ -636,9 +636,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
                 }
                 GenericArgKind::Const(c) => {
                     self.push("K");
-                    // FIXME(const_generics) implement `ty::print::Print` on `ty::Const`.
-                    // self = c.print(self)?;
-                    self = self.print_const(c)?;
+                    self = c.print(self)?;
                 }
             }
         }
diff --git a/src/librustc_target/Cargo.toml b/src/librustc_target/Cargo.toml
index c73490e4513..21796e84985 100644
--- a/src/librustc_target/Cargo.toml
+++ b/src/librustc_target/Cargo.toml
@@ -10,7 +10,7 @@ path = "lib.rs"
 
 [dependencies]
 bitflags = "1.2.1"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_macros = { path = "../librustc_macros" }
 rustc_serialize = { path = "../librustc_serialize" }
diff --git a/src/librustc_target/spec/thumbv4t_none_eabi.rs b/src/librustc_target/spec/thumbv4t_none_eabi.rs
index 31417b01547..a8c78f057fc 100644
--- a/src/librustc_target/spec/thumbv4t_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv4t_none_eabi.rs
@@ -29,7 +29,7 @@ pub fn target() -> TargetResult {
          * native integers are 32-bit
          * All other elements are default
          */
-        data_layout: "e-S64-p:32:32-i64:64-m:e-n32".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         linker_flavor: LinkerFlavor::Ld,
         options: TargetOptions {
             linker: Some("arm-none-eabi-ld".to_string()),
diff --git a/src/librustc_trait_selection/Cargo.toml b/src/librustc_trait_selection/Cargo.toml
index fd11a85a9c4..c43fe3f2c0c 100644
--- a/src/librustc_trait_selection/Cargo.toml
+++ b/src/librustc_trait_selection/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_parse_format = { path = "../librustc_parse_format" }
-log = { version = "0.4", features = ["release_max_level_info", "std"] }
+log = { package = "tracing", version = "0.1" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_middle = { path = "../librustc_middle" }
 rustc_ast = { path = "../librustc_ast" }
diff --git a/src/librustc_trait_selection/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs
index 6fe67509660..05a0c52badb 100644
--- a/src/librustc_trait_selection/traits/auto_trait.rs
+++ b/src/librustc_trait_selection/traits/auto_trait.rs
@@ -802,6 +802,38 @@ impl AutoTraitFinder<'tcx> {
                         _ => {}
                     };
                 }
+                ty::PredicateAtom::ConstEquate(c1, c2) => {
+                    let evaluate = |c: &'tcx ty::Const<'tcx>| {
+                        if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
+                            match select.infcx().const_eval_resolve(
+                                obligation.param_env,
+                                def,
+                                substs,
+                                promoted,
+                                Some(obligation.cause.span),
+                            ) {
+                                Ok(val) => Ok(ty::Const::from_value(select.tcx(), val, c.ty)),
+                                Err(err) => Err(err),
+                            }
+                        } else {
+                            Ok(c)
+                        }
+                    };
+
+                    match (evaluate(c1), evaluate(c2)) {
+                        (Ok(c1), Ok(c2)) => {
+                            match select
+                                .infcx()
+                                .at(&obligation.cause, obligation.param_env)
+                                .eq(c1, c2)
+                            {
+                                Ok(_) => (),
+                                Err(_) => return false,
+                            }
+                        }
+                        _ => return false,
+                    }
+                }
                 _ => panic!("Unexpected predicate {:?} {:?}", ty, predicate),
             };
         }
diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml
index 079b9b10fd0..f8487982e3d 100644
--- a/src/librustc_traits/Cargo.toml
+++ b/src/librustc_traits/Cargo.toml
@@ -9,7 +9,7 @@ name = "rustc_traits"
 path = "lib.rs"
 
 [dependencies]
-log = { version = "0.4" }
+log = { package = "tracing", version = "0.1" }
 rustc_middle = { path = "../librustc_middle" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_hir = { path = "../librustc_hir" }
diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml
index b6db75e44f9..6cdb3530002 100644
--- a/src/librustc_ty/Cargo.toml
+++ b/src/librustc_ty/Cargo.toml
@@ -9,7 +9,7 @@ name = "rustc_ty"
 path = "lib.rs"
 
 [dependencies]
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_middle = { path = "../librustc_middle" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs
index 324ae4ec29e..1e0c4055af3 100644
--- a/src/librustc_ty/instance.rs
+++ b/src/librustc_ty/instance.rs
@@ -137,7 +137,7 @@ fn resolve_associated_item<'tcx>(
                 });
 
             let substs = tcx.infer_ctxt().enter(|infcx| {
-                let param_env = param_env.with_reveal_all();
+                let param_env = param_env.with_reveal_all_normalized(tcx);
                 let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
                 let substs = translate_substs(
                     &infcx,
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
index 7f954dacf3e..dfb28b473ff 100644
--- a/src/librustc_ty/ty.rs
+++ b/src/librustc_ty/ty.rs
@@ -276,6 +276,10 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
 }
 
+fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
+    tcx.param_env(def_id).with_reveal_all_normalized(tcx)
+}
+
 fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
     assert_eq!(crate_num, LOCAL_CRATE);
     tcx.sess.local_crate_disambiguator()
@@ -502,6 +506,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
         adt_sized_constraint,
         def_span,
         param_env,
+        param_env_reveal_all_normalized,
         trait_of_item,
         crate_disambiguator,
         original_crate_name,
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
index 93b503c976b..963deda162d 100644
--- a/src/librustc_typeck/Cargo.toml
+++ b/src/librustc_typeck/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
 
 [dependencies]
 rustc_arena = { path = "../librustc_arena" }
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 rustc_middle = { path = "../librustc_middle" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index c7e9b97e2db..db8cdfc5b20 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -456,7 +456,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         //
         // Both of these trigger a special `CoerceUnsized`-related error (E0376)
         //
-        // We can take advantage of this fact to avoid performing unecessary work.
+        // We can take advantage of this fact to avoid performing unnecessary work.
         // If either `source` or `target` is a type variable, then any applicable impl
         // would need to be generic over the self-type (`impl<T> CoerceUnsized<SomeType> for T`)
         // or generic over the `CoerceUnsized` type parameter (`impl<T> CoerceUnsized<T> for
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index ae2cf6daf53..e69102d1995 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -678,6 +678,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .collect::<Vec<(usize, String)>>();
                     for ((span, empty_where), obligations) in type_params.into_iter() {
                         restrict_type_params = true;
+                        // #74886: Sort here so that the output is always the same.
+                        let mut obligations = obligations.into_iter().collect::<Vec<_>>();
+                        obligations.sort();
                         err.span_suggestion_verbose(
                             span,
                             &format!(
@@ -688,7 +691,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             format!(
                                 "{} {}",
                                 if empty_where { " where" } else { "," },
-                                obligations.into_iter().collect::<Vec<_>>().join(", ")
+                                obligations.join(", ")
                             ),
                             Applicability::MaybeIncorrect,
                         );
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 41aac3569d1..fd516c88ec6 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -562,7 +562,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                    on the left and may require reallocation. This \
                    requires ownership of the string on the left";
 
-        let is_std_string = |ty| &format!("{:?}", ty) == "std::string::String";
+        let string_type = self.tcx.get_diagnostic_item(sym::string_type);
+        let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() {
+            Some(ty_def) => Some(ty_def.did) == string_type,
+            None => false,
+        };
 
         match (&lhs_ty.kind, &rhs_ty.kind) {
             (&Ref(_, l_ty, _), &Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 42170bc199c..9c7ea34bf51 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -345,7 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             debug!("inspecting {:?}", expected);
 
             debug!("current discriminant is Ref, inserting implicit deref");
-            // Preserve the reference type. We'll need it later during HAIR lowering.
+            // Preserve the reference type. We'll need it later during THIR lowering.
             pat_adjustments.push(expected);
 
             expected = inner_ty;
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 76439af79f3..8715dacb324 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -858,7 +858,6 @@ fn convert_variant(
         _ => false,
     };
     ty::VariantDef::new(
-        tcx,
         ident,
         variant_did.map(LocalDefId::to_def_id),
         ctor_did.map(LocalDefId::to_def_id),
@@ -868,6 +867,10 @@ fn convert_variant(
         adt_kind,
         parent_did.to_def_id(),
         recovered,
+        adt_kind == AdtKind::Struct && tcx.has_attr(parent_did.to_def_id(), sym::non_exhaustive)
+            || variant_did.map_or(false, |variant_did| {
+                tcx.has_attr(variant_did.to_def_id(), sym::non_exhaustive)
+            }),
     )
 }
 
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index cae09267994..b810c9824ce 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -161,6 +161,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_sig(current_item, tcx.fn_sig(def_id), self.covariant);
             }
 
+            ty::Error(_) => {}
             _ => {
                 span_bug!(
                     tcx.def_span(def_id),
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 98d8f100b27..9c44d27447d 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -430,14 +430,14 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
     }
 
     // Converts the calculated ParamEnv and lifetime information to a clean::Generics, suitable for
-    // display on the docs page. Cleaning the Predicates produces sub-optimal WherePredicate's,
+    // display on the docs page. Cleaning the Predicates produces sub-optimal `WherePredicate`s,
     // so we fix them up:
     //
     // * Multiple bounds for the same type are coalesced into one: e.g., 'T: Copy', 'T: Debug'
     // becomes 'T: Copy + Debug'
     // * Fn bounds are handled specially - instead of leaving it as 'T: Fn(), <T as Fn::Output> =
     // K', we use the dedicated syntax 'T: Fn() -> K'
-    // * We explcitly add a '?Sized' bound if we didn't find any 'Sized' predicates for a type
+    // * We explicitly add a '?Sized' bound if we didn't find any 'Sized' predicates for a type
     fn param_env_to_generics(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -480,6 +480,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                 .clean(self.cx)
                 .params;
 
+        debug!(
+            "param_env_to_generics({:?}): generic_params={:?}",
+            param_env_def_id, generic_params
+        );
+
         let mut has_sized = FxHashSet::default();
         let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
         let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
@@ -588,7 +593,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                                         .args;
 
                                     match args {
-                                        // Convert somethiung like '<T as Iterator::Item> = u8'
+                                        // Convert something like '<T as Iterator::Item> = u8'
                                         // to 'T: Iterator<Item=u8>'
                                         GenericArgs::AngleBracketed {
                                             ref mut bindings, ..
@@ -712,7 +717,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
     // since FxHasher has different behavior for 32-bit and 64-bit platforms.
     //
     // Obviously, it's extremely undesirable for documentation rendering
-    // to be depndent on the platform it's run on. Apart from being confusing
+    // to be dependent on the platform it's run on. Apart from being confusing
     // to end users, it makes writing tests much more difficult, as predicates
     // can appear in any order in the final result.
     //
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index cc3a60c596a..5b048372624 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -716,11 +716,11 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
         // Bounds in the type_params and lifetimes fields are repeated in the
         // predicates field (see rustc_typeck::collect::ty_generics), so remove
         // them.
-        let stripped_typarams = gens
+        let stripped_params = gens
             .params
             .iter()
             .filter_map(|param| match param.kind {
-                ty::GenericParamDefKind::Lifetime => None,
+                ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
                 ty::GenericParamDefKind::Type { synthetic, .. } => {
                     if param.name == kw::SelfUpper {
                         assert_eq!(param.index, 0);
@@ -732,7 +732,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
                     }
                     Some(param.clean(cx))
                 }
-                ty::GenericParamDefKind::Const { .. } => None,
+                ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
             })
             .collect::<Vec<GenericParamDef>>();
 
@@ -844,8 +844,10 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
 
         // Run through the type parameters again and insert a ?Sized
         // unbound for any we didn't find to be Sized.
-        for tp in &stripped_typarams {
-            if !sized_params.contains(&tp.name) {
+        for tp in &stripped_params {
+            if matches!(tp.kind, types::GenericParamDefKind::Type { .. })
+                && !sized_params.contains(&tp.name)
+            {
                 where_predicates.push(WP::BoundPredicate {
                     ty: Type::Generic(tp.name.clone()),
                     bounds: vec![GenericBound::maybe_sized(cx)],
@@ -858,16 +860,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
         // and instead see `where T: Foo + Bar + Sized + 'a`
 
         Generics {
-            params: gens
-                .params
-                .iter()
-                .flat_map(|param| match param.kind {
-                    ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
-                    ty::GenericParamDefKind::Type { .. } => None,
-                    ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
-                })
-                .chain(simplify::ty_params(stripped_typarams).into_iter())
-                .collect(),
+            params: stripped_params,
             where_predicates: simplify::where_clauses(cx, where_predicates),
         }
     }
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 0f995a60c22..990189f6ea0 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -12,7 +12,6 @@
 //! bounds by special casing scenarios such as these. Fun!
 
 use std::collections::BTreeMap;
-use std::mem;
 
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty;
@@ -118,18 +117,6 @@ pub fn merge_bounds(
     })
 }
 
-pub fn ty_params(mut params: Vec<clean::GenericParamDef>) -> Vec<clean::GenericParamDef> {
-    for param in &mut params {
-        match param.kind {
-            clean::GenericParamDefKind::Type { ref mut bounds, .. } => {
-                *bounds = mem::take(bounds);
-            }
-            _ => panic!("expected only type parameters"),
-        }
-    }
-    params
-}
-
 fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) -> bool {
     if child == trait_ {
         return true;
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 071834c59d6..89549eae2cb 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -32,8 +32,9 @@ use crate::clean::inline;
 use crate::clean::types::Type::{QPath, ResolvedPath};
 use crate::core::DocContext;
 use crate::doctree;
-use crate::html::item_type::ItemType;
-use crate::html::render::{cache, ExternalLocation};
+use crate::formats::cache::cache;
+use crate::formats::item_type::ItemType;
+use crate::html::render::cache::ExternalLocation;
 
 use self::FnRetTy::*;
 use self::ItemEnum::*;
@@ -1172,7 +1173,7 @@ impl GetDefId for Type {
     fn def_id(&self) -> Option<DefId> {
         match *self {
             ResolvedPath { did, .. } => Some(did),
-            Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
+            Primitive(p) => cache().primitive_locations.get(&p).cloned(),
             BorrowedRef { type_: box Generic(..), .. } => {
                 Primitive(PrimitiveType::Reference).def_id()
             }
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 39e33da4496..4f751decc80 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -4,6 +4,9 @@ use std::ffi::OsStr;
 use std::fmt;
 use std::path::PathBuf;
 
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def_id::DefId;
+use rustc_middle::middle::privacy::AccessLevels;
 use rustc_session::config::{self, parse_crate_types_from_list, parse_externs, CrateType};
 use rustc_session::config::{
     build_codegen_options, build_debugging_options, get_cmd_lint_options, host_triple,
@@ -249,6 +252,20 @@ pub struct RenderOptions {
     pub document_hidden: bool,
 }
 
+/// Temporary storage for data obtained during `RustdocVisitor::clean()`.
+/// Later on moved into `CACHE_KEY`.
+#[derive(Default, Clone)]
+pub struct RenderInfo {
+    pub inlined: FxHashSet<DefId>,
+    pub external_paths: crate::core::ExternalPaths,
+    pub exact_paths: FxHashMap<DefId, Vec<String>>,
+    pub access_levels: AccessLevels<DefId>,
+    pub deref_trait_did: Option<DefId>,
+    pub deref_mut_trait_did: Option<DefId>,
+    pub owned_box_did: Option<DefId>,
+    pub output_format: Option<OutputFormat>,
+}
+
 impl Options {
     /// Parses the given command-line for options. If an error message or other early-return has
     /// been printed, returns `Err` with the exit code.
@@ -491,7 +508,7 @@ impl Options {
         let output_format = match matches.opt_str("output-format") {
             Some(s) => match OutputFormat::try_from(s.as_str()) {
                 Ok(o) => {
-                    if o.is_json() && !show_coverage {
+                    if o.is_json() && !(show_coverage || nightly_options::is_nightly_build()) {
                         diag.struct_err("json output format isn't supported for doc generation")
                             .emit();
                         return Err(1);
@@ -609,7 +626,9 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han
 
     for flag in deprecated_flags.iter() {
         if matches.opt_present(flag) {
-            if *flag == "output-format" && matches.opt_present("show-coverage") {
+            if *flag == "output-format"
+                && (matches.opt_present("show-coverage") || nightly_options::is_nightly_build())
+            {
                 continue;
             }
             let mut err =
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 263909d5559..cbd0ca0de64 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -32,8 +32,8 @@ use std::rc::Rc;
 
 use crate::clean;
 use crate::clean::{AttributesExt, MAX_DEF_ID};
+use crate::config::RenderInfo;
 use crate::config::{Options as RustdocOptions, RenderOptions};
-use crate::html::render::RenderInfo;
 use crate::passes::{self, Condition::*, ConditionalPass};
 
 pub use rustc_session::config::{CodegenOptions, DebuggingOptions, Input, Options};
@@ -44,9 +44,9 @@ pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
 pub struct DocContext<'tcx> {
     pub tcx: TyCtxt<'tcx>,
     pub resolver: Rc<RefCell<interface::BoxedResolver>>,
-    /// Later on moved into `html::render::CACHE_KEY`
+    /// Later on moved into `CACHE_KEY`
     pub renderinfo: RefCell<RenderInfo>,
-    /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
+    /// Later on moved through `clean::Crate` into `CACHE_KEY`
     pub external_traits: Rc<RefCell<FxHashMap<DefId, clean::Trait>>>,
     /// Used while populating `external_traits` to ensure we don't process the same trait twice at
     /// the same time.
@@ -315,7 +315,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
     let cpath = Some(input.clone());
     let input = Input::File(input);
 
-    let intra_link_resolution_failure_name = lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE.name;
+    let intra_link_resolution_failure_name = lint::builtin::BROKEN_INTRA_DOC_LINKS.name;
     let missing_docs = rustc_lint::builtin::MISSING_DOCS.name;
     let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name;
     let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name;
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index 9a11e8fce28..4ce6bcbe274 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -13,8 +13,7 @@ use std::fs;
 use std::io;
 use std::path::Path;
 use std::string::ToString;
-use std::sync::mpsc::{channel, Receiver, Sender};
-use std::sync::Arc;
+use std::sync::mpsc::Sender;
 
 macro_rules! try_err {
     ($e:expr, $file:expr) => {
@@ -31,47 +30,24 @@ pub trait PathError {
         S: ToString + Sized;
 }
 
-pub struct ErrorStorage {
-    sender: Option<Sender<Option<String>>>,
-    receiver: Receiver<Option<String>>,
-}
-
-impl ErrorStorage {
-    pub fn new() -> ErrorStorage {
-        let (sender, receiver) = channel();
-        ErrorStorage { sender: Some(sender), receiver }
-    }
-
-    /// Prints all stored errors. Returns the number of printed errors.
-    pub fn write_errors(&mut self, diag: &rustc_errors::Handler) -> usize {
-        let mut printed = 0;
-        // In order to drop the sender part of the channel.
-        self.sender = None;
-
-        for msg in self.receiver.iter() {
-            if let Some(ref error) = msg {
-                diag.struct_err(&error).emit();
-                printed += 1;
-            }
-        }
-        printed
-    }
-}
-
 pub struct DocFS {
     sync_only: bool,
-    errors: Arc<ErrorStorage>,
+    errors: Option<Sender<String>>,
 }
 
 impl DocFS {
-    pub fn new(errors: &Arc<ErrorStorage>) -> DocFS {
-        DocFS { sync_only: false, errors: Arc::clone(errors) }
+    pub fn new(errors: Sender<String>) -> DocFS {
+        DocFS { sync_only: false, errors: Some(errors) }
     }
 
     pub fn set_sync_only(&mut self, sync_only: bool) {
         self.sync_only = sync_only;
     }
 
+    pub fn close(&mut self) {
+        self.errors = None;
+    }
+
     pub fn create_dir_all<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
         // For now, dir creation isn't a huge time consideration, do it
         // synchronously, which avoids needing ordering between write() actions
@@ -88,20 +64,15 @@ impl DocFS {
         if !self.sync_only && cfg!(windows) {
             // A possible future enhancement after more detailed profiling would
             // be to create the file sync so errors are reported eagerly.
-            let contents = contents.as_ref().to_vec();
             let path = path.as_ref().to_path_buf();
-            let sender = self.errors.sender.clone().unwrap();
-            rayon::spawn(move || match fs::write(&path, &contents) {
-                Ok(_) => {
-                    sender.send(None).unwrap_or_else(|_| {
-                        panic!("failed to send error on \"{}\"", path.display())
-                    });
-                }
-                Err(e) => {
-                    sender.send(Some(format!("\"{}\": {}", path.display(), e))).unwrap_or_else(
-                        |_| panic!("failed to send non-error on \"{}\"", path.display()),
-                    );
-                }
+            let contents = contents.as_ref().to_vec();
+            let sender = self.errors.clone().expect("can't write after closing");
+            rayon::spawn(move || {
+                fs::write(&path, contents).unwrap_or_else(|e| {
+                    sender
+                        .send(format!("\"{}\": {}", path.display(), e))
+                        .expect(&format!("failed to send error on \"{}\"", path.display()));
+                });
             });
             Ok(())
         } else {
diff --git a/src/librustdoc/error.rs b/src/librustdoc/error.rs
new file mode 100644
index 00000000000..77063ab4639
--- /dev/null
+++ b/src/librustdoc/error.rs
@@ -0,0 +1,56 @@
+use std::error;
+use std::fmt::{self, Formatter};
+use std::path::{Path, PathBuf};
+
+use crate::docfs::PathError;
+
+#[derive(Debug)]
+pub struct Error {
+    pub file: PathBuf,
+    pub error: String,
+}
+
+impl error::Error for Error {}
+
+impl std::fmt::Display for Error {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        let file = self.file.display().to_string();
+        if file.is_empty() {
+            write!(f, "{}", self.error)
+        } else {
+            write!(f, "\"{}\": {}", self.file.display(), self.error)
+        }
+    }
+}
+
+impl PathError for Error {
+    fn new<S, P: AsRef<Path>>(e: S, path: P) -> Error
+    where
+        S: ToString + Sized,
+    {
+        Error { file: path.as_ref().to_path_buf(), error: e.to_string() }
+    }
+}
+
+#[macro_export]
+macro_rules! try_none {
+    ($e:expr, $file:expr) => {{
+        use std::io;
+        match $e {
+            Some(e) => e,
+            None => {
+                return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"), $file));
+            }
+        }
+    }};
+}
+
+#[macro_export]
+macro_rules! try_err {
+    ($e:expr, $file:expr) => {{
+        match $e {
+            Ok(e) => e,
+            Err(e) => return Err(Error::new(e, $file)),
+        }
+    }};
+}
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
new file mode 100644
index 00000000000..99b31473f87
--- /dev/null
+++ b/src/librustdoc/formats/cache.rs
@@ -0,0 +1,488 @@
+use std::cell::RefCell;
+use std::collections::BTreeMap;
+use std::mem;
+use std::path::{Path, PathBuf};
+use std::sync::Arc;
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
+use rustc_middle::middle::privacy::AccessLevels;
+use rustc_span::source_map::FileName;
+
+use crate::clean::{self, GetDefId};
+use crate::config::RenderInfo;
+use crate::fold::DocFolder;
+use crate::formats::item_type::ItemType;
+use crate::formats::Impl;
+use crate::html::render::cache::{extern_location, get_index_search_type, ExternalLocation};
+use crate::html::render::IndexItem;
+use crate::html::render::{plain_summary_line, shorten};
+
+thread_local!(crate static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
+
+/// This cache is used to store information about the `clean::Crate` being
+/// rendered in order to provide more useful documentation. This contains
+/// information like all implementors of a trait, all traits a type implements,
+/// documentation for all known traits, etc.
+///
+/// This structure purposefully does not implement `Clone` because it's intended
+/// to be a fairly large and expensive structure to clone. Instead this adheres
+/// to `Send` so it may be stored in a `Arc` instance and shared among the various
+/// rendering threads.
+#[derive(Default)]
+pub struct Cache {
+    /// Maps a type ID to all known implementations for that type. This is only
+    /// recognized for intra-crate `ResolvedPath` types, and is used to print
+    /// out extra documentation on the page of an enum/struct.
+    ///
+    /// The values of the map are a list of implementations and documentation
+    /// found on that implementation.
+    pub impls: FxHashMap<DefId, Vec<Impl>>,
+
+    /// Maintains a mapping of local crate `DefId`s to the fully qualified name
+    /// and "short type description" of that node. This is used when generating
+    /// URLs when a type is being linked to. External paths are not located in
+    /// this map because the `External` type itself has all the information
+    /// necessary.
+    pub paths: FxHashMap<DefId, (Vec<String>, ItemType)>,
+
+    /// Similar to `paths`, but only holds external paths. This is only used for
+    /// generating explicit hyperlinks to other crates.
+    pub external_paths: FxHashMap<DefId, (Vec<String>, ItemType)>,
+
+    /// Maps local `DefId`s of exported types to fully qualified paths.
+    /// Unlike 'paths', this mapping ignores any renames that occur
+    /// due to 'use' statements.
+    ///
+    /// This map is used when writing out the special 'implementors'
+    /// javascript file. By using the exact path that the type
+    /// is declared with, we ensure that each path will be identical
+    /// to the path used if the corresponding type is inlined. By
+    /// doing this, we can detect duplicate impls on a trait page, and only display
+    /// the impl for the inlined type.
+    pub exact_paths: FxHashMap<DefId, Vec<String>>,
+
+    /// This map contains information about all known traits of this crate.
+    /// Implementations of a crate should inherit the documentation of the
+    /// parent trait if no extra documentation is specified, and default methods
+    /// should show up in documentation about trait implementations.
+    pub traits: FxHashMap<DefId, clean::Trait>,
+
+    /// When rendering traits, it's often useful to be able to list all
+    /// implementors of the trait, and this mapping is exactly, that: a mapping
+    /// of trait ids to the list of known implementors of the trait
+    pub implementors: FxHashMap<DefId, Vec<Impl>>,
+
+    /// Cache of where external crate documentation can be found.
+    pub extern_locations: FxHashMap<CrateNum, (String, PathBuf, ExternalLocation)>,
+
+    /// Cache of where documentation for primitives can be found.
+    pub primitive_locations: FxHashMap<clean::PrimitiveType, DefId>,
+
+    // Note that external items for which `doc(hidden)` applies to are shown as
+    // non-reachable while local items aren't. This is because we're reusing
+    // the access levels from the privacy check pass.
+    pub access_levels: AccessLevels<DefId>,
+
+    /// The version of the crate being documented, if given from the `--crate-version` flag.
+    pub crate_version: Option<String>,
+
+    /// Whether to document private items.
+    /// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
+    pub document_private: bool,
+
+    // Private fields only used when initially crawling a crate to build a cache
+    stack: Vec<String>,
+    parent_stack: Vec<DefId>,
+    parent_is_trait_impl: bool,
+    stripped_mod: bool,
+    masked_crates: FxHashSet<CrateNum>,
+
+    pub search_index: Vec<IndexItem>,
+    pub deref_trait_did: Option<DefId>,
+    pub deref_mut_trait_did: Option<DefId>,
+    pub owned_box_did: Option<DefId>,
+
+    // In rare case where a structure is defined in one module but implemented
+    // in another, if the implementing module is parsed before defining module,
+    // then the fully qualified name of the structure isn't presented in `paths`
+    // yet when its implementation methods are being indexed. Caches such methods
+    // and their parent id here and indexes them at the end of crate parsing.
+    pub orphan_impl_items: Vec<(DefId, clean::Item)>,
+
+    // Similarly to `orphan_impl_items`, sometimes trait impls are picked up
+    // even though the trait itself is not exported. This can happen if a trait
+    // was defined in function/expression scope, since the impl will be picked
+    // up by `collect-trait-impls` but the trait won't be scraped out in the HIR
+    // crawl. In order to prevent crashes when looking for spotlight traits or
+    // when gathering trait documentation on a type, hold impls here while
+    // folding and add them to the cache later on if we find the trait.
+    orphan_trait_impls: Vec<(DefId, FxHashSet<DefId>, Impl)>,
+
+    /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
+    /// we need the alias element to have an array of items.
+    pub aliases: BTreeMap<String, Vec<usize>>,
+}
+
+impl Cache {
+    pub fn from_krate(
+        render_info: RenderInfo,
+        document_private: bool,
+        extern_html_root_urls: &BTreeMap<String, String>,
+        dst: &Path,
+        mut krate: clean::Crate,
+    ) -> (clean::Crate, Cache) {
+        // Crawl the crate to build various caches used for the output
+        let RenderInfo {
+            inlined: _,
+            external_paths,
+            exact_paths,
+            access_levels,
+            deref_trait_did,
+            deref_mut_trait_did,
+            owned_box_did,
+            ..
+        } = render_info;
+
+        let external_paths =
+            external_paths.into_iter().map(|(k, (v, t))| (k, (v, ItemType::from(t)))).collect();
+
+        let mut cache = Cache {
+            external_paths,
+            exact_paths,
+            parent_is_trait_impl: false,
+            stripped_mod: false,
+            access_levels,
+            crate_version: krate.version.take(),
+            document_private,
+            traits: krate.external_traits.replace(Default::default()),
+            deref_trait_did,
+            deref_mut_trait_did,
+            owned_box_did,
+            masked_crates: mem::take(&mut krate.masked_crates),
+            ..Cache::default()
+        };
+
+        // Cache where all our extern crates are located
+        // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
+        for &(n, ref e) in &krate.externs {
+            let src_root = match e.src {
+                FileName::Real(ref p) => match p.local_path().parent() {
+                    Some(p) => p.to_path_buf(),
+                    None => PathBuf::new(),
+                },
+                _ => PathBuf::new(),
+            };
+            let extern_url = extern_html_root_urls.get(&e.name).map(|u| &**u);
+            cache
+                .extern_locations
+                .insert(n, (e.name.clone(), src_root, extern_location(e, extern_url, &dst)));
+
+            let did = DefId { krate: n, index: CRATE_DEF_INDEX };
+            cache.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
+        }
+
+        // Cache where all known primitives have their documentation located.
+        //
+        // Favor linking to as local extern as possible, so iterate all crates in
+        // reverse topological order.
+        for &(_, ref e) in krate.externs.iter().rev() {
+            for &(def_id, prim, _) in &e.primitives {
+                cache.primitive_locations.insert(prim, def_id);
+            }
+        }
+        for &(def_id, prim, _) in &krate.primitives {
+            cache.primitive_locations.insert(prim, def_id);
+        }
+
+        cache.stack.push(krate.name.clone());
+        krate = cache.fold_crate(krate);
+
+        for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) {
+            if cache.traits.contains_key(&trait_did) {
+                for did in dids {
+                    cache.impls.entry(did).or_default().push(impl_.clone());
+                }
+            }
+        }
+
+        (krate, cache)
+    }
+}
+
+impl DocFolder for Cache {
+    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+        if item.def_id.is_local() {
+            debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id);
+        }
+
+        // If this is a stripped module,
+        // we don't want it or its children in the search index.
+        let orig_stripped_mod = match item.inner {
+            clean::StrippedItem(box clean::ModuleItem(..)) => {
+                mem::replace(&mut self.stripped_mod, true)
+            }
+            _ => self.stripped_mod,
+        };
+
+        // If the impl is from a masked crate or references something from a
+        // masked crate then remove it completely.
+        if let clean::ImplItem(ref i) = item.inner {
+            if self.masked_crates.contains(&item.def_id.krate)
+                || i.trait_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate))
+                || i.for_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate))
+            {
+                return None;
+            }
+        }
+
+        // Propagate a trait method's documentation to all implementors of the
+        // trait.
+        if let clean::TraitItem(ref t) = item.inner {
+            self.traits.entry(item.def_id).or_insert_with(|| t.clone());
+        }
+
+        // Collect all the implementors of traits.
+        if let clean::ImplItem(ref i) = item.inner {
+            if let Some(did) = i.trait_.def_id() {
+                if i.blanket_impl.is_none() {
+                    self.implementors
+                        .entry(did)
+                        .or_default()
+                        .push(Impl { impl_item: item.clone() });
+                }
+            }
+        }
+
+        // Index this method for searching later on.
+        if let Some(ref s) = item.name {
+            let (parent, is_inherent_impl_item) = match item.inner {
+                clean::StrippedItem(..) => ((None, None), false),
+                clean::AssocConstItem(..) | clean::TypedefItem(_, true)
+                    if self.parent_is_trait_impl =>
+                {
+                    // skip associated items in trait impls
+                    ((None, None), false)
+                }
+                clean::AssocTypeItem(..)
+                | clean::TyMethodItem(..)
+                | clean::StructFieldItem(..)
+                | clean::VariantItem(..) => (
+                    (
+                        Some(*self.parent_stack.last().expect("parent_stack is empty")),
+                        Some(&self.stack[..self.stack.len() - 1]),
+                    ),
+                    false,
+                ),
+                clean::MethodItem(..) | clean::AssocConstItem(..) => {
+                    if self.parent_stack.is_empty() {
+                        ((None, None), false)
+                    } else {
+                        let last = self.parent_stack.last().expect("parent_stack is empty 2");
+                        let did = *last;
+                        let path = match self.paths.get(&did) {
+                            // The current stack not necessarily has correlation
+                            // for where the type was defined. On the other
+                            // hand, `paths` always has the right
+                            // information if present.
+                            Some(&(
+                                ref fqp,
+                                ItemType::Trait
+                                | ItemType::Struct
+                                | ItemType::Union
+                                | ItemType::Enum,
+                            )) => Some(&fqp[..fqp.len() - 1]),
+                            Some(..) => Some(&*self.stack),
+                            None => None,
+                        };
+                        ((Some(*last), path), true)
+                    }
+                }
+                _ => ((None, Some(&*self.stack)), false),
+            };
+
+            match parent {
+                (parent, Some(path)) if is_inherent_impl_item || !self.stripped_mod => {
+                    debug_assert!(!item.is_stripped());
+
+                    // A crate has a module at its root, containing all items,
+                    // which should not be indexed. The crate-item itself is
+                    // inserted later on when serializing the search-index.
+                    if item.def_id.index != CRATE_DEF_INDEX {
+                        self.search_index.push(IndexItem {
+                            ty: item.type_(),
+                            name: s.to_string(),
+                            path: path.join("::"),
+                            desc: shorten(plain_summary_line(item.doc_value())),
+                            parent,
+                            parent_idx: None,
+                            search_type: get_index_search_type(&item),
+                        });
+
+                        for alias in item.attrs.get_doc_aliases() {
+                            self.aliases
+                                .entry(alias.to_lowercase())
+                                .or_insert(Vec::new())
+                                .push(self.search_index.len() - 1);
+                        }
+                    }
+                }
+                (Some(parent), None) if is_inherent_impl_item => {
+                    // We have a parent, but we don't know where they're
+                    // defined yet. Wait for later to index this item.
+                    self.orphan_impl_items.push((parent, item.clone()));
+                }
+                _ => {}
+            }
+        }
+
+        // Keep track of the fully qualified path for this item.
+        let pushed = match item.name {
+            Some(ref n) if !n.is_empty() => {
+                self.stack.push(n.to_string());
+                true
+            }
+            _ => false,
+        };
+
+        match item.inner {
+            clean::StructItem(..)
+            | clean::EnumItem(..)
+            | clean::TypedefItem(..)
+            | clean::TraitItem(..)
+            | clean::FunctionItem(..)
+            | clean::ModuleItem(..)
+            | clean::ForeignFunctionItem(..)
+            | clean::ForeignStaticItem(..)
+            | clean::ConstantItem(..)
+            | clean::StaticItem(..)
+            | clean::UnionItem(..)
+            | clean::ForeignTypeItem
+            | clean::MacroItem(..)
+            | clean::ProcMacroItem(..)
+            | clean::VariantItem(..)
+                if !self.stripped_mod =>
+            {
+                // Re-exported items mean that the same id can show up twice
+                // in the rustdoc ast that we're looking at. We know,
+                // however, that a re-exported item doesn't show up in the
+                // `public_items` map, so we can skip inserting into the
+                // paths map if there was already an entry present and we're
+                // not a public item.
+                if !self.paths.contains_key(&item.def_id)
+                    || self.access_levels.is_public(item.def_id)
+                {
+                    self.paths.insert(item.def_id, (self.stack.clone(), item.type_()));
+                }
+            }
+            clean::PrimitiveItem(..) => {
+                self.paths.insert(item.def_id, (self.stack.clone(), item.type_()));
+            }
+
+            _ => {}
+        }
+
+        // Maintain the parent stack
+        let orig_parent_is_trait_impl = self.parent_is_trait_impl;
+        let parent_pushed = match item.inner {
+            clean::TraitItem(..)
+            | clean::EnumItem(..)
+            | clean::ForeignTypeItem
+            | clean::StructItem(..)
+            | clean::UnionItem(..)
+            | clean::VariantItem(..) => {
+                self.parent_stack.push(item.def_id);
+                self.parent_is_trait_impl = false;
+                true
+            }
+            clean::ImplItem(ref i) => {
+                self.parent_is_trait_impl = i.trait_.is_some();
+                match i.for_ {
+                    clean::ResolvedPath { did, .. } => {
+                        self.parent_stack.push(did);
+                        true
+                    }
+                    ref t => {
+                        let prim_did = t
+                            .primitive_type()
+                            .and_then(|t| self.primitive_locations.get(&t).cloned());
+                        match prim_did {
+                            Some(did) => {
+                                self.parent_stack.push(did);
+                                true
+                            }
+                            None => false,
+                        }
+                    }
+                }
+            }
+            _ => false,
+        };
+
+        // Once we've recursively found all the generics, hoard off all the
+        // implementations elsewhere.
+        let ret = self.fold_item_recur(item).and_then(|item| {
+            if let clean::Item { inner: clean::ImplItem(_), .. } = item {
+                // Figure out the id of this impl. This may map to a
+                // primitive rather than always to a struct/enum.
+                // Note: matching twice to restrict the lifetime of the `i` borrow.
+                let mut dids = FxHashSet::default();
+                if let clean::Item { inner: clean::ImplItem(ref i), .. } = item {
+                    match i.for_ {
+                        clean::ResolvedPath { did, .. }
+                        | clean::BorrowedRef {
+                            type_: box clean::ResolvedPath { did, .. }, ..
+                        } => {
+                            dids.insert(did);
+                        }
+                        ref t => {
+                            let did = t
+                                .primitive_type()
+                                .and_then(|t| self.primitive_locations.get(&t).cloned());
+
+                            if let Some(did) = did {
+                                dids.insert(did);
+                            }
+                        }
+                    }
+
+                    if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
+                        for bound in generics {
+                            if let Some(did) = bound.def_id() {
+                                dids.insert(did);
+                            }
+                        }
+                    }
+                } else {
+                    unreachable!()
+                };
+                let impl_item = Impl { impl_item: item };
+                if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) {
+                    for did in dids {
+                        self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
+                    }
+                } else {
+                    let trait_did = impl_item.trait_did().expect("no trait did");
+                    self.orphan_trait_impls.push((trait_did, dids, impl_item));
+                }
+                None
+            } else {
+                Some(item)
+            }
+        });
+
+        if pushed {
+            self.stack.pop().expect("stack already empty");
+        }
+        if parent_pushed {
+            self.parent_stack.pop().expect("parent stack already empty");
+        }
+        self.stripped_mod = orig_stripped_mod;
+        self.parent_is_trait_impl = orig_parent_is_trait_impl;
+        ret
+    }
+}
+
+crate fn cache() -> Arc<Cache> {
+    CACHE_KEY.with(|c| c.borrow().clone())
+}
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/formats/item_type.rs
index cc78b4682d2..696bdae94fc 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -13,7 +13,7 @@ use crate::clean;
 /// The search index uses item types encoded as smaller numbers which equal to
 /// discriminants. JavaScript then is used to decode them into the original value.
 /// Consequently, every change to this type should be synchronized to
-/// the `itemTypes` mapping table in `static/main.js`.
+/// the `itemTypes` mapping table in `html/static/main.js`.
 ///
 /// In addition, code in `html::render` uses this enum to generate CSS classes, page prefixes, and
 /// module headings. If you are adding to this enum and want to ensure that the sidebar also prints
diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs
new file mode 100644
index 00000000000..dcb0184c58c
--- /dev/null
+++ b/src/librustdoc/formats/mod.rs
@@ -0,0 +1,44 @@
+pub mod cache;
+pub mod item_type;
+pub mod renderer;
+
+pub use renderer::{run_format, FormatRenderer};
+
+use rustc_span::def_id::DefId;
+
+use crate::clean;
+use crate::clean::types::GetDefId;
+
+/// Specifies whether rendering directly implemented trait items or ones from a certain Deref
+/// impl.
+pub enum AssocItemRender<'a> {
+    All,
+    DerefFor { trait_: &'a clean::Type, type_: &'a clean::Type, deref_mut_: bool },
+}
+
+/// For different handling of associated items from the Deref target of a type rather than the type
+/// itself.
+#[derive(Copy, Clone, PartialEq)]
+pub enum RenderMode {
+    Normal,
+    ForDeref { mut_: bool },
+}
+
+/// Metadata about implementations for a type or trait.
+#[derive(Clone, Debug)]
+pub struct Impl {
+    pub impl_item: clean::Item,
+}
+
+impl Impl {
+    pub fn inner_impl(&self) -> &clean::Impl {
+        match self.impl_item.inner {
+            clean::ImplItem(ref impl_) => impl_,
+            _ => panic!("non-impl item found in impl"),
+        }
+    }
+
+    pub fn trait_did(&self) -> Option<DefId> {
+        self.inner_impl().trait_.def_id()
+    }
+}
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
new file mode 100644
index 00000000000..90ace4d44c4
--- /dev/null
+++ b/src/librustdoc/formats/renderer.rs
@@ -0,0 +1,106 @@
+use std::sync::Arc;
+
+use rustc_span::edition::Edition;
+
+use crate::clean;
+use crate::config::{RenderInfo, RenderOptions};
+use crate::error::Error;
+use crate::formats::cache::{Cache, CACHE_KEY};
+
+/// Allows for different backends to rustdoc to be used with the `run_format()` function. Each
+/// backend renderer has hooks for initialization, documenting an item, entering and exiting a
+/// module, and cleanup/finalizing output.
+pub trait FormatRenderer: Clone {
+    /// Sets up any state required for the renderer. When this is called the cache has already been
+    /// populated.
+    fn init(
+        krate: clean::Crate,
+        options: RenderOptions,
+        render_info: RenderInfo,
+        edition: Edition,
+        cache: &mut Cache,
+    ) -> Result<(Self, clean::Crate), Error>;
+
+    /// Renders a single non-module item. This means no recursive sub-item rendering is required.
+    fn item(&mut self, item: clean::Item, cache: &Cache) -> Result<(), Error>;
+
+    /// Renders a module (should not handle recursing into children).
+    fn mod_item_in(
+        &mut self,
+        item: &clean::Item,
+        item_name: &str,
+        cache: &Cache,
+    ) -> Result<(), Error>;
+
+    /// Runs after recursively rendering all sub-items of a module.
+    fn mod_item_out(&mut self, item_name: &str) -> Result<(), Error>;
+
+    /// Post processing hook for cleanup and dumping output to files.
+    fn after_krate(&mut self, krate: &clean::Crate, cache: &Cache) -> Result<(), Error>;
+
+    /// Called after everything else to write out errors.
+    fn after_run(&mut self, diag: &rustc_errors::Handler) -> Result<(), Error>;
+}
+
+/// Main method for rendering a crate.
+pub fn run_format<T: FormatRenderer>(
+    krate: clean::Crate,
+    options: RenderOptions,
+    render_info: RenderInfo,
+    diag: &rustc_errors::Handler,
+    edition: Edition,
+) -> Result<(), Error> {
+    let (krate, mut cache) = Cache::from_krate(
+        render_info.clone(),
+        options.document_private,
+        &options.extern_html_root_urls,
+        &options.output,
+        krate,
+    );
+
+    let (mut format_renderer, mut krate) =
+        T::init(krate, options, render_info, edition, &mut cache)?;
+
+    let cache = Arc::new(cache);
+    // Freeze the cache now that the index has been built. Put an Arc into TLS for future
+    // parallelization opportunities
+    CACHE_KEY.with(|v| *v.borrow_mut() = cache.clone());
+
+    let mut item = match krate.module.take() {
+        Some(i) => i,
+        None => return Ok(()),
+    };
+
+    item.name = Some(krate.name.clone());
+
+    // Render the crate documentation
+    let mut work = vec![(format_renderer.clone(), item)];
+
+    while let Some((mut cx, item)) = work.pop() {
+        if item.is_mod() {
+            // modules are special because they add a namespace. We also need to
+            // recurse into the items of the module as well.
+            let name = item.name.as_ref().unwrap().to_string();
+            if name.is_empty() {
+                panic!("Unexpected module with empty name");
+            }
+
+            cx.mod_item_in(&item, &name, &cache)?;
+            let module = match item.inner {
+                clean::StrippedItem(box clean::ModuleItem(m)) | clean::ModuleItem(m) => m,
+                _ => unreachable!(),
+            };
+            for it in module.items {
+                debug!("Adding {:?} to worklist", it.name);
+                work.push((cx.clone(), it));
+            }
+
+            cx.mod_item_out(&name)?;
+        } else if item.name.is_some() {
+            cx.item(item, &cache)?;
+        }
+    }
+
+    format_renderer.after_krate(&krate, &cache)?;
+    format_renderer.after_run(diag)
+}
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 0d8284029af..699f8c36cba 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -11,13 +11,15 @@ use std::fmt;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_span::def_id::DefId;
 use rustc_target::spec::abi::Abi;
 
 use crate::clean::{self, PrimitiveType};
+use crate::formats::cache::cache;
+use crate::formats::item_type::ItemType;
 use crate::html::escape::Escape;
-use crate::html::item_type::ItemType;
-use crate::html::render::{self, cache, CURRENT_DEPTH};
+use crate::html::render::cache::ExternalLocation;
+use crate::html::render::CURRENT_DEPTH;
 
 pub trait Print {
     fn print(self, buffer: &mut Buffer);
@@ -493,9 +495,9 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
                 fqp,
                 shortty,
                 match cache.extern_locations[&did.krate] {
-                    (.., render::Remote(ref s)) => s.to_string(),
-                    (.., render::Local) => "../".repeat(depth),
-                    (.., render::Unknown) => return None,
+                    (.., ExternalLocation::Remote(ref s)) => s.to_string(),
+                    (.., ExternalLocation::Local) => "../".repeat(depth),
+                    (.., ExternalLocation::Unknown) => return None,
                 },
             )
         }
@@ -574,12 +576,12 @@ fn primitive_link(
             }
             Some(&def_id) => {
                 let loc = match m.extern_locations[&def_id.krate] {
-                    (ref cname, _, render::Remote(ref s)) => Some((cname, s.to_string())),
-                    (ref cname, _, render::Local) => {
+                    (ref cname, _, ExternalLocation::Remote(ref s)) => Some((cname, s.to_string())),
+                    (ref cname, _, ExternalLocation::Local) => {
                         let len = CURRENT_DEPTH.with(|s| s.get());
                         Some((cname, "../".repeat(len)))
                     }
-                    (.., render::Unknown) => None,
+                    (.., ExternalLocation::Unknown) => None,
                 };
                 if let Some((cname, root)) = loc {
                     write!(
diff --git a/src/librustdoc/html/mod.rs b/src/librustdoc/html/mod.rs
new file mode 100644
index 00000000000..367538d440e
--- /dev/null
+++ b/src/librustdoc/html/mod.rs
@@ -0,0 +1,9 @@
+crate mod escape;
+crate mod format;
+crate mod highlight;
+crate mod layout;
+pub mod markdown;
+pub mod render;
+crate mod sources;
+crate mod static_files;
+crate mod toc;
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 1b5c8a9378e..378efa1a1be 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -1,18 +1,16 @@
-use crate::clean::{self, AttributesExt, GetDefId};
-use crate::fold::DocFolder;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
-use rustc_middle::middle::privacy::AccessLevels;
-use rustc_span::source_map::FileName;
-use rustc_span::symbol::sym;
 use std::collections::BTreeMap;
-use std::mem;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_span::symbol::sym;
 use serde::Serialize;
 
-use super::{plain_summary_line, shorten, Impl, IndexItem, IndexItemFunctionType, ItemType};
-use super::{Generic, RenderInfo, RenderType, TypeWithKind};
+use crate::clean::types::GetDefId;
+use crate::clean::{self, AttributesExt};
+use crate::formats::cache::Cache;
+use crate::formats::item_type::ItemType;
+use crate::html::render::{plain_summary_line, shorten};
+use crate::html::render::{Generic, IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
 
 /// Indicates where an external crate can be found.
 pub enum ExternalLocation {
@@ -24,483 +22,9 @@ pub enum ExternalLocation {
     Unknown,
 }
 
-/// This cache is used to store information about the `clean::Crate` being
-/// rendered in order to provide more useful documentation. This contains
-/// information like all implementors of a trait, all traits a type implements,
-/// documentation for all known traits, etc.
-///
-/// This structure purposefully does not implement `Clone` because it's intended
-/// to be a fairly large and expensive structure to clone. Instead this adheres
-/// to `Send` so it may be stored in a `Arc` instance and shared among the various
-/// rendering threads.
-#[derive(Default)]
-crate struct Cache {
-    /// Maps a type ID to all known implementations for that type. This is only
-    /// recognized for intra-crate `ResolvedPath` types, and is used to print
-    /// out extra documentation on the page of an enum/struct.
-    ///
-    /// The values of the map are a list of implementations and documentation
-    /// found on that implementation.
-    pub impls: FxHashMap<DefId, Vec<Impl>>,
-
-    /// Maintains a mapping of local crate `DefId`s to the fully qualified name
-    /// and "short type description" of that node. This is used when generating
-    /// URLs when a type is being linked to. External paths are not located in
-    /// this map because the `External` type itself has all the information
-    /// necessary.
-    pub paths: FxHashMap<DefId, (Vec<String>, ItemType)>,
-
-    /// Similar to `paths`, but only holds external paths. This is only used for
-    /// generating explicit hyperlinks to other crates.
-    pub external_paths: FxHashMap<DefId, (Vec<String>, ItemType)>,
-
-    /// Maps local `DefId`s of exported types to fully qualified paths.
-    /// Unlike 'paths', this mapping ignores any renames that occur
-    /// due to 'use' statements.
-    ///
-    /// This map is used when writing out the special 'implementors'
-    /// javascript file. By using the exact path that the type
-    /// is declared with, we ensure that each path will be identical
-    /// to the path used if the corresponding type is inlined. By
-    /// doing this, we can detect duplicate impls on a trait page, and only display
-    /// the impl for the inlined type.
-    pub exact_paths: FxHashMap<DefId, Vec<String>>,
-
-    /// This map contains information about all known traits of this crate.
-    /// Implementations of a crate should inherit the documentation of the
-    /// parent trait if no extra documentation is specified, and default methods
-    /// should show up in documentation about trait implementations.
-    pub traits: FxHashMap<DefId, clean::Trait>,
-
-    /// When rendering traits, it's often useful to be able to list all
-    /// implementors of the trait, and this mapping is exactly, that: a mapping
-    /// of trait ids to the list of known implementors of the trait
-    pub implementors: FxHashMap<DefId, Vec<Impl>>,
-
-    /// Cache of where external crate documentation can be found.
-    pub extern_locations: FxHashMap<CrateNum, (String, PathBuf, ExternalLocation)>,
-
-    /// Cache of where documentation for primitives can be found.
-    pub primitive_locations: FxHashMap<clean::PrimitiveType, DefId>,
-
-    // Note that external items for which `doc(hidden)` applies to are shown as
-    // non-reachable while local items aren't. This is because we're reusing
-    // the access levels from the privacy check pass.
-    pub access_levels: AccessLevels<DefId>,
-
-    /// The version of the crate being documented, if given from the `--crate-version` flag.
-    pub crate_version: Option<String>,
-
-    /// Whether to document private items.
-    /// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
-    pub document_private: bool,
-
-    // Private fields only used when initially crawling a crate to build a cache
-    stack: Vec<String>,
-    parent_stack: Vec<DefId>,
-    parent_is_trait_impl: bool,
-    search_index: Vec<IndexItem>,
-    stripped_mod: bool,
-    pub deref_trait_did: Option<DefId>,
-    pub deref_mut_trait_did: Option<DefId>,
-    pub owned_box_did: Option<DefId>,
-    masked_crates: FxHashSet<CrateNum>,
-
-    // In rare case where a structure is defined in one module but implemented
-    // in another, if the implementing module is parsed before defining module,
-    // then the fully qualified name of the structure isn't presented in `paths`
-    // yet when its implementation methods are being indexed. Caches such methods
-    // and their parent id here and indexes them at the end of crate parsing.
-    orphan_impl_items: Vec<(DefId, clean::Item)>,
-
-    // Similarly to `orphan_impl_items`, sometimes trait impls are picked up
-    // even though the trait itself is not exported. This can happen if a trait
-    // was defined in function/expression scope, since the impl will be picked
-    // up by `collect-trait-impls` but the trait won't be scraped out in the HIR
-    // crawl. In order to prevent crashes when looking for spotlight traits or
-    // when gathering trait documentation on a type, hold impls here while
-    // folding and add them to the cache later on if we find the trait.
-    orphan_trait_impls: Vec<(DefId, FxHashSet<DefId>, Impl)>,
-
-    /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
-    /// we need the alias element to have an array of items.
-    pub(super) aliases: BTreeMap<String, Vec<usize>>,
-}
-
-impl Cache {
-    pub fn from_krate(
-        renderinfo: RenderInfo,
-        document_private: bool,
-        extern_html_root_urls: &BTreeMap<String, String>,
-        dst: &Path,
-        mut krate: clean::Crate,
-    ) -> (clean::Crate, String, Cache) {
-        // Crawl the crate to build various caches used for the output
-        let RenderInfo {
-            inlined: _,
-            external_paths,
-            exact_paths,
-            access_levels,
-            deref_trait_did,
-            deref_mut_trait_did,
-            owned_box_did,
-            ..
-        } = renderinfo;
-
-        let external_paths =
-            external_paths.into_iter().map(|(k, (v, t))| (k, (v, ItemType::from(t)))).collect();
-
-        let mut cache = Cache {
-            impls: Default::default(),
-            external_paths,
-            exact_paths,
-            paths: Default::default(),
-            implementors: Default::default(),
-            stack: Vec::new(),
-            parent_stack: Vec::new(),
-            search_index: Vec::new(),
-            parent_is_trait_impl: false,
-            extern_locations: Default::default(),
-            primitive_locations: Default::default(),
-            stripped_mod: false,
-            access_levels,
-            crate_version: krate.version.take(),
-            document_private,
-            orphan_impl_items: Vec::new(),
-            orphan_trait_impls: Vec::new(),
-            traits: krate.external_traits.replace(Default::default()),
-            deref_trait_did,
-            deref_mut_trait_did,
-            owned_box_did,
-            masked_crates: mem::take(&mut krate.masked_crates),
-            aliases: Default::default(),
-        };
-
-        // Cache where all our extern crates are located
-        for &(n, ref e) in &krate.externs {
-            let src_root = match e.src {
-                FileName::Real(ref p) => match p.local_path().parent() {
-                    Some(p) => p.to_path_buf(),
-                    None => PathBuf::new(),
-                },
-                _ => PathBuf::new(),
-            };
-            let extern_url = extern_html_root_urls.get(&e.name).map(|u| &**u);
-            cache
-                .extern_locations
-                .insert(n, (e.name.clone(), src_root, extern_location(e, extern_url, &dst)));
-
-            let did = DefId { krate: n, index: CRATE_DEF_INDEX };
-            cache.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
-        }
-
-        // Cache where all known primitives have their documentation located.
-        //
-        // Favor linking to as local extern as possible, so iterate all crates in
-        // reverse topological order.
-        for &(_, ref e) in krate.externs.iter().rev() {
-            for &(def_id, prim, _) in &e.primitives {
-                cache.primitive_locations.insert(prim, def_id);
-            }
-        }
-        for &(def_id, prim, _) in &krate.primitives {
-            cache.primitive_locations.insert(prim, def_id);
-        }
-
-        cache.stack.push(krate.name.clone());
-        krate = cache.fold_crate(krate);
-
-        for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) {
-            if cache.traits.contains_key(&trait_did) {
-                for did in dids {
-                    cache.impls.entry(did).or_insert(vec![]).push(impl_.clone());
-                }
-            }
-        }
-
-        // Build our search index
-        let index = build_index(&krate, &mut cache);
-
-        (krate, index, cache)
-    }
-}
-
-impl DocFolder for Cache {
-    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
-        if item.def_id.is_local() {
-            debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id);
-        }
-
-        // If this is a stripped module,
-        // we don't want it or its children in the search index.
-        let orig_stripped_mod = match item.inner {
-            clean::StrippedItem(box clean::ModuleItem(..)) => {
-                mem::replace(&mut self.stripped_mod, true)
-            }
-            _ => self.stripped_mod,
-        };
-
-        // If the impl is from a masked crate or references something from a
-        // masked crate then remove it completely.
-        if let clean::ImplItem(ref i) = item.inner {
-            if self.masked_crates.contains(&item.def_id.krate)
-                || i.trait_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate))
-                || i.for_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate))
-            {
-                return None;
-            }
-        }
-
-        // Propagate a trait method's documentation to all implementors of the
-        // trait.
-        if let clean::TraitItem(ref t) = item.inner {
-            self.traits.entry(item.def_id).or_insert_with(|| t.clone());
-        }
-
-        // Collect all the implementors of traits.
-        if let clean::ImplItem(ref i) = item.inner {
-            if let Some(did) = i.trait_.def_id() {
-                if i.blanket_impl.is_none() {
-                    self.implementors
-                        .entry(did)
-                        .or_default()
-                        .push(Impl { impl_item: item.clone() });
-                }
-            }
-        }
-
-        // Index this method for searching later on.
-        if let Some(ref s) = item.name {
-            let (parent, is_inherent_impl_item) = match item.inner {
-                clean::StrippedItem(..) => ((None, None), false),
-                clean::AssocConstItem(..) | clean::TypedefItem(_, true)
-                    if self.parent_is_trait_impl =>
-                {
-                    // skip associated items in trait impls
-                    ((None, None), false)
-                }
-                clean::AssocTypeItem(..)
-                | clean::TyMethodItem(..)
-                | clean::StructFieldItem(..)
-                | clean::VariantItem(..) => (
-                    (
-                        Some(*self.parent_stack.last().expect("parent_stack is empty")),
-                        Some(&self.stack[..self.stack.len() - 1]),
-                    ),
-                    false,
-                ),
-                clean::MethodItem(..) | clean::AssocConstItem(..) => {
-                    if self.parent_stack.is_empty() {
-                        ((None, None), false)
-                    } else {
-                        let last = self.parent_stack.last().expect("parent_stack is empty 2");
-                        let did = *last;
-                        let path = match self.paths.get(&did) {
-                            // The current stack not necessarily has correlation
-                            // for where the type was defined. On the other
-                            // hand, `paths` always has the right
-                            // information if present.
-                            Some(&(
-                                ref fqp,
-                                ItemType::Trait
-                                | ItemType::Struct
-                                | ItemType::Union
-                                | ItemType::Enum,
-                            )) => Some(&fqp[..fqp.len() - 1]),
-                            Some(..) => Some(&*self.stack),
-                            None => None,
-                        };
-                        ((Some(*last), path), true)
-                    }
-                }
-                _ => ((None, Some(&*self.stack)), false),
-            };
-
-            match parent {
-                (parent, Some(path)) if is_inherent_impl_item || !self.stripped_mod => {
-                    debug_assert!(!item.is_stripped());
-
-                    // A crate has a module at its root, containing all items,
-                    // which should not be indexed. The crate-item itself is
-                    // inserted later on when serializing the search-index.
-                    if item.def_id.index != CRATE_DEF_INDEX {
-                        self.search_index.push(IndexItem {
-                            ty: item.type_(),
-                            name: s.to_string(),
-                            path: path.join("::"),
-                            desc: shorten(plain_summary_line(item.doc_value())),
-                            parent,
-                            parent_idx: None,
-                            search_type: get_index_search_type(&item),
-                        });
-
-                        for alias in item.attrs.get_doc_aliases() {
-                            self.aliases
-                                .entry(alias.to_lowercase())
-                                .or_insert(Vec::new())
-                                .push(self.search_index.len() - 1);
-                        }
-                    }
-                }
-                (Some(parent), None) if is_inherent_impl_item => {
-                    // We have a parent, but we don't know where they're
-                    // defined yet. Wait for later to index this item.
-                    self.orphan_impl_items.push((parent, item.clone()));
-                }
-                _ => {}
-            }
-        }
-
-        // Keep track of the fully qualified path for this item.
-        let pushed = match item.name {
-            Some(ref n) if !n.is_empty() => {
-                self.stack.push(n.to_string());
-                true
-            }
-            _ => false,
-        };
-
-        match item.inner {
-            clean::StructItem(..)
-            | clean::EnumItem(..)
-            | clean::TypedefItem(..)
-            | clean::TraitItem(..)
-            | clean::FunctionItem(..)
-            | clean::ModuleItem(..)
-            | clean::ForeignFunctionItem(..)
-            | clean::ForeignStaticItem(..)
-            | clean::ConstantItem(..)
-            | clean::StaticItem(..)
-            | clean::UnionItem(..)
-            | clean::ForeignTypeItem
-            | clean::MacroItem(..)
-            | clean::ProcMacroItem(..)
-            | clean::VariantItem(..)
-                if !self.stripped_mod =>
-            {
-                // Re-exported items mean that the same id can show up twice
-                // in the rustdoc ast that we're looking at. We know,
-                // however, that a re-exported item doesn't show up in the
-                // `public_items` map, so we can skip inserting into the
-                // paths map if there was already an entry present and we're
-                // not a public item.
-                if !self.paths.contains_key(&item.def_id)
-                    || self.access_levels.is_public(item.def_id)
-                {
-                    self.paths.insert(item.def_id, (self.stack.clone(), item.type_()));
-                }
-            }
-            clean::PrimitiveItem(..) => {
-                self.paths.insert(item.def_id, (self.stack.clone(), item.type_()));
-            }
-
-            _ => {}
-        }
-
-        // Maintain the parent stack
-        let orig_parent_is_trait_impl = self.parent_is_trait_impl;
-        let parent_pushed = match item.inner {
-            clean::TraitItem(..)
-            | clean::EnumItem(..)
-            | clean::ForeignTypeItem
-            | clean::StructItem(..)
-            | clean::UnionItem(..)
-            | clean::VariantItem(..) => {
-                self.parent_stack.push(item.def_id);
-                self.parent_is_trait_impl = false;
-                true
-            }
-            clean::ImplItem(ref i) => {
-                self.parent_is_trait_impl = i.trait_.is_some();
-                match i.for_ {
-                    clean::ResolvedPath { did, .. } => {
-                        self.parent_stack.push(did);
-                        true
-                    }
-                    ref t => {
-                        let prim_did = t
-                            .primitive_type()
-                            .and_then(|t| self.primitive_locations.get(&t).cloned());
-                        match prim_did {
-                            Some(did) => {
-                                self.parent_stack.push(did);
-                                true
-                            }
-                            None => false,
-                        }
-                    }
-                }
-            }
-            _ => false,
-        };
-
-        // Once we've recursively found all the generics, hoard off all the
-        // implementations elsewhere.
-        let ret = self.fold_item_recur(item).and_then(|item| {
-            if let clean::Item { inner: clean::ImplItem(_), .. } = item {
-                // Figure out the id of this impl. This may map to a
-                // primitive rather than always to a struct/enum.
-                // Note: matching twice to restrict the lifetime of the `i` borrow.
-                let mut dids = FxHashSet::default();
-                if let clean::Item { inner: clean::ImplItem(ref i), .. } = item {
-                    match i.for_ {
-                        clean::ResolvedPath { did, .. }
-                        | clean::BorrowedRef {
-                            type_: box clean::ResolvedPath { did, .. }, ..
-                        } => {
-                            dids.insert(did);
-                        }
-                        ref t => {
-                            let did = t
-                                .primitive_type()
-                                .and_then(|t| self.primitive_locations.get(&t).cloned());
-
-                            if let Some(did) = did {
-                                dids.insert(did);
-                            }
-                        }
-                    }
-
-                    if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
-                        for bound in generics {
-                            if let Some(did) = bound.def_id() {
-                                dids.insert(did);
-                            }
-                        }
-                    }
-                } else {
-                    unreachable!()
-                };
-                let impl_item = Impl { impl_item: item };
-                if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) {
-                    for did in dids {
-                        self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
-                    }
-                } else {
-                    let trait_did = impl_item.trait_did().expect("no trait did");
-                    self.orphan_trait_impls.push((trait_did, dids, impl_item));
-                }
-                None
-            } else {
-                Some(item)
-            }
-        });
-
-        if pushed {
-            self.stack.pop().expect("stack already empty");
-        }
-        if parent_pushed {
-            self.parent_stack.pop().expect("parent stack already empty");
-        }
-        self.stripped_mod = orig_stripped_mod;
-        self.parent_is_trait_impl = orig_parent_is_trait_impl;
-        ret
-    }
-}
-
 /// Attempts to find where an external crate is located, given that we're
 /// rendering in to the specified source destination.
-fn extern_location(
+pub fn extern_location(
     e: &clean::ExternalCrate,
     extern_url: Option<&str>,
     dst: &Path,
@@ -538,7 +62,7 @@ fn extern_location(
 }
 
 /// Builds the search index from the collected metadata
-fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
+pub fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     let mut defid_to_pathid = FxHashMap::default();
     let mut crate_items = Vec::with_capacity(cache.search_index.len());
     let mut crate_paths = vec![];
@@ -640,7 +164,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     )
 }
 
-fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
+crate fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
     let (all_types, ret_types) = match item.inner {
         clean::FunctionItem(ref f) => (&f.all_types, &f.ret_types),
         clean::MethodItem(ref m) => (&m.all_types, &m.ret_types),
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render/mod.rs
index f7050cf3777..5fb2d9f6f91 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -25,14 +25,18 @@
 //! These threads are not parallelized (they haven't been a bottleneck yet), and
 //! both occur before the crate is rendered.
 
+pub mod cache;
+
+#[cfg(test)]
+mod tests;
+
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
 use std::cmp::Ordering;
 use std::collections::{BTreeMap, VecDeque};
 use std::default::Default;
-use std::error;
 use std::ffi::OsStr;
-use std::fmt::{self, Formatter, Write};
+use std::fmt::{self, Write};
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io::{self, BufReader};
@@ -40,6 +44,7 @@ use std::path::{Component, Path, PathBuf};
 use std::rc::Rc;
 use std::str;
 use std::string::ToString;
+use std::sync::mpsc::{channel, Receiver};
 use std::sync::Arc;
 
 use itertools::Itertools;
@@ -50,7 +55,6 @@ use rustc_feature::UnstableFeatures;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::Mutability;
-use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::middle::stability;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::MacroKind;
@@ -60,26 +64,23 @@ use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
 
 use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind};
-use crate::config::{OutputFormat, RenderOptions};
-use crate::docfs::{DocFS, ErrorStorage, PathError};
+use crate::config::RenderInfo;
+use crate::config::RenderOptions;
+use crate::docfs::{DocFS, PathError};
 use crate::doctree;
+use crate::error::Error;
+use crate::formats::cache::{cache, Cache};
+use crate::formats::item_type::ItemType;
+use crate::formats::{AssocItemRender, FormatRenderer, Impl, RenderMode};
 use crate::html::escape::Escape;
 use crate::html::format::fmt_impl_for_trait_page;
 use crate::html::format::Function;
 use crate::html::format::{href, print_default_space, print_generic_bounds, WhereClause};
 use crate::html::format::{print_abi_with_space, Buffer, PrintWithSpace};
-use crate::html::item_type::ItemType;
 use crate::html::markdown::{self, ErrorCodes, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine};
 use crate::html::sources;
 use crate::html::{highlight, layout, static_files};
-
-#[cfg(test)]
-mod tests;
-
-mod cache;
-
-use cache::Cache;
-crate use cache::ExternalLocation::{self, *};
+use cache::{build_index, ExternalLocation};
 
 /// A pair of name and its optional document.
 pub type NameDoc = (String, Option<String>);
@@ -90,55 +91,6 @@ crate fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ {
     })
 }
 
-#[derive(Debug)]
-pub struct Error {
-    pub file: PathBuf,
-    pub error: String,
-}
-
-impl error::Error for Error {}
-
-impl std::fmt::Display for Error {
-    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
-        let file = self.file.display().to_string();
-        if file.is_empty() {
-            write!(f, "{}", self.error)
-        } else {
-            write!(f, "\"{}\": {}", self.file.display(), self.error)
-        }
-    }
-}
-
-impl PathError for Error {
-    fn new<S, P: AsRef<Path>>(e: S, path: P) -> Error
-    where
-        S: ToString + Sized,
-    {
-        Error { file: path.as_ref().to_path_buf(), error: e.to_string() }
-    }
-}
-
-macro_rules! try_none {
-    ($e:expr, $file:expr) => {{
-        use std::io;
-        match $e {
-            Some(e) => e,
-            None => {
-                return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"), $file));
-            }
-        }
-    }};
-}
-
-macro_rules! try_err {
-    ($e:expr, $file:expr) => {{
-        match $e {
-            Ok(e) => e,
-            Err(e) => return Err(Error::new(e, $file)),
-        }
-    }};
-}
-
 /// Major driving force in all rustdoc rendering. This contains information
 /// about where in the tree-like hierarchy rendering is occurring and controls
 /// how the current page is being rendered.
@@ -147,7 +99,7 @@ macro_rules! try_err {
 /// easily cloned because it is cloned per work-job (about once per item in the
 /// rustdoc tree).
 #[derive(Clone)]
-struct Context {
+crate struct Context {
     /// Current hierarchy of components leading down to what's currently being
     /// rendered
     pub current: Vec<String>,
@@ -161,7 +113,10 @@ struct Context {
     /// The map used to ensure all generated 'id=' attributes are unique.
     id_map: Rc<RefCell<IdMap>>,
     pub shared: Arc<SharedContext>,
-    pub cache: Arc<Cache>,
+    all: Rc<RefCell<AllTypes>>,
+    /// Storage for the errors produced while generating documentation so they
+    /// can be printed together at the end.
+    pub errors: Rc<Receiver<String>>,
 }
 
 crate struct SharedContext {
@@ -241,53 +196,20 @@ impl SharedContext {
     }
 }
 
-/// Metadata about implementations for a type or trait.
-#[derive(Clone, Debug)]
-pub struct Impl {
-    pub impl_item: clean::Item,
-}
-
-impl Impl {
-    fn inner_impl(&self) -> &clean::Impl {
-        match self.impl_item.inner {
-            clean::ImplItem(ref impl_) => impl_,
-            _ => panic!("non-impl item found in impl"),
-        }
-    }
-
-    fn trait_did(&self) -> Option<DefId> {
-        self.inner_impl().trait_.def_id()
-    }
-}
-
-/// Temporary storage for data obtained during `RustdocVisitor::clean()`.
-/// Later on moved into `CACHE_KEY`.
-#[derive(Default)]
-pub struct RenderInfo {
-    pub inlined: FxHashSet<DefId>,
-    pub external_paths: crate::core::ExternalPaths,
-    pub exact_paths: FxHashMap<DefId, Vec<String>>,
-    pub access_levels: AccessLevels<DefId>,
-    pub deref_trait_did: Option<DefId>,
-    pub deref_mut_trait_did: Option<DefId>,
-    pub owned_box_did: Option<DefId>,
-    pub output_format: Option<OutputFormat>,
-}
-
 // Helper structs for rendering items/sidebars and carrying along contextual
 // information
 
 /// Struct representing one entry in the JS search index. These are all emitted
 /// by hand to a large JS file at the end of cache-creation.
 #[derive(Debug)]
-struct IndexItem {
-    ty: ItemType,
-    name: String,
-    path: String,
-    desc: String,
-    parent: Option<DefId>,
-    parent_idx: Option<usize>,
-    search_type: Option<IndexItemFunctionType>,
+pub struct IndexItem {
+    pub ty: ItemType,
+    pub name: String,
+    pub path: String,
+    pub desc: String,
+    pub parent: Option<DefId>,
+    pub parent_idx: Option<usize>,
+    pub search_type: Option<IndexItemFunctionType>,
 }
 
 impl Serialize for IndexItem {
@@ -309,7 +231,7 @@ impl Serialize for IndexItem {
 
 /// A type used for the search index.
 #[derive(Debug)]
-struct RenderType {
+crate struct RenderType {
     ty: Option<DefId>,
     idx: Option<usize>,
     name: Option<String>,
@@ -340,7 +262,7 @@ impl Serialize for RenderType {
 
 /// A type used for the search index.
 #[derive(Debug)]
-struct Generic {
+crate struct Generic {
     name: String,
     defid: Option<DefId>,
     idx: Option<usize>,
@@ -361,7 +283,7 @@ impl Serialize for Generic {
 
 /// Full type of functions/methods in the search index.
 #[derive(Debug)]
-struct IndexItemFunctionType {
+pub struct IndexItemFunctionType {
     inputs: Vec<TypeWithKind>,
     output: Option<Vec<TypeWithKind>>,
 }
@@ -394,7 +316,7 @@ impl Serialize for IndexItemFunctionType {
 }
 
 #[derive(Debug)]
-pub struct TypeWithKind {
+crate struct TypeWithKind {
     ty: RenderType,
     kind: TypeKind,
 }
@@ -426,7 +348,6 @@ pub struct StylePath {
     pub disabled: bool,
 }
 
-thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
 thread_local!(pub static CURRENT_DEPTH: Cell<usize> = Cell::new(0));
 
 pub fn initial_ids() -> Vec<String> {
@@ -454,147 +375,301 @@ pub fn initial_ids() -> Vec<String> {
 }
 
 /// Generates the documentation for `crate` into the directory `dst`
-pub fn run(
-    mut krate: clean::Crate,
-    options: RenderOptions,
-    renderinfo: RenderInfo,
-    diag: &rustc_errors::Handler,
-    edition: Edition,
-) -> Result<(), Error> {
-    // need to save a copy of the options for rendering the index page
-    let md_opts = options.clone();
-    let RenderOptions {
-        output,
-        external_html,
-        id_map,
-        playground_url,
-        sort_modules_alphabetically,
-        themes: style_files,
-        extension_css,
-        extern_html_root_urls,
-        resource_suffix,
-        static_root_path,
-        generate_search_filter,
-        document_private,
-        ..
-    } = options;
-
-    let src_root = match krate.src {
-        FileName::Real(ref p) => match p.local_path().parent() {
-            Some(p) => p.to_path_buf(),
-            None => PathBuf::new(),
-        },
-        _ => PathBuf::new(),
-    };
-    let mut errors = Arc::new(ErrorStorage::new());
-    // If user passed in `--playground-url` arg, we fill in crate name here
-    let mut playground = None;
-    if let Some(url) = playground_url {
-        playground = Some(markdown::Playground { crate_name: Some(krate.name.clone()), url });
-    }
-    let mut layout = layout::Layout {
-        logo: String::new(),
-        favicon: String::new(),
-        external_html,
-        krate: krate.name.clone(),
-        css_file_extension: extension_css,
-        generate_search_filter,
-    };
-    let mut issue_tracker_base_url = None;
-    let mut include_sources = true;
-
-    // Crawl the crate attributes looking for attributes which control how we're
-    // going to emit HTML
-    if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
-        for attr in attrs.lists(sym::doc) {
-            match (attr.name_or_empty(), attr.value_str()) {
-                (sym::html_favicon_url, Some(s)) => {
-                    layout.favicon = s.to_string();
-                }
-                (sym::html_logo_url, Some(s)) => {
-                    layout.logo = s.to_string();
-                }
-                (sym::html_playground_url, Some(s)) => {
-                    playground = Some(markdown::Playground {
-                        crate_name: Some(krate.name.clone()),
-                        url: s.to_string(),
-                    });
-                }
-                (sym::issue_tracker_base_url, Some(s)) => {
-                    issue_tracker_base_url = Some(s.to_string());
-                }
-                (sym::html_no_source, None) if attr.is_word() => {
-                    include_sources = false;
+impl FormatRenderer for Context {
+    fn init(
+        mut krate: clean::Crate,
+        options: RenderOptions,
+        _render_info: RenderInfo,
+        edition: Edition,
+        cache: &mut Cache,
+    ) -> Result<(Context, clean::Crate), Error> {
+        // need to save a copy of the options for rendering the index page
+        let md_opts = options.clone();
+        let RenderOptions {
+            output,
+            external_html,
+            id_map,
+            playground_url,
+            sort_modules_alphabetically,
+            themes: style_files,
+            extension_css,
+            resource_suffix,
+            static_root_path,
+            generate_search_filter,
+            ..
+        } = options;
+
+        let src_root = match krate.src {
+            FileName::Real(ref p) => match p.local_path().parent() {
+                Some(p) => p.to_path_buf(),
+                None => PathBuf::new(),
+            },
+            _ => PathBuf::new(),
+        };
+        // If user passed in `--playground-url` arg, we fill in crate name here
+        let mut playground = None;
+        if let Some(url) = playground_url {
+            playground = Some(markdown::Playground { crate_name: Some(krate.name.clone()), url });
+        }
+        let mut layout = layout::Layout {
+            logo: String::new(),
+            favicon: String::new(),
+            external_html,
+            krate: krate.name.clone(),
+            css_file_extension: extension_css,
+            generate_search_filter,
+        };
+        let mut issue_tracker_base_url = None;
+        let mut include_sources = true;
+
+        // Crawl the crate attributes looking for attributes which control how we're
+        // going to emit HTML
+        if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
+            for attr in attrs.lists(sym::doc) {
+                match (attr.name_or_empty(), attr.value_str()) {
+                    (sym::html_favicon_url, Some(s)) => {
+                        layout.favicon = s.to_string();
+                    }
+                    (sym::html_logo_url, Some(s)) => {
+                        layout.logo = s.to_string();
+                    }
+                    (sym::html_playground_url, Some(s)) => {
+                        playground = Some(markdown::Playground {
+                            crate_name: Some(krate.name.clone()),
+                            url: s.to_string(),
+                        });
+                    }
+                    (sym::issue_tracker_base_url, Some(s)) => {
+                        issue_tracker_base_url = Some(s.to_string());
+                    }
+                    (sym::html_no_source, None) if attr.is_word() => {
+                        include_sources = false;
+                    }
+                    _ => {}
                 }
-                _ => {}
             }
         }
+        let (sender, receiver) = channel();
+        let mut scx = SharedContext {
+            collapsed: krate.collapsed,
+            src_root,
+            include_sources,
+            local_sources: Default::default(),
+            issue_tracker_base_url,
+            layout,
+            created_dirs: Default::default(),
+            sort_modules_alphabetically,
+            style_files,
+            resource_suffix,
+            static_root_path,
+            fs: DocFS::new(sender),
+            edition,
+            codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()),
+            playground,
+        };
+
+        // Add the default themes to the `Vec` of stylepaths
+        //
+        // Note that these must be added before `sources::render` is called
+        // so that the resulting source pages are styled
+        //
+        // `light.css` is not disabled because it is the stylesheet that stays loaded
+        // by the browser as the theme stylesheet. The theme system (hackily) works by
+        // changing the href to this stylesheet. All other themes are disabled to
+        // prevent rule conflicts
+        scx.style_files.push(StylePath { path: PathBuf::from("light.css"), disabled: false });
+        scx.style_files.push(StylePath { path: PathBuf::from("dark.css"), disabled: true });
+        scx.style_files.push(StylePath { path: PathBuf::from("ayu.css"), disabled: true });
+
+        let dst = output;
+        scx.ensure_dir(&dst)?;
+        krate = sources::render(&dst, &mut scx, krate)?;
+
+        // Build our search index
+        let index = build_index(&krate, cache);
+
+        let cache = Arc::new(cache);
+        let mut cx = Context {
+            current: Vec::new(),
+            dst,
+            render_redirect_pages: false,
+            id_map: Rc::new(RefCell::new(id_map)),
+            shared: Arc::new(scx),
+            all: Rc::new(RefCell::new(AllTypes::new())),
+            errors: Rc::new(receiver),
+        };
+
+        CURRENT_DEPTH.with(|s| s.set(0));
+
+        // Write shared runs within a flock; disable thread dispatching of IO temporarily.
+        Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
+        write_shared(&cx, &krate, index, &md_opts, &cache)?;
+        Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
+        Ok((cx, krate))
     }
-    let mut scx = SharedContext {
-        collapsed: krate.collapsed,
-        src_root,
-        include_sources,
-        local_sources: Default::default(),
-        issue_tracker_base_url,
-        layout,
-        created_dirs: Default::default(),
-        sort_modules_alphabetically,
-        style_files,
-        resource_suffix,
-        static_root_path,
-        fs: DocFS::new(&errors),
-        edition,
-        codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()),
-        playground,
-    };
 
-    // Add the default themes to the `Vec` of stylepaths
-    //
-    // Note that these must be added before `sources::render` is called
-    // so that the resulting source pages are styled
-    //
-    // `light.css` is not disabled because it is the stylesheet that stays loaded
-    // by the browser as the theme stylesheet. The theme system (hackily) works by
-    // changing the href to this stylesheet. All other themes are disabled to
-    // prevent rule conflicts
-    scx.style_files.push(StylePath { path: PathBuf::from("light.css"), disabled: false });
-    scx.style_files.push(StylePath { path: PathBuf::from("dark.css"), disabled: true });
-    scx.style_files.push(StylePath { path: PathBuf::from("ayu.css"), disabled: true });
-
-    let dst = output;
-    scx.ensure_dir(&dst)?;
-    krate = sources::render(&dst, &mut scx, krate)?;
-    let (new_crate, index, cache) =
-        Cache::from_krate(renderinfo, document_private, &extern_html_root_urls, &dst, krate);
-    krate = new_crate;
-    let cache = Arc::new(cache);
-    let mut cx = Context {
-        current: Vec::new(),
-        dst,
-        render_redirect_pages: false,
-        id_map: Rc::new(RefCell::new(id_map)),
-        shared: Arc::new(scx),
-        cache: cache.clone(),
-    };
+    fn after_run(&mut self, diag: &rustc_errors::Handler) -> Result<(), Error> {
+        Arc::get_mut(&mut self.shared).unwrap().fs.close();
+        let nb_errors = self.errors.iter().map(|err| diag.struct_err(&err).emit()).count();
+        if nb_errors > 0 {
+            Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
+        } else {
+            Ok(())
+        }
+    }
+
+    fn after_krate(&mut self, krate: &clean::Crate, cache: &Cache) -> Result<(), Error> {
+        let final_file = self.dst.join(&krate.name).join("all.html");
+        let settings_file = self.dst.join("settings.html");
+        let crate_name = krate.name.clone();
 
-    // Freeze the cache now that the index has been built. Put an Arc into TLS
-    // for future parallelization opportunities
-    CACHE_KEY.with(|v| *v.borrow_mut() = cache.clone());
-    CURRENT_DEPTH.with(|s| s.set(0));
+        let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
+        if !root_path.ends_with('/') {
+            root_path.push('/');
+        }
+        let mut page = layout::Page {
+            title: "List of all items in this crate",
+            css_class: "mod",
+            root_path: "../",
+            static_root_path: self.shared.static_root_path.as_deref(),
+            description: "List of all items in this crate",
+            keywords: BASIC_KEYWORDS,
+            resource_suffix: &self.shared.resource_suffix,
+            extra_scripts: &[],
+            static_extra_scripts: &[],
+        };
+        let sidebar = if let Some(ref version) = cache.crate_version {
+            format!(
+                "<p class='location'>Crate {}</p>\
+                     <div class='block version'>\
+                         <p>Version {}</p>\
+                     </div>\
+                     <a id='all-types' href='index.html'><p>Back to index</p></a>",
+                crate_name,
+                Escape(version),
+            )
+        } else {
+            String::new()
+        };
+        let all = self.all.replace(AllTypes::new());
+        let v = layout::render(
+            &self.shared.layout,
+            &page,
+            sidebar,
+            |buf: &mut Buffer| all.print(buf),
+            &self.shared.style_files,
+        );
+        self.shared.fs.write(&final_file, v.as_bytes())?;
 
-    // Write shared runs within a flock; disable thread dispatching of IO temporarily.
-    Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
-    write_shared(&cx, &krate, index, &md_opts)?;
-    Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
+        // Generating settings page.
+        page.title = "Rustdoc settings";
+        page.description = "Settings of Rustdoc";
+        page.root_path = "./";
 
-    // And finally render the whole crate's documentation
-    let ret = cx.krate(krate);
-    let nb_errors = Arc::get_mut(&mut errors).map_or_else(|| 0, |errors| errors.write_errors(diag));
-    if ret.is_err() {
-        ret
-    } else if nb_errors > 0 {
-        Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
-    } else {
+        let mut style_files = self.shared.style_files.clone();
+        let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>";
+        style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
+        let v = layout::render(
+            &self.shared.layout,
+            &page,
+            sidebar,
+            settings(
+                self.shared.static_root_path.as_deref().unwrap_or("./"),
+                &self.shared.resource_suffix,
+            ),
+            &style_files,
+        );
+        self.shared.fs.write(&settings_file, v.as_bytes())?;
+        Ok(())
+    }
+
+    fn mod_item_in(
+        &mut self,
+        item: &clean::Item,
+        item_name: &str,
+        cache: &Cache,
+    ) -> Result<(), Error> {
+        // Stripped modules survive the rustdoc passes (i.e., `strip-private`)
+        // if they contain impls for public types. These modules can also
+        // contain items such as publicly re-exported structures.
+        //
+        // External crates will provide links to these structures, so
+        // these modules are recursed into, but not rendered normally
+        // (a flag on the context).
+        if !self.render_redirect_pages {
+            self.render_redirect_pages = item.is_stripped();
+        }
+        let scx = &self.shared;
+        self.dst.push(item_name);
+        self.current.push(item_name.to_owned());
+
+        info!("Recursing into {}", self.dst.display());
+
+        let buf = self.render_item(item, false, cache);
+        // buf will be empty if the module is stripped and there is no redirect for it
+        if !buf.is_empty() {
+            self.shared.ensure_dir(&self.dst)?;
+            let joint_dst = self.dst.join("index.html");
+            scx.fs.write(&joint_dst, buf.as_bytes())?;
+        }
+
+        // Render sidebar-items.js used throughout this module.
+        if !self.render_redirect_pages {
+            let module = match item.inner {
+                clean::StrippedItem(box clean::ModuleItem(ref m)) | clean::ModuleItem(ref m) => m,
+                _ => unreachable!(),
+            };
+            let items = self.build_sidebar_items(module);
+            let js_dst = self.dst.join("sidebar-items.js");
+            let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap());
+            scx.fs.write(&js_dst, &v)?;
+        }
+        Ok(())
+    }
+
+    fn mod_item_out(&mut self, _item_name: &str) -> Result<(), Error> {
+        info!("Recursed; leaving {}", self.dst.display());
+
+        // Go back to where we were at
+        self.dst.pop();
+        self.current.pop();
+        Ok(())
+    }
+
+    fn item(&mut self, item: clean::Item, cache: &Cache) -> Result<(), Error> {
+        // Stripped modules survive the rustdoc passes (i.e., `strip-private`)
+        // if they contain impls for public types. These modules can also
+        // contain items such as publicly re-exported structures.
+        //
+        // External crates will provide links to these structures, so
+        // these modules are recursed into, but not rendered normally
+        // (a flag on the context).
+        if !self.render_redirect_pages {
+            self.render_redirect_pages = item.is_stripped();
+        }
+
+        let buf = self.render_item(&item, true, cache);
+        // buf will be empty if the item is stripped and there is no redirect for it
+        if !buf.is_empty() {
+            let name = item.name.as_ref().unwrap();
+            let item_type = item.type_();
+            let file_name = &item_path(item_type, name);
+            self.shared.ensure_dir(&self.dst)?;
+            let joint_dst = self.dst.join(file_name);
+            self.shared.fs.write(&joint_dst, buf.as_bytes())?;
+
+            if !self.render_redirect_pages {
+                self.all.borrow_mut().append(full_path(self, &item), &item_type);
+            }
+            // If the item is a macro, redirect from the old macro URL (with !)
+            // to the new one (without).
+            if item_type == ItemType::Macro {
+                let redir_name = format!("{}.{}!.html", item_type, name);
+                let redir_dst = self.dst.join(redir_name);
+                let v = layout::redirect(file_name);
+                self.shared.fs.write(&redir_dst, v.as_bytes())?;
+            }
+        }
         Ok(())
     }
 }
@@ -604,6 +679,7 @@ fn write_shared(
     krate: &clean::Crate,
     search_index: String,
     options: &RenderOptions,
+    cache: &Cache,
 ) -> Result<(), Error> {
     // Write out the shared files. Note that these are shared among all rustdoc
     // docs placed in the output directory, so this needs to be a synchronized
@@ -1001,7 +1077,7 @@ themePicker.onblur = handleThemeButtonsBlur;
 
     // Update the list of all implementors for traits
     let dst = cx.dst.join("implementors");
-    for (&did, imps) in &cx.cache.implementors {
+    for (&did, imps) in &cache.implementors {
         // Private modules can leak through to this phase of rustdoc, which
         // could contain implementations for otherwise private types. In some
         // rare cases we could find an implementation for an item which wasn't
@@ -1009,9 +1085,9 @@ themePicker.onblur = handleThemeButtonsBlur;
         //
         // FIXME: this is a vague explanation for why this can't be a `get`, in
         //        theory it should be...
-        let &(ref remote_path, remote_item_type) = match cx.cache.paths.get(&did) {
+        let &(ref remote_path, remote_item_type) = match cache.paths.get(&did) {
             Some(p) => p,
-            None => match cx.cache.external_paths.get(&did) {
+            None => match cache.external_paths.get(&did) {
                 Some(p) => p,
                 None => continue,
             },
@@ -1049,7 +1125,7 @@ themePicker.onblur = handleThemeButtonsBlur;
         // Only create a js file if we have impls to add to it. If the trait is
         // documented locally though we always create the file to avoid dead
         // links.
-        if implementors.is_empty() && !cx.cache.paths.contains_key(&did) {
+        if implementors.is_empty() && !cache.paths.contains_key(&did) {
             continue;
         }
 
@@ -1354,93 +1430,7 @@ impl Context {
         "../".repeat(self.current.len())
     }
 
-    /// Main method for rendering a crate.
-    ///
-    /// This currently isn't parallelized, but it'd be pretty easy to add
-    /// parallelization to this function.
-    fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
-        let mut item = match krate.module.take() {
-            Some(i) => i,
-            None => return Ok(()),
-        };
-        let final_file = self.dst.join(&krate.name).join("all.html");
-        let settings_file = self.dst.join("settings.html");
-
-        let crate_name = krate.name.clone();
-        item.name = Some(krate.name);
-
-        let mut all = AllTypes::new();
-
-        {
-            // Render the crate documentation
-            let mut work = vec![(self.clone(), item)];
-
-            while let Some((mut cx, item)) = work.pop() {
-                cx.item(item, &mut all, |cx, item| work.push((cx.clone(), item)))?
-            }
-        }
-
-        let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
-        if !root_path.ends_with('/') {
-            root_path.push('/');
-        }
-        let mut page = layout::Page {
-            title: "List of all items in this crate",
-            css_class: "mod",
-            root_path: "../",
-            static_root_path: self.shared.static_root_path.as_deref(),
-            description: "List of all items in this crate",
-            keywords: BASIC_KEYWORDS,
-            resource_suffix: &self.shared.resource_suffix,
-            extra_scripts: &[],
-            static_extra_scripts: &[],
-        };
-        let sidebar = if let Some(ref version) = self.cache.crate_version {
-            format!(
-                "<p class='location'>Crate {}</p>\
-                     <div class='block version'>\
-                         <p>Version {}</p>\
-                     </div>\
-                     <a id='all-types' href='index.html'><p>Back to index</p></a>",
-                crate_name,
-                Escape(version),
-            )
-        } else {
-            String::new()
-        };
-        let v = layout::render(
-            &self.shared.layout,
-            &page,
-            sidebar,
-            |buf: &mut Buffer| all.print(buf),
-            &self.shared.style_files,
-        );
-        self.shared.fs.write(&final_file, v.as_bytes())?;
-
-        // Generating settings page.
-        page.title = "Rustdoc settings";
-        page.description = "Settings of Rustdoc";
-        page.root_path = "./";
-
-        let mut style_files = self.shared.style_files.clone();
-        let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>";
-        style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
-        let v = layout::render(
-            &self.shared.layout,
-            &page,
-            sidebar,
-            settings(
-                self.shared.static_root_path.as_deref().unwrap_or("./"),
-                &self.shared.resource_suffix,
-            ),
-            &style_files,
-        );
-        self.shared.fs.write(&settings_file, v.as_bytes())?;
-
-        Ok(())
-    }
-
-    fn render_item(&self, it: &clean::Item, pushname: bool) -> String {
+    fn render_item(&self, it: &clean::Item, pushname: bool, cache: &Cache) -> String {
         // A little unfortunate that this is done like this, but it sure
         // does make formatting *a lot* nicer.
         CURRENT_DEPTH.with(|slot| {
@@ -1493,13 +1483,13 @@ impl Context {
             layout::render(
                 &self.shared.layout,
                 &page,
-                |buf: &mut _| print_sidebar(self, it, buf),
-                |buf: &mut _| print_item(self, it, buf),
+                |buf: &mut _| print_sidebar(self, it, buf, cache),
+                |buf: &mut _| print_item(self, it, buf, cache),
                 &self.shared.style_files,
             )
         } else {
             let mut url = self.root_path();
-            if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id) {
+            if let Some(&(ref names, ty)) = cache.paths.get(&it.def_id) {
                 for name in &names[..names.len() - 1] {
                     url.push_str(name);
                     url.push_str("/");
@@ -1512,97 +1502,6 @@ impl Context {
         }
     }
 
-    /// Non-parallelized version of rendering an item. This will take the input
-    /// item, render its contents, and then invoke the specified closure with
-    /// all sub-items which need to be rendered.
-    ///
-    /// The rendering driver uses this closure to queue up more work.
-    fn item<F>(&mut self, item: clean::Item, all: &mut AllTypes, mut f: F) -> Result<(), Error>
-    where
-        F: FnMut(&mut Context, clean::Item),
-    {
-        // Stripped modules survive the rustdoc passes (i.e., `strip-private`)
-        // if they contain impls for public types. These modules can also
-        // contain items such as publicly re-exported structures.
-        //
-        // External crates will provide links to these structures, so
-        // these modules are recursed into, but not rendered normally
-        // (a flag on the context).
-        if !self.render_redirect_pages {
-            self.render_redirect_pages = item.is_stripped();
-        }
-
-        if item.is_mod() {
-            // modules are special because they add a namespace. We also need to
-            // recurse into the items of the module as well.
-            let name = item.name.as_ref().unwrap().to_string();
-            let scx = &self.shared;
-            if name.is_empty() {
-                panic!("Unexpected empty destination: {:?}", self.current);
-            }
-            let prev = self.dst.clone();
-            self.dst.push(&name);
-            self.current.push(name);
-
-            info!("Recursing into {}", self.dst.display());
-
-            let buf = self.render_item(&item, false);
-            // buf will be empty if the module is stripped and there is no redirect for it
-            if !buf.is_empty() {
-                self.shared.ensure_dir(&self.dst)?;
-                let joint_dst = self.dst.join("index.html");
-                scx.fs.write(&joint_dst, buf.as_bytes())?;
-            }
-
-            let m = match item.inner {
-                clean::StrippedItem(box clean::ModuleItem(m)) | clean::ModuleItem(m) => m,
-                _ => unreachable!(),
-            };
-
-            // Render sidebar-items.js used throughout this module.
-            if !self.render_redirect_pages {
-                let items = self.build_sidebar_items(&m);
-                let js_dst = self.dst.join("sidebar-items.js");
-                let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap());
-                scx.fs.write(&js_dst, &v)?;
-            }
-
-            for item in m.items {
-                f(self, item);
-            }
-
-            info!("Recursed; leaving {}", self.dst.display());
-
-            // Go back to where we were at
-            self.dst = prev;
-            self.current.pop().unwrap();
-        } else if item.name.is_some() {
-            let buf = self.render_item(&item, true);
-            // buf will be empty if the item is stripped and there is no redirect for it
-            if !buf.is_empty() {
-                let name = item.name.as_ref().unwrap();
-                let item_type = item.type_();
-                let file_name = &item_path(item_type, name);
-                self.shared.ensure_dir(&self.dst)?;
-                let joint_dst = self.dst.join(file_name);
-                self.shared.fs.write(&joint_dst, buf.as_bytes())?;
-
-                if !self.render_redirect_pages {
-                    all.append(full_path(self, &item), &item_type);
-                }
-                // If the item is a macro, redirect from the old macro URL (with !)
-                // to the new one (without).
-                if item_type == ItemType::Macro {
-                    let redir_name = format!("{}.{}!.html", item_type, name);
-                    let redir_dst = self.dst.join(redir_name);
-                    let v = layout::redirect(file_name);
-                    self.shared.fs.write(&redir_dst, v.as_bytes())?;
-                }
-            }
-        }
-        Ok(())
-    }
-
     fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<NameDoc>> {
         // BTreeMap instead of HashMap to get a sorted output
         let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new();
@@ -1629,9 +1528,7 @@ impl Context {
         }
         map
     }
-}
 
-impl Context {
     /// Generates a url appropriate for an `href` attribute back to the source of
     /// this item.
     ///
@@ -1641,7 +1538,7 @@ impl Context {
     /// If `None` is returned, then a source link couldn't be generated. This
     /// may happen, for example, with externally inlined items where the source
     /// of their crate documentation isn't known.
-    fn src_href(&self, item: &clean::Item) -> Option<String> {
+    fn src_href(&self, item: &clean::Item, cache: &Cache) -> Option<String> {
         let mut root = self.root_path();
 
         let mut path = String::new();
@@ -1660,13 +1557,13 @@ impl Context {
                 return None;
             }
         } else {
-            let (krate, src_root) = match *self.cache.extern_locations.get(&item.source.cnum)? {
-                (ref name, ref src, Local) => (name, src),
-                (ref name, ref src, Remote(ref s)) => {
+            let (krate, src_root) = match *cache.extern_locations.get(&item.source.cnum)? {
+                (ref name, ref src, ExternalLocation::Local) => (name, src),
+                (ref name, ref src, ExternalLocation::Remote(ref s)) => {
                     root = s.to_string();
                     (name, src)
                 }
-                (_, _, Unknown) => return None,
+                (_, _, ExternalLocation::Unknown) => return None,
             };
 
             sources::clean_path(&src_root, file, false, |component| {
@@ -1703,7 +1600,7 @@ where
     write!(w, "</div>")
 }
 
-fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) {
+fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache) {
     debug_assert!(!item.is_stripped());
     // Write the breadcrumb trail header for the top
     write!(buf, "<h1 class='fqn'><span class='out-of-band'>");
@@ -1731,7 +1628,7 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) {
     // this page, and this link will be auto-clicked. The `id` attribute is
     // used to find the link to auto-click.
     if cx.shared.include_sources && !item.is_primitive() {
-        if let Some(l) = cx.src_href(item) {
+        if let Some(l) = cx.src_href(item, cache) {
             write!(buf, "<a class='srclink' href='{}' title='{}'>[src]</a>", l, "goto source code");
         }
     }
@@ -1792,20 +1689,20 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) {
         clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => {
             item_function(buf, cx, item, f)
         }
-        clean::TraitItem(ref t) => item_trait(buf, cx, item, t),
-        clean::StructItem(ref s) => item_struct(buf, cx, item, s),
-        clean::UnionItem(ref s) => item_union(buf, cx, item, s),
-        clean::EnumItem(ref e) => item_enum(buf, cx, item, e),
-        clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t),
+        clean::TraitItem(ref t) => item_trait(buf, cx, item, t, cache),
+        clean::StructItem(ref s) => item_struct(buf, cx, item, s, cache),
+        clean::UnionItem(ref s) => item_union(buf, cx, item, s, cache),
+        clean::EnumItem(ref e) => item_enum(buf, cx, item, e, cache),
+        clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t, cache),
         clean::MacroItem(ref m) => item_macro(buf, cx, item, m),
         clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m),
-        clean::PrimitiveItem(_) => item_primitive(buf, cx, item),
+        clean::PrimitiveItem(_) => item_primitive(buf, cx, item, cache),
         clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => item_static(buf, cx, item, i),
         clean::ConstantItem(ref c) => item_constant(buf, cx, item, c),
-        clean::ForeignTypeItem => item_foreign_type(buf, cx, item),
+        clean::ForeignTypeItem => item_foreign_type(buf, cx, item, cache),
         clean::KeywordItem(_) => item_keyword(buf, cx, item),
-        clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e),
-        clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta),
+        clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e, cache),
+        clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta, cache),
         _ => {
             // We don't generate pages for any other type.
             unreachable!();
@@ -1828,7 +1725,7 @@ fn full_path(cx: &Context, item: &clean::Item) -> String {
 }
 
 #[inline]
-fn plain_summary_line(s: Option<&str>) -> String {
+crate fn plain_summary_line(s: Option<&str>) -> String {
     let s = s.unwrap_or("");
     // This essentially gets the first paragraph of text in one line.
     let mut line = s
@@ -1845,7 +1742,7 @@ fn plain_summary_line(s: Option<&str>) -> String {
     markdown::plain_summary_line(&line[..])
 }
 
-fn shorten(s: String) -> String {
+crate fn shorten(s: String) -> String {
     if s.chars().count() > 60 {
         let mut len = 0;
         let mut ret = s
@@ -2415,6 +2312,7 @@ fn render_implementor(
     w: &mut Buffer,
     implementor_dups: &FxHashMap<&str, (DefId, bool)>,
     aliases: &[String],
+    cache: &Cache,
 ) {
     // If there's already another implementor that has the same abbridged name, use the
     // full path, for example in `std::iter::ExactSizeIterator`
@@ -2438,10 +2336,17 @@ fn render_implementor(
         false,
         false,
         aliases,
+        cache,
     );
 }
 
-fn render_impls(cx: &Context, w: &mut Buffer, traits: &[&&Impl], containing_item: &clean::Item) {
+fn render_impls(
+    cx: &Context,
+    w: &mut Buffer,
+    traits: &[&&Impl],
+    containing_item: &clean::Item,
+    cache: &Cache,
+) {
     let mut impls = traits
         .iter()
         .map(|i| {
@@ -2460,6 +2365,7 @@ fn render_impls(cx: &Context, w: &mut Buffer, traits: &[&&Impl], containing_item
                 false,
                 true,
                 &[],
+                cache,
             );
             buffer.into_inner()
         })
@@ -2492,7 +2398,7 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering {
     name_key(&lhs).cmp(&name_key(&rhs))
 }
 
-fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait) {
+fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait, cache: &Cache) {
     let bounds = bounds(&t.bounds, false);
     let types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
     let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
@@ -2652,9 +2558,9 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
     }
 
     // If there are methods directly on this trait object, render them here.
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All);
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache);
 
-    if let Some(implementors) = cx.cache.implementors.get(&it.def_id) {
+    if let Some(implementors) = cache.implementors.get(&it.def_id) {
         // The DefId is for the first Type found with that name. The bool is
         // if any Types with the same name but different DefId have been found.
         let mut implementor_dups: FxHashMap<&str, (DefId, bool)> = FxHashMap::default();
@@ -2676,7 +2582,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
         }
 
         let (local, foreign) = implementors.iter().partition::<Vec<_>, _>(|i| {
-            i.inner_impl().for_.def_id().map_or(true, |d| cx.cache.paths.contains_key(&d))
+            i.inner_impl().for_.def_id().map_or(true, |d| cache.paths.contains_key(&d))
         });
 
         let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
@@ -2705,6 +2611,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
                     true,
                     false,
                     &[],
+                    cache,
                 );
             }
             write_loading_content(w, "");
@@ -2717,7 +2624,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
             "<div class='item-list' id='implementors-list'>",
         );
         for implementor in concrete {
-            render_implementor(cx, implementor, w, &implementor_dups, &[]);
+            render_implementor(cx, implementor, w, &implementor_dups, &[], cache);
         }
         write_loading_content(w, "</div>");
 
@@ -2735,6 +2642,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
                     w,
                     &implementor_dups,
                     &collect_paths_for_type(implementor.inner_impl().for_.clone()),
+                    cache,
                 );
             }
             write_loading_content(w, "</div>");
@@ -2770,7 +2678,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
         path = if it.def_id.is_local() {
             cx.current.join("/")
         } else {
-            let (ref path, _) = cx.cache.external_paths[&it.def_id];
+            let (ref path, _) = cache.external_paths[&it.def_id];
             path[..path.len() - 1].join("/")
         },
         ty = it.type_(),
@@ -2779,7 +2687,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
 }
 
 fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>) -> String {
-    use crate::html::item_type::ItemType::*;
+    use crate::formats::item_type::ItemType::*;
 
     let name = it.name.as_ref().unwrap();
     let ty = match it.type_() {
@@ -2945,7 +2853,7 @@ fn render_assoc_item(
     }
 }
 
-fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct) {
+fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct, cache: &Cache) {
     wrap_into_docblock(w, |w| {
         write!(w, "<pre class='rust struct'>");
         render_attributes(w, it, true);
@@ -2992,10 +2900,10 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
             }
         }
     }
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union) {
+fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union, cache: &Cache) {
     wrap_into_docblock(w, |w| {
         write!(w, "<pre class='rust union'>");
         render_attributes(w, it, true);
@@ -3038,10 +2946,10 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union)
             document(w, cx, field);
         }
     }
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
+fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, cache: &Cache) {
     wrap_into_docblock(w, |w| {
         write!(w, "<pre class='rust enum'>");
         render_attributes(w, it, true);
@@ -3166,7 +3074,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
             render_stability_since(w, variant, it);
         }
     }
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
 const ALLOWED_ATTRIBUTES: &[Symbol] = &[
@@ -3348,26 +3256,15 @@ impl<'a> AssocItemLink<'a> {
     }
 }
 
-enum AssocItemRender<'a> {
-    All,
-    DerefFor { trait_: &'a clean::Type, type_: &'a clean::Type, deref_mut_: bool },
-}
-
-#[derive(Copy, Clone, PartialEq)]
-enum RenderMode {
-    Normal,
-    ForDeref { mut_: bool },
-}
-
 fn render_assoc_items(
     w: &mut Buffer,
     cx: &Context,
     containing_item: &clean::Item,
     it: DefId,
     what: AssocItemRender<'_>,
+    cache: &Cache,
 ) {
-    let c = &cx.cache;
-    let v = match c.impls.get(&it) {
+    let v = match cache.impls.get(&it) {
         Some(v) => v,
         None => return,
     };
@@ -3413,6 +3310,7 @@ fn render_assoc_items(
                 false,
                 true,
                 &[],
+                cache,
             );
         }
     }
@@ -3421,11 +3319,11 @@ fn render_assoc_items(
     }
     if !traits.is_empty() {
         let deref_impl =
-            traits.iter().find(|t| t.inner_impl().trait_.def_id() == c.deref_trait_did);
+            traits.iter().find(|t| t.inner_impl().trait_.def_id() == cache.deref_trait_did);
         if let Some(impl_) = deref_impl {
             let has_deref_mut =
-                traits.iter().any(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did);
-            render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
+                traits.iter().any(|t| t.inner_impl().trait_.def_id() == cache.deref_mut_trait_did);
+            render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, cache);
         }
 
         let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
@@ -3434,7 +3332,7 @@ fn render_assoc_items(
             concrete.into_iter().partition(|t| t.inner_impl().blanket_impl.is_some());
 
         let mut impls = Buffer::empty_from(&w);
-        render_impls(cx, &mut impls, &concrete, containing_item);
+        render_impls(cx, &mut impls, &concrete, containing_item, cache);
         let impls = impls.into_inner();
         if !impls.is_empty() {
             write!(
@@ -3459,7 +3357,7 @@ fn render_assoc_items(
                 <div id='synthetic-implementations-list'>\
             "
             );
-            render_impls(cx, w, &synthetic, containing_item);
+            render_impls(cx, w, &synthetic, containing_item, cache);
             write!(w, "</div>");
         }
 
@@ -3474,7 +3372,7 @@ fn render_assoc_items(
                 <div id='blanket-implementations-list'>\
             "
             );
-            render_impls(cx, w, &blanket_impl, containing_item);
+            render_impls(cx, w, &blanket_impl, containing_item, cache);
             write!(w, "</div>");
         }
     }
@@ -3486,6 +3384,7 @@ fn render_deref_methods(
     impl_: &Impl,
     container_item: &clean::Item,
     deref_mut: bool,
+    cache: &Cache,
 ) {
     let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
     let (target, real_target) = impl_
@@ -3503,11 +3402,11 @@ fn render_deref_methods(
     let what =
         AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
     if let Some(did) = target.def_id() {
-        render_assoc_items(w, cx, container_item, did, what);
+        render_assoc_items(w, cx, container_item, did, what, cache);
     } else {
         if let Some(prim) = target.primitive_type() {
-            if let Some(&did) = cx.cache.primitive_locations.get(&prim) {
-                render_assoc_items(w, cx, container_item, did, what);
+            if let Some(&did) = cache.primitive_locations.get(&prim) {
+                render_assoc_items(w, cx, container_item, did, what, cache);
             }
         }
     }
@@ -3609,6 +3508,7 @@ fn render_impl(
     // This argument is used to reference same type with different paths to avoid duplication
     // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
+    cache: &Cache,
 ) {
     if render_mode == RenderMode::Normal {
         let id = cx.derive_id(match i.inner_impl().trait_ {
@@ -3651,7 +3551,7 @@ fn render_impl(
         write!(w, "<a href='#{}' class='anchor'></a>", id);
         let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
         render_stability_since_raw(w, since, outer_version);
-        if let Some(l) = cx.src_href(&i.impl_item) {
+        if let Some(l) = cx.src_href(&i.impl_item, cache) {
             write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>", l, "goto source code");
         }
         write!(w, "</h3>");
@@ -3683,6 +3583,7 @@ fn render_impl(
         outer_version: Option<&str>,
         trait_: Option<&clean::Trait>,
         show_def_docs: bool,
+        cache: &Cache,
     ) {
         let item_type = item.type_();
         let name = item.name.as_ref().unwrap();
@@ -3711,7 +3612,7 @@ fn render_impl(
                     render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
                     write!(w, "</code>");
                     render_stability_since_raw(w, item.stable_since(), outer_version);
-                    if let Some(l) = cx.src_href(item) {
+                    if let Some(l) = cx.src_href(item, cache) {
                         write!(
                             w,
                             "<a class='srclink' href='{}' title='{}'>[src]</a>",
@@ -3733,7 +3634,7 @@ fn render_impl(
                 assoc_const(w, item, ty, default.as_ref(), link.anchor(&id), "");
                 write!(w, "</code>");
                 render_stability_since_raw(w, item.stable_since(), outer_version);
-                if let Some(l) = cx.src_href(item) {
+                if let Some(l) = cx.src_href(item, cache) {
                     write!(
                         w,
                         "<a class='srclink' href='{}' title='{}'>[src]</a>",
@@ -3784,7 +3685,7 @@ fn render_impl(
         }
     }
 
-    let traits = &cx.cache.traits;
+    let traits = &cache.traits;
     let trait_ = i.trait_did().map(|did| &traits[&did]);
 
     write!(w, "<div class='impl-items'>");
@@ -3799,6 +3700,7 @@ fn render_impl(
             outer_version,
             trait_,
             show_def_docs,
+            cache,
         );
     }
 
@@ -3810,6 +3712,7 @@ fn render_impl(
         render_mode: RenderMode,
         outer_version: Option<&str>,
         show_def_docs: bool,
+        cache: &Cache,
     ) {
         for trait_item in &t.items {
             let n = trait_item.name.clone();
@@ -3829,6 +3732,7 @@ fn render_impl(
                 outer_version,
                 None,
                 show_def_docs,
+                cache,
             );
         }
     }
@@ -3847,13 +3751,20 @@ fn render_impl(
                 render_mode,
                 outer_version,
                 show_def_docs,
+                cache,
             );
         }
     }
     write!(w, "</div>");
 }
 
-fn item_opaque_ty(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::OpaqueTy) {
+fn item_opaque_ty(
+    w: &mut Buffer,
+    cx: &Context,
+    it: &clean::Item,
+    t: &clean::OpaqueTy,
+    cache: &Cache,
+) {
     write!(w, "<pre class='rust opaque'>");
     render_attributes(w, it, false);
     write!(
@@ -3871,10 +3782,16 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Opa
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_trait_alias(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::TraitAlias) {
+fn item_trait_alias(
+    w: &mut Buffer,
+    cx: &Context,
+    it: &clean::Item,
+    t: &clean::TraitAlias,
+    cache: &Cache,
+) {
     write!(w, "<pre class='rust trait-alias'>");
     render_attributes(w, it, false);
     write!(
@@ -3892,10 +3809,10 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::T
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typedef) {
+fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typedef, cache: &Cache) {
     write!(w, "<pre class='rust typedef'>");
     render_attributes(w, it, false);
     write!(
@@ -3913,10 +3830,10 @@ fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typed
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item) {
+fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cache) {
     writeln!(w, "<pre class='rust foreigntype'>extern {{");
     render_attributes(w, it, false);
     write!(
@@ -3928,10 +3845,10 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item) {
 
     document(w, cx, it);
 
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) {
+fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer, cache: &Cache) {
     let parentlen = cx.current.len() - if it.is_mod() { 1 } else { 0 };
 
     if it.is_struct()
@@ -3966,7 +3883,7 @@ fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) {
     }
 
     if it.is_crate() {
-        if let Some(ref version) = cx.cache.crate_version {
+        if let Some(ref version) = cache.crate_version {
             write!(
                 buffer,
                 "<div class='block version'>\
@@ -4603,9 +4520,9 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::Pr
     document(w, cx, it)
 }
 
-fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item) {
+fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cache) {
     document(w, cx, it);
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
 fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) {
@@ -4670,7 +4587,3 @@ fn collect_paths_for_type(first_ty: clean::Type) -> Vec<String> {
     }
     out
 }
-
-crate fn cache() -> Arc<Cache> {
-    CACHE_KEY.with(|c| c.borrow().clone())
-}
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index e3215921f12..aaa73b100c2 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -1,10 +1,11 @@
 use crate::clean;
 use crate::docfs::PathError;
+use crate::error::Error;
 use crate::fold::DocFolder;
 use crate::html::format::Buffer;
 use crate::html::highlight;
 use crate::html::layout;
-use crate::html::render::{Error, SharedContext, BASIC_KEYWORDS};
+use crate::html::render::{SharedContext, BASIC_KEYWORDS};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_span::source_map::FileName;
 use std::ffi::OsStr;
diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css
index 01b7ae87786..f4710f6ae87 100644
--- a/src/librustdoc/html/static/themes/ayu.css
+++ b/src/librustdoc/html/static/themes/ayu.css
@@ -197,9 +197,8 @@ pre {
 	color: #a37acc;
 }
 
-pre.rust .comment, pre.rust .doccomment {
-	color: #788797;
-}
+pre.rust .comment { color: #788797; }
+pre.rust .doccomment { color: #a1ac88; }
 
 nav:not(.sidebar) {
 	border-bottom-color: #424c57;
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
new file mode 100644
index 00000000000..14f87ec2aa9
--- /dev/null
+++ b/src/librustdoc/json/mod.rs
@@ -0,0 +1,47 @@
+use crate::clean;
+use crate::config::{RenderInfo, RenderOptions};
+use crate::error::Error;
+use crate::formats::cache::Cache;
+use crate::formats::FormatRenderer;
+
+use rustc_span::edition::Edition;
+
+#[derive(Clone)]
+pub struct JsonRenderer {}
+
+impl FormatRenderer for JsonRenderer {
+    fn init(
+        _krate: clean::Crate,
+        _options: RenderOptions,
+        _render_info: RenderInfo,
+        _edition: Edition,
+        _cache: &mut Cache,
+    ) -> Result<(Self, clean::Crate), Error> {
+        unimplemented!()
+    }
+
+    fn item(&mut self, _item: clean::Item, _cache: &Cache) -> Result<(), Error> {
+        unimplemented!()
+    }
+
+    fn mod_item_in(
+        &mut self,
+        _item: &clean::Item,
+        _item_name: &str,
+        _cache: &Cache,
+    ) -> Result<(), Error> {
+        unimplemented!()
+    }
+
+    fn mod_item_out(&mut self, _item_name: &str) -> Result<(), Error> {
+        unimplemented!()
+    }
+
+    fn after_krate(&mut self, _krate: &clean::Crate, _cache: &Cache) -> Result<(), Error> {
+        unimplemented!()
+    }
+
+    fn after_run(&mut self, _diag: &rustc_errors::Handler) -> Result<(), Error> {
+        unimplemented!()
+    }
+}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index cbf53d52ef0..002c5f96710 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -14,7 +14,6 @@
 #![feature(never_type)]
 #![recursion_limit = "256"]
 
-extern crate env_logger;
 #[macro_use]
 extern crate lazy_static;
 extern crate rustc_ast;
@@ -63,19 +62,12 @@ mod config;
 mod core;
 mod docfs;
 mod doctree;
+#[macro_use]
+mod error;
 mod fold;
-pub mod html {
-    crate mod escape;
-    crate mod format;
-    crate mod highlight;
-    crate mod item_type;
-    crate mod layout;
-    pub mod markdown;
-    crate mod render;
-    crate mod sources;
-    crate mod static_files;
-    crate mod toc;
-}
+crate mod formats;
+pub mod html;
+mod json;
 mod markdown;
 mod passes;
 mod test;
@@ -85,7 +77,7 @@ mod visit_lib;
 
 struct Output {
     krate: clean::Crate,
-    renderinfo: html::render::RenderInfo,
+    renderinfo: config::RenderInfo,
     renderopts: config::RenderOptions,
 }
 
@@ -97,7 +89,8 @@ pub fn main() {
     };
     rustc_driver::set_sigpipe_handler();
     rustc_driver::install_ice_hook();
-    env_logger::init_from_env("RUSTDOC_LOG");
+    rustc_driver::init_env_logger("RUSTDOC_LOG");
+
     let res = std::thread::Builder::new()
         .stack_size(thread_stack_size)
         .spawn(move || get_args().map(|args| main_args(&args)).unwrap_or(1))
@@ -458,6 +451,28 @@ fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> i32 {
     }
 }
 
+fn run_renderer<T: formats::FormatRenderer>(
+    krate: clean::Crate,
+    renderopts: config::RenderOptions,
+    render_info: config::RenderInfo,
+    diag: &rustc_errors::Handler,
+    edition: rustc_span::edition::Edition,
+) -> i32 {
+    match formats::run_format::<T>(krate, renderopts, render_info, &diag, edition) {
+        Ok(_) => rustc_driver::EXIT_SUCCESS,
+        Err(e) => {
+            let mut msg = diag.struct_err(&format!("couldn't generate documentation: {}", e.error));
+            let file = e.file.display().to_string();
+            if file.is_empty() {
+                msg.emit()
+            } else {
+                msg.note(&format!("failed to create or modify \"{}\"", file)).emit()
+            }
+            rustc_driver::EXIT_FAILURE
+        }
+    }
+}
+
 fn main_options(options: config::Options) -> i32 {
     let diag = core::new_handler(options.error_format, None, &options.debugging_options);
 
@@ -488,6 +503,7 @@ fn main_options(options: config::Options) -> i32 {
     let result = rustc_driver::catch_fatal_errors(move || {
         let crate_name = options.crate_name.clone();
         let crate_version = options.crate_version.clone();
+        let output_format = options.output_format;
         let (mut krate, renderinfo, renderopts) = core::run_core(options);
 
         info!("finished with rustc");
@@ -510,13 +526,12 @@ fn main_options(options: config::Options) -> i32 {
         info!("going to format");
         let (error_format, edition, debugging_options) = diag_opts;
         let diag = core::new_handler(error_format, None, &debugging_options);
-        match html::render::run(krate, renderopts, renderinfo, &diag, edition) {
-            Ok(_) => rustc_driver::EXIT_SUCCESS,
-            Err(e) => {
-                diag.struct_err(&format!("couldn't generate documentation: {}", e.error))
-                    .note(&format!("failed to create or modify \"{}\"", e.file.display()))
-                    .emit();
-                rustc_driver::EXIT_FAILURE
+        match output_format {
+            None | Some(config::OutputFormat::Html) => {
+                run_renderer::<html::render::Context>(krate, renderopts, renderinfo, &diag, edition)
+            }
+            Some(config::OutputFormat::Json) => {
+                run_renderer::<json::JsonRenderer>(krate, renderopts, renderinfo, &diag, edition)
             }
         }
     });
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 418238181e9..bf7a43236e0 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -867,46 +867,40 @@ fn report_diagnostic(
     let attrs = &item.attrs;
     let sp = span_of_attrs(attrs).unwrap_or(item.source.span());
 
-    cx.tcx.struct_span_lint_hir(
-        lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-        hir_id,
-        sp,
-        |lint| {
-            let mut diag = lint.build(msg);
-
-            let span = link_range
-                .as_ref()
-                .and_then(|range| super::source_span_for_markdown_range(cx, dox, range, attrs));
-
-            if let Some(link_range) = link_range {
-                if let Some(sp) = span {
-                    diag.set_span(sp);
-                } else {
-                    // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
-                    //                       ^     ~~~~
-                    //                       |     link_range
-                    //                       last_new_line_offset
-                    let last_new_line_offset =
-                        dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
-                    let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
-
-                    // Print the line containing the `link_range` and manually mark it with '^'s.
-                    diag.note(&format!(
-                        "the link appears in this line:\n\n{line}\n\
+    cx.tcx.struct_span_lint_hir(lint::builtin::BROKEN_INTRA_DOC_LINKS, hir_id, sp, |lint| {
+        let mut diag = lint.build(msg);
+
+        let span = link_range
+            .as_ref()
+            .and_then(|range| super::source_span_for_markdown_range(cx, dox, range, attrs));
+
+        if let Some(link_range) = link_range {
+            if let Some(sp) = span {
+                diag.set_span(sp);
+            } else {
+                // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
+                //                       ^     ~~~~
+                //                       |     link_range
+                //                       last_new_line_offset
+                let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
+                let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
+
+                // Print the line containing the `link_range` and manually mark it with '^'s.
+                diag.note(&format!(
+                    "the link appears in this line:\n\n{line}\n\
                          {indicator: <before$}{indicator:^<found$}",
-                        line = line,
-                        indicator = "",
-                        before = link_range.start - last_new_line_offset,
-                        found = link_range.len(),
-                    ));
-                }
+                    line = line,
+                    indicator = "",
+                    before = link_range.start - last_new_line_offset,
+                    found = link_range.len(),
+                ));
             }
+        }
 
-            decorate(&mut diag, span);
+        decorate(&mut diag, span);
 
-            diag.emit();
-        },
-    );
+        diag.emit();
+    });
 }
 
 fn resolution_failure(
diff --git a/src/rustllvm/CoverageMappingWrapper.cpp b/src/rustllvm/CoverageMappingWrapper.cpp
index c6c4cdb5562..7c8481540aa 100644
--- a/src/rustllvm/CoverageMappingWrapper.cpp
+++ b/src/rustllvm/CoverageMappingWrapper.cpp
@@ -8,60 +8,6 @@
 
 using namespace llvm;
 
-extern "C" SmallVectorTemplateBase<coverage::CounterExpression>
-    *LLVMRustCoverageSmallVectorCounterExpressionCreate() {
-  return new SmallVector<coverage::CounterExpression, 32>();
-}
-
-extern "C" void LLVMRustCoverageSmallVectorCounterExpressionDispose(
-    SmallVectorTemplateBase<coverage::CounterExpression> *Vector) {
-  delete Vector;
-}
-
-extern "C" void LLVMRustCoverageSmallVectorCounterExpressionAdd(
-    SmallVectorTemplateBase<coverage::CounterExpression> *Expressions,
-    coverage::CounterExpression::ExprKind Kind,
-    unsigned LeftIndex,
-    unsigned RightIndex) {
-  auto LHS = coverage::Counter::getCounter(LeftIndex);
-  auto RHS = coverage::Counter::getCounter(RightIndex);
-  Expressions->push_back(coverage::CounterExpression { Kind, LHS, RHS });
-}
-
-extern "C" SmallVectorTemplateBase<coverage::CounterMappingRegion>
-    *LLVMRustCoverageSmallVectorCounterMappingRegionCreate() {
-  return new SmallVector<coverage::CounterMappingRegion, 32>();
-}
-
-extern "C" void LLVMRustCoverageSmallVectorCounterMappingRegionDispose(
-    SmallVectorTemplateBase<coverage::CounterMappingRegion> *Vector) {
-  delete Vector;
-}
-
-extern "C" void LLVMRustCoverageSmallVectorCounterMappingRegionAdd(
-    SmallVectorTemplateBase<coverage::CounterMappingRegion> *MappingRegions,
-    unsigned Index,
-    unsigned FileID,
-    unsigned LineStart,
-    unsigned ColumnStart,
-    unsigned LineEnd,
-    unsigned ColumnEnd) {
-  auto Counter = coverage::Counter::getCounter(Index);
-  MappingRegions->push_back(coverage::CounterMappingRegion::makeRegion(
-           Counter, FileID, LineStart,
-           ColumnStart, LineEnd, ColumnEnd));
-
-  // FIXME(richkadel): As applicable, implement additional CounterMappingRegion types using the
-  // static method alternatives to `coverage::CounterMappingRegion::makeRegion`:
-  //
-  //   makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
-  //                 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
-  //   makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart,
-  //               unsigned LineEnd, unsigned ColumnEnd) {
-  //   makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart,
-  //                 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
-}
-
 extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
     const char* const Filenames[],
     size_t FilenamesLen,
@@ -79,13 +25,15 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
 extern "C" void LLVMRustCoverageWriteMappingToBuffer(
     const unsigned *VirtualFileMappingIDs,
     unsigned NumVirtualFileMappingIDs,
-    const SmallVectorImpl<coverage::CounterExpression> *Expressions,
-    SmallVectorImpl<coverage::CounterMappingRegion> *MappingRegions,
+    const coverage::CounterExpression *Expressions,
+    unsigned NumExpressions,
+    coverage::CounterMappingRegion *MappingRegions,
+    unsigned NumMappingRegions,
     RustStringRef BufferOut) {
   auto CoverageMappingWriter = coverage::CoverageMappingWriter(
-    makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
-    makeArrayRef(*Expressions),
-    MutableArrayRef<coverage::CounterMappingRegion> { *MappingRegions });
+      makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
+      makeArrayRef(Expressions, NumExpressions),
+      makeMutableArrayRef(MappingRegions, NumMappingRegions));
   RawRustStringOstream OS(BufferOut);
   CoverageMappingWriter.write(OS);
 }
diff --git a/src/test/assembly/asm/aarch64-modifiers.rs b/src/test/assembly/asm/aarch64-modifiers.rs
index c2484e9b6d0..150997ee807 100644
--- a/src/test/assembly/asm/aarch64-modifiers.rs
+++ b/src/test/assembly/asm/aarch64-modifiers.rs
@@ -2,6 +2,7 @@
 // assembly-output: emit-asm
 // compile-flags: -O
 // compile-flags: --target aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
 
 #![feature(no_core, lang_items, rustc_attrs)]
 #![crate_type = "rlib"]
diff --git a/src/test/assembly/asm/aarch64-types.rs b/src/test/assembly/asm/aarch64-types.rs
index ce2f0082a06..b78a8cbb559 100644
--- a/src/test/assembly/asm/aarch64-types.rs
+++ b/src/test/assembly/asm/aarch64-types.rs
@@ -1,6 +1,7 @@
 // no-system-llvm
 // assembly-output: emit-asm
 // compile-flags: --target aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd)]
 #![crate_type = "rlib"]
diff --git a/src/test/assembly/asm/arm-modifiers.rs b/src/test/assembly/asm/arm-modifiers.rs
index b71503d0a53..ad4ab63f265 100644
--- a/src/test/assembly/asm/arm-modifiers.rs
+++ b/src/test/assembly/asm/arm-modifiers.rs
@@ -3,6 +3,7 @@
 // compile-flags: -O
 // compile-flags: --target armv7-unknown-linux-gnueabihf
 // compile-flags: -C target-feature=+neon
+// needs-llvm-components: arm
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd)]
 #![crate_type = "rlib"]
diff --git a/src/test/assembly/asm/arm-types.rs b/src/test/assembly/asm/arm-types.rs
index 1e338f56c4d..07e25a38e45 100644
--- a/src/test/assembly/asm/arm-types.rs
+++ b/src/test/assembly/asm/arm-types.rs
@@ -2,6 +2,7 @@
 // assembly-output: emit-asm
 // compile-flags: --target armv7-unknown-linux-gnueabihf
 // compile-flags: -C target-feature=+neon
+// needs-llvm-components: arm
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd)]
 #![crate_type = "rlib"]
diff --git a/src/test/assembly/asm/hexagon-types.rs b/src/test/assembly/asm/hexagon-types.rs
index ba2d8a363cd..b6b3b54cd71 100644
--- a/src/test/assembly/asm/hexagon-types.rs
+++ b/src/test/assembly/asm/hexagon-types.rs
@@ -1,6 +1,7 @@
 // no-system-llvm
 // assembly-output: emit-asm
 // compile-flags: --target hexagon-unknown-linux-musl
+// needs-llvm-components: hexagon
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd)]
 #![crate_type = "rlib"]
diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs
index 4ee79d1bcc8..77fd5141357 100644
--- a/src/test/assembly/asm/nvptx-types.rs
+++ b/src/test/assembly/asm/nvptx-types.rs
@@ -2,6 +2,7 @@
 // assembly-output: emit-asm
 // compile-flags: --target nvptx64-nvidia-cuda
 // compile-flags: --crate-type cdylib
+// needs-llvm-components: nvptx
 
 #![feature(no_core, lang_items, rustc_attrs)]
 #![no_core]
diff --git a/src/test/assembly/asm/riscv-modifiers.rs b/src/test/assembly/asm/riscv-modifiers.rs
index 8c816e3220b..b6735153b5d 100644
--- a/src/test/assembly/asm/riscv-modifiers.rs
+++ b/src/test/assembly/asm/riscv-modifiers.rs
@@ -3,6 +3,7 @@
 // compile-flags: -O
 // compile-flags: --target riscv64gc-unknown-linux-gnu
 // compile-flags: -C target-feature=+f
+// needs-llvm-components: riscv
 
 #![feature(no_core, lang_items, rustc_attrs)]
 #![crate_type = "rlib"]
diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs
index 449213471cc..0ff0bf1f949 100644
--- a/src/test/assembly/asm/riscv-types.rs
+++ b/src/test/assembly/asm/riscv-types.rs
@@ -4,6 +4,7 @@
 //[riscv64] compile-flags: --target riscv64imac-unknown-none-elf
 //[riscv32] compile-flags: --target riscv32imac-unknown-none-elf
 // compile-flags: -C target-feature=+d
+// needs-llvm-components: riscv
 
 #![feature(no_core, lang_items, rustc_attrs)]
 #![crate_type = "rlib"]
diff --git a/src/test/codegen/abi-efiapi.rs b/src/test/codegen/abi-efiapi.rs
index 7c61b780990..1c0b77ad9c7 100644
--- a/src/test/codegen/abi-efiapi.rs
+++ b/src/test/codegen/abi-efiapi.rs
@@ -1,12 +1,14 @@
 // Checks if the correct annotation for the efiapi ABI is passed to llvm.
 
-// revisions:x86_64 i686 arm
-
+// revisions:x86_64 i686 aarch64 arm riscv
 // min-llvm-version: 9.0
+// needs-llvm-components: aarch64 arm riscv
 
 //[x86_64] compile-flags: --target x86_64-unknown-uefi
 //[i686] compile-flags: --target i686-unknown-linux-musl
+//[aarch64] compile-flags: --target aarch64-unknown-none
 //[arm] compile-flags: --target armv7r-none-eabi
+//[riscv] compile-flags: --target riscv64gc-unknown-none-elf
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
@@ -22,6 +24,8 @@ trait Copy { }
 
 //x86_64: define win64cc void @has_efiapi
 //i686: define void @has_efiapi
+//aarch64: define void @has_efiapi
 //arm: define void @has_efiapi
+//riscv: define void @has_efiapi
 #[no_mangle]
 pub extern "efiapi" fn has_efiapi() {}
diff --git a/src/test/codegen/avr/avr-func-addrspace.rs b/src/test/codegen/avr/avr-func-addrspace.rs
index 7759d9603a5..6d25ca56f14 100644
--- a/src/test/codegen/avr/avr-func-addrspace.rs
+++ b/src/test/codegen/avr/avr-func-addrspace.rs
@@ -1,4 +1,5 @@
 // compile-flags: -O --target=avr-unknown-unknown --crate-type=rlib
+// needs-llvm-components: avr
 
 // This test validates that function pointers can be stored in global variables
 // and called upon. It ensures that Rust emits function pointers in the correct
diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs
index 493c1b9f0ba..758c6c4da92 100644
--- a/src/test/codegen/naked-functions.rs
+++ b/src/test/codegen/naked-functions.rs
@@ -18,7 +18,7 @@ pub fn naked_empty() {
 // CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}})
 pub fn naked_with_args(a: isize) {
     // CHECK-NEXT: {{.+}}:
-    // CHECK-NEXT: %a = alloca i{{[0-9]+}}
+    // CHECK-NEXT: %_1 = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
     // CHECK: ret void
 }
@@ -39,7 +39,7 @@ pub fn naked_with_return() -> isize {
 #[naked]
 pub fn naked_with_args_and_return(a: isize) -> isize {
     // CHECK-NEXT: {{.+}}:
-    // CHECK-NEXT: %a = alloca i{{[0-9]+}}
+    // CHECK-NEXT: %_1 = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
     // CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
     a
diff --git a/src/test/debuginfo/function-arguments-naked.rs b/src/test/debuginfo/function-arguments-naked.rs
new file mode 100644
index 00000000000..e88a99b322e
--- /dev/null
+++ b/src/test/debuginfo/function-arguments-naked.rs
@@ -0,0 +1,40 @@
+// min-lldb-version: 310
+
+// We have to ignore android because of this issue:
+// https://github.com/rust-lang/rust/issues/74847
+// ignore-android
+
+// compile-flags:-g
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command:run
+
+// gdb-command:info args
+// gdb-check:No arguments.
+// gdb-command:continue
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command:run
+
+// lldb-command:frame variable
+// lldbg-check:(unsigned long) = 111 (unsigned long) = 222
+// lldbr-check:(unsigned long) = 111 (unsigned long) = 222
+// lldb-command:continue
+
+
+#![feature(naked_functions)]
+#![feature(omit_gdb_pretty_printer_section)]
+#![omit_gdb_pretty_printer_section]
+
+fn main() {
+    naked(111, 222);
+}
+
+#[naked]
+fn naked(x: usize, y: usize) {
+    zzz(); // #break
+}
+
+fn zzz() { () }
diff --git a/src/test/mir-opt/address-of.rs b/src/test/mir-opt/address-of.rs
index 6cd14ccf434..c4bea5613e4 100644
--- a/src/test/mir-opt/address-of.rs
+++ b/src/test/mir-opt/address-of.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.address_of_reborrow.SimplifyCfg-initial.after.mir
+// EMIT_MIR address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
 
 fn address_of_reborrow() {
     let y = &[0; 10];
@@ -37,7 +37,7 @@ fn address_of_reborrow() {
 }
 
 // The normal borrows here should be preserved
-// EMIT_MIR rustc.borrow_and_cast.SimplifyCfg-initial.after.mir
+// EMIT_MIR address_of.borrow_and_cast.SimplifyCfg-initial.after.mir
 fn borrow_and_cast(mut x: i32) {
     let p = &x as *const i32;
     let q = &mut x as *const i32;
diff --git a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
index 07793b3598f..07793b3598f 100644
--- a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/address-of/rustc.borrow_and_cast.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir
index 4a7e8de29ec..4a7e8de29ec 100644
--- a/src/test/mir-opt/address-of/rustc.borrow_and_cast.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array-index-is-temporary.rs
index 4667c4f66b2..0e4c486e464 100644
--- a/src/test/mir-opt/array-index-is-temporary.rs
+++ b/src/test/mir-opt/array-index-is-temporary.rs
@@ -8,7 +8,7 @@ unsafe fn foo(z: *mut usize) -> u32 {
 }
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.main.SimplifyCfg-elaborate-drops.after.mir
+// EMIT_MIR array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir
 fn main() {
     let mut x = [42, 43, 44];
     let mut y = 1;
diff --git a/src/test/mir-opt/array-index-is-temporary/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.32bit
index 2a3a18d6c5b..2a3a18d6c5b 100644
--- a/src/test/mir-opt/array-index-is-temporary/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.32bit
diff --git a/src/test/mir-opt/array-index-is-temporary/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.64bit
index 093c170cf7a..093c170cf7a 100644
--- a/src/test/mir-opt/array-index-is-temporary/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir.64bit
diff --git a/src/test/mir-opt/basic_assignment/rustc.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
index de423cd907a..de423cd907a 100644
--- a/src/test/mir-opt/basic_assignment/rustc.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs
index 17141b6334c..ac350271e9f 100644
--- a/src/test/mir-opt/basic_assignment.rs
+++ b/src/test/mir-opt/basic_assignment.rs
@@ -1,6 +1,6 @@
 // this tests move up progration, which is not yet implemented
 
-// EMIT_MIR rustc.main.SimplifyCfg-initial.after.mir
+// EMIT_MIR basic_assignment.main.SimplifyCfg-initial.after.mir
 
 // Check codegen for assignments (`a = b`) where the left-hand-side is
 // not yet initialized. Assignments tend to be absent in simple code,
diff --git a/src/test/mir-opt/box_expr/rustc.main.ElaborateDrops.before.mir b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir
index 259501c7de9..259501c7de9 100644
--- a/src/test/mir-opt/box_expr/rustc.main.ElaborateDrops.before.mir
+++ b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir
diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs
index beaf0baf12c..a214504f6dd 100644
--- a/src/test/mir-opt/box_expr.rs
+++ b/src/test/mir-opt/box_expr.rs
@@ -2,7 +2,7 @@
 
 #![feature(box_syntax)]
 
-// EMIT_MIR rustc.main.ElaborateDrops.before.mir
+// EMIT_MIR box_expr.main.ElaborateDrops.before.mir
 fn main() {
     let x = box S::new();
     drop(x);
diff --git a/src/test/mir-opt/byte_slice/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir
index 54e01dceb50..54e01dceb50 100644
--- a/src/test/mir-opt/byte_slice/rustc.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir
diff --git a/src/test/mir-opt/byte_slice.rs b/src/test/mir-opt/byte_slice.rs
index 317e96d6f52..48e9c48c120 100644
--- a/src/test/mir-opt/byte_slice.rs
+++ b/src/test/mir-opt/byte_slice.rs
@@ -1,6 +1,6 @@
 // compile-flags: -Z mir-opt-level=0
 
-// EMIT_MIR rustc.main.SimplifyCfg-elaborate-drops.after.mir
+// EMIT_MIR byte_slice.main.SimplifyCfg-elaborate-drops.after.mir
 fn main() {
     let x = b"foo";
     let y = [5u8, b'x'];
diff --git a/src/test/mir-opt/combine_array_len/32bit/rustc.norm2.InstCombine.diff b/src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.32bit
index 65db967fe5f..65db967fe5f 100644
--- a/src/test/mir-opt/combine_array_len/32bit/rustc.norm2.InstCombine.diff
+++ b/src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.32bit
diff --git a/src/test/mir-opt/combine_array_len/64bit/rustc.norm2.InstCombine.diff b/src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.64bit
index 712c4eb230c..712c4eb230c 100644
--- a/src/test/mir-opt/combine_array_len/64bit/rustc.norm2.InstCombine.diff
+++ b/src/test/mir-opt/combine_array_len.norm2.InstCombine.diff.64bit
diff --git a/src/test/mir-opt/combine_array_len.rs b/src/test/mir-opt/combine_array_len.rs
index aa1c7459ea1..93490c14fd6 100644
--- a/src/test/mir-opt/combine_array_len.rs
+++ b/src/test/mir-opt/combine_array_len.rs
@@ -1,5 +1,5 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.norm2.InstCombine.diff
+// EMIT_MIR combine_array_len.norm2.InstCombine.diff
 
 fn norm2(x: [f32; 2]) -> f32 {
     let a = x[0];
diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs
index c9d350a98fd..e63309a9bd2 100644
--- a/src/test/mir-opt/const-promotion-extern-static.rs
+++ b/src/test/mir-opt/const-promotion-extern-static.rs
@@ -4,12 +4,12 @@ extern "C" {
 
 static Y: i32 = 42;
 
-// EMIT_MIR rustc.BAR.PromoteTemps.diff
-// EMIT_MIR rustc.BAR-promoted[0].ConstProp.after.mir
+// EMIT_MIR const_promotion_extern_static.BAR.PromoteTemps.diff
+// EMIT_MIR const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir
 static mut BAR: *const &i32 = [&Y].as_ptr();
 
-// EMIT_MIR rustc.FOO.PromoteTemps.diff
-// EMIT_MIR rustc.FOO-promoted[0].ConstProp.after.mir
+// EMIT_MIR const_promotion_extern_static.FOO.PromoteTemps.diff
+// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir
 static mut FOO: *const &i32 = [unsafe { &X }].as_ptr();
 
 fn main() {}
diff --git a/src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.mir.32bit
index 30a383fd162..30a383fd162 100644
--- a/src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.mir.32bit
diff --git a/src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.mir.64bit
index 5fa54ae5a58..5fa54ae5a58 100644
--- a/src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.mir.64bit
diff --git a/src/test/mir-opt/const_allocation.rs b/src/test/mir-opt/const_allocation.rs
index aaf996ee8e1..bb1c48e8e3c 100644
--- a/src/test/mir-opt/const_allocation.rs
+++ b/src/test/mir-opt/const_allocation.rs
@@ -3,7 +3,7 @@
 static FOO: &[(Option<i32>, &[&str])] =
     &[(None, &[]), (None, &["foo", "bar"]), (Some(42), &["meh", "mop", "möp"])];
 
-// EMIT_MIR rustc.main.ConstProp.after.mir
+// EMIT_MIR const_allocation.main.ConstProp.after.mir
 fn main() {
     FOO;
 }
diff --git a/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit
index d386d247829..d386d247829 100644
--- a/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit
diff --git a/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit
index d7acd0f0f43..d7acd0f0f43 100644
--- a/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit
diff --git a/src/test/mir-opt/const_allocation2.rs b/src/test/mir-opt/const_allocation2.rs
index ca61b84c0bc..56839255c0e 100644
--- a/src/test/mir-opt/const_allocation2.rs
+++ b/src/test/mir-opt/const_allocation2.rs
@@ -1,6 +1,6 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
-// EMIT_MIR rustc.main.ConstProp.after.mir
+// EMIT_MIR const_allocation2.main.ConstProp.after.mir
 fn main() {
     FOO;
 }
diff --git a/src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.32bit
index 39c60ad987a..39c60ad987a 100644
--- a/src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.32bit
diff --git a/src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.64bit
index 96024f1c82c..96024f1c82c 100644
--- a/src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.mir.64bit
diff --git a/src/test/mir-opt/const_allocation3.rs b/src/test/mir-opt/const_allocation3.rs
index 73bb58e1a98..2ce289aea3f 100644
--- a/src/test/mir-opt/const_allocation3.rs
+++ b/src/test/mir-opt/const_allocation3.rs
@@ -1,6 +1,6 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
-// EMIT_MIR rustc.main.ConstProp.after.mir
+// EMIT_MIR const_allocation3.main.ConstProp.after.mir
 fn main() {
     FOO;
 }
diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir
index 509947071b0..509947071b0 100644
--- a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir
+++ b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir
diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
index 0e0d8ea9063..0e0d8ea9063 100644
--- a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir
index d9c6b4f0029..d9c6b4f0029 100644
--- a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir
+++ b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir
diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
index a885b4d3bae..a885b4d3bae 100644
--- a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
diff --git a/src/test/mir-opt/const_prop/aggregate/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff
index e84e88b93fc..e84e88b93fc 100644
--- a/src/test/mir-opt/const_prop/aggregate/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/aggregate.rs b/src/test/mir-opt/const_prop/aggregate.rs
index 928ed8265d3..7a3b26a7317 100644
--- a/src/test/mir-opt/const_prop/aggregate.rs
+++ b/src/test/mir-opt/const_prop/aggregate.rs
@@ -1,6 +1,6 @@
 // compile-flags: -O
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR aggregate.main.ConstProp.diff
 fn main() {
     let x = (0, 1, 2).1 + 0;
 }
diff --git a/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.32bit
index bbd6c8042f1..bbd6c8042f1 100644
--- a/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.32bit
diff --git a/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.64bit
index d9096e5f3f1..d9096e5f3f1 100644
--- a/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.diff.64bit
diff --git a/src/test/mir-opt/const_prop/array_index.rs b/src/test/mir-opt/const_prop/array_index.rs
index 9301e6f5d03..2c5254b5deb 100644
--- a/src/test/mir-opt/const_prop/array_index.rs
+++ b/src/test/mir-opt/const_prop/array_index.rs
@@ -1,6 +1,6 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR array_index.main.ConstProp.diff
 fn main() {
     let x: u32 = [0, 1, 2, 3][2];
 }
diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
index 4bd4bb0dd7d..4bd4bb0dd7d 100644
--- a/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs b/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs
index 0cd1f37c9a7..6f39209b970 100644
--- a/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs
+++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
     let y = 0;
diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
index ecd030e32b4..ecd030e32b4 100644
--- a/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs
index 26bccbb90ec..cc16a4a5aa7 100644
--- a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs
+++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR bad_op_mod_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
     let y = 0;
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.32bit
index 2b5010759d7..2b5010759d7 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.32bit
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.64bit
index 301aaf29247..301aaf29247 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.diff.64bit
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
index e517e467c37..cf22b06d5e5 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
@@ -1,5 +1,5 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR bad_op_unsafe_oob_for_slices.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
     let a: *const [_] = &[1, 2, 3];
diff --git a/src/test/mir-opt/const_prop/boolean_identities.rs b/src/test/mir-opt/const_prop/boolean_identities.rs
index 4e09acbaa53..6dae07dfbd1 100644
--- a/src/test/mir-opt/const_prop/boolean_identities.rs
+++ b/src/test/mir-opt/const_prop/boolean_identities.rs
@@ -1,6 +1,6 @@
 // compile-flags: -O -Zmir-opt-level=3
 
-// EMIT_MIR rustc.test.ConstProp.diff
+// EMIT_MIR boolean_identities.test.ConstProp.diff
 pub fn test(x: bool, y: bool) -> bool {
     (y | true) & (x & false)
 }
diff --git a/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff b/src/test/mir-opt/const_prop/boolean_identities.test.ConstProp.diff
index b8f0ad4d434..b8f0ad4d434 100644
--- a/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/boolean_identities.test.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/boxes/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff
index f271188ebfd..f271188ebfd 100644
--- a/src/test/mir-opt/const_prop/boxes/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/boxes.rs b/src/test/mir-opt/const_prop/boxes.rs
index d45804ebb6c..fea666a4455 100644
--- a/src/test/mir-opt/const_prop/boxes.rs
+++ b/src/test/mir-opt/const_prop/boxes.rs
@@ -7,7 +7,7 @@
 
 // Note: this test verifies that we, in fact, do not const prop `box`
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR boxes.main.ConstProp.diff
 fn main() {
     let x = *(box 42) + 0;
 }
diff --git a/src/test/mir-opt/const_prop/cast/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff
index 54af804d19b..54af804d19b 100644
--- a/src/test/mir-opt/const_prop/cast/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/cast.rs b/src/test/mir-opt/const_prop/cast.rs
index 2af5f32a668..680cab00740 100644
--- a/src/test/mir-opt/const_prop/cast.rs
+++ b/src/test/mir-opt/const_prop/cast.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR cast.main.ConstProp.diff
 
 fn main() {
     let x = 42u8 as u32;
diff --git a/src/test/mir-opt/const_prop/checked_add/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff
index e3690d71294..e3690d71294 100644
--- a/src/test/mir-opt/const_prop/checked_add/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/checked_add.rs b/src/test/mir-opt/const_prop/checked_add.rs
index 439bd2df91f..08d59b6fbc3 100644
--- a/src/test/mir-opt/const_prop/checked_add.rs
+++ b/src/test/mir-opt/const_prop/checked_add.rs
@@ -1,6 +1,6 @@
 // compile-flags: -C overflow-checks=on
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR checked_add.main.ConstProp.diff
 fn main() {
     let x: u32 = 1 + 1;
 }
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
index f3efef387a3..f3efef387a3 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
index c6c006c0809..8bd68527f37 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
@@ -1,7 +1,7 @@
 #[inline(never)]
 fn read(_: usize) { }
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR const_prop_fails_gracefully.main.ConstProp.diff
 fn main() {
     const FOO: &i32 = &1;
     let x = FOO as *const i32 as usize;
diff --git a/src/test/mir-opt/const_prop/control-flow-simplification.rs b/src/test/mir-opt/const_prop/control-flow-simplification.rs
index 1071590dd9e..aa4ce19f620 100644
--- a/src/test/mir-opt/const_prop/control-flow-simplification.rs
+++ b/src/test/mir-opt/const_prop/control-flow-simplification.rs
@@ -6,8 +6,8 @@ trait NeedsDrop:Sized{
 
 impl<This> NeedsDrop for This{}
 
-// EMIT_MIR rustc.hello.ConstProp.diff
-// EMIT_MIR rustc.hello.PreCodegen.before.mir
+// EMIT_MIR control_flow_simplification.hello.ConstProp.diff
+// EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir
 fn hello<T>(){
     if <bool>::NEEDS {
         panic!()
diff --git a/src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
index 474b9ffefba..474b9ffefba 100644
--- a/src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.PreCodegen.before.mir b/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir
index 3569b9897f9..3569b9897f9 100644
--- a/src/test/mir-opt/const_prop/control-flow-simplification/rustc.hello.PreCodegen.before.mir
+++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.PreCodegen.before.mir
diff --git a/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit
index 539a16f52dc..539a16f52dc 100644
--- a/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit
diff --git a/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit
index 20875448edd..20875448edd 100644
--- a/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit
diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs
index 13e8eb3e44e..67538b3c7a5 100644
--- a/src/test/mir-opt/const_prop/discriminant.rs
+++ b/src/test/mir-opt/const_prop/discriminant.rs
@@ -6,7 +6,7 @@
 // Fixing either of those will allow us to const-prop this away.
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR discriminant.main.ConstProp.diff
 fn main() {
     let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0;
 }
diff --git a/src/test/mir-opt/const_prop/indirect/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
index 57906b1cabd..57906b1cabd 100644
--- a/src/test/mir-opt/const_prop/indirect/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/indirect.rs b/src/test/mir-opt/const_prop/indirect.rs
index 961e4447d8b..37217ca8134 100644
--- a/src/test/mir-opt/const_prop/indirect.rs
+++ b/src/test/mir-opt/const_prop/indirect.rs
@@ -1,6 +1,6 @@
 // compile-flags: -C overflow-checks=on
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR indirect.main.ConstProp.diff
 fn main() {
     let x = (2u32 as u8) + 1;
 }
diff --git a/src/test/mir-opt/const_prop/issue-66971.rs b/src/test/mir-opt/const_prop/issue-66971.rs
index 50a1405b77b..986177b5c0a 100644
--- a/src/test/mir-opt/const_prop/issue-66971.rs
+++ b/src/test/mir-opt/const_prop/issue-66971.rs
@@ -11,7 +11,7 @@ fn encode(this: ((), u8, u8)) {
     assert!(this.2 == 0);
 }
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR issue_66971.main.ConstProp.diff
 fn main() {
     encode(((), 0, 0));
 }
diff --git a/src/test/mir-opt/const_prop/issue-67019.rs b/src/test/mir-opt/const_prop/issue-67019.rs
index 3c832eb1344..d277bd5869c 100644
--- a/src/test/mir-opt/const_prop/issue-67019.rs
+++ b/src/test/mir-opt/const_prop/issue-67019.rs
@@ -6,7 +6,7 @@ fn test(this: ((u8, u8),)) {
     assert!((this.0).0 == 1);
 }
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR issue_67019.main.ConstProp.diff
 fn main() {
     test(((1, 2),));
 }
diff --git a/src/test/mir-opt/const_prop/issue-66971/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
index 242907b5599..242907b5599 100644
--- a/src/test/mir-opt/const_prop/issue-66971/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/issue-67019/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
index d5c1105d7ca..d5c1105d7ca 100644
--- a/src/test/mir-opt/const_prop/issue-67019/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mult_by_zero.rs b/src/test/mir-opt/const_prop/mult_by_zero.rs
index f40faee3110..1cb50155b5e 100644
--- a/src/test/mir-opt/const_prop/mult_by_zero.rs
+++ b/src/test/mir-opt/const_prop/mult_by_zero.rs
@@ -1,6 +1,6 @@
 // compile-flags: -O -Zmir-opt-level=3
 
-// EMIT_MIR rustc.test.ConstProp.diff
+// EMIT_MIR mult_by_zero.test.ConstProp.diff
 fn test(x : i32) -> i32 {
   x * 0
 }
diff --git a/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff b/src/test/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff
index 7b36669bf15..7b36669bf15 100644
--- a/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff
index 3d4309a8aec..3d4309a8aec 100644
--- a/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable.rs b/src/test/mir-opt/const_prop/mutable_variable.rs
index b3a2d80fa95..801e7a9fcbb 100644
--- a/src/test/mir-opt/const_prop/mutable_variable.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable.rs
@@ -1,6 +1,6 @@
 // compile-flags: -O
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR mutable_variable.main.ConstProp.diff
 fn main() {
     let mut x = 42;
     x = 99;
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff
index f581b222c83..f581b222c83 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs
index 3c5fb4574b6..e0b4b77bac4 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs
@@ -1,6 +1,6 @@
 // compile-flags: -O
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR mutable_variable_aggregate.main.ConstProp.diff
 fn main() {
     let mut x = (42, 43);
     x.1 = 99;
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff
index e78bc31b774..e78bc31b774 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
index fc13cbf2abd..79ac497c783 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
@@ -1,6 +1,6 @@
 // compile-flags: -O
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR mutable_variable_aggregate_mut_ref.main.ConstProp.diff
 fn main() {
     let mut x = (42, 43);
     let z = &mut x;
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
index b1a0ab88fcc..b1a0ab88fcc 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
index 4f43ec8c947..9bb62b8973c 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
@@ -1,6 +1,6 @@
 // compile-flags: -O
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR mutable_variable_aggregate_partial_read.main.ConstProp.diff
 fn main() {
     let mut x: (i32, i32) = foo();
     x.1 = 99;
diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
index 3b72af2d0b9..3b72af2d0b9 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs b/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs
index 8c9cd005096..4126fb3c68c 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs
@@ -2,7 +2,7 @@
 
 static mut STATIC: u32 = 42;
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR mutable_variable_no_prop.main.ConstProp.diff
 fn main() {
     let mut x = 42;
     unsafe {
diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
index b59b180b07d..b59b180b07d 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs
index 40f801b1b5e..13f1b3f47f2 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs
@@ -1,6 +1,6 @@
 // compile-flags: -O
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR mutable_variable_unprop_assign.main.ConstProp.diff
 fn main() {
     let a = foo();
     let mut x: (i32, i32) = (1, 2);
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit
index 5312784bc8a..5312784bc8a 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit
index 7af99841366..7af99841366 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.SimplifyLocals.after.mir b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.32bit
index 7b74bf81d96..7b74bf81d96 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.32bit
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.SimplifyLocals.after.mir b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.64bit
index 7b74bf81d96..7b74bf81d96 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.mir.64bit
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.rs b/src/test/mir-opt/const_prop/optimizes_into_variable.rs
index 0ae172e777b..17265b7eb85 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.rs
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.rs
@@ -6,8 +6,8 @@ struct Point {
 }
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.main.ConstProp.diff
-// EMIT_MIR rustc.main.SimplifyLocals.after.mir
+// EMIT_MIR optimizes_into_variable.main.ConstProp.diff
+// EMIT_MIR optimizes_into_variable.main.SimplifyLocals.after.mir
 fn main() {
     let x = 2 + 2;
     let y = [0, 1, 2, 3, 4, 5][3];
diff --git a/src/test/mir-opt/const_prop/read_immutable_static/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff
index 36edfc42b9a..36edfc42b9a 100644
--- a/src/test/mir-opt/const_prop/read_immutable_static/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs
index 9635f7050a6..8a5f12c6f3d 100644
--- a/src/test/mir-opt/const_prop/read_immutable_static.rs
+++ b/src/test/mir-opt/const_prop/read_immutable_static.rs
@@ -2,7 +2,7 @@
 
 static FOO: u8 = 2;
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR read_immutable_static.main.ConstProp.diff
 fn main() {
     let x = FOO + FOO;
 }
diff --git a/src/test/mir-opt/const_prop/ref_deref/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
index ba5ac8d3ddf..ba5ac8d3ddf 100644
--- a/src/test/mir-opt/const_prop/ref_deref/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/ref_deref/rustc.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
index fa68eb34818..fa68eb34818 100644
--- a/src/test/mir-opt/const_prop/ref_deref/rustc.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
diff --git a/src/test/mir-opt/const_prop/ref_deref.rs b/src/test/mir-opt/const_prop/ref_deref.rs
index fc33e0e1f3b..30ec9766367 100644
--- a/src/test/mir-opt/const_prop/ref_deref.rs
+++ b/src/test/mir-opt/const_prop/ref_deref.rs
@@ -1,5 +1,5 @@
-// EMIT_MIR rustc.main.PromoteTemps.diff
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR ref_deref.main.PromoteTemps.diff
+// EMIT_MIR ref_deref.main.ConstProp.diff
 
 fn main() {
     *(&4);
diff --git a/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
index 483e5f1b9a4..483e5f1b9a4 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
index 86e6aacab45..86e6aacab45 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project/rustc.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.rs b/src/test/mir-opt/const_prop/ref_deref_project.rs
index 0322e300643..c7cc73651f6 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project.rs
+++ b/src/test/mir-opt/const_prop/ref_deref_project.rs
@@ -1,5 +1,5 @@
-// EMIT_MIR rustc.main.PromoteTemps.diff
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR ref_deref_project.main.PromoteTemps.diff
+// EMIT_MIR ref_deref_project.main.ConstProp.diff
 
 fn main() {
     *(&(4, 5).1); // This does not currently propagate (#67862)
diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
index 93fe856c8e8..93fe856c8e8 100644
--- a/src/test/mir-opt/const_prop/reify_fn_ptr/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.rs b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
index 834eb0cb1e9..bfe2563ad8a 100644
--- a/src/test/mir-opt/const_prop/reify_fn_ptr.rs
+++ b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR reify_fn_ptr.main.ConstProp.diff
 
 fn main() {
     let _ = main as usize as *const fn();
diff --git a/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.32bit
index c30075bbb05..c30075bbb05 100644
--- a/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.32bit
diff --git a/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.64bit
index cadce59cf95..cadce59cf95 100644
--- a/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.diff.64bit
diff --git a/src/test/mir-opt/const_prop/repeat.rs b/src/test/mir-opt/const_prop/repeat.rs
index cdbfc46d6ca..36d9b9fc62d 100644
--- a/src/test/mir-opt/const_prop/repeat.rs
+++ b/src/test/mir-opt/const_prop/repeat.rs
@@ -1,7 +1,7 @@
 // compile-flags: -O
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR repeat.main.ConstProp.diff
 fn main() {
     let x: u32 = [42; 8][2] + 0;
 }
diff --git a/src/test/mir-opt/const_prop/return_place/rustc.add.ConstProp.diff b/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff
index 5e39c8e6d52..5e39c8e6d52 100644
--- a/src/test/mir-opt/const_prop/return_place/rustc.add.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/return_place/rustc.add.PreCodegen.before.mir b/src/test/mir-opt/const_prop/return_place.add.PreCodegen.before.mir
index 23ad8d057ba..23ad8d057ba 100644
--- a/src/test/mir-opt/const_prop/return_place/rustc.add.PreCodegen.before.mir
+++ b/src/test/mir-opt/const_prop/return_place.add.PreCodegen.before.mir
diff --git a/src/test/mir-opt/const_prop/return_place.rs b/src/test/mir-opt/const_prop/return_place.rs
index 8d5b63b9afd..06a85369679 100644
--- a/src/test/mir-opt/const_prop/return_place.rs
+++ b/src/test/mir-opt/const_prop/return_place.rs
@@ -1,7 +1,7 @@
 // compile-flags: -C overflow-checks=on
 
-// EMIT_MIR rustc.add.ConstProp.diff
-// EMIT_MIR rustc.add.PreCodegen.before.mir
+// EMIT_MIR return_place.add.ConstProp.diff
+// EMIT_MIR return_place.add.PreCodegen.before.mir
 fn add() -> u32 {
     2 + 2
 }
diff --git a/src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
index 43e0eb09a2e..43e0eb09a2e 100644
--- a/src/test/mir-opt/const_prop/scalar_literal_propagation/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/scalar_literal_propagation.rs b/src/test/mir-opt/const_prop/scalar_literal_propagation.rs
index a740e69dca2..8724e4d5711 100644
--- a/src/test/mir-opt/const_prop/scalar_literal_propagation.rs
+++ b/src/test/mir-opt/const_prop/scalar_literal_propagation.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR scalar_literal_propagation.main.ConstProp.diff
 fn main() {
     let x = 1;
     consume(x);
diff --git a/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.32bit
index 0a07a1a11f2..0a07a1a11f2 100644
--- a/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.32bit
diff --git a/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.64bit
index f8c6f29e854..f8c6f29e854 100644
--- a/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.diff.64bit
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs
index 0312f5e8e3a..fa9eafa8b0b 100644
--- a/src/test/mir-opt/const_prop/slice_len.rs
+++ b/src/test/mir-opt/const_prop/slice_len.rs
@@ -1,6 +1,6 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR slice_len.main.ConstProp.diff
 fn main() {
     (&[1u32, 2, 3] as &[u32])[1];
 }
diff --git a/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff
index 9580b99da9e..9580b99da9e 100644
--- a/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff
index 54f37e609ec..54f37e609ec 100644
--- a/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff
+++ b/src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff
diff --git a/src/test/mir-opt/const_prop/switch_int.rs b/src/test/mir-opt/const_prop/switch_int.rs
index 46e6efb8180..9e7c7340448 100644
--- a/src/test/mir-opt/const_prop/switch_int.rs
+++ b/src/test/mir-opt/const_prop/switch_int.rs
@@ -1,8 +1,8 @@
 #[inline(never)]
 fn foo(_: i32) { }
 
-// EMIT_MIR rustc.main.ConstProp.diff
-// EMIT_MIR rustc.main.SimplifyBranches-after-const-prop.diff
+// EMIT_MIR switch_int.main.ConstProp.diff
+// EMIT_MIR switch_int.main.SimplifyBranches-after-const-prop.diff
 fn main() {
     match 1 {
         1 => foo(0),
diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
index 941ec64a3cc..941ec64a3cc 100644
--- a/src/test/mir-opt/const_prop/tuple_literal_propagation/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation.rs b/src/test/mir-opt/const_prop/tuple_literal_propagation.rs
index 015607cbab1..e644baec4a8 100644
--- a/src/test/mir-opt/const_prop/tuple_literal_propagation.rs
+++ b/src/test/mir-opt/const_prop/tuple_literal_propagation.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR tuple_literal_propagation.main.ConstProp.diff
 fn main() {
     let x = (1, 2);
 
diff --git a/src/test/mir-opt/const_prop_miscompile/rustc.bar.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff
index 5fe35b479c1..5fe35b479c1 100644
--- a/src/test/mir-opt/const_prop_miscompile/rustc.bar.ConstProp.diff
+++ b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop_miscompile/rustc.foo.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff
index 98e9825c1c4..98e9825c1c4 100644
--- a/src/test/mir-opt/const_prop_miscompile/rustc.foo.ConstProp.diff
+++ b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop_miscompile.rs b/src/test/mir-opt/const_prop_miscompile.rs
index 043b22870f4..bc54556b349 100644
--- a/src/test/mir-opt/const_prop_miscompile.rs
+++ b/src/test/mir-opt/const_prop_miscompile.rs
@@ -1,13 +1,13 @@
 #![feature(raw_ref_op)]
 
-// EMIT_MIR rustc.foo.ConstProp.diff
+// EMIT_MIR const_prop_miscompile.foo.ConstProp.diff
 fn foo() {
     let mut u = (1,);
     *&mut u.0 = 5;
     let y = { u.0 } == 5;
 }
 
-// EMIT_MIR rustc.bar.ConstProp.diff
+// EMIT_MIR const_prop_miscompile.bar.ConstProp.diff
 fn bar() {
     let mut v = (1,);
     unsafe {
diff --git a/src/test/mir-opt/copy_propagation.rs b/src/test/mir-opt/copy_propagation.rs
index b5db5497d48..ee460a488b6 100644
--- a/src/test/mir-opt/copy_propagation.rs
+++ b/src/test/mir-opt/copy_propagation.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.test.CopyPropagation.diff
+// EMIT_MIR copy_propagation.test.CopyPropagation.diff
 
 fn test(x: u32) -> u32 {
     let y = x;
diff --git a/src/test/mir-opt/copy_propagation/rustc.test.CopyPropagation.diff b/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff
index f2838638aca..f2838638aca 100644
--- a/src/test/mir-opt/copy_propagation/rustc.test.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff
diff --git a/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff
index 22fbf4e836b..22fbf4e836b 100644
--- a/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff
diff --git a/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.bar.CopyPropagation.diff
index 6953a80a5f0..6953a80a5f0 100644
--- a/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.bar.CopyPropagation.diff
diff --git a/src/test/mir-opt/copy_propagation_arg/rustc.baz.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff
index ee20553f7cc..ee20553f7cc 100644
--- a/src/test/mir-opt/copy_propagation_arg/rustc.baz.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff
diff --git a/src/test/mir-opt/copy_propagation_arg/rustc.foo.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff
index 33aaa748678..33aaa748678 100644
--- a/src/test/mir-opt/copy_propagation_arg/rustc.foo.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff
diff --git a/src/test/mir-opt/copy_propagation_arg.rs b/src/test/mir-opt/copy_propagation_arg.rs
index c4858be7f2b..3a00fc58a4e 100644
--- a/src/test/mir-opt/copy_propagation_arg.rs
+++ b/src/test/mir-opt/copy_propagation_arg.rs
@@ -5,25 +5,25 @@ fn dummy(x: u8) -> u8 {
     x
 }
 
-// EMIT_MIR rustc.foo.CopyPropagation.diff
+// EMIT_MIR copy_propagation_arg.foo.CopyPropagation.diff
 fn foo(mut x: u8) {
     // calling `dummy` to make an use of `x` that copyprop cannot eliminate
     x = dummy(x); // this will assign a local to `x`
 }
 
-// EMIT_MIR rustc.bar.CopyPropagation.diff
+// EMIT_MIR copy_propagation_arg.bar.CopyPropagation.diff
 fn bar(mut x: u8) {
     dummy(x);
     x = 5;
 }
 
-// EMIT_MIR rustc.baz.CopyPropagation.diff
+// EMIT_MIR copy_propagation_arg.baz.CopyPropagation.diff
 fn baz(mut x: i32) {
     // self-assignment to a function argument should be eliminated
     x = x;
 }
 
-// EMIT_MIR rustc.arg_src.CopyPropagation.diff
+// EMIT_MIR copy_propagation_arg.arg_src.CopyPropagation.diff
 fn arg_src(mut x: i32) -> i32 {
     let y = x;
     x = 123; // Don't propagate this assignment to `y`
diff --git a/src/test/mir-opt/deaggregator_test/rustc.bar.Deaggregator.diff b/src/test/mir-opt/deaggregator_test.bar.Deaggregator.diff
index 524156e0b92..524156e0b92 100644
--- a/src/test/mir-opt/deaggregator_test/rustc.bar.Deaggregator.diff
+++ b/src/test/mir-opt/deaggregator_test.bar.Deaggregator.diff
diff --git a/src/test/mir-opt/deaggregator_test.rs b/src/test/mir-opt/deaggregator_test.rs
index 9004a631291..342e222431b 100644
--- a/src/test/mir-opt/deaggregator_test.rs
+++ b/src/test/mir-opt/deaggregator_test.rs
@@ -4,7 +4,7 @@ struct Baz {
     z: bool,
 }
 
-// EMIT_MIR rustc.bar.Deaggregator.diff
+// EMIT_MIR deaggregator_test.bar.Deaggregator.diff
 fn bar(a: usize) -> Baz {
     Baz { x: a, y: 0.0, z: false }
 }
diff --git a/src/test/mir-opt/deaggregator_test_enum/rustc.bar.Deaggregator.diff b/src/test/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff
index 5af9a536693..5af9a536693 100644
--- a/src/test/mir-opt/deaggregator_test_enum/rustc.bar.Deaggregator.diff
+++ b/src/test/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff
diff --git a/src/test/mir-opt/deaggregator_test_enum.rs b/src/test/mir-opt/deaggregator_test_enum.rs
index e74eafd011f..02b63a1f55d 100644
--- a/src/test/mir-opt/deaggregator_test_enum.rs
+++ b/src/test/mir-opt/deaggregator_test_enum.rs
@@ -3,7 +3,7 @@ enum Baz {
     Foo { x: usize },
 }
 
-// EMIT_MIR rustc.bar.Deaggregator.diff
+// EMIT_MIR deaggregator_test_enum.bar.Deaggregator.diff
 fn bar(a: usize) -> Baz {
     Baz::Foo { x: a }
 }
diff --git a/src/test/mir-opt/deaggregator_test_enum_2.rs b/src/test/mir-opt/deaggregator_test_enum_2.rs
index d5201ed72a8..489854ff0aa 100644
--- a/src/test/mir-opt/deaggregator_test_enum_2.rs
+++ b/src/test/mir-opt/deaggregator_test_enum_2.rs
@@ -5,7 +5,7 @@ enum Foo {
     B(i32),
 }
 
-// EMIT_MIR rustc.test1.Deaggregator.diff
+// EMIT_MIR deaggregator_test_enum_2.test1.Deaggregator.diff
 fn test1(x: bool, y: i32) -> Foo {
     if x {
         Foo::A(y)
diff --git a/src/test/mir-opt/deaggregator_test_enum_2/rustc.test1.Deaggregator.diff b/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
index bf99f7efb4d..bf99f7efb4d 100644
--- a/src/test/mir-opt/deaggregator_test_enum_2/rustc.test1.Deaggregator.diff
+++ b/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
diff --git a/src/test/mir-opt/deaggregator_test_multiple.rs b/src/test/mir-opt/deaggregator_test_multiple.rs
index 824a970ce2f..9730b9aa8e5 100644
--- a/src/test/mir-opt/deaggregator_test_multiple.rs
+++ b/src/test/mir-opt/deaggregator_test_multiple.rs
@@ -5,7 +5,7 @@ enum Foo {
     B,
 }
 
-// EMIT_MIR rustc.test.Deaggregator.diff
+// EMIT_MIR deaggregator_test_multiple.test.Deaggregator.diff
 fn test(x: i32) -> [Foo; 2] {
     [Foo::A(x), Foo::A(x)]
 }
diff --git a/src/test/mir-opt/deaggregator_test_multiple/rustc.test.Deaggregator.diff b/src/test/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff
index f5d8d0607c6..f5d8d0607c6 100644
--- a/src/test/mir-opt/deaggregator_test_multiple/rustc.test.Deaggregator.diff
+++ b/src/test/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff
diff --git a/src/test/mir-opt/exponential-or.rs b/src/test/mir-opt/exponential-or.rs
index 9fce7928f6a..1d6f7b81890 100644
--- a/src/test/mir-opt/exponential-or.rs
+++ b/src/test/mir-opt/exponential-or.rs
@@ -2,7 +2,7 @@
 
 #![feature(or_patterns)]
 
-// EMIT_MIR rustc.match_tuple.SimplifyCfg-initial.after.mir
+// EMIT_MIR exponential_or.match_tuple.SimplifyCfg-initial.after.mir
 fn match_tuple(x: (u32, bool, Option<i32>, u32)) -> u32 {
     match x {
         (y @ (1 | 4), true | false, Some(1 | 8) | None, z @ (6..=9 | 13..=16)) => y ^ z,
diff --git a/src/test/mir-opt/exponential-or/rustc.match_tuple.SimplifyCfg-initial.after.mir b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
index 00942cd12b4..00942cd12b4 100644
--- a/src/test/mir-opt/exponential-or/rustc.match_tuple.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/fn-ptr-shim.rs b/src/test/mir-opt/fn-ptr-shim.rs
index 08413c9f6fc..796bec0be1e 100644
--- a/src/test/mir-opt/fn-ptr-shim.rs
+++ b/src/test/mir-opt/fn-ptr-shim.rs
@@ -3,7 +3,7 @@
 // Tests that the `<fn() as Fn>` shim does not create a `Call` terminator with a `Self` callee
 // (as only `FnDef` and `FnPtr` callees are allowed in MIR).
 
-// EMIT_MIR rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
+// EMIT_MIR core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
 fn main() {
     call(noop as fn());
 }
diff --git a/src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir b/src/test/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
index 199cbcf8375..199cbcf8375 100644
--- a/src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
+++ b/src/test/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
diff --git a/src/test/mir-opt/generator-drop-cleanup.rs b/src/test/mir-opt/generator-drop-cleanup.rs
index 3e9707c6491..f4fc2aec706 100644
--- a/src/test/mir-opt/generator-drop-cleanup.rs
+++ b/src/test/mir-opt/generator-drop-cleanup.rs
@@ -5,7 +5,7 @@
 // Regression test for #58892, generator drop shims should not have blocks
 // spuriously marked as cleanup
 
-// EMIT_MIR rustc.main-{{closure}}.generator_drop.0.mir
+// EMIT_MIR generator_drop_cleanup.main-{{closure}}.generator_drop.0.mir
 fn main() {
     let gen = || {
         let _s = String::new();
diff --git a/src/test/mir-opt/generator-storage-dead-unwind.rs b/src/test/mir-opt/generator-storage-dead-unwind.rs
index abfb39c77d6..ae9faaefdd5 100644
--- a/src/test/mir-opt/generator-storage-dead-unwind.rs
+++ b/src/test/mir-opt/generator-storage-dead-unwind.rs
@@ -17,7 +17,7 @@ struct Bar(i32);
 
 fn take<T>(_x: T) {}
 
-// EMIT_MIR rustc.main-{{closure}}.StateTransform.before.mir
+// EMIT_MIR generator_storage_dead_unwind.main-{{closure}}.StateTransform.before.mir
 fn main() {
     let _gen = || {
         let a = Foo(5);
diff --git a/src/test/mir-opt/generator-tiny.rs b/src/test/mir-opt/generator-tiny.rs
index c86e2865ca8..0e79f16255b 100644
--- a/src/test/mir-opt/generator-tiny.rs
+++ b/src/test/mir-opt/generator-tiny.rs
@@ -14,7 +14,7 @@ impl Drop for HasDrop {
 
 fn callee() {}
 
-// EMIT_MIR rustc.main-{{closure}}.generator_resume.0.mir
+// EMIT_MIR generator_tiny.main-{{closure}}.generator_resume.0.mir
 fn main() {
     let _gen = |_x: u8| {
         let _d = HasDrop;
diff --git a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir b/src/test/mir-opt/generator_drop_cleanup.main-{{closure}}.generator_drop.0.mir
index bd64a31663a..bd64a31663a 100644
--- a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir
+++ b/src/test/mir-opt/generator_drop_cleanup.main-{{closure}}.generator_drop.0.mir
diff --git a/src/test/mir-opt/generator-storage-dead-unwind/rustc.main-{{closure}}.StateTransform.before.mir b/src/test/mir-opt/generator_storage_dead_unwind.main-{{closure}}.StateTransform.before.mir
index 7dcfda32ca4..7dcfda32ca4 100644
--- a/src/test/mir-opt/generator-storage-dead-unwind/rustc.main-{{closure}}.StateTransform.before.mir
+++ b/src/test/mir-opt/generator_storage_dead_unwind.main-{{closure}}.StateTransform.before.mir
diff --git a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir b/src/test/mir-opt/generator_tiny.main-{{closure}}.generator_resume.0.mir
index 8776e5919bd..8776e5919bd 100644
--- a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir
+++ b/src/test/mir-opt/generator_tiny.main-{{closure}}.generator_resume.0.mir
diff --git a/src/test/mir-opt/graphviz/rustc.main.mir_map.0.dot b/src/test/mir-opt/graphviz.main.mir_map.0.dot
index f5d8b84812a..f5d8b84812a 100644
--- a/src/test/mir-opt/graphviz/rustc.main.mir_map.0.dot
+++ b/src/test/mir-opt/graphviz.main.mir_map.0.dot
diff --git a/src/test/mir-opt/graphviz.rs b/src/test/mir-opt/graphviz.rs
index b1c0f0dd3c8..074dba2c373 100644
--- a/src/test/mir-opt/graphviz.rs
+++ b/src/test/mir-opt/graphviz.rs
@@ -1,5 +1,5 @@
 // Test graphviz output
 // compile-flags: -Z dump-mir-graphviz
 
-// EMIT_MIR rustc.main.mir_map.0.dot
+// EMIT_MIR graphviz.main.mir_map.0.dot
 fn main() {}
diff --git a/src/test/mir-opt/inline/inline-any-operand.rs b/src/test/mir-opt/inline/inline-any-operand.rs
index 2edde12d72e..fb0de020f73 100644
--- a/src/test/mir-opt/inline/inline-any-operand.rs
+++ b/src/test/mir-opt/inline/inline-any-operand.rs
@@ -6,7 +6,7 @@ fn main() {
     println!("{}", bar());
 }
 
-// EMIT_MIR rustc.bar.Inline.after.mir
+// EMIT_MIR inline_any_operand.bar.Inline.after.mir
 fn bar() -> bool {
     let f = foo;
     f(1, -1)
diff --git a/src/test/mir-opt/inline/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline/inline-closure-borrows-arg.rs
index a82a91945d8..218bc3553a1 100644
--- a/src/test/mir-opt/inline/inline-closure-borrows-arg.rs
+++ b/src/test/mir-opt/inline/inline-closure-borrows-arg.rs
@@ -7,7 +7,7 @@ fn main() {
     println!("{}", foo(0, &14));
 }
 
-// EMIT_MIR rustc.foo.Inline.after.mir
+// EMIT_MIR inline_closure_borrows_arg.foo.Inline.after.mir
 fn foo<T: Copy>(_t: T, q: &i32) -> i32 {
     let x = |r: &i32, _s: &i32| {
         let variable = &*r;
diff --git a/src/test/mir-opt/inline/inline-closure-captures.rs b/src/test/mir-opt/inline/inline-closure-captures.rs
index 4a0aad9b0e6..52b6817e401 100644
--- a/src/test/mir-opt/inline/inline-closure-captures.rs
+++ b/src/test/mir-opt/inline/inline-closure-captures.rs
@@ -6,7 +6,7 @@ fn main() {
     println!("{:?}", foo(0, 14));
 }
 
-// EMIT_MIR rustc.foo.Inline.after.mir
+// EMIT_MIR inline_closure_captures.foo.Inline.after.mir
 fn foo<T: Copy>(t: T, q: i32) -> (i32, T) {
     let x = |_q| (q, t);
     x(q)
diff --git a/src/test/mir-opt/inline/inline-closure.rs b/src/test/mir-opt/inline/inline-closure.rs
index 77e424a2bb3..715fd0138a7 100644
--- a/src/test/mir-opt/inline/inline-closure.rs
+++ b/src/test/mir-opt/inline/inline-closure.rs
@@ -6,7 +6,7 @@ fn main() {
     println!("{}", foo(0, 14));
 }
 
-// EMIT_MIR rustc.foo.Inline.after.mir
+// EMIT_MIR inline_closure.foo.Inline.after.mir
 fn foo<T: Copy>(_t: T, q: i32) -> i32 {
     let x = |_t, _q| _t;
     x(q, q)
diff --git a/src/test/mir-opt/inline/inline-into-box-place.rs b/src/test/mir-opt/inline/inline-into-box-place.rs
index 77834e9661c..30c9a5d6b8f 100644
--- a/src/test/mir-opt/inline/inline-into-box-place.rs
+++ b/src/test/mir-opt/inline/inline-into-box-place.rs
@@ -3,7 +3,7 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 #![feature(box_syntax)]
 
-// EMIT_MIR rustc.main.Inline.diff
+// EMIT_MIR inline_into_box_place.main.Inline.diff
 fn main() {
     let _x: Box<Vec<u32>> = box Vec::new();
 }
diff --git a/src/test/mir-opt/inline/inline-retag.rs b/src/test/mir-opt/inline/inline-retag.rs
index d7e425ec658..c6950f26925 100644
--- a/src/test/mir-opt/inline/inline-retag.rs
+++ b/src/test/mir-opt/inline/inline-retag.rs
@@ -6,7 +6,7 @@ fn main() {
     println!("{}", bar());
 }
 
-// EMIT_MIR rustc.bar.Inline.after.mir
+// EMIT_MIR inline_retag.bar.Inline.after.mir
 fn bar() -> bool {
     let f = foo;
     f(&1, &-1)
diff --git a/src/test/mir-opt/inline/inline-specialization.rs b/src/test/mir-opt/inline/inline-specialization.rs
index fcdaca460a9..87275b4e514 100644
--- a/src/test/mir-opt/inline/inline-specialization.rs
+++ b/src/test/mir-opt/inline/inline-specialization.rs
@@ -1,6 +1,6 @@
 #![feature(specialization)]
 
-// EMIT_MIR rustc.main.Inline.diff
+// EMIT_MIR inline_specialization.main.Inline.diff
 fn main() {
     let x = <Vec::<()> as Foo>::bar();
 }
diff --git a/src/test/mir-opt/inline/inline-trait-method.rs b/src/test/mir-opt/inline/inline-trait-method.rs
index cb3db9b5592..74be53f5512 100644
--- a/src/test/mir-opt/inline/inline-trait-method.rs
+++ b/src/test/mir-opt/inline/inline-trait-method.rs
@@ -4,7 +4,7 @@ fn main() {
     println!("{}", test(&()));
 }
 
-// EMIT_MIR rustc.test.Inline.after.mir
+// EMIT_MIR inline_trait_method.test.Inline.after.mir
 fn test(x: &dyn X) -> u32 {
     x.y()
 }
diff --git a/src/test/mir-opt/inline/inline-trait-method_2.rs b/src/test/mir-opt/inline/inline-trait-method_2.rs
index e37f091c5cd..6e5de8315a1 100644
--- a/src/test/mir-opt/inline/inline-trait-method_2.rs
+++ b/src/test/mir-opt/inline/inline-trait-method_2.rs
@@ -1,6 +1,6 @@
 // compile-flags: -Z span_free_formats -Z mir-opt-level=3
 
-// EMIT_MIR rustc.test2.Inline.after.mir
+// EMIT_MIR inline_trait_method_2.test2.Inline.after.mir
 fn test2(x: &dyn X) -> bool {
     test(x)
 }
diff --git a/src/test/mir-opt/inline/inline-any-operand/rustc.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir
index c9ff1fe29f5..c9ff1fe29f5 100644
--- a/src/test/mir-opt/inline/inline-any-operand/rustc.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir
diff --git a/src/test/mir-opt/inline/inline-closure/rustc.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir
index bd0ec8c7ddb..bd0ec8c7ddb 100644
--- a/src/test/mir-opt/inline/inline-closure/rustc.foo.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir
diff --git a/src/test/mir-opt/inline/inline-closure-borrows-arg/rustc.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
index cea3c59a3e4..cea3c59a3e4 100644
--- a/src/test/mir-opt/inline/inline-closure-borrows-arg/rustc.foo.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
diff --git a/src/test/mir-opt/inline/inline-closure-captures/rustc.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
index eeff914ccff..eeff914ccff 100644
--- a/src/test/mir-opt/inline/inline-closure-captures/rustc.foo.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
diff --git a/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.32bit
index 855811964b1..855811964b1 100644
--- a/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.32bit
diff --git a/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.64bit
index 507e45a445b..507e45a445b 100644
--- a/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.diff.64bit
diff --git a/src/test/mir-opt/inline/inline-retag/rustc.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
index d6ac1c57a63..d6ac1c57a63 100644
--- a/src/test/mir-opt/inline/inline-retag/rustc.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
diff --git a/src/test/mir-opt/inline/inline-specialization/rustc.main.Inline.diff b/src/test/mir-opt/inline/inline_specialization.main.Inline.diff
index c273c43c429..c273c43c429 100644
--- a/src/test/mir-opt/inline/inline-specialization/rustc.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_specialization.main.Inline.diff
diff --git a/src/test/mir-opt/inline/inline-trait-method/rustc.test.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir
index 8acc5ad5c09..8acc5ad5c09 100644
--- a/src/test/mir-opt/inline/inline-trait-method/rustc.test.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir
diff --git a/src/test/mir-opt/inline/inline-trait-method_2/rustc.test2.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
index afea1d5ebff..afea1d5ebff 100644
--- a/src/test/mir-opt/inline/inline-trait-method_2/rustc.test2.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs
index 317705f7612..94f926d3964 100644
--- a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs
+++ b/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut.rs
@@ -1,19 +1,19 @@
-// EMIT_MIR rustc.a.Inline.after.mir
+// EMIT_MIR issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
 pub fn a<T>(x: &mut [T]) -> &mut [T] {
     x.as_mut()
 }
 
-// EMIT_MIR rustc.b.Inline.after.mir
+// EMIT_MIR issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
 pub fn b<T>(x: &mut Box<T>) -> &mut T {
     x.as_mut()
 }
 
-// EMIT_MIR rustc.c.Inline.after.mir
+// EMIT_MIR issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
 pub fn c<T>(x: &[T]) -> &[T] {
     x.as_ref()
 }
 
-// EMIT_MIR rustc.d.Inline.after.mir
+// EMIT_MIR issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
 pub fn d<T>(x: &Box<T>) -> &T {
     x.as_ref()
 }
diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.a.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
index 501e3e9cf96..501e3e9cf96 100644
--- a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.a.Inline.after.mir
+++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.b.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
index 6add8d9d75a..6add8d9d75a 100644
--- a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.b.Inline.after.mir
+++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.c.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
index 77492c89379..77492c89379 100644
--- a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.c.Inline.after.mir
+++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
diff --git a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.d.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
index 51bda6d334c..51bda6d334c 100644
--- a/src/test/mir-opt/inline/issue-58867-inline-as-ref-as-mut/rustc.d.Inline.after.mir
+++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
diff --git a/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff
index e7fef4622b1..96df5c6a518 100644
--- a/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff
+++ b/src/test/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff
@@ -7,7 +7,7 @@
   
       bb0: {
 +         StorageLive(_1);                 // scope 0 at $DIR/instrument_coverage.rs:18:18: 18:18
-+         _1 = const std::intrinsics::count_code_region(const 10208505205182607101_u64, const 0_u32, const 501_u32, const 513_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:18: 18:18
++         _1 = const std::intrinsics::count_code_region(const 10208505205182607101_u64, const 0_u32, const 529_u32, const 541_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:18: 18:18
 +                                          // ty::Const
 +                                          // + ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region}
 +                                          // + val: Value(Scalar(<ZST>))
@@ -28,16 +28,16 @@
 +                                          // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) }
 +                                          // ty::Const
 +                                          // + ty: u32
-+                                          // + val: Value(Scalar(0x000001f5))
++                                          // + val: Value(Scalar(0x00000211))
 +                                          // mir::Constant
 +                                          // + span: $DIR/instrument_coverage.rs:18:18: 18:18
-+                                          // + literal: Const { ty: u32, val: Value(Scalar(0x000001f5)) }
++                                          // + literal: Const { ty: u32, val: Value(Scalar(0x00000211)) }
 +                                          // ty::Const
 +                                          // + ty: u32
-+                                          // + val: Value(Scalar(0x00000201))
++                                          // + val: Value(Scalar(0x0000021d))
 +                                          // mir::Constant
 +                                          // + span: $DIR/instrument_coverage.rs:18:18: 18:18
-+                                          // + literal: Const { ty: u32, val: Value(Scalar(0x00000201)) }
++                                          // + literal: Const { ty: u32, val: Value(Scalar(0x0000021d)) }
 +     }
 + 
 +     bb1 (cleanup): {
diff --git a/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
index 51378c216da..1bcc98de8d4 100644
--- a/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff
+++ b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
@@ -11,7 +11,7 @@
       bb0: {
 -         falseUnwind -> [real: bb1, cleanup: bb2]; // scope 0 at $DIR/instrument_coverage.rs:10:5: 14:6
 +         StorageLive(_4);                 // scope 0 at $DIR/instrument_coverage.rs:9:11: 9:11
-+         _4 = const std::intrinsics::count_code_region(const 16004455475339839479_u64, const 0_u32, const 397_u32, const 465_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:11: 9:11
++         _4 = const std::intrinsics::count_code_region(const 16004455475339839479_u64, const 0_u32, const 425_u32, const 493_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:11: 9:11
 +                                          // ty::Const
 +                                          // + ty: unsafe extern "rust-intrinsic" fn(u64, u32, u32, u32) {std::intrinsics::count_code_region}
 +                                          // + val: Value(Scalar(<ZST>))
@@ -32,16 +32,16 @@
 +                                          // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) }
 +                                          // ty::Const
 +                                          // + ty: u32
-+                                          // + val: Value(Scalar(0x0000018d))
++                                          // + val: Value(Scalar(0x000001a9))
 +                                          // mir::Constant
 +                                          // + span: $DIR/instrument_coverage.rs:9:11: 9:11
-+                                          // + literal: Const { ty: u32, val: Value(Scalar(0x0000018d)) }
++                                          // + literal: Const { ty: u32, val: Value(Scalar(0x000001a9)) }
 +                                          // ty::Const
 +                                          // + ty: u32
-+                                          // + val: Value(Scalar(0x000001d1))
++                                          // + val: Value(Scalar(0x000001ed))
 +                                          // mir::Constant
 +                                          // + span: $DIR/instrument_coverage.rs:9:11: 9:11
-+                                          // + literal: Const { ty: u32, val: Value(Scalar(0x000001d1)) }
++                                          // + literal: Const { ty: u32, val: Value(Scalar(0x000001ed)) }
       }
   
       bb1: {
diff --git a/src/test/mir-opt/instrument_coverage.rs b/src/test/mir-opt/instrument_coverage.rs
index 3fe010ef68f..4770ec9b66e 100644
--- a/src/test/mir-opt/instrument_coverage.rs
+++ b/src/test/mir-opt/instrument_coverage.rs
@@ -4,8 +4,8 @@
 
 // needs-profiler-support
 // compile-flags: -Zinstrument-coverage
-// EMIT_MIR rustc.main.InstrumentCoverage.diff
-// EMIT_MIR rustc.bar.InstrumentCoverage.diff
+// EMIT_MIR instrument_coverage.main.InstrumentCoverage.diff
+// EMIT_MIR instrument_coverage.bar.InstrumentCoverage.diff
 fn main() {
     loop {
         if bar() {
diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue-38669.rs
index f6883ac8086..db3f89472c9 100644
--- a/src/test/mir-opt/issue-38669.rs
+++ b/src/test/mir-opt/issue-38669.rs
@@ -1,6 +1,6 @@
 // check that we don't StorageDead booleans before they are used
 
-// EMIT_MIR rustc.main.SimplifyCfg-initial.after.mir
+// EMIT_MIR issue_38669.main.SimplifyCfg-initial.after.mir
 fn main() {
     let mut should_break = false;
     loop {
diff --git a/src/test/mir-opt/issue-41110.rs b/src/test/mir-opt/issue-41110.rs
index cc35b8785a7..638dc601ec8 100644
--- a/src/test/mir-opt/issue-41110.rs
+++ b/src/test/mir-opt/issue-41110.rs
@@ -3,14 +3,14 @@
 // check that we don't emit multiple drop flags when they are not needed.
 
 
-// EMIT_MIR rustc.main.ElaborateDrops.after.mir
+// EMIT_MIR issue_41110.main.ElaborateDrops.after.mir
 fn main() {
     let x = S.other(S.id());
 }
 
 // no_mangle to make sure this gets instantiated even in an executable.
 #[no_mangle]
-// EMIT_MIR rustc.test.ElaborateDrops.after.mir
+// EMIT_MIR issue_41110.test.ElaborateDrops.after.mir
 pub fn test() {
     let u = S;
     let mut v = S;
diff --git a/src/test/mir-opt/issue-41697.rs b/src/test/mir-opt/issue-41697.rs
index 07b9d175677..c90cfc792a9 100644
--- a/src/test/mir-opt/issue-41697.rs
+++ b/src/test/mir-opt/issue-41697.rs
@@ -14,7 +14,7 @@ trait Foo {
 }
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir
+// EMIT_MIR issue_41697.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir
 impl Foo for [u8; 1+1] {
     fn get(&self) -> [u8; 2] {
         *self
diff --git a/src/test/mir-opt/issue-41888.rs b/src/test/mir-opt/issue-41888.rs
index 6caaa59d0af..c1046c14dbf 100644
--- a/src/test/mir-opt/issue-41888.rs
+++ b/src/test/mir-opt/issue-41888.rs
@@ -2,7 +2,7 @@
 // check that we clear the "ADT master drop flag" even when there are
 // no fields to be dropped.
 
-// EMIT_MIR rustc.main.ElaborateDrops.after.mir
+// EMIT_MIR issue_41888.main.ElaborateDrops.after.mir
 fn main() {
     let e;
     if cond() {
diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs
index 7d308980b90..86494c76aec 100644
--- a/src/test/mir-opt/issue-49232.rs
+++ b/src/test/mir-opt/issue-49232.rs
@@ -1,7 +1,7 @@
 // We must mark a variable whose initialization fails due to an
 // abort statement as StorageDead.
 
-// EMIT_MIR rustc.main.mir_map.0.mir
+// EMIT_MIR issue_49232.main.mir_map.0.mir
 fn main() {
     loop {
         let beacon = {
diff --git a/src/test/mir-opt/issue-62289.rs b/src/test/mir-opt/issue-62289.rs
index f0d57c572b3..37e3390d5fc 100644
--- a/src/test/mir-opt/issue-62289.rs
+++ b/src/test/mir-opt/issue-62289.rs
@@ -4,7 +4,7 @@
 
 #![feature(box_syntax)]
 
-// EMIT_MIR rustc.test.ElaborateDrops.before.mir
+// EMIT_MIR issue_62289.test.ElaborateDrops.before.mir
 fn test() -> Option<Box<u32>> {
     Some(box (None?))
 }
diff --git a/src/test/mir-opt/issue-72181-1.rs b/src/test/mir-opt/issue-72181-1.rs
index 6d65f847a2c..91e98adbe80 100644
--- a/src/test/mir-opt/issue-72181-1.rs
+++ b/src/test/mir-opt/issue-72181-1.rs
@@ -6,12 +6,12 @@
 
 enum Void {}
 
-// EMIT_MIR rustc.f.mir_map.0.mir
+// EMIT_MIR issue_72181_1.f.mir_map.0.mir
 fn f(v: Void) -> ! {
     match v {}
 }
 
-// EMIT_MIR rustc.main.mir_map.0.mir
+// EMIT_MIR issue_72181_1.main.mir_map.0.mir
 fn main() {
     let v: Void = unsafe {
         std::mem::transmute::<(), Void>(())
diff --git a/src/test/mir-opt/issue-72181.rs b/src/test/mir-opt/issue-72181.rs
index 9373ce12032..844d53a4b2b 100644
--- a/src/test/mir-opt/issue-72181.rs
+++ b/src/test/mir-opt/issue-72181.rs
@@ -12,14 +12,14 @@ union Foo {
 }
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.foo.mir_map.0.mir
+// EMIT_MIR issue_72181.foo.mir_map.0.mir
 fn foo(xs: [(Never, u32); 1]) -> u32 { xs[0].1 }
 
-// EMIT_MIR rustc.bar.mir_map.0.mir
+// EMIT_MIR issue_72181.bar.mir_map.0.mir
 fn bar([(_, x)]: [(Never, u32); 1]) -> u32 { x }
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.main.mir_map.0.mir
+// EMIT_MIR issue_72181.main.mir_map.0.mir
 fn main() {
     let _ = mem::size_of::<Foo>();
 
diff --git a/src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir b/src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir
deleted file mode 100644
index 3b6dc46d055..00000000000
--- a/src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir
+++ /dev/null
@@ -1,25 +0,0 @@
-// MIR for `bar` 0 mir_map
-
-fn bar(_1: [(Never, u32); 1]) -> u32 {
-    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-72181.rs:18:40: 18:43
-    let _2: u32;                         // in scope 0 at $DIR/issue-72181.rs:18:13: 18:14
-    scope 1 {
-        debug x => _2;                   // in scope 1 at $DIR/issue-72181.rs:18:13: 18:14
-    }
-
-    bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/issue-72181.rs:18:13: 18:14
-        _2 = (_1[0 of 1].1: u32);        // scope 0 at $DIR/issue-72181.rs:18:13: 18:14
-        _0 = _2;                         // scope 1 at $DIR/issue-72181.rs:18:46: 18:47
-        StorageDead(_2);                 // scope 0 at $DIR/issue-72181.rs:18:48: 18:49
-        goto -> bb2;                     // scope 0 at $DIR/issue-72181.rs:18:49: 18:49
-    }
-
-    bb1 (cleanup): {
-        resume;                          // scope 0 at $DIR/issue-72181.rs:18:1: 18:49
-    }
-
-    bb2: {
-        return;                          // scope 0 at $DIR/issue-72181.rs:18:49: 18:49
-    }
-}
diff --git a/src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir b/src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir
deleted file mode 100644
index 2941e282cf4..00000000000
--- a/src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir
+++ /dev/null
@@ -1,37 +0,0 @@
-// MIR for `foo` 0 mir_map
-
-fn foo(_1: [(Never, u32); 1]) -> u32 {
-    debug xs => _1;                      // in scope 0 at $DIR/issue-72181.rs:15:8: 15:10
-    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-72181.rs:15:34: 15:37
-    let _2: usize;                       // in scope 0 at $DIR/issue-72181.rs:15:43: 15:44
-    let mut _3: usize;                   // in scope 0 at $DIR/issue-72181.rs:15:40: 15:45
-    let mut _4: bool;                    // in scope 0 at $DIR/issue-72181.rs:15:40: 15:45
-
-    bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/issue-72181.rs:15:43: 15:44
-        _2 = const 0usize;               // scope 0 at $DIR/issue-72181.rs:15:43: 15:44
-                                         // ty::Const
-                                         // + ty: usize
-                                         // + val: Value(Scalar(0x0000000000000000))
-                                         // mir::Constant
-                                         // + span: $DIR/issue-72181.rs:15:43: 15:44
-                                         // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
-        _3 = Len(_1);                    // scope 0 at $DIR/issue-72181.rs:15:40: 15:45
-        _4 = Lt(_2, _3);                 // scope 0 at $DIR/issue-72181.rs:15:40: 15:45
-        assert(move _4, "index out of bounds: the len is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:15:40: 15:45
-    }
-
-    bb1 (cleanup): {
-        resume;                          // scope 0 at $DIR/issue-72181.rs:15:1: 15:49
-    }
-
-    bb2: {
-        _0 = (_1[_2].1: u32);            // scope 0 at $DIR/issue-72181.rs:15:40: 15:47
-        StorageDead(_2);                 // scope 0 at $DIR/issue-72181.rs:15:48: 15:49
-        goto -> bb3;                     // scope 0 at $DIR/issue-72181.rs:15:49: 15:49
-    }
-
-    bb3: {
-        return;                          // scope 0 at $DIR/issue-72181.rs:15:49: 15:49
-    }
-}
diff --git a/src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir
deleted file mode 100644
index 65f4de0e235..00000000000
--- a/src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir
+++ /dev/null
@@ -1,93 +0,0 @@
-// MIR for `main` 0 mir_map
-
-fn main() -> () {
-    let mut _0: ();                      // return place in scope 0 at $DIR/issue-72181.rs:21:11: 21:11
-    let mut _1: usize;                   // in scope 0 at $DIR/issue-72181.rs:22:13: 22:34
-    let mut _3: Foo;                     // in scope 0 at $DIR/issue-72181.rs:24:14: 24:27
-    let mut _4: Foo;                     // in scope 0 at $DIR/issue-72181.rs:24:29: 24:42
-    let mut _5: u64;                     // in scope 0 at $DIR/issue-72181.rs:25:13: 25:30
-    let _6: usize;                       // in scope 0 at $DIR/issue-72181.rs:25:24: 25:25
-    let mut _7: usize;                   // in scope 0 at $DIR/issue-72181.rs:25:22: 25:26
-    let mut _8: bool;                    // in scope 0 at $DIR/issue-72181.rs:25:22: 25:26
-    scope 1 {
-        let _2: [Foo; 2];                // in scope 1 at $DIR/issue-72181.rs:24:9: 24:10
-        scope 2 {
-            debug f => _2;               // in scope 2 at $DIR/issue-72181.rs:24:9: 24:10
-            scope 3 {
-            }
-            scope 4 {
-            }
-        }
-    }
-
-    bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/issue-72181.rs:22:13: 22:34
-        _1 = const std::mem::size_of::<Foo>() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:22:13: 22:34
-                                         // ty::Const
-                                         // + ty: fn() -> usize {std::mem::size_of::<Foo>}
-                                         // + val: Value(Scalar(<ZST>))
-                                         // mir::Constant
-                                         // + span: $DIR/issue-72181.rs:22:13: 22:32
-                                         // + literal: Const { ty: fn() -> usize {std::mem::size_of::<Foo>}, val: Value(Scalar(<ZST>)) }
-    }
-
-    bb1 (cleanup): {
-        resume;                          // scope 0 at $DIR/issue-72181.rs:21:1: 26:2
-    }
-
-    bb2: {
-        StorageDead(_1);                 // scope 0 at $DIR/issue-72181.rs:22:34: 22:35
-        StorageLive(_2);                 // scope 1 at $DIR/issue-72181.rs:24:9: 24:10
-        StorageLive(_3);                 // scope 1 at $DIR/issue-72181.rs:24:14: 24:27
-        _3 = Foo { a: const 42u64 };     // scope 1 at $DIR/issue-72181.rs:24:14: 24:27
-                                         // ty::Const
-                                         // + ty: u64
-                                         // + val: Value(Scalar(0x000000000000002a))
-                                         // mir::Constant
-                                         // + span: $DIR/issue-72181.rs:24:23: 24:25
-                                         // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000002a)) }
-        StorageLive(_4);                 // scope 1 at $DIR/issue-72181.rs:24:29: 24:42
-        _4 = Foo { a: const 10u64 };     // scope 1 at $DIR/issue-72181.rs:24:29: 24:42
-                                         // ty::Const
-                                         // + ty: u64
-                                         // + val: Value(Scalar(0x000000000000000a))
-                                         // mir::Constant
-                                         // + span: $DIR/issue-72181.rs:24:38: 24:40
-                                         // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000000a)) }
-        _2 = [move _3, move _4];         // scope 1 at $DIR/issue-72181.rs:24:13: 24:43
-        StorageDead(_4);                 // scope 1 at $DIR/issue-72181.rs:24:42: 24:43
-        StorageDead(_3);                 // scope 1 at $DIR/issue-72181.rs:24:42: 24:43
-        FakeRead(ForLet, _2);            // scope 1 at $DIR/issue-72181.rs:24:9: 24:10
-        StorageLive(_5);                 // scope 2 at $DIR/issue-72181.rs:25:13: 25:30
-        StorageLive(_6);                 // scope 4 at $DIR/issue-72181.rs:25:24: 25:25
-        _6 = const 0usize;               // scope 4 at $DIR/issue-72181.rs:25:24: 25:25
-                                         // ty::Const
-                                         // + ty: usize
-                                         // + val: Value(Scalar(0x0000000000000000))
-                                         // mir::Constant
-                                         // + span: $DIR/issue-72181.rs:25:24: 25:25
-                                         // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
-        _7 = Len(_2);                    // scope 4 at $DIR/issue-72181.rs:25:22: 25:26
-        _8 = Lt(_6, _7);                 // scope 4 at $DIR/issue-72181.rs:25:22: 25:26
-        assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:25:22: 25:26
-    }
-
-    bb3: {
-        _5 = (_2[_6].0: u64);            // scope 4 at $DIR/issue-72181.rs:25:22: 25:28
-        StorageDead(_6);                 // scope 2 at $DIR/issue-72181.rs:25:30: 25:31
-        StorageDead(_5);                 // scope 2 at $DIR/issue-72181.rs:25:30: 25:31
-        _0 = const ();                   // scope 0 at $DIR/issue-72181.rs:21:11: 26:2
-                                         // ty::Const
-                                         // + ty: ()
-                                         // + val: Value(Scalar(<ZST>))
-                                         // mir::Constant
-                                         // + span: $DIR/issue-72181.rs:21:11: 26:2
-                                         // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
-        StorageDead(_2);                 // scope 1 at $DIR/issue-72181.rs:26:1: 26:2
-        goto -> bb4;                     // scope 0 at $DIR/issue-72181.rs:26:2: 26:2
-    }
-
-    bb4: {
-        return;                          // scope 0 at $DIR/issue-72181.rs:26:2: 26:2
-    }
-}
diff --git a/src/test/mir-opt/issue-73223.rs b/src/test/mir-opt/issue-73223.rs
index d93805e6cd1..703b8761231 100644
--- a/src/test/mir-opt/issue-73223.rs
+++ b/src/test/mir-opt/issue-73223.rs
@@ -9,5 +9,5 @@ fn main() {
 }
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.main.SimplifyArmIdentity.diff
-// EMIT_MIR rustc.main.PreCodegen.diff
+// EMIT_MIR issue_73223.main.SimplifyArmIdentity.diff
+// EMIT_MIR issue_73223.main.PreCodegen.diff
diff --git a/src/test/mir-opt/issue-38669/rustc.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
index 7b58dc1f624..7b58dc1f624 100644
--- a/src/test/mir-opt/issue-38669/rustc.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/issue-41110/rustc.main.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir
index 77763f2d3a0..77763f2d3a0 100644
--- a/src/test/mir-opt/issue-41110/rustc.main.ElaborateDrops.after.mir
+++ b/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir
diff --git a/src/test/mir-opt/issue-41110/rustc.test.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir
index a99846bd15d..a99846bd15d 100644
--- a/src/test/mir-opt/issue-41110/rustc.test.ElaborateDrops.after.mir
+++ b/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir
diff --git a/src/test/mir-opt/issue-41697/32bit/rustc.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir.32bit
index 403555964ca..403555964ca 100644
--- a/src/test/mir-opt/issue-41697/32bit/rustc.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir
+++ b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir.32bit
diff --git a/src/test/mir-opt/issue-41697/64bit/rustc.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir.64bit
index df933d3ac25..df933d3ac25 100644
--- a/src/test/mir-opt/issue-41697/64bit/rustc.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir
+++ b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir.64bit
diff --git a/src/test/mir-opt/issue-41888/rustc.main.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
index 76ad865bcc8..76ad865bcc8 100644
--- a/src/test/mir-opt/issue-41888/rustc.main.ElaborateDrops.after.mir
+++ b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
diff --git a/src/test/mir-opt/issue-49232/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue_49232.main.mir_map.0.mir
index 918dc5ec387..918dc5ec387 100644
--- a/src/test/mir-opt/issue-49232/rustc.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue_49232.main.mir_map.0.mir
diff --git a/src/test/mir-opt/issue-62289/rustc.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
index 56916d676ed..56916d676ed 100644
--- a/src/test/mir-opt/issue-62289/rustc.test.ElaborateDrops.before.mir
+++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
diff --git a/src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir b/src/test/mir-opt/issue_72181.bar.mir_map.0.mir.32bit
index 29654c2b1f8..29654c2b1f8 100644
--- a/src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181.bar.mir_map.0.mir.32bit
diff --git a/src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir b/src/test/mir-opt/issue_72181.bar.mir_map.0.mir.64bit
index 29654c2b1f8..29654c2b1f8 100644
--- a/src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181.bar.mir_map.0.mir.64bit
diff --git a/src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir b/src/test/mir-opt/issue_72181.foo.mir_map.0.mir.32bit
index 9f8810e752c..9f8810e752c 100644
--- a/src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181.foo.mir_map.0.mir.32bit
diff --git a/src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir b/src/test/mir-opt/issue_72181.foo.mir_map.0.mir.64bit
index aab8efb415c..aab8efb415c 100644
--- a/src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181.foo.mir_map.0.mir.64bit
diff --git a/src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.mir.32bit
index e3fb5eb193a..e3fb5eb193a 100644
--- a/src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181.main.mir_map.0.mir.32bit
diff --git a/src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.mir.64bit
index d9e791b86bc..d9e791b86bc 100644
--- a/src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181.main.mir_map.0.mir.64bit
diff --git a/src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir b/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir
index 1821365898e..1821365898e 100644
--- a/src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir
diff --git a/src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
index b87d0294fb8..b87d0294fb8 100644
--- a/src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
diff --git a/src/test/mir-opt/issue-73223/32bit/rustc.main.PreCodegen.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit
index 4c9da471f0b..4c9da471f0b 100644
--- a/src/test/mir-opt/issue-73223/32bit/rustc.main.PreCodegen.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit
diff --git a/src/test/mir-opt/issue-73223/64bit/rustc.main.PreCodegen.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit
index 4c9da471f0b..4c9da471f0b 100644
--- a/src/test/mir-opt/issue-73223/64bit/rustc.main.PreCodegen.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit
diff --git a/src/test/mir-opt/issue-73223/32bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit
index dd0e8f4b2ad..dd0e8f4b2ad 100644
--- a/src/test/mir-opt/issue-73223/32bit/rustc.main.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit
diff --git a/src/test/mir-opt/issue-73223/64bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit
index d465f60f34d..d465f60f34d 100644
--- a/src/test/mir-opt/issue-73223/64bit/rustc.main.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit
diff --git a/src/test/mir-opt/loop_test/rustc.main.SimplifyCfg-qualify-consts.after.mir b/src/test/mir-opt/loop_test.main.SimplifyCfg-qualify-consts.after.mir
index e699abf421d..e699abf421d 100644
--- a/src/test/mir-opt/loop_test/rustc.main.SimplifyCfg-qualify-consts.after.mir
+++ b/src/test/mir-opt/loop_test.main.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs
index cb23a4c671b..5d0c30d4410 100644
--- a/src/test/mir-opt/loop_test.rs
+++ b/src/test/mir-opt/loop_test.rs
@@ -2,7 +2,7 @@
 
 // Tests to make sure we correctly generate falseUnwind edges in loops
 
-// EMIT_MIR rustc.main.SimplifyCfg-qualify-consts.after.mir
+// EMIT_MIR loop_test.main.SimplifyCfg-qualify-consts.after.mir
 fn main() {
     // Exit early at runtime. Since only care about the generated MIR
     // and not the runtime behavior (which is exercised by other tests)
diff --git a/src/test/mir-opt/match-arm-scopes.rs b/src/test/mir-opt/match-arm-scopes.rs
index 2c5816c51e3..7b7de7788c2 100644
--- a/src/test/mir-opt/match-arm-scopes.rs
+++ b/src/test/mir-opt/match-arm-scopes.rs
@@ -9,7 +9,7 @@
 //   all of the bindings for that scope.
 // * No drop flags are used.
 
-// EMIT_MIR rustc.complicated_match SimplifyCfg-initial.after ElaborateDrops.after
+// EMIT_MIR match_arm_scopes.complicated_match SimplifyCfg-initial.after ElaborateDrops.after
 fn complicated_match(cond: bool, items: (bool, bool, String)) -> i32 {
     match items {
         (false, a, s) | (a, false, s) if if cond { return 3 } else { a } => 1,
diff --git a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 58847e1bcee..58847e1bcee 100644
--- a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
diff --git a/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
index c53c9cf1db7..c53c9cf1db7 100644
--- a/src/test/mir-opt/match_false_edges/rustc.full_tested_match.PromoteTemps.after.mir
+++ b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
diff --git a/src/test/mir-opt/match_false_edges/rustc.full_tested_match2.PromoteTemps.before.mir b/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir
index b79416fe31a..b79416fe31a 100644
--- a/src/test/mir-opt/match_false_edges/rustc.full_tested_match2.PromoteTemps.before.mir
+++ b/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir
diff --git a/src/test/mir-opt/match_false_edges/rustc.main.PromoteTemps.before.mir b/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir
index 5b449da93d4..5b449da93d4 100644
--- a/src/test/mir-opt/match_false_edges/rustc.main.PromoteTemps.before.mir
+++ b/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs
index 91f4aad165e..42dea9c7082 100644
--- a/src/test/mir-opt/match_false_edges.rs
+++ b/src/test/mir-opt/match_false_edges.rs
@@ -10,7 +10,7 @@ fn guard2(_: i32) -> bool {
 
 // no_mangle to make sure this gets instantiated even in an executable.
 #[no_mangle]
-// EMIT_MIR rustc.full_tested_match.PromoteTemps.after.mir
+// EMIT_MIR match_false_edges.full_tested_match.PromoteTemps.after.mir
 pub fn full_tested_match() {
     let _ = match Some(42) {
         Some(x) if guard() => (1, x),
@@ -21,7 +21,7 @@ pub fn full_tested_match() {
 
 // no_mangle to make sure this gets instantiated even in an executable.
 #[no_mangle]
-// EMIT_MIR rustc.full_tested_match2.PromoteTemps.before.mir
+// EMIT_MIR match_false_edges.full_tested_match2.PromoteTemps.before.mir
 pub fn full_tested_match2() {
     let _ = match Some(42) {
         Some(x) if guard() => (1, x),
@@ -30,7 +30,7 @@ pub fn full_tested_match2() {
     };
 }
 
-// EMIT_MIR rustc.main.PromoteTemps.before.mir
+// EMIT_MIR match_false_edges.main.PromoteTemps.before.mir
 fn main() {
     let _ = match Some(1) {
         Some(_w) if guard() => 1,
diff --git a/src/test/mir-opt/match_test/rustc.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
index 16895942cb8..16895942cb8 100644
--- a/src/test/mir-opt/match_test/rustc.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
diff --git a/src/test/mir-opt/match_test.rs b/src/test/mir-opt/match_test.rs
index c3b07d42f5e..3a21077905b 100644
--- a/src/test/mir-opt/match_test.rs
+++ b/src/test/mir-opt/match_test.rs
@@ -2,7 +2,7 @@
 
 #![feature(exclusive_range_pattern)]
 
-// EMIT_MIR rustc.main.SimplifyCfg-initial.after.mir
+// EMIT_MIR match_test.main.SimplifyCfg-initial.after.mir
 fn main() {
     let x = 3;
     let b = true;
diff --git a/src/test/mir-opt/nll/named-lifetimes-basic.rs b/src/test/mir-opt/nll/named-lifetimes-basic.rs
index 073ccf7e6c6..73bd6d64e86 100644
--- a/src/test/mir-opt/nll/named-lifetimes-basic.rs
+++ b/src/test/mir-opt/nll/named-lifetimes-basic.rs
@@ -8,7 +8,7 @@
 
 #![allow(warnings)]
 
-// EMIT_MIR rustc.use_x.nll.0.mir
+// EMIT_MIR named_lifetimes_basic.use_x.nll.0.mir
 fn use_x<'a, 'b: 'a, 'c>(w: &'a mut i32, x: &'b u32, y: &'a u32, z: &'c u32) -> bool { true }
 
 fn main() {
diff --git a/src/test/mir-opt/nll/named-lifetimes-basic/rustc.use_x.nll.0.mir b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir
index dcfb069b84a..dcfb069b84a 100644
--- a/src/test/mir-opt/nll/named-lifetimes-basic/rustc.use_x.nll.0.mir
+++ b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs
index 66d7cda2b85..224a495c788 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic.rs
+++ b/src/test/mir-opt/nll/region-subtyping-basic.rs
@@ -12,7 +12,7 @@ fn use_x(_: usize) -> bool {
 }
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.main.nll.0.mir
+// EMIT_MIR region_subtyping_basic.main.nll.0.mir
 fn main() {
     let mut v = [1, 2, 3];
     let p = &v[0];
diff --git a/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.32bit
index e3f113fea28..e3f113fea28 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.32bit
diff --git a/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.64bit
index a69952ff07f..a69952ff07f 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.mir.64bit
diff --git a/src/test/mir-opt/no-drop-for-inactive-variant.rs b/src/test/mir-opt/no-drop-for-inactive-variant.rs
index cf6426b878a..34e2b1a134f 100644
--- a/src/test/mir-opt/no-drop-for-inactive-variant.rs
+++ b/src/test/mir-opt/no-drop-for-inactive-variant.rs
@@ -3,7 +3,7 @@
 // Ensure that there are no drop terminators in `unwrap<T>` (except the one along the cleanup
 // path).
 
-// EMIT_MIR rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir
+// EMIT_MIR no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
 fn unwrap<T>(opt: Option<T>) -> T {
     match opt {
         Some(x) => x,
diff --git a/src/test/mir-opt/no-spurious-drop-after-call.rs b/src/test/mir-opt/no-spurious-drop-after-call.rs
index ab58654e07c..bb5bb9aa4e5 100644
--- a/src/test/mir-opt/no-spurious-drop-after-call.rs
+++ b/src/test/mir-opt/no-spurious-drop-after-call.rs
@@ -4,7 +4,7 @@
 // MIR drop of the argument. (We used to have a `DROP(_2)` in the code
 // below, as part of bb3.)
 
-// EMIT_MIR rustc.main.ElaborateDrops.before.mir
+// EMIT_MIR no_spurious_drop_after_call.main.ElaborateDrops.before.mir
 fn main() {
     std::mem::drop("".to_string());
 }
diff --git a/src/test/mir-opt/no-drop-for-inactive-variant/rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
index f59390ba84e..f59390ba84e 100644
--- a/src/test/mir-opt/no-drop-for-inactive-variant/rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
diff --git a/src/test/mir-opt/no-spurious-drop-after-call/rustc.main.ElaborateDrops.before.mir b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
index 0af213e425f..0af213e425f 100644
--- a/src/test/mir-opt/no-spurious-drop-after-call/rustc.main.ElaborateDrops.before.mir
+++ b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
diff --git a/src/test/mir-opt/nrvo-simple.rs b/src/test/mir-opt/nrvo-simple.rs
index bf3a0efeada..f0eb711b3f0 100644
--- a/src/test/mir-opt/nrvo-simple.rs
+++ b/src/test/mir-opt/nrvo-simple.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.nrvo.RenameReturnPlace.diff
+// EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff
 fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
     let mut buf = [0; 1024];
     init(&mut buf);
diff --git a/src/test/mir-opt/nrvo-simple/rustc.nrvo.RenameReturnPlace.diff b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
index 18fbffb4630..18fbffb4630 100644
--- a/src/test/mir-opt/nrvo-simple/rustc.nrvo.RenameReturnPlace.diff
+++ b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
diff --git a/src/test/mir-opt/packed-struct-drop-aligned.rs b/src/test/mir-opt/packed-struct-drop-aligned.rs
index daf397c3d9c..6c2e265d514 100644
--- a/src/test/mir-opt/packed-struct-drop-aligned.rs
+++ b/src/test/mir-opt/packed-struct-drop-aligned.rs
@@ -1,7 +1,7 @@
 // ignore-wasm32-bare compiled with panic=abort by default
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.main.SimplifyCfg-elaborate-drops.after.mir
+// EMIT_MIR packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
 fn main() {
     let mut x = Packed(Aligned(Droppy(0)));
     x.0 = Aligned(Droppy(0));
diff --git a/src/test/mir-opt/packed-struct-drop-aligned/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.32bit
index 075c7647c67..075c7647c67 100644
--- a/src/test/mir-opt/packed-struct-drop-aligned/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.32bit
diff --git a/src/test/mir-opt/packed-struct-drop-aligned/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.64bit
index 99a74b6b24f..99a74b6b24f 100644
--- a/src/test/mir-opt/packed-struct-drop-aligned/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir.64bit
diff --git a/src/test/mir-opt/remove-never-const.rs b/src/test/mir-opt/remove-never-const.rs
index b2d4f14aa4c..1673f14b45c 100644
--- a/src/test/mir-opt/remove-never-const.rs
+++ b/src/test/mir-opt/remove-never-const.rs
@@ -15,7 +15,7 @@ impl<T> PrintName<T> {
     const VOID: ! = panic!();
 }
 
-// EMIT_MIR rustc.no_codegen.PreCodegen.after.mir
+// EMIT_MIR remove_never_const.no_codegen.PreCodegen.after.mir
 fn no_codegen<T>() {
     let _ = PrintName::<T>::VOID;
 }
diff --git a/src/test/mir-opt/remove_fake_borrows/rustc.match_guard.CleanupNonCodegenStatements.diff b/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
index 0822d8cc03c..0822d8cc03c 100644
--- a/src/test/mir-opt/remove_fake_borrows/rustc.match_guard.CleanupNonCodegenStatements.diff
+++ b/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
diff --git a/src/test/mir-opt/remove_fake_borrows.rs b/src/test/mir-opt/remove_fake_borrows.rs
index fd2f1d0dbff..a980f386b69 100644
--- a/src/test/mir-opt/remove_fake_borrows.rs
+++ b/src/test/mir-opt/remove_fake_borrows.rs
@@ -2,7 +2,7 @@
 
 // ignore-wasm32-bare compiled with panic=abort by default
 
-// EMIT_MIR rustc.match_guard.CleanupNonCodegenStatements.diff
+// EMIT_MIR remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
 fn match_guard(x: Option<&&i32>, c: bool) -> i32 {
     match x {
         Some(0) if c => 0,
diff --git a/src/test/mir-opt/remove-never-const/rustc.no_codegen.PreCodegen.after.mir b/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir
index 6f4a024d20f..6f4a024d20f 100644
--- a/src/test/mir-opt/remove-never-const/rustc.no_codegen.PreCodegen.after.mir
+++ b/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir
diff --git a/src/test/mir-opt/retag/rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
index 694c387986f..694c387986f 100644
--- a/src/test/mir-opt/retag/rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
diff --git a/src/test/mir-opt/retag/rustc.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir
index 01f5fbb7d23..01f5fbb7d23 100644
--- a/src/test/mir-opt/retag/rustc.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir
diff --git a/src/test/mir-opt/retag/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
index b61d9368375..b61d9368375 100644
--- a/src/test/mir-opt/retag/rustc.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs
index eba0f567c4a..12d7cb30d97 100644
--- a/src/test/mir-opt/retag.rs
+++ b/src/test/mir-opt/retag.rs
@@ -6,8 +6,8 @@
 
 struct Test(i32);
 
-// EMIT_MIR rustc.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir
-// EMIT_MIR rustc.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir
+// EMIT_MIR retag.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir
+// EMIT_MIR retag.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir
 impl Test {
     // Make sure we run the pass on a method, not just on bare functions.
     fn foo<'x>(&self, x: &'x mut i32) -> &'x mut i32 {
@@ -18,14 +18,14 @@ impl Test {
     }
 }
 
-// EMIT_MIR rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+// EMIT_MIR core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
 
 impl Drop for Test {
     fn drop(&mut self) {}
 }
 
-// EMIT_MIR rustc.main.SimplifyCfg-elaborate-drops.after.mir
-// EMIT_MIR rustc.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir
+// EMIT_MIR retag.main.SimplifyCfg-elaborate-drops.after.mir
+// EMIT_MIR retag.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir
 fn main() {
     let mut x = 0;
     {
diff --git a/src/test/mir-opt/retag/rustc.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir
index f9ed3932d33..f9ed3932d33 100644
--- a/src/test/mir-opt/retag/rustc.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir
diff --git a/src/test/mir-opt/retag/rustc.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir
index 87a8603a931..87a8603a931 100644
--- a/src/test/mir-opt/retag/rustc.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir
diff --git a/src/test/mir-opt/simple-match.rs b/src/test/mir-opt/simple-match.rs
index c8c7e9188c2..44adc55b6f7 100644
--- a/src/test/mir-opt/simple-match.rs
+++ b/src/test/mir-opt/simple-match.rs
@@ -1,7 +1,7 @@
 // Test that we don't generate unnecessarily large MIR for very simple matches
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.match_bool.mir_map.0.mir
+// EMIT_MIR simple_match.match_bool.mir_map.0.mir
 fn match_bool(x: bool) -> usize {
     match x {
         true => 10,
diff --git a/src/test/mir-opt/simple-match/32bit/rustc.match_bool.mir_map.0.mir b/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.32bit
index da3191554f0..da3191554f0 100644
--- a/src/test/mir-opt/simple-match/32bit/rustc.match_bool.mir_map.0.mir
+++ b/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.32bit
diff --git a/src/test/mir-opt/simple-match/64bit/rustc.match_bool.mir_map.0.mir b/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.64bit
index 55b51a899bc..55b51a899bc 100644
--- a/src/test/mir-opt/simple-match/64bit/rustc.match_bool.mir_map.0.mir
+++ b/src/test/mir-opt/simple_match.match_bool.mir_map.0.mir.64bit
diff --git a/src/test/mir-opt/simplify-arm-identity.rs b/src/test/mir-opt/simplify-arm-identity.rs
index 24e91b3ff61..0a59032e87b 100644
--- a/src/test/mir-opt/simplify-arm-identity.rs
+++ b/src/test/mir-opt/simplify-arm-identity.rs
@@ -13,7 +13,7 @@ enum Dst {
     Foo(u8),
 }
 
-// EMIT_MIR rustc.main.SimplifyArmIdentity.diff
+// EMIT_MIR simplify_arm_identity.main.SimplifyArmIdentity.diff
 fn main() {
     let e: Src = Src::Foo(0);
     let _: Dst = match e {
diff --git a/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff
deleted file mode 100644
index e7373391b79..00000000000
--- a/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff
+++ /dev/null
@@ -1,70 +0,0 @@
-- // MIR for `main` before SimplifyArmIdentity
-+ // MIR for `main` after SimplifyArmIdentity
-  
-  fn main() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/simplify-arm-identity.rs:16:11: 16:11
-      let _1: Src as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/simplify-arm-identity.rs:17:9: 17:10
-      let mut _2: Dst;                     // in scope 0 at $DIR/simplify-arm-identity.rs:18:18: 21:6
-      let mut _3: isize;                   // in scope 0 at $DIR/simplify-arm-identity.rs:19:9: 19:20
-      let mut _5: u8;                      // in scope 0 at $DIR/simplify-arm-identity.rs:19:33: 19:34
-      scope 1 {
-          debug e => _1;                   // in scope 1 at $DIR/simplify-arm-identity.rs:17:9: 17:10
-          let _4: u8;                      // in scope 1 at $DIR/simplify-arm-identity.rs:19:18: 19:19
-          scope 2 {
-          }
-          scope 3 {
-              debug x => _4;               // in scope 3 at $DIR/simplify-arm-identity.rs:19:18: 19:19
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/simplify-arm-identity.rs:17:9: 17:10
-          ((_1 as Foo).0: u8) = const 0u8; // scope 0 at $DIR/simplify-arm-identity.rs:17:18: 17:29
-                                           // ty::Const
-                                           // + ty: u8
-                                           // + val: Value(Scalar(0x00))
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-arm-identity.rs:17:27: 17:28
-                                           // + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
-          discriminant(_1) = 0;            // scope 0 at $DIR/simplify-arm-identity.rs:17:18: 17:29
-          StorageLive(_2);                 // scope 1 at $DIR/simplify-arm-identity.rs:18:18: 21:6
-          _3 = discriminant(_1);           // scope 1 at $DIR/simplify-arm-identity.rs:19:9: 19:20
-          switchInt(move _3) -> [0isize: bb3, 1isize: bb1, otherwise: bb2]; // scope 1 at $DIR/simplify-arm-identity.rs:19:9: 19:20
-      }
-  
-      bb1: {
-          _2 = const Dst::Foo(0u8);        // bb1[0]: scope 1 at $DIR/simplify-arm-identity.rs:20:21: 20:32
-                                           // ty::Const
-                                           // + ty: Dst
-                                           // + val: Value(Scalar(0x00))
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-arm-identity.rs:20:21: 20:32
-                                           // + literal: Const { ty: Dst, val: Value(Scalar(0x00)) }
-          goto -> bb4;                     // bb1[1]: scope 1 at $DIR/simplify-arm-identity.rs:18:18: 21:6
-      }
-  
-      bb2: {
-          unreachable;                     // scope 1 at $DIR/simplify-arm-identity.rs:18:24: 18:25
-      }
-  
-      bb3: {
-          _4 = ((_1 as Foo).0: u8);        // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 19:19
-          ((_2 as Foo).0: u8) = move _4;   // scope 3 at $DIR/simplify-arm-identity.rs:19:24: 19:35
-          discriminant(_2) = 0;            // scope 3 at $DIR/simplify-arm-identity.rs:19:24: 19:35
-          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:18:18: 21:6
-      }
-  
-      bb4: {
-          StorageDead(_2);                 // scope 1 at $DIR/simplify-arm-identity.rs:21:6: 21:7
-          _0 = const ();                   // scope 0 at $DIR/simplify-arm-identity.rs:16:11: 22:2
-                                           // ty::Const
-                                           // + ty: ()
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/simplify-arm-identity.rs:16:11: 22:2
-                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
-          StorageDead(_1);                 // scope 0 at $DIR/simplify-arm-identity.rs:22:1: 22:2
-          return;                          // scope 0 at $DIR/simplify-arm-identity.rs:22:2: 22:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify-arm.rs
index 0e3f86501bb..20b4e67f53b 100644
--- a/src/test/mir-opt/simplify-arm.rs
+++ b/src/test/mir-opt/simplify-arm.rs
@@ -1,10 +1,10 @@
 // compile-flags: -Z mir-opt-level=1
-// EMIT_MIR rustc.id.SimplifyArmIdentity.diff
-// EMIT_MIR rustc.id.SimplifyBranchSame.diff
-// EMIT_MIR rustc.id_result.SimplifyArmIdentity.diff
-// EMIT_MIR rustc.id_result.SimplifyBranchSame.diff
-// EMIT_MIR rustc.id_try.SimplifyArmIdentity.diff
-// EMIT_MIR rustc.id_try.SimplifyBranchSame.diff
+// EMIT_MIR simplify_arm.id.SimplifyArmIdentity.diff
+// EMIT_MIR simplify_arm.id.SimplifyBranchSame.diff
+// EMIT_MIR simplify_arm.id_result.SimplifyArmIdentity.diff
+// EMIT_MIR simplify_arm.id_result.SimplifyBranchSame.diff
+// EMIT_MIR simplify_arm.id_try.SimplifyArmIdentity.diff
+// EMIT_MIR simplify_arm.id_try.SimplifyBranchSame.diff
 
 fn id(o: Option<u8>) -> Option<u8> {
     match o {
diff --git a/src/test/mir-opt/simplify-locals-fixedpoint.rs b/src/test/mir-opt/simplify-locals-fixedpoint.rs
index aa5bc345359..78b1f9f55e5 100644
--- a/src/test/mir-opt/simplify-locals-fixedpoint.rs
+++ b/src/test/mir-opt/simplify-locals-fixedpoint.rs
@@ -12,4 +12,4 @@ fn main() {
     foo::<()>();
 }
 
-// EMIT_MIR rustc.foo.SimplifyLocals.diff
+// EMIT_MIR simplify_locals_fixedpoint.foo.SimplifyLocals.diff
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs
index 48cee3c30d2..17999454472 100644
--- a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs
+++ b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs
@@ -8,7 +8,7 @@ struct Temp {
 
 fn use_u8(_: u8) {}
 
-// EMIT_MIR rustc.main.SimplifyLocals.diff
+// EMIT_MIR simplify_locals_removes_unused_consts.main.SimplifyLocals.diff
 fn main() {
     let ((), ()) = ((), ());
     use_zst(((), ()));
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs
index 7047b542aa6..cf8940ec330 100644
--- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs
+++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs
@@ -10,4 +10,4 @@ fn main() {
 }
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.map.SimplifyLocals.diff
+// EMIT_MIR simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff
diff --git a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff
index 0cddcb061cf..0cddcb061cf 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff
diff --git a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
index cd5962c682a..cd5962c682a 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
diff --git a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff
index 642ccc1ab14..642ccc1ab14 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff
diff --git a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff
index 95ce09a39ed..95ce09a39ed 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff
diff --git a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
index b46ca21fb90..b46ca21fb90 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
diff --git a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
index 93412d1a74f..93412d1a74f 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
diff --git a/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit
index 0de80f72a1e..0de80f72a1e 100644
--- a/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit
diff --git a/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit
index 4fa0aff8fa0..4fa0aff8fa0 100644
--- a/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit
diff --git a/src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-early-opt.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
index 3b472ed3a03..3b472ed3a03 100644
--- a/src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-early-opt.diff
+++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
diff --git a/src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-initial.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
index 1ba05b1cb38..1ba05b1cb38 100644
--- a/src/test/mir-opt/simplify_cfg/rustc.main.SimplifyCfg-initial.diff
+++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
diff --git a/src/test/mir-opt/simplify_cfg.rs b/src/test/mir-opt/simplify_cfg.rs
index 8d588a39d65..c464005c448 100644
--- a/src/test/mir-opt/simplify_cfg.rs
+++ b/src/test/mir-opt/simplify_cfg.rs
@@ -1,7 +1,7 @@
 // Test that the goto chain starting from bb0 is collapsed.
 
-// EMIT_MIR rustc.main.SimplifyCfg-initial.diff
-// EMIT_MIR rustc.main.SimplifyCfg-early-opt.diff
+// EMIT_MIR simplify_cfg.main.SimplifyCfg-initial.diff
+// EMIT_MIR simplify_cfg.main.SimplifyCfg-early-opt.diff
 fn main() {
     loop {
         if bar() {
diff --git a/src/test/mir-opt/simplify_if/rustc.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff
index e94e49bf0cb..e94e49bf0cb 100644
--- a/src/test/mir-opt/simplify_if/rustc.main.SimplifyBranches-after-const-prop.diff
+++ b/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff
diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs
index e2d3ebe69c4..67b2027b710 100644
--- a/src/test/mir-opt/simplify_if.rs
+++ b/src/test/mir-opt/simplify_if.rs
@@ -1,7 +1,7 @@
 #[inline(never)]
 fn noop() {}
 
-// EMIT_MIR rustc.main.SimplifyBranches-after-const-prop.diff
+// EMIT_MIR simplify_if.main.SimplifyBranches-after-const-prop.diff
 fn main() {
     if false {
         noop();
diff --git a/src/test/mir-opt/simplify-locals-fixedpoint/rustc.foo.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
index 720296a2c66..720296a2c66 100644
--- a/src/test/mir-opt/simplify-locals-fixedpoint/rustc.foo.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff
index db06b0392df..db06b0392df 100644
--- a/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit
index 440c5f8772e..440c5f8772e 100644
--- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit
index c12d1715b48..c12d1715b48 100644
--- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit
diff --git a/src/test/mir-opt/simplify_match/rustc.main.ConstProp.diff b/src/test/mir-opt/simplify_match.main.ConstProp.diff
index 8003112c46c..8003112c46c 100644
--- a/src/test/mir-opt/simplify_match/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/simplify_match.main.ConstProp.diff
diff --git a/src/test/mir-opt/simplify_match.rs b/src/test/mir-opt/simplify_match.rs
index b8e1ea6f981..216203f9ff0 100644
--- a/src/test/mir-opt/simplify_match.rs
+++ b/src/test/mir-opt/simplify_match.rs
@@ -1,7 +1,7 @@
 #[inline(never)]
 fn noop() {}
 
-// EMIT_MIR rustc.main.ConstProp.diff
+// EMIT_MIR simplify_match.main.ConstProp.diff
 fn main() {
     match { let x = false; x } {
         true => noop(),
diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs
index 88a0451a76f..fa127de13df 100644
--- a/src/test/mir-opt/simplify_try.rs
+++ b/src/test/mir-opt/simplify_try.rs
@@ -1,6 +1,6 @@
-// EMIT_MIR rustc.try_identity.SimplifyArmIdentity.diff
-// EMIT_MIR rustc.try_identity.SimplifyBranchSame.after.mir
-// EMIT_MIR rustc.try_identity.SimplifyLocals.after.mir
+// EMIT_MIR simplify_try.try_identity.SimplifyArmIdentity.diff
+// EMIT_MIR simplify_try.try_identity.SimplifyBranchSame.after.mir
+// EMIT_MIR simplify_try.try_identity.SimplifyLocals.after.mir
 
 fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
     let y = x?;
diff --git a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
index 26ce290b549..26ce290b549 100644
--- a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
diff --git a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyBranchSame.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
index dc4aae176f2..dc4aae176f2 100644
--- a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyBranchSame.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
diff --git a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyLocals.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
index d65a2b12c0f..d65a2b12c0f 100644
--- a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
diff --git a/src/test/mir-opt/simplify_try_if_let.rs b/src/test/mir-opt/simplify_try_if_let.rs
index daa961c3c8c..b37db738421 100644
--- a/src/test/mir-opt/simplify_try_if_let.rs
+++ b/src/test/mir-opt/simplify_try_if_let.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Zmir-opt-level=1
-// EMIT_MIR rustc.{{impl}}-append.SimplifyArmIdentity.diff
+// EMIT_MIR simplify_try_if_let.{{impl}}-append.SimplifyArmIdentity.diff
 
 use std::ptr::NonNull;
 
diff --git a/src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try_if_let.{{impl}}-append.SimplifyArmIdentity.diff
index 4471f4d206c..4471f4d206c 100644
--- a/src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_try_if_let.{{impl}}-append.SimplifyArmIdentity.diff
diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs
index 5d8d37e0bc5..3b98b8474e5 100644
--- a/src/test/mir-opt/slice-drop-shim.rs
+++ b/src/test/mir-opt/slice-drop-shim.rs
@@ -1,7 +1,7 @@
 // compile-flags: -Zmir-opt-level=0
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
-// EMIT_MIR rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
+// EMIT_MIR core.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
 fn main() {
     let _fn = std::ptr::drop_in_place::<[String]> as unsafe fn(_);
 }
diff --git a/src/test/mir-opt/slice-drop-shim/32bit/rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir.32bit
index b3ee08c3e03..b3ee08c3e03 100644
--- a/src/test/mir-opt/slice-drop-shim/32bit/rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
+++ b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir.32bit
diff --git a/src/test/mir-opt/slice-drop-shim/64bit/rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir.64bit
index ea22af65dda..ea22af65dda 100644
--- a/src/test/mir-opt/slice-drop-shim/64bit/rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
+++ b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir.64bit
diff --git a/src/test/mir-opt/storage_live_dead_in_statics/rustc.XXX.mir_map.0.mir b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir
index d7f73a22c26..d7f73a22c26 100644
--- a/src/test/mir-opt/storage_live_dead_in_statics/rustc.XXX.mir_map.0.mir
+++ b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir
diff --git a/src/test/mir-opt/storage_live_dead_in_statics.rs b/src/test/mir-opt/storage_live_dead_in_statics.rs
index a269914f262..b03de8612fc 100644
--- a/src/test/mir-opt/storage_live_dead_in_statics.rs
+++ b/src/test/mir-opt/storage_live_dead_in_statics.rs
@@ -1,7 +1,7 @@
 // Check that when we compile the static `XXX` into MIR, we do not
 // generate `StorageStart` or `StorageEnd` statements.
 
-// EMIT_MIR rustc.XXX.mir_map.0.mir
+// EMIT_MIR storage_live_dead_in_statics.XXX.mir_map.0.mir
 static XXX: &'static Foo = &Foo {
     tup: "hi",
     data: &[
diff --git a/src/test/mir-opt/storage_ranges/rustc.main.nll.0.mir b/src/test/mir-opt/storage_ranges.main.nll.0.mir
index 099535c0ad2..099535c0ad2 100644
--- a/src/test/mir-opt/storage_ranges/rustc.main.nll.0.mir
+++ b/src/test/mir-opt/storage_ranges.main.nll.0.mir
diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs
index 7b3c77aca27..996051a2941 100644
--- a/src/test/mir-opt/storage_ranges.rs
+++ b/src/test/mir-opt/storage_ranges.rs
@@ -1,4 +1,4 @@
-// EMIT_MIR rustc.main.nll.0.mir
+// EMIT_MIR storage_ranges.main.nll.0.mir
 
 fn main() {
     let a = 0;
diff --git a/src/test/mir-opt/tls-access.rs b/src/test/mir-opt/tls-access.rs
index 4f3f6b1b3ac..b585fd0c808 100644
--- a/src/test/mir-opt/tls-access.rs
+++ b/src/test/mir-opt/tls-access.rs
@@ -10,4 +10,4 @@ fn main() {
     }
 }
 
-// EMIT_MIR rustc.main.SimplifyCfg-final.after.mir
+// EMIT_MIR tls_access.main.SimplifyCfg-final.after.mir
diff --git a/src/test/mir-opt/tls-access/rustc.main.SimplifyCfg-final.after.mir b/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir
index 5ceca2d091e..5ceca2d091e 100644
--- a/src/test/mir-opt/tls-access/rustc.main.SimplifyCfg-final.after.mir
+++ b/src/test/mir-opt/tls_access.main.SimplifyCfg-final.after.mir
diff --git a/src/test/mir-opt/uniform_array_move_out/rustc.move_out_by_subslice.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir
index eb40baa2000..eb40baa2000 100644
--- a/src/test/mir-opt/uniform_array_move_out/rustc.move_out_by_subslice.mir_map.0.mir
+++ b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir
diff --git a/src/test/mir-opt/uniform_array_move_out/rustc.move_out_from_end.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir
index 7beceb66577..7beceb66577 100644
--- a/src/test/mir-opt/uniform_array_move_out/rustc.move_out_from_end.mir_map.0.mir
+++ b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir
diff --git a/src/test/mir-opt/uniform_array_move_out.rs b/src/test/mir-opt/uniform_array_move_out.rs
index c1b7ebdbc3a..35e42552870 100644
--- a/src/test/mir-opt/uniform_array_move_out.rs
+++ b/src/test/mir-opt/uniform_array_move_out.rs
@@ -1,12 +1,12 @@
 #![feature(box_syntax)]
 
-// EMIT_MIR rustc.move_out_from_end.mir_map.0.mir
+// EMIT_MIR uniform_array_move_out.move_out_from_end.mir_map.0.mir
 fn move_out_from_end() {
     let a = [box 1, box 2];
     let [.., _y] = a;
 }
 
-// EMIT_MIR rustc.move_out_by_subslice.mir_map.0.mir
+// EMIT_MIR uniform_array_move_out.move_out_by_subslice.mir_map.0.mir
 fn move_out_by_subslice() {
     let a = [box 1, box 2];
     let [_y @ ..] = a;
diff --git a/src/test/mir-opt/uninhabited-enum.rs b/src/test/mir-opt/uninhabited-enum.rs
index 6503e193608..97c6e8cd531 100644
--- a/src/test/mir-opt/uninhabited-enum.rs
+++ b/src/test/mir-opt/uninhabited-enum.rs
@@ -2,13 +2,13 @@
 
 pub enum Void {}
 
-// EMIT_MIR rustc.process_never.SimplifyLocals.after.mir
+// EMIT_MIR uninhabited_enum.process_never.SimplifyLocals.after.mir
 #[no_mangle]
 pub fn process_never(input: *const !) {
    let _input = unsafe { &*input };
 }
 
-// EMIT_MIR rustc.process_void.SimplifyLocals.after.mir
+// EMIT_MIR uninhabited_enum.process_void.SimplifyLocals.after.mir
 #[no_mangle]
 pub fn process_void(input: *const Void) {
    let _input = unsafe { &*input };
diff --git a/src/test/mir-opt/uninhabited-enum/rustc.process_never.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir
index c17fe3bb757..c17fe3bb757 100644
--- a/src/test/mir-opt/uninhabited-enum/rustc.process_never.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir
diff --git a/src/test/mir-opt/uninhabited-enum/rustc.process_void.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir
index 8cfcd64a70f..8cfcd64a70f 100644
--- a/src/test/mir-opt/uninhabited-enum/rustc.process_void.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir
diff --git a/src/test/mir-opt/uninhabited_enum_branching/rustc.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
index 4f4fb7defc3..4f4fb7defc3 100644
--- a/src/test/mir-opt/uninhabited_enum_branching/rustc.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
+++ b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
diff --git a/src/test/mir-opt/uninhabited_enum_branching/rustc.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
index d262c9432ca..d262c9432ca 100644
--- a/src/test/mir-opt/uninhabited_enum_branching/rustc.main.UninhabitedEnumBranching.diff
+++ b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
diff --git a/src/test/mir-opt/uninhabited_enum_branching.rs b/src/test/mir-opt/uninhabited_enum_branching.rs
index daf1156d20e..0ef604c3088 100644
--- a/src/test/mir-opt/uninhabited_enum_branching.rs
+++ b/src/test/mir-opt/uninhabited_enum_branching.rs
@@ -14,8 +14,8 @@ enum Test2 {
     E = 5,
 }
 
-// EMIT_MIR rustc.main.UninhabitedEnumBranching.diff
-// EMIT_MIR rustc.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
+// EMIT_MIR uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
+// EMIT_MIR uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
 fn main() {
     match Test1::C {
         Test1::A(_) => "A(Empty)",
diff --git a/src/test/mir-opt/unreachable/rustc.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
index e7abf578800..e7abf578800 100644
--- a/src/test/mir-opt/unreachable/rustc.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
diff --git a/src/test/mir-opt/unreachable.rs b/src/test/mir-opt/unreachable.rs
index 6f0c4ca3cf5..6098b525b55 100644
--- a/src/test/mir-opt/unreachable.rs
+++ b/src/test/mir-opt/unreachable.rs
@@ -4,7 +4,7 @@ fn empty() -> Option<Empty> {
     None
 }
 
-// EMIT_MIR rustc.main.UnreachablePropagation.diff
+// EMIT_MIR unreachable.main.UnreachablePropagation.diff
 fn main() {
     if let Some(_x) = empty() {
         let mut _y;
diff --git a/src/test/mir-opt/unreachable_asm/rustc.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff
index 50694900024..50694900024 100644
--- a/src/test/mir-opt/unreachable_asm/rustc.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff
diff --git a/src/test/mir-opt/unreachable_asm.rs b/src/test/mir-opt/unreachable_asm.rs
index 4bbf22b8227..cbef05a3c05 100644
--- a/src/test/mir-opt/unreachable_asm.rs
+++ b/src/test/mir-opt/unreachable_asm.rs
@@ -6,7 +6,7 @@ fn empty() -> Option<Empty> {
     None
 }
 
-// EMIT_MIR rustc.main.UnreachablePropagation.diff
+// EMIT_MIR unreachable_asm.main.UnreachablePropagation.diff
 fn main() {
     if let Some(_x) = empty() {
         let mut _y;
diff --git a/src/test/mir-opt/unreachable_asm_2/rustc.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff
index 9be05aefcf6..9be05aefcf6 100644
--- a/src/test/mir-opt/unreachable_asm_2/rustc.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff
diff --git a/src/test/mir-opt/unreachable_asm_2.rs b/src/test/mir-opt/unreachable_asm_2.rs
index f1610db999e..e0d8e725147 100644
--- a/src/test/mir-opt/unreachable_asm_2.rs
+++ b/src/test/mir-opt/unreachable_asm_2.rs
@@ -6,7 +6,7 @@ fn empty() -> Option<Empty> {
     None
 }
 
-// EMIT_MIR rustc.main.UnreachablePropagation.diff
+// EMIT_MIR unreachable_asm_2.main.UnreachablePropagation.diff
 fn main() {
     if let Some(_x) = empty() {
         let mut _y;
diff --git a/src/test/mir-opt/unreachable_diverging/rustc.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
index e7886f683c0..e7886f683c0 100644
--- a/src/test/mir-opt/unreachable_diverging/rustc.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
diff --git a/src/test/mir-opt/unreachable_diverging.rs b/src/test/mir-opt/unreachable_diverging.rs
index 53c753f717b..bbf28efc7dd 100644
--- a/src/test/mir-opt/unreachable_diverging.rs
+++ b/src/test/mir-opt/unreachable_diverging.rs
@@ -8,7 +8,7 @@ fn loop_forever() {
     loop {}
 }
 
-// EMIT_MIR rustc.main.UnreachablePropagation.diff
+// EMIT_MIR unreachable_diverging.main.UnreachablePropagation.diff
 fn main() {
     let x = true;
     if let Some(bomb) = empty() {
diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs
index ffe8ca01dfb..249a851af25 100644
--- a/src/test/mir-opt/unusual-item-types.rs
+++ b/src/test/mir-opt/unusual-item-types.rs
@@ -5,25 +5,25 @@
 
 struct A;
 
-// EMIT_MIR rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir
+// EMIT_MIR unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir
 impl A {
     const ASSOCIATED_CONSTANT: i32 = 2;
 }
 
 // See #59021
-// EMIT_MIR rustc.Test-X-{{constructor}}.mir_map.0.mir
+// EMIT_MIR unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir
 enum Test {
     X(usize),
     Y { a: usize },
 }
 
-// EMIT_MIR rustc.E-V-{{constant}}.mir_map.0.mir
+// EMIT_MIR unusual_item_types.E-V-{{constant}}.mir_map.0.mir
 enum E {
     V = 5,
 }
 
 fn main() {
     let f = Test::X as fn(usize) -> Test;
-// EMIT_MIR rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
+// EMIT_MIR core.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
     let v = Vec::<i32>::new();
 }
diff --git a/src/test/mir-opt/unusual-item-types/32bit/rustc.E-V-{{constant}}.mir_map.0.mir b/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.32bit
index 7f0266d6589..7f0266d6589 100644
--- a/src/test/mir-opt/unusual-item-types/32bit/rustc.E-V-{{constant}}.mir_map.0.mir
+++ b/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.32bit
diff --git a/src/test/mir-opt/unusual-item-types/64bit/rustc.E-V-{{constant}}.mir_map.0.mir b/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.64bit
index f2c1e9c97dd..f2c1e9c97dd 100644
--- a/src/test/mir-opt/unusual-item-types/64bit/rustc.E-V-{{constant}}.mir_map.0.mir
+++ b/src/test/mir-opt/unusual_item_types.E-V-{{constant}}.mir_map.0.mir.64bit
diff --git a/src/test/mir-opt/unusual-item-types/32bit/rustc.Test-X-{{constructor}}.mir_map.0.mir b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.32bit
index 832f18e14c2..832f18e14c2 100644
--- a/src/test/mir-opt/unusual-item-types/32bit/rustc.Test-X-{{constructor}}.mir_map.0.mir
+++ b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.32bit
diff --git a/src/test/mir-opt/unusual-item-types/64bit/rustc.Test-X-{{constructor}}.mir_map.0.mir b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.64bit
index 832f18e14c2..832f18e14c2 100644
--- a/src/test/mir-opt/unusual-item-types/64bit/rustc.Test-X-{{constructor}}.mir_map.0.mir
+++ b/src/test/mir-opt/unusual_item_types.Test-X-{{constructor}}.mir_map.0.mir.64bit
diff --git a/src/test/mir-opt/unusual-item-types/32bit/rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir.32bit
index 321f13b4927..321f13b4927 100644
--- a/src/test/mir-opt/unusual-item-types/32bit/rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
+++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir.32bit
diff --git a/src/test/mir-opt/unusual-item-types/64bit/rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir.64bit
index 321f13b4927..321f13b4927 100644
--- a/src/test/mir-opt/unusual-item-types/64bit/rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
+++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir.64bit
diff --git a/src/test/mir-opt/unusual-item-types/32bit/rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir b/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.32bit
index 4af856c654e..4af856c654e 100644
--- a/src/test/mir-opt/unusual-item-types/32bit/rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir
+++ b/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.32bit
diff --git a/src/test/mir-opt/unusual-item-types/64bit/rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir b/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.64bit
index 4af856c654e..4af856c654e 100644
--- a/src/test/mir-opt/unusual-item-types/64bit/rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir
+++ b/src/test/mir-opt/unusual_item_types.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir.64bit
diff --git a/src/test/mir-opt/while-storage.rs b/src/test/mir-opt/while-storage.rs
index 56f6c3380a7..afd083acb34 100644
--- a/src/test/mir-opt/while-storage.rs
+++ b/src/test/mir-opt/while-storage.rs
@@ -5,7 +5,7 @@ fn get_bool(c: bool) -> bool {
     c
 }
 
-// EMIT_MIR rustc.while_loop.PreCodegen.after.mir
+// EMIT_MIR while_storage.while_loop.PreCodegen.after.mir
 fn while_loop(c: bool) {
     while get_bool(c) {
         if get_bool(c) {
diff --git a/src/test/mir-opt/while-storage/rustc.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
index 3ddf82c2fb2..3ddf82c2fb2 100644
--- a/src/test/mir-opt/while-storage/rustc.while_loop.PreCodegen.after.mir
+++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
diff --git a/src/test/pretty/block-comment-wchar.pp b/src/test/pretty/block-comment-wchar.pp
index 9317b36ba49..2bfcdd75e15 100644
--- a/src/test/pretty/block-comment-wchar.pp
+++ b/src/test/pretty/block-comment-wchar.pp
@@ -73,7 +73,6 @@ fn f() {
     */
 
 
-
     /* */
 
     /*
@@ -81,7 +80,6 @@ fn f() {
       Space 6+2:                     compare A
       Ogham Space Mark 6+2: compare B
     */
-
     /* */
 
     /*
diff --git a/src/test/pretty/issue-74745.rs b/src/test/pretty/issue-74745.rs
new file mode 100644
index 00000000000..e255cd6caa8
--- /dev/null
+++ b/src/test/pretty/issue-74745.rs
@@ -0,0 +1,5 @@
+// ignore-tidy-trailing-newlines
+// pretty-compare-only
+
+/*
+*/
\ No newline at end of file
diff --git a/src/test/run-make-fulldeps/exit-code/lint-failure.rs b/src/test/run-make-fulldeps/exit-code/lint-failure.rs
index 70bdddc6246..df876ec237f 100644
--- a/src/test/run-make-fulldeps/exit-code/lint-failure.rs
+++ b/src/test/run-make-fulldeps/exit-code/lint-failure.rs
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 /// [intradoc::failure]
 pub fn main() {
diff --git a/src/test/run-make-fulldeps/mingw-export-call-convention/Makefile b/src/test/run-make-fulldeps/mingw-export-call-convention/Makefile
new file mode 100644
index 00000000000..4a60059cc54
--- /dev/null
+++ b/src/test/run-make-fulldeps/mingw-export-call-convention/Makefile
@@ -0,0 +1,9 @@
+include ../tools.mk
+
+# only-windows-gnu
+
+all:
+	$(RUSTC) foo.rs
+	# FIXME: we should make sure __stdcall calling convention is used here
+	# but that only works with LLD right now
+	nm -g "$(call IMPLIB,foo)" | $(CGREP) bar
diff --git a/src/test/run-make-fulldeps/mingw-export-call-convention/foo.rs b/src/test/run-make-fulldeps/mingw-export-call-convention/foo.rs
new file mode 100644
index 00000000000..1fec00311ef
--- /dev/null
+++ b/src/test/run-make-fulldeps/mingw-export-call-convention/foo.rs
@@ -0,0 +1,4 @@
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+pub extern "system" fn bar() {}
diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk
index 8b885f1dc6d..f9b6d342295 100644
--- a/src/test/run-make-fulldeps/tools.mk
+++ b/src/test/run-make-fulldeps/tools.mk
@@ -51,6 +51,7 @@ ifdef IS_MSVC
 STATICLIB = $(TMPDIR)/$(1).lib
 STATICLIB_GLOB = $(1)*.lib
 else
+IMPLIB = $(TMPDIR)/lib$(1).dll.a
 STATICLIB = $(TMPDIR)/lib$(1).a
 STATICLIB_GLOB = lib$(1)*.a
 endif
diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs
index 9e64e6eb399..54e7689f316 100644
--- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs
+++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.rs
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 /// [v2] //~ ERROR
 pub fn foo() {}
diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
index 894518faa31..7530e3ad0f5 100644
--- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
+++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
@@ -7,8 +7,8 @@ LL | /// [v2]
 note: the lint level is defined here
   --> $DIR/deny-intra-link-resolution-failure.rs:1:9
    |
-LL | #![deny(intra_doc_link_resolution_failure)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.rs b/src/test/rustdoc-ui/intra-doc-alias-ice.rs
index 9657d573d50..c053e378e71 100644
--- a/src/test/rustdoc-ui/intra-doc-alias-ice.rs
+++ b/src/test/rustdoc-ui/intra-doc-alias-ice.rs
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 pub type TypeAlias = usize;
 
diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr
index d2b2b90a4e5..f1c07e31cd7 100644
--- a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr
+++ b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr
@@ -7,8 +7,8 @@ LL | /// [broken cross-reference](TypeAlias::hoge)
 note: the lint level is defined here
   --> $DIR/intra-doc-alias-ice.rs:1:9
    |
-LL | #![deny(intra_doc_link_resolution_failure)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.rs b/src/test/rustdoc-ui/intra-link-span-ice-55723.rs
index 95388003f84..7764a6df6ee 100644
--- a/src/test/rustdoc-ui/intra-link-span-ice-55723.rs
+++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.rs
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 // An error in calculating spans while reporting intra-doc link resolution errors caused rustdoc to
 // attempt to slice in the middle of a multibyte character. See
diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
index 156e214a79f..6b0ff8f1162 100644
--- a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
+++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
@@ -7,8 +7,8 @@ LL | /// (arr[i])
 note: the lint level is defined here
   --> $DIR/intra-link-span-ice-55723.rs:1:9
    |
-LL | #![deny(intra_doc_link_resolution_failure)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/intra-links-ambiguity.rs b/src/test/rustdoc-ui/intra-links-ambiguity.rs
index 7316fcdad67..d1597cdca66 100644
--- a/src/test/rustdoc-ui/intra-links-ambiguity.rs
+++ b/src/test/rustdoc-ui/intra-links-ambiguity.rs
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 #![allow(non_camel_case_types)]
 #![allow(non_upper_case_globals)]
 
diff --git a/src/test/rustdoc-ui/intra-links-ambiguity.stderr b/src/test/rustdoc-ui/intra-links-ambiguity.stderr
index 7b9821b3d04..35262c1b612 100644
--- a/src/test/rustdoc-ui/intra-links-ambiguity.stderr
+++ b/src/test/rustdoc-ui/intra-links-ambiguity.stderr
@@ -7,8 +7,8 @@ LL | /// [`ambiguous`] is ambiguous.
 note: the lint level is defined here
   --> $DIR/intra-links-ambiguity.rs:1:9
    |
-LL | #![deny(intra_doc_link_resolution_failure)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 help: to link to the struct, prefix with the item type
    |
 LL | /// [`struct@ambiguous`] is ambiguous.
diff --git a/src/test/rustdoc-ui/intra-links-anchors.rs b/src/test/rustdoc-ui/intra-links-anchors.rs
index 7e61bd72535..ccefd2e6fab 100644
--- a/src/test/rustdoc-ui/intra-links-anchors.rs
+++ b/src/test/rustdoc-ui/intra-links-anchors.rs
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 // A few tests on anchors.
 
diff --git a/src/test/rustdoc-ui/intra-links-anchors.stderr b/src/test/rustdoc-ui/intra-links-anchors.stderr
index ef33d8f3e06..e737b84320d 100644
--- a/src/test/rustdoc-ui/intra-links-anchors.stderr
+++ b/src/test/rustdoc-ui/intra-links-anchors.stderr
@@ -7,8 +7,8 @@ LL | /// Or maybe [Foo::f#hola].
 note: the lint level is defined here
   --> $DIR/intra-links-anchors.rs:1:9
    |
-LL | #![deny(intra_doc_link_resolution_failure)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: `hello#people#!` contains multiple anchors
   --> $DIR/intra-links-anchors.rs:31:28
diff --git a/src/test/rustdoc-ui/intra-links-private.private.stderr b/src/test/rustdoc-ui/intra-links-private.private.stderr
index a2148b82f81..77c4b67a652 100644
--- a/src/test/rustdoc-ui/intra-links-private.private.stderr
+++ b/src/test/rustdoc-ui/intra-links-private.private.stderr
@@ -4,7 +4,7 @@ warning: public documentation for `DocMe` links to private item `DontDocMe`
 LL | /// docs [DontDocMe]
    |           ^^^^^^^^^ this item is private
    |
-   = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: `#[warn(broken_intra_doc_links)]` on by default
    = note: this link resolves only because you passed `--document-private-items`, but will break without
 
 warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/intra-links-private.public.stderr b/src/test/rustdoc-ui/intra-links-private.public.stderr
index 56742406992..312a78e8c3e 100644
--- a/src/test/rustdoc-ui/intra-links-private.public.stderr
+++ b/src/test/rustdoc-ui/intra-links-private.public.stderr
@@ -4,7 +4,7 @@ warning: public documentation for `DocMe` links to private item `DontDocMe`
 LL | /// docs [DontDocMe]
    |           ^^^^^^^^^ this item is private
    |
-   = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: `#[warn(broken_intra_doc_links)]` on by default
    = note: this link will resolve properly if you pass `--document-private-items`
 
 warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr
index bc31264c170..1e3a26fadfa 100644
--- a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr
+++ b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr
@@ -4,7 +4,7 @@ warning: unresolved link to `error`
 LL | /// [error]
    |      ^^^^^ unresolved link
    |
-   = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: `#[warn(broken_intra_doc_links)]` on by default
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 warning: unresolved link to `error1`
diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr
index 81931399c24..53f2476295e 100644
--- a/src/test/rustdoc-ui/intra-links-warning.stderr
+++ b/src/test/rustdoc-ui/intra-links-warning.stderr
@@ -4,7 +4,7 @@ warning: unresolved link to `Foo::baz`
 LL |        //! Test with [Foo::baz], [Bar::foo], ...
    |                       ^^^^^^^^ unresolved link
    |
-   = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: `#[warn(broken_intra_doc_links)]` on by default
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 warning: unresolved link to `Bar::foo`
diff --git a/src/test/rustdoc-ui/issue-74134.private.stderr b/src/test/rustdoc-ui/issue-74134.private.stderr
index 9c5cdf0117c..58772109140 100644
--- a/src/test/rustdoc-ui/issue-74134.private.stderr
+++ b/src/test/rustdoc-ui/issue-74134.private.stderr
@@ -4,7 +4,7 @@ warning: public documentation for `public_item` links to private item `PrivateTy
 LL |     /// [`PrivateType`]
    |          ^^^^^^^^^^^^^ this item is private
    |
-   = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: `#[warn(broken_intra_doc_links)]` on by default
    = note: this link resolves only because you passed `--document-private-items`, but will break without
 
 warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/issue-74134.public.stderr b/src/test/rustdoc-ui/issue-74134.public.stderr
index ff2951d864e..b5bea190941 100644
--- a/src/test/rustdoc-ui/issue-74134.public.stderr
+++ b/src/test/rustdoc-ui/issue-74134.public.stderr
@@ -4,7 +4,7 @@ warning: public documentation for `public_item` links to private item `PrivateTy
 LL |     /// [`PrivateType`]
    |          ^^^^^^^^^^^^^ this item is private
    |
-   = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: `#[warn(broken_intra_doc_links)]` on by default
    = note: this link will resolve properly if you pass `--document-private-items`
 
 warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr
index ad923c714da..04296d2e44a 100644
--- a/src/test/rustdoc-ui/lint-group.stderr
+++ b/src/test/rustdoc-ui/lint-group.stderr
@@ -39,7 +39,7 @@ note: the lint level is defined here
    |
 LL | #![deny(rustdoc)]
    |         ^^^^^^^
-   = note: `#[deny(intra_doc_link_resolution_failure)]` implied by `#[deny(rustdoc)]`
+   = note: `#[deny(broken_intra_doc_links)]` implied by `#[deny(rustdoc)]`
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: aborting due to 3 previous errors
diff --git a/src/test/rustdoc-ui/reference-link-has-one-warning.stderr b/src/test/rustdoc-ui/reference-link-has-one-warning.stderr
index 5bbc62b76dd..a1eeb60f178 100644
--- a/src/test/rustdoc-ui/reference-link-has-one-warning.stderr
+++ b/src/test/rustdoc-ui/reference-link-has-one-warning.stderr
@@ -4,7 +4,7 @@ warning: `[with#anchor#error]` has an issue with the link anchor.
 LL | /// docs [label][with#anchor#error]
    |                  ^^^^^^^^^^^^^^^^^ only one `#` is allowed in a link
    |
-   = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: `#[warn(broken_intra_doc_links)]` on by default
 
 warning: 1 warning emitted
 
diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs
index 7361b22b747..03f5bb2ca43 100644
--- a/src/test/rustdoc/const-generics/const-impl.rs
+++ b/src/test/rustdoc/const-generics/const-impl.rs
@@ -11,8 +11,8 @@ pub enum Order {
 }
 
 // @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>'
-// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl<const ORDER: Order, T> Send for VSet<T, ORDER>'
-// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl<const ORDER: Order, T> Sync for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
 pub struct VSet<T, const ORDER: Order> {
     inner: Vec<T>,
 }
diff --git a/src/test/rustdoc/intra-doc-crate/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/additional_doc.rs
index adfa7f5754e..837390b3c71 100644
--- a/src/test/rustdoc/intra-doc-crate/additional_doc.rs
+++ b/src/test/rustdoc/intra-doc-crate/additional_doc.rs
@@ -1,6 +1,6 @@
 // aux-build:additional_doc.rs
 // build-aux-docs
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 extern crate my_rand;
 
diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs
index 8b8793e75ed..849d2568733 100644
--- a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs
+++ b/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs
@@ -1,5 +1,5 @@
 #![crate_name = "my_rand"]
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 pub trait RngCore {}
 /// Rng extends [`RngCore`].
diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/hidden.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/hidden.rs
index 23e38523a4f..b543ae764c0 100644
--- a/src/test/rustdoc/intra-doc-crate/auxiliary/hidden.rs
+++ b/src/test/rustdoc/intra-doc-crate/auxiliary/hidden.rs
@@ -1,5 +1,5 @@
 #![crate_name = "hidden_dep"]
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 #[doc(hidden)]
 pub mod __reexport {
diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs
index 2ee5835a7df..5342baecbc4 100644
--- a/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs
+++ b/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs
@@ -1,5 +1,5 @@
 #![crate_name = "a"]
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 pub struct Foo;
 
diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs
index abd41fec130..a94f9e5dcca 100644
--- a/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs
+++ b/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs
@@ -1,5 +1,5 @@
 #![crate_name = "macro_inner"]
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 pub struct Foo;
 
diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/module.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/module.rs
index 5d63d7e37b6..b7e3913f108 100644
--- a/src/test/rustdoc/intra-doc-crate/auxiliary/module.rs
+++ b/src/test/rustdoc/intra-doc-crate/auxiliary/module.rs
@@ -1,5 +1,5 @@
 #![crate_name = "module_inner"]
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 /// [SomeType] links to [bar]
 pub struct SomeType;
 pub trait SomeTrait {}
diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs
index 3a22d13e673..8ae0f6c16b3 100644
--- a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs
+++ b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs
@@ -1,5 +1,5 @@
 #![crate_name = "a"]
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 pub mod bar {
    pub struct Bar;
diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs
index b8ca4e44e1f..d90c529e385 100644
--- a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs
+++ b/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs
@@ -1,5 +1,5 @@
 #![crate_name = "bar"]
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 pub trait Foo {
     /// [`Bar`] [`Baz`]
diff --git a/src/test/rustdoc/intra-doc-crate/basic.rs b/src/test/rustdoc/intra-doc-crate/basic.rs
index a245a0f8453..6ab9140c3c3 100644
--- a/src/test/rustdoc/intra-doc-crate/basic.rs
+++ b/src/test/rustdoc/intra-doc-crate/basic.rs
@@ -1,6 +1,6 @@
 // aux-build:intra-doc-basic.rs
 // build-aux-docs
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 // from https://github.com/rust-lang/rust/issues/65983
 extern crate a;
diff --git a/src/test/rustdoc/intra-doc-crate/hidden.rs b/src/test/rustdoc/intra-doc-crate/hidden.rs
index e3d2af16db1..9c9d4c64945 100644
--- a/src/test/rustdoc/intra-doc-crate/hidden.rs
+++ b/src/test/rustdoc/intra-doc-crate/hidden.rs
@@ -1,6 +1,6 @@
 // aux-build:hidden.rs
 // build-aux-docs
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 // tests https://github.com/rust-lang/rust/issues/73363
 
diff --git a/src/test/rustdoc/intra-doc-crate/macro.rs b/src/test/rustdoc/intra-doc-crate/macro.rs
index 72fd57b6b0c..311b16dff13 100644
--- a/src/test/rustdoc/intra-doc-crate/macro.rs
+++ b/src/test/rustdoc/intra-doc-crate/macro.rs
@@ -2,7 +2,7 @@
 // aux-build:macro_inner.rs
 // aux-build:proc_macro.rs
 // build-aux-docs
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 extern crate macro_inner;
 extern crate proc_macro_inner;
 
diff --git a/src/test/rustdoc/intra-doc-crate/module.rs b/src/test/rustdoc/intra-doc-crate/module.rs
index 67fa7293f37..9039e344f7b 100644
--- a/src/test/rustdoc/intra-doc-crate/module.rs
+++ b/src/test/rustdoc/intra-doc-crate/module.rs
@@ -1,7 +1,7 @@
 // outer.rs
 // aux-build: module.rs
 // build-aux-docs
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 extern crate module_inner;
 // @has 'module/bar/index.html' '//a[@href="../../module_inner/trait.SomeTrait.html"]' 'SomeTrait'
 // @has 'module/bar/index.html' '//a[@href="../../module_inner/struct.SomeType.html"]' 'SomeType'
diff --git a/src/test/rustdoc/intra-doc-crate/submodule-inner.rs b/src/test/rustdoc/intra-doc-crate/submodule-inner.rs
index b4b615bf9ed..e1465816368 100644
--- a/src/test/rustdoc/intra-doc-crate/submodule-inner.rs
+++ b/src/test/rustdoc/intra-doc-crate/submodule-inner.rs
@@ -1,6 +1,6 @@
 // aux-build:submodule-inner.rs
 // build-aux-docs
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 extern crate a;
 
diff --git a/src/test/rustdoc/intra-doc-crate/submodule-outer.rs b/src/test/rustdoc/intra-doc-crate/submodule-outer.rs
index 6b30ef8b3de..45f561328f2 100644
--- a/src/test/rustdoc/intra-doc-crate/submodule-outer.rs
+++ b/src/test/rustdoc/intra-doc-crate/submodule-outer.rs
@@ -1,6 +1,6 @@
 // aux-build:submodule-outer.rs
 // edition:2018
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 extern crate bar as bar_;
 
diff --git a/src/test/rustdoc/intra-doc-crate/traits.rs b/src/test/rustdoc/intra-doc-crate/traits.rs
index 61733123690..07f9fb63313 100644
--- a/src/test/rustdoc/intra-doc-crate/traits.rs
+++ b/src/test/rustdoc/intra-doc-crate/traits.rs
@@ -3,7 +3,7 @@
 // aux-build:traits.rs
 // build-aux-docs
 // ignore-tidy-line-length
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 extern crate inner;
 use inner::SomeTrait;
diff --git a/src/test/rustdoc/intra-doc-link-mod-ambiguity.rs b/src/test/rustdoc/intra-doc-link-mod-ambiguity.rs
index 65187f48539..bd733e10230 100644
--- a/src/test/rustdoc/intra-doc-link-mod-ambiguity.rs
+++ b/src/test/rustdoc/intra-doc-link-mod-ambiguity.rs
@@ -1,6 +1,6 @@
 // ignore-tidy-linelength
 
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 
 pub fn foo() {
diff --git a/src/test/rustdoc/intra-link-extern-crate.rs b/src/test/rustdoc/intra-link-extern-crate.rs
index bbe3edaea8c..193bca704bf 100644
--- a/src/test/rustdoc/intra-link-extern-crate.rs
+++ b/src/test/rustdoc/intra-link-extern-crate.rs
@@ -4,6 +4,6 @@
 // though they would never actually get displayed. This tripped intra-doc-link resolution failures,
 // for items that aren't under our control, and not actually getting documented!
 
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 extern crate inner;
diff --git a/src/test/rustdoc/intra-link-in-bodies.rs b/src/test/rustdoc/intra-link-in-bodies.rs
index 4c693907226..ec965a99dc2 100644
--- a/src/test/rustdoc/intra-link-in-bodies.rs
+++ b/src/test/rustdoc/intra-link-in-bodies.rs
@@ -1,6 +1,6 @@
 // we need to make sure that intra-doc links on trait impls get resolved in the right scope
 
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 pub mod inner {
     pub struct SomethingOutOfScope;
diff --git a/src/test/rustdoc/intra-link-libstd-re-export.rs b/src/test/rustdoc/intra-link-libstd-re-export.rs
index 6f239292ec2..d0af3aec660 100644
--- a/src/test/rustdoc/intra-link-libstd-re-export.rs
+++ b/src/test/rustdoc/intra-link-libstd-re-export.rs
@@ -1,3 +1,3 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 pub use std::*;
diff --git a/src/test/rustdoc/intra-link-prim-methods-external-core.rs b/src/test/rustdoc/intra-link-prim-methods-external-core.rs
index e09d36594ed..c8ef4c01599 100644
--- a/src/test/rustdoc/intra-link-prim-methods-external-core.rs
+++ b/src/test/rustdoc/intra-link-prim-methods-external-core.rs
@@ -4,7 +4,7 @@
 // ignore-windows
 // ignore-tidy-linelength
 
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 #![feature(no_core, lang_items)]
 #![no_core]
 #![crate_type = "rlib"]
diff --git a/src/test/rustdoc/intra-link-prim-methods-local.rs b/src/test/rustdoc/intra-link-prim-methods-local.rs
index d24cd2cbb5e..d448acf7f96 100644
--- a/src/test/rustdoc/intra-link-prim-methods-local.rs
+++ b/src/test/rustdoc/intra-link-prim-methods-local.rs
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 #![feature(no_core, lang_items)]
 #![no_core]
 #![crate_type = "rlib"]
diff --git a/src/test/rustdoc/intra-link-prim-methods.rs b/src/test/rustdoc/intra-link-prim-methods.rs
index 76636b80b5e..94c80c996c1 100644
--- a/src/test/rustdoc/intra-link-prim-methods.rs
+++ b/src/test/rustdoc/intra-link-prim-methods.rs
@@ -1,4 +1,4 @@
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 // ignore-tidy-linelength
 
diff --git a/src/test/rustdoc/intra-link-prim-precedence.rs b/src/test/rustdoc/intra-link-prim-precedence.rs
index d7ebb73b3be..5f10c1ec4a7 100644
--- a/src/test/rustdoc/intra-link-prim-precedence.rs
+++ b/src/test/rustdoc/intra-link-prim-precedence.rs
@@ -1,5 +1,5 @@
 // ignore-tidy-linelength
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 pub mod char {}
 
diff --git a/src/test/rustdoc/intra-link-private.rs b/src/test/rustdoc/intra-link-private.rs
index c99b4d70684..cf8bc0b1586 100644
--- a/src/test/rustdoc/intra-link-private.rs
+++ b/src/test/rustdoc/intra-link-private.rs
@@ -2,7 +2,7 @@
 // These failures were legitimate, but not truly relevant - the docs in question couldn't be
 // checked for accuracy anyway.
 
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 /// ooh, i'm a [rebel] just for kicks
 struct SomeStruct;
diff --git a/src/test/rustdoc/intra-link-proc-macro.rs b/src/test/rustdoc/intra-link-proc-macro.rs
index 7b6ea5d60f8..7a8403255ed 100644
--- a/src/test/rustdoc/intra-link-proc-macro.rs
+++ b/src/test/rustdoc/intra-link-proc-macro.rs
@@ -1,6 +1,6 @@
 // aux-build:intra-link-proc-macro-macro.rs
 // build-aux-docs
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 extern crate intra_link_proc_macro_macro;
 
diff --git a/src/test/rustdoc/intra-links-external-traits.rs b/src/test/rustdoc/intra-links-external-traits.rs
index d6b4a8ad58a..de76f29476c 100644
--- a/src/test/rustdoc/intra-links-external-traits.rs
+++ b/src/test/rustdoc/intra-links-external-traits.rs
@@ -2,7 +2,7 @@
 // ignore-cross-compile
 
 #![crate_name = "outer"]
-#![deny(intra_doc_link_resolution_failure)]
+#![deny(broken_intra_doc_links)]
 
 // using a trait that has intra-doc links on it from another crate (whether re-exporting or just
 // implementing it) used to give spurious resolution failure warnings
diff --git a/src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs b/src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs
new file mode 100644
index 00000000000..6cc02f78c62
--- /dev/null
+++ b/src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs
@@ -0,0 +1,18 @@
+#![crate_name = "foo"]
+#![feature(lazy_normalization_consts)]
+#![allow(incomplete_features)]
+
+// Checking if `Send` is implemented for `Hasher` requires us to evaluate a `ConstEquate` predicate,
+// which previously caused an ICE.
+
+pub struct Hasher<T> {
+    cv_stack: T,
+}
+
+unsafe impl<T: Default> Send for Hasher<T> {}
+
+// @has foo/struct.Foo.html
+// @has - '//code' 'impl Send for Foo'
+pub struct Foo {
+    hasher: Hasher<[u8; 3]>,
+}
diff --git a/src/test/rustdoc/through-proc-macro.rs b/src/test/rustdoc/through-proc-macro.rs
index 348c9eea2dc..613410871f0 100644
--- a/src/test/rustdoc/through-proc-macro.rs
+++ b/src/test/rustdoc/through-proc-macro.rs
@@ -1,6 +1,6 @@
 // aux-build:through-proc-macro-aux.rs
 // build-aux-docs
-#![warn(intra_doc_link_resolution_failure)]
+#![warn(broken_intra_doc_links)]
 extern crate some_macros;
 
 #[some_macros::second]
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
index cd635c6a722..876d8b079a1 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
@@ -9,13 +9,13 @@
 #[cfg_attr(all(), deprecated, must_use)]
 struct MustUseDeprecated {}
 
-impl MustUseDeprecated { //~ warning: use of deprecated item
-    fn new() -> MustUseDeprecated { //~ warning: use of deprecated item
-        MustUseDeprecated {} //~ warning: use of deprecated item
+impl MustUseDeprecated { //~ warning: use of deprecated
+    fn new() -> MustUseDeprecated { //~ warning: use of deprecated
+        MustUseDeprecated {} //~ warning: use of deprecated
     }
 }
 
 fn main() {
-    MustUseDeprecated::new(); //~ warning: use of deprecated item
+    MustUseDeprecated::new(); //~ warning: use of deprecated
     //~| warning: unused `MustUseDeprecated` that must be used
 }
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr
index d7b5d2d263a..21b3a6f1f33 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr
@@ -1,4 +1,4 @@
-warning: use of deprecated item 'MustUseDeprecated'
+warning: use of deprecated struct `MustUseDeprecated`
   --> $DIR/cfg-attr-multi-true.rs:12:6
    |
 LL | impl MustUseDeprecated {
@@ -6,19 +6,19 @@ LL | impl MustUseDeprecated {
    |
    = note: `#[warn(deprecated)]` on by default
 
-warning: use of deprecated item 'MustUseDeprecated'
+warning: use of deprecated struct `MustUseDeprecated`
   --> $DIR/cfg-attr-multi-true.rs:19:5
    |
 LL |     MustUseDeprecated::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'MustUseDeprecated'
+warning: use of deprecated struct `MustUseDeprecated`
   --> $DIR/cfg-attr-multi-true.rs:13:17
    |
 LL |     fn new() -> MustUseDeprecated {
    |                 ^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'MustUseDeprecated'
+warning: use of deprecated struct `MustUseDeprecated`
   --> $DIR/cfg-attr-multi-true.rs:14:9
    |
 LL |         MustUseDeprecated {}
diff --git a/src/test/ui/const-generics/coerce_unsized_array.rs b/src/test/ui/const-generics/coerce_unsized_array.rs
new file mode 100644
index 00000000000..b28768a5163
--- /dev/null
+++ b/src/test/ui/const-generics/coerce_unsized_array.rs
@@ -0,0 +1,11 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+fn foo<const N: usize>(v: &[u8; N]) -> &[u8] {
+    v
+}
+
+fn main() {
+    assert_eq!(foo(&[1, 2]), &[1, 2]);
+}
diff --git a/src/test/ui/const-generics/nested-type.rs b/src/test/ui/const-generics/nested-type.rs
new file mode 100644
index 00000000000..12ea850c8f6
--- /dev/null
+++ b/src/test/ui/const-generics/nested-type.rs
@@ -0,0 +1,18 @@
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: [u8; {
+//~^ ERROR cycle detected
+//~| ERROR cycle detected
+    struct Foo<const N: usize>;
+
+    impl<const N: usize> Foo<N> {
+        fn value() -> usize {
+            N
+        }
+    }
+
+    Foo::<17>::value()
+}]>;
+
+fn main() {}
diff --git a/src/test/ui/const-generics/nested-type.stderr b/src/test/ui/const-generics/nested-type.stderr
new file mode 100644
index 00000000000..da0e8032404
--- /dev/null
+++ b/src/test/ui/const-generics/nested-type.stderr
@@ -0,0 +1,159 @@
+error[E0391]: cycle detected when computing type of `Foo`
+  --> $DIR/nested-type.rs:4:1
+   |
+LL | struct Foo<const N: [u8; {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of `Foo::N`...
+  --> $DIR/nested-type.rs:4:18
+   |
+LL | struct Foo<const N: [u8; {
+   |                  ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:4:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |     struct Foo<const N: usize>;
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:4:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |     struct Foo<const N: usize>;
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:4:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |     struct Foo<const N: usize>;
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:4:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |     struct Foo<const N: usize>;
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+  --> $DIR/nested-type.rs:7:5
+   |
+LL |     struct Foo<const N: usize>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing the variances for items in this crate...
+   = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/nested-type.rs:1:1
+   |
+LL | / #![feature(const_generics)]
+LL | | #![allow(incomplete_features)]
+LL | |
+LL | | struct Foo<const N: [u8; {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error[E0391]: cycle detected when computing type of `Foo`
+  --> $DIR/nested-type.rs:4:1
+   |
+LL | struct Foo<const N: [u8; {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of `Foo::N`...
+  --> $DIR/nested-type.rs:4:18
+   |
+LL | struct Foo<const N: [u8; {
+   |                  ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:4:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |     struct Foo<const N: usize>;
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:4:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |     struct Foo<const N: usize>;
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:4:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |     struct Foo<const N: usize>;
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:4:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |     struct Foo<const N: usize>;
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+  --> $DIR/nested-type.rs:7:5
+   |
+LL |     struct Foo<const N: usize>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing the variances for items in this crate...
+   = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/nested-type.rs:1:1
+   |
+LL | / #![feature(const_generics)]
+LL | | #![allow(incomplete_features)]
+LL | |
+LL | | struct Foo<const N: [u8; {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs
new file mode 100644
index 00000000000..96a8a8452ed
--- /dev/null
+++ b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs
@@ -0,0 +1,14 @@
+#![feature(extern_types)]
+#![feature(core_intrinsics)]
+#![feature(const_size_of_val, const_align_of_val)]
+
+use std::intrinsics::{size_of_val, min_align_of_val};
+
+extern {
+    type Opaque;
+}
+
+const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR
+const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR
+
+fn main() {}
diff --git a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
new file mode 100644
index 00000000000..d3f1b04d251
--- /dev/null
+++ b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
@@ -0,0 +1,20 @@
+error: any use of this value will cause an error
+  --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31
+   |
+LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
+   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                               |
+   |                               `extern type` does not have known layout
+   |
+   = note: `#[deny(const_err)]` on by default
+
+error: any use of this value will cause an error
+  --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32
+   |
+LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) };
+   | -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+   |                                |
+   |                                `extern type` does not have known layout
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/consts/const-size_of_val-align_of_val.rs b/src/test/ui/consts/const-size_of_val-align_of_val.rs
new file mode 100644
index 00000000000..e8e6f1d3900
--- /dev/null
+++ b/src/test/ui/consts/const-size_of_val-align_of_val.rs
@@ -0,0 +1,45 @@
+// run-pass
+
+#![feature(const_size_of_val, const_align_of_val)]
+
+use std::mem;
+
+struct Foo(u32);
+
+#[derive(Clone, Copy)]
+struct Bar {
+    _x: u8,
+    _y: u16,
+    _z: u8,
+}
+
+union Ugh {
+    _a: [u8; 3],
+    _b: Bar,
+}
+
+const FOO: Foo = Foo(4);
+const BAR: Bar = Bar { _x: 4, _y: 1, _z: 2 };
+const UGH: Ugh = Ugh { _a: [0; 3] };
+
+const SIZE_OF_FOO: usize = mem::size_of_val(&FOO);
+const SIZE_OF_BAR: usize = mem::size_of_val(&BAR);
+const SIZE_OF_UGH: usize = mem::size_of_val(&UGH);
+
+const ALIGN_OF_FOO: usize = mem::align_of_val(&FOO);
+const ALIGN_OF_BAR: usize = mem::align_of_val(&BAR);
+const ALIGN_OF_UGH: usize = mem::align_of_val(&UGH);
+
+const SIZE_OF_SLICE: usize = mem::size_of_val("foobar".as_bytes());
+
+fn main() {
+    assert_eq!(SIZE_OF_FOO, mem::size_of::<Foo>());
+    assert_eq!(SIZE_OF_BAR, mem::size_of::<Bar>());
+    assert_eq!(SIZE_OF_UGH, mem::size_of::<Ugh>());
+
+    assert_eq!(ALIGN_OF_FOO, mem::align_of::<Foo>());
+    assert_eq!(ALIGN_OF_BAR, mem::align_of::<Bar>());
+    assert_eq!(ALIGN_OF_UGH, mem::align_of::<Ugh>());
+
+    assert_eq!(SIZE_OF_SLICE, "foobar".len());
+}
diff --git a/src/test/ui/consts/const-typeid-of-rpass.rs b/src/test/ui/consts/const-typeid-of-rpass.rs
index 225acb60ac4..c49141050b2 100644
--- a/src/test/ui/consts/const-typeid-of-rpass.rs
+++ b/src/test/ui/consts/const-typeid-of-rpass.rs
@@ -1,6 +1,5 @@
 // run-pass
 #![feature(core_intrinsics)]
-#![feature(const_type_id)]
 
 use std::any::TypeId;
 
diff --git a/src/test/ui/consts/const-typeid-of.rs b/src/test/ui/consts/const-typeid-of.rs
deleted file mode 100644
index 3829c481da8..00000000000
--- a/src/test/ui/consts/const-typeid-of.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use std::any::TypeId;
-
-struct A;
-
-fn main() {
-    const A_ID: TypeId = TypeId::of::<A>();
-    //~^ ERROR `std::any::TypeId::of` is not yet stable as a const fn
-}
diff --git a/src/test/ui/consts/const-typeid-of.stderr b/src/test/ui/consts/const-typeid-of.stderr
deleted file mode 100644
index 05347fbc819..00000000000
--- a/src/test/ui/consts/const-typeid-of.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: `std::any::TypeId::of` is not yet stable as a const fn
-  --> $DIR/const-typeid-of.rs:6:26
-   |
-LL |     const A_ID: TypeId = TypeId::of::<A>();
-   |                          ^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(const_type_id)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/consts/const-unwrap.rs b/src/test/ui/consts/const-unwrap.rs
new file mode 100644
index 00000000000..6ed60ed87bf
--- /dev/null
+++ b/src/test/ui/consts/const-unwrap.rs
@@ -0,0 +1,14 @@
+// check-fail
+
+#![feature(const_option)]
+
+const FOO: i32 = Some(42i32).unwrap();
+
+// This causes an error, but it is attributed to the `panic` *inside* `Option::unwrap` (maybe due
+// to `track_caller`?). A note points to the originating `const`.
+const BAR: i32 = Option::<i32>::None.unwrap(); //~ NOTE
+
+fn main() {
+    println!("{}", FOO);
+    println!("{}", BAR);
+}
diff --git a/src/test/ui/consts/const-unwrap.stderr b/src/test/ui/consts/const-unwrap.stderr
new file mode 100644
index 00000000000..7f2c1f41510
--- /dev/null
+++ b/src/test/ui/consts/const-unwrap.stderr
@@ -0,0 +1,20 @@
+error: any use of this value will cause an error
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+   |
+LL |             None => panic!("called `Option::unwrap()` on a `None` value"),
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     |
+   |                     the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:9:38
+   |                     inside `std::option::Option::<i32>::unwrap` at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+   |                     inside `BAR` at $DIR/const-unwrap.rs:9:18
+   | 
+  ::: $DIR/const-unwrap.rs:9:1
+   |
+LL | const BAR: i32 = Option::<i32>::None.unwrap();
+   | ----------------------------------------------
+   |
+   = note: `#[deny(const_err)]` on by default
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const_constructor/const-construct-call.rs b/src/test/ui/consts/const_constructor/const-construct-call.rs
index d883d3fa6e4..d3e6cf78bc9 100644
--- a/src/test/ui/consts/const_constructor/const-construct-call.rs
+++ b/src/test/ui/consts/const_constructor/const-construct-call.rs
@@ -6,7 +6,7 @@
 
 #![cfg_attr(const_fn, feature(const_fn))]
 
-// Ctor(..) is transformed to Ctor { 0: ... } in HAIR lowering, so directly
+// Ctor(..) is transformed to Ctor { 0: ... } in THIR lowering, so directly
 // calling constructors doesn't require them to be const.
 
 type ExternalType = std::panic::AssertUnwindSafe<(Option<i32>, Result<i32, bool>)>;
diff --git a/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs b/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs
index c6b794de195..51e1af359cd 100644
--- a/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs
+++ b/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs
@@ -10,7 +10,7 @@
 // const-evaluator computes a value that *does* meet the conditions for
 // structural-match, but the const expression itself has abstractions (like
 // calls to const functions) that may fit better with a type-based analysis
-// rather than a committment to a specific value.
+// rather than a commitment to a specific value.
 
 #![warn(indirect_structural_match)]
 
diff --git a/src/test/ui/consts/issue-73976-monomorphic.rs b/src/test/ui/consts/issue-73976-monomorphic.rs
index 7706a97f23b..1db0fdc87c3 100644
--- a/src/test/ui/consts/issue-73976-monomorphic.rs
+++ b/src/test/ui/consts/issue-73976-monomorphic.rs
@@ -5,7 +5,6 @@
 // will be properly rejected. This test will ensure that monomorphic use of these
 // would not be wrongly rejected in patterns.
 
-#![feature(const_type_id)]
 #![feature(const_type_name)]
 
 use std::any::{self, TypeId};
diff --git a/src/test/ui/consts/issue-73976-polymorphic.rs b/src/test/ui/consts/issue-73976-polymorphic.rs
index 28b84518719..b3d8610ff51 100644
--- a/src/test/ui/consts/issue-73976-polymorphic.rs
+++ b/src/test/ui/consts/issue-73976-polymorphic.rs
@@ -1,11 +1,10 @@
 // This test is from #73976. We previously did not check if a type is monomorphized
-// before calculating its type id, which leads to the bizzare behaviour below that
+// before calculating its type id, which leads to the bizarre behaviour below that
 // TypeId of a generic type does not match itself.
 //
 // This test case should either run-pass or be rejected at compile time.
 // Currently we just disallow this usage and require pattern is monomorphic.
 
-#![feature(const_type_id)]
 #![feature(const_type_name)]
 
 use std::any::{self, TypeId};
@@ -18,8 +17,8 @@ impl<T: 'static> GetTypeId<T> {
 
 const fn check_type_id<T: 'static>() -> bool {
     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
-    //~^ ERROR could not evaluate constant pattern
-    //~| ERROR could not evaluate constant pattern
+    //~^ ERROR constant pattern depends on a generic parameter
+    //~| ERROR constant pattern depends on a generic parameter
 }
 
 pub struct GetTypeNameLen<T>(T);
@@ -30,8 +29,8 @@ impl<T: 'static> GetTypeNameLen<T> {
 
 const fn check_type_name_len<T: 'static>() -> bool {
     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
-    //~^ ERROR could not evaluate constant pattern
-    //~| ERROR could not evaluate constant pattern
+    //~^ ERROR constant pattern depends on a generic parameter
+    //~| ERROR constant pattern depends on a generic parameter
 }
 
 fn main() {
diff --git a/src/test/ui/consts/issue-73976-polymorphic.stderr b/src/test/ui/consts/issue-73976-polymorphic.stderr
index c90ce2bd06a..250f1536d85 100644
--- a/src/test/ui/consts/issue-73976-polymorphic.stderr
+++ b/src/test/ui/consts/issue-73976-polymorphic.stderr
@@ -1,23 +1,23 @@
-error: could not evaluate constant pattern
-  --> $DIR/issue-73976-polymorphic.rs:20:37
+error: constant pattern depends on a generic parameter
+  --> $DIR/issue-73976-polymorphic.rs:19:37
    |
 LL |     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
    |                                     ^^^^^^^^^^^^^^^^^^^^^
 
-error: could not evaluate constant pattern
-  --> $DIR/issue-73976-polymorphic.rs:32:42
+error: constant pattern depends on a generic parameter
+  --> $DIR/issue-73976-polymorphic.rs:31:42
    |
 LL |     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: could not evaluate constant pattern
-  --> $DIR/issue-73976-polymorphic.rs:20:37
+error: constant pattern depends on a generic parameter
+  --> $DIR/issue-73976-polymorphic.rs:19:37
    |
 LL |     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
    |                                     ^^^^^^^^^^^^^^^^^^^^^
 
-error: could not evaluate constant pattern
-  --> $DIR/issue-73976-polymorphic.rs:32:42
+error: constant pattern depends on a generic parameter
+  --> $DIR/issue-73976-polymorphic.rs:31:42
    |
 LL |     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/deprecation/atomic_initializers.fixed b/src/test/ui/deprecation/atomic_initializers.fixed
index d8485ed7da1..4fb0aeeb573 100644
--- a/src/test/ui/deprecation/atomic_initializers.fixed
+++ b/src/test/ui/deprecation/atomic_initializers.fixed
@@ -6,6 +6,6 @@ use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
 
 #[allow(dead_code)]
 static FOO: AtomicIsize = AtomicIsize::new(0);
-//~^ WARN use of deprecated item
+//~^ WARN use of deprecated constant
 
 fn main() {}
diff --git a/src/test/ui/deprecation/atomic_initializers.rs b/src/test/ui/deprecation/atomic_initializers.rs
index b15a1bbfd92..1dcfd36d7d5 100644
--- a/src/test/ui/deprecation/atomic_initializers.rs
+++ b/src/test/ui/deprecation/atomic_initializers.rs
@@ -6,6 +6,6 @@ use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
 
 #[allow(dead_code)]
 static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
-//~^ WARN use of deprecated item
+//~^ WARN use of deprecated constant
 
 fn main() {}
diff --git a/src/test/ui/deprecation/atomic_initializers.stderr b/src/test/ui/deprecation/atomic_initializers.stderr
index 75baf4a1bf9..eaf5c61b440 100644
--- a/src/test/ui/deprecation/atomic_initializers.stderr
+++ b/src/test/ui/deprecation/atomic_initializers.stderr
@@ -1,8 +1,8 @@
-warning: use of deprecated item 'std::sync::atomic::ATOMIC_ISIZE_INIT': the `new` function is now preferred
+warning: use of deprecated constant `std::sync::atomic::ATOMIC_ISIZE_INIT`: the `new` function is now preferred
   --> $DIR/atomic_initializers.rs:8:27
    |
 LL | static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
-   |                           ^^^^^^^^^^^^^^^^^ help: replace the use of the deprecated item: `AtomicIsize::new(0)`
+   |                           ^^^^^^^^^^^^^^^^^ help: replace the use of the deprecated constant: `AtomicIsize::new(0)`
    |
    = note: `#[warn(deprecated)]` on by default
 
diff --git a/src/test/ui/deprecation/deprecation-in-future.rs b/src/test/ui/deprecation/deprecation-in-future.rs
index bfeab49548f..53826183d06 100644
--- a/src/test/ui/deprecation/deprecation-in-future.rs
+++ b/src/test/ui/deprecation/deprecation-in-future.rs
@@ -7,7 +7,7 @@ pub fn deprecated_future() {}
 
 fn test() {
     deprecated_future(); // ok; deprecated_in_future only applies to rustc_deprecated
-    //~^ WARNING use of deprecated item 'deprecated_future': text [deprecated]
+    //~^ WARNING use of deprecated function `deprecated_future`: text [deprecated]
 }
 
 fn main() {}
diff --git a/src/test/ui/deprecation/deprecation-in-future.stderr b/src/test/ui/deprecation/deprecation-in-future.stderr
index 3040dcd9939..6561ec74349 100644
--- a/src/test/ui/deprecation/deprecation-in-future.stderr
+++ b/src/test/ui/deprecation/deprecation-in-future.stderr
@@ -1,4 +1,4 @@
-warning: use of deprecated item 'deprecated_future': text
+warning: use of deprecated function `deprecated_future`: text
   --> $DIR/deprecation-in-future.rs:9:5
    |
 LL |     deprecated_future(); // ok; deprecated_in_future only applies to rustc_deprecated
diff --git a/src/test/ui/deprecation/deprecation-lint-2.rs b/src/test/ui/deprecation/deprecation-lint-2.rs
index 2aa0d0c64d2..16ed6d4ecd6 100644
--- a/src/test/ui/deprecation/deprecation-lint-2.rs
+++ b/src/test/ui/deprecation/deprecation-lint-2.rs
@@ -1,5 +1,5 @@
 // aux-build:deprecation-lint.rs
-// error-pattern: use of deprecated item
+// error-pattern: use of deprecated function
 
 #![deny(deprecated)]
 
diff --git a/src/test/ui/deprecation/deprecation-lint-2.stderr b/src/test/ui/deprecation/deprecation-lint-2.stderr
index 65152a2f9ab..b81d4bf402a 100644
--- a/src/test/ui/deprecation/deprecation-lint-2.stderr
+++ b/src/test/ui/deprecation/deprecation-lint-2.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated item 'deprecation_lint::deprecated': text
+error: use of deprecated function `deprecation_lint::deprecated`: text
   --> $DIR/deprecation-lint-2.rs:12:5
    |
 LL |     macro_test!();
diff --git a/src/test/ui/deprecation/deprecation-lint-3.rs b/src/test/ui/deprecation/deprecation-lint-3.rs
index ae2dd7aac81..e6e1587daeb 100644
--- a/src/test/ui/deprecation/deprecation-lint-3.rs
+++ b/src/test/ui/deprecation/deprecation-lint-3.rs
@@ -1,5 +1,5 @@
 // aux-build:deprecation-lint.rs
-// error-pattern: use of deprecated item
+// error-pattern: use of deprecated function
 
 #![deny(deprecated)]
 #![allow(warnings)]
diff --git a/src/test/ui/deprecation/deprecation-lint-3.stderr b/src/test/ui/deprecation/deprecation-lint-3.stderr
index b450f74d7f3..6f7cd9be2dd 100644
--- a/src/test/ui/deprecation/deprecation-lint-3.stderr
+++ b/src/test/ui/deprecation/deprecation-lint-3.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated item 'deprecation_lint::deprecated_text': text
+error: use of deprecated function `deprecation_lint::deprecated_text`: text
   --> $DIR/deprecation-lint-3.rs:13:5
    |
 LL |     macro_test_arg_nested!(deprecated_text);
diff --git a/src/test/ui/deprecation/deprecation-lint-nested.rs b/src/test/ui/deprecation/deprecation-lint-nested.rs
index ee6f0a22363..589522cdbdf 100644
--- a/src/test/ui/deprecation/deprecation-lint-nested.rs
+++ b/src/test/ui/deprecation/deprecation-lint-nested.rs
@@ -52,19 +52,19 @@ mod loud {
     #[deprecated]
     const DEPRECATED_CONST: u8 = 1;
 
-    struct Foo(DeprecatedType); //~ ERROR use of deprecated item
+    struct Foo(DeprecatedType); //~ ERROR use of deprecated type alias
 
-    impl DeprecatedTrait for Foo {} //~ ERROR use of deprecated item
+    impl DeprecatedTrait for Foo {} //~ ERROR use of deprecated trait
 
     impl Foo {
-        fn bar<T: DeprecatedTrait>() { //~ ERROR use of deprecated item
-            deprecated_fn(); //~ ERROR use of deprecated item
+        fn bar<T: DeprecatedTrait>() { //~ ERROR use of deprecated trait
+            deprecated_fn(); //~ ERROR use of deprecated function
         }
     }
 
     fn foo() -> u8 {
-        DEPRECATED_STATIC + //~ ERROR use of deprecated item
-        DEPRECATED_CONST //~ ERROR use of deprecated item
+        DEPRECATED_STATIC + //~ ERROR use of deprecated static
+        DEPRECATED_CONST //~ ERROR use of deprecated const
     }
 }
 
diff --git a/src/test/ui/deprecation/deprecation-lint-nested.stderr b/src/test/ui/deprecation/deprecation-lint-nested.stderr
index b71f90014fe..47607b8cc7c 100644
--- a/src/test/ui/deprecation/deprecation-lint-nested.stderr
+++ b/src/test/ui/deprecation/deprecation-lint-nested.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated item 'loud::DeprecatedType'
+error: use of deprecated type alias `loud::DeprecatedType`
   --> $DIR/deprecation-lint-nested.rs:55:16
    |
 LL |     struct Foo(DeprecatedType);
@@ -10,31 +10,31 @@ note: the lint level is defined here
 LL | #![deny(deprecated)]
    |         ^^^^^^^^^^
 
-error: use of deprecated item 'loud::DeprecatedTrait'
+error: use of deprecated trait `loud::DeprecatedTrait`
   --> $DIR/deprecation-lint-nested.rs:57:10
    |
 LL |     impl DeprecatedTrait for Foo {}
    |          ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'loud::DEPRECATED_STATIC'
+error: use of deprecated static `loud::DEPRECATED_STATIC`
   --> $DIR/deprecation-lint-nested.rs:66:9
    |
 LL |         DEPRECATED_STATIC +
    |         ^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'loud::DEPRECATED_CONST'
+error: use of deprecated constant `loud::DEPRECATED_CONST`
   --> $DIR/deprecation-lint-nested.rs:67:9
    |
 LL |         DEPRECATED_CONST
    |         ^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'loud::DeprecatedTrait'
+error: use of deprecated trait `loud::DeprecatedTrait`
   --> $DIR/deprecation-lint-nested.rs:60:19
    |
 LL |         fn bar<T: DeprecatedTrait>() {
    |                   ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'loud::deprecated_fn'
+error: use of deprecated function `loud::deprecated_fn`
   --> $DIR/deprecation-lint-nested.rs:61:13
    |
 LL |             deprecated_fn();
diff --git a/src/test/ui/deprecation/deprecation-lint.rs b/src/test/ui/deprecation/deprecation-lint.rs
index 26271395005..1932344fc57 100644
--- a/src/test/ui/deprecation/deprecation-lint.rs
+++ b/src/test/ui/deprecation/deprecation-lint.rs
@@ -14,86 +14,86 @@ mod cross_crate {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::deprecated'
-        foo.method_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated'
-        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated'
-        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated'
-        foo.trait_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
-
-        deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_text': text
-        foo.method_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
-        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
-        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
-
-        let _ = DeprecatedStruct { //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedStruct': text
-            i: 0 //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedStruct::i': text
+        deprecated(); //~ ERROR use of deprecated function `deprecation_lint::deprecated`
+        foo.method_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`
+        foo.trait_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+
+        deprecated_text(); //~ ERROR use of deprecated function `deprecation_lint::deprecated_text`: text
+        foo.method_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+
+        let _ = DeprecatedStruct { //~ ERROR use of deprecated struct `deprecation_lint::DeprecatedStruct`: text
+            i: 0 //~ ERROR use of deprecated field `deprecation_lint::DeprecatedStruct::i`: text
         };
 
-        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedUnitStruct': text
+        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated struct `deprecation_lint::DeprecatedUnitStruct`: text
 
-        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'deprecation_lint::Enum::DeprecatedVariant': text
+        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated variant `deprecation_lint::Enum::DeprecatedVariant`: text
 
-        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedTupleStruct': text
+        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated struct `deprecation_lint::DeprecatedTupleStruct`: text
 
-        let _ = nested::DeprecatedStruct { //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedStruct': text
-            i: 0 //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedStruct::i': text
+        let _ = nested::DeprecatedStruct { //~ ERROR use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text
+            i: 0 //~ ERROR use of deprecated field `deprecation_lint::nested::DeprecatedStruct::i`: text
         };
 
-        let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedUnitStruct': text
+        let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated struct `deprecation_lint::nested::DeprecatedUnitStruct`: text
 
-        let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'deprecation_lint::nested::Enum::DeprecatedVariant': text
+        let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text
 
-        let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'deprecation_lint::nested::DeprecatedTupleStruct': text
+        let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated struct `deprecation_lint::nested::DeprecatedTupleStruct`: text
 
         // At the moment, the lint checker only checks stability in
         // in the arguments of macros.
         // Eventually, we will want to lint the contents of the
         // macro in the module *defining* it. Also, stability levels
         // on macros themselves are not yet linted.
-        macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_text': text
-        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_text': text
+        macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated function `deprecation_lint::deprecated_text`: text
+        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated function `deprecation_lint::deprecated_text`: text
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        foo.trait_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
     }
 
     fn test_method_object(foo: &Trait) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated'
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+        foo.trait_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
     }
 
     struct S;
 
-    impl DeprecatedTrait for S {} //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedTrait': text
-    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item 'deprecation_lint::DeprecatedTrait': text
+    impl DeprecatedTrait for S {} //~ ERROR use of deprecated trait `deprecation_lint::DeprecatedTrait`: text
+    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated trait `deprecation_lint::DeprecatedTrait`: text
 
     pub fn foo() {
         let x = Stable {
             override2: 3,
-            //~^ ERROR use of deprecated item 'deprecation_lint::Stable::override2': text
+            //~^ ERROR use of deprecated field `deprecation_lint::Stable::override2`: text
         };
 
         let _ = x.override2;
-        //~^ ERROR use of deprecated item 'deprecation_lint::Stable::override2': text
+        //~^ ERROR use of deprecated field `deprecation_lint::Stable::override2`: text
 
         let Stable {
             override2: _
-            //~^ ERROR use of deprecated item 'deprecation_lint::Stable::override2': text
+            //~^ ERROR use of deprecated field `deprecation_lint::Stable::override2`: text
         } = x;
         // all fine
         let Stable { .. } = x;
@@ -101,56 +101,56 @@ mod cross_crate {
         let x = Stable2(1, 2, 3);
 
         let _ = x.2;
-        //~^ ERROR use of deprecated item 'deprecation_lint::Stable2::2': text
+        //~^ ERROR use of deprecated field `deprecation_lint::Stable2::2`: text
 
         let Stable2(_,
                    _,
                    _)
-            //~^ ERROR use of deprecated item 'deprecation_lint::Stable2::2': text
+            //~^ ERROR use of deprecated field `deprecation_lint::Stable2::2`: text
             = x;
         // all fine
         let Stable2(..) = x;
 
         let x = Deprecated {
-            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated': text
+            //~^ ERROR use of deprecated struct `deprecation_lint::Deprecated`: text
             inherit: 1,
-            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+            //~^ ERROR use of deprecated field `deprecation_lint::Deprecated::inherit`: text
         };
 
         let _ = x.inherit;
-        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+        //~^ ERROR use of deprecated field `deprecation_lint::Deprecated::inherit`: text
 
         let Deprecated {
-            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated': text
+            //~^ ERROR use of deprecated struct `deprecation_lint::Deprecated`: text
             inherit: _,
-            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+            //~^ ERROR use of deprecated field `deprecation_lint::Deprecated::inherit`: text
         } = x;
 
         let Deprecated
-            //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated': text
+            //~^ ERROR use of deprecated struct `deprecation_lint::Deprecated`: text
             { .. } = x;
 
         let x = Deprecated2(1, 2, 3);
-        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2': text
+        //~^ ERROR use of deprecated struct `deprecation_lint::Deprecated2`: text
 
         let _ = x.0;
-        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::0': text
+        //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::0`: text
         let _ = x.1;
-        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::1': text
+        //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::1`: text
         let _ = x.2;
-        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::2': text
+        //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::2`: text
 
         let Deprecated2
-        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2': text
+        //~^ ERROR use of deprecated struct `deprecation_lint::Deprecated2`: text
             (_,
-             //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::0': text
+             //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::0`: text
              _,
-             //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::1': text
+             //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::1`: text
              _)
-             //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2::2': text
+             //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::2`: text
             = x;
         let Deprecated2
-        //~^ ERROR use of deprecated item 'deprecation_lint::Deprecated2': text
+        //~^ ERROR use of deprecated struct `deprecation_lint::Deprecated2`: text
             // the patterns are all fine:
             (..) = x;
     }
@@ -160,7 +160,7 @@ mod inheritance {
     use deprecation_lint::*;
 
     fn test_inheritance() {
-        deprecated_mod::deprecated(); //~ ERROR use of deprecated item 'deprecation_lint::deprecated_mod::deprecated': text
+        deprecated_mod::deprecated(); //~ ERROR use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text
     }
 }
 
@@ -243,65 +243,65 @@ mod this_crate {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ ERROR use of deprecated item 'this_crate::deprecated'
-        foo.method_deprecated(); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated'
-        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated'
-        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated'
-        foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
-
-        deprecated_text(); //~ ERROR use of deprecated item 'this_crate::deprecated_text': text
-        foo.method_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        deprecated(); //~ ERROR use of deprecated function `this_crate::deprecated`
+        foo.method_deprecated(); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated`
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated`
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated`
+        foo.trait_deprecated(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+
+        deprecated_text(); //~ ERROR use of deprecated function `this_crate::deprecated_text`: text
+        foo.method_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
 
         // Future deprecations are only permitted for rustc_deprecated.
-        deprecated_future(); //~ ERROR use of deprecated item
-        deprecated_future_text(); //~ ERROR use of deprecated item
+        deprecated_future(); //~ ERROR use of deprecated function
+        deprecated_future_text(); //~ ERROR use of deprecated function
 
         let _ = DeprecatedStruct {
-            //~^ ERROR use of deprecated item 'this_crate::DeprecatedStruct': text
-            i: 0 //~ ERROR use of deprecated item 'this_crate::DeprecatedStruct::i': text
+            //~^ ERROR use of deprecated struct `this_crate::DeprecatedStruct`: text
+            i: 0 //~ ERROR use of deprecated field `this_crate::DeprecatedStruct::i`: text
         };
 
-        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::DeprecatedUnitStruct': text
+        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text
 
-        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
+        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text
 
-        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::DeprecatedTupleStruct': text
+        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text
 
         let _ = nested::DeprecatedStruct {
-            //~^ ERROR use of deprecated item 'this_crate::nested::DeprecatedStruct': text
-            i: 0 //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedStruct::i': text
+            //~^ ERROR use of deprecated struct `this_crate::nested::DeprecatedStruct`: text
+            i: 0 //~ ERROR use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text
         };
 
-        let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedUnitStruct': text
+        let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
 
-        let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::nested::Enum::DeprecatedVariant': text
+        let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text
 
-        let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedTupleStruct': text
+        let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        foo.trait_deprecated(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
     }
 
     fn test_method_object(foo: &Trait) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        foo.trait_deprecated(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
     }
 
     #[deprecated(since = "1.0.0", note = "text")]
@@ -314,7 +314,7 @@ mod this_crate {
         let _ = || {
             #[deprecated]
             fn bar() { }
-            bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}#0::bar'
+            bar(); //~ ERROR use of deprecated function `this_crate::test_fn_closure_body::{{closure}}#0::bar`
         };
     }
 
@@ -333,9 +333,9 @@ mod this_crate {
 
     struct S;
 
-    impl DeprecatedTrait for S { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text
+    impl DeprecatedTrait for S { } //~ ERROR use of deprecated trait `this_crate::DeprecatedTrait`: text
 
-    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text
+    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated trait `this_crate::DeprecatedTrait`: text
 }
 
 mod this_crate2 {
@@ -361,15 +361,15 @@ mod this_crate2 {
     pub fn foo() {
         let x = Stable {
             override2: 3,
-            //~^ ERROR use of deprecated item 'this_crate2::Stable::override2': text
+            //~^ ERROR use of deprecated field `this_crate2::Stable::override2`: text
         };
 
         let _ = x.override2;
-        //~^ ERROR use of deprecated item 'this_crate2::Stable::override2': text
+        //~^ ERROR use of deprecated field `this_crate2::Stable::override2`: text
 
         let Stable {
             override2: _
-            //~^ ERROR use of deprecated item 'this_crate2::Stable::override2': text
+            //~^ ERROR use of deprecated field `this_crate2::Stable::override2`: text
         } = x;
         // all fine
         let Stable { .. } = x;
@@ -377,57 +377,57 @@ mod this_crate2 {
         let x = Stable2(1, 2, 3);
 
         let _ = x.2;
-        //~^ ERROR use of deprecated item 'this_crate2::Stable2::2': text
+        //~^ ERROR use of deprecated field `this_crate2::Stable2::2`: text
 
         let Stable2(_,
                    _,
                    _)
-            //~^ ERROR use of deprecated item 'this_crate2::Stable2::2': text
+            //~^ ERROR use of deprecated field `this_crate2::Stable2::2`: text
             = x;
         // all fine
         let Stable2(..) = x;
 
         let x = Deprecated {
-            //~^ ERROR use of deprecated item 'this_crate2::Deprecated': text
+            //~^ ERROR use of deprecated struct `this_crate2::Deprecated`: text
             inherit: 1,
-            //~^ ERROR use of deprecated item 'this_crate2::Deprecated::inherit': text
+            //~^ ERROR use of deprecated field `this_crate2::Deprecated::inherit`: text
         };
 
         let _ = x.inherit;
-        //~^ ERROR use of deprecated item 'this_crate2::Deprecated::inherit': text
+        //~^ ERROR use of deprecated field `this_crate2::Deprecated::inherit`: text
 
         let Deprecated {
-            //~^ ERROR use of deprecated item 'this_crate2::Deprecated': text
+            //~^ ERROR use of deprecated struct `this_crate2::Deprecated`: text
             inherit: _,
-            //~^ ERROR use of deprecated item 'this_crate2::Deprecated::inherit': text
+            //~^ ERROR use of deprecated field `this_crate2::Deprecated::inherit`: text
         } = x;
 
         let Deprecated
-            //~^ ERROR use of deprecated item 'this_crate2::Deprecated': text
+            //~^ ERROR use of deprecated struct `this_crate2::Deprecated`: text
             // the patterns are all fine:
             { .. } = x;
 
         let x = Deprecated2(1, 2, 3);
-        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2': text
+        //~^ ERROR use of deprecated tuple struct `this_crate2::Deprecated2`: text
 
         let _ = x.0;
-        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::0': text
+        //~^ ERROR use of deprecated field `this_crate2::Deprecated2::0`: text
         let _ = x.1;
-        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::1': text
+        //~^ ERROR use of deprecated field `this_crate2::Deprecated2::1`: text
         let _ = x.2;
-        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::2': text
+        //~^ ERROR use of deprecated field `this_crate2::Deprecated2::2`: text
 
         let Deprecated2
-        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2': text
+        //~^ ERROR use of deprecated tuple struct `this_crate2::Deprecated2`: text
             (_,
-             //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::0': text
+             //~^ ERROR use of deprecated field `this_crate2::Deprecated2::0`: text
              _,
-             //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::1': text
+             //~^ ERROR use of deprecated field `this_crate2::Deprecated2::1`: text
              _)
-            //~^ ERROR use of deprecated item 'this_crate2::Deprecated2::2': text
+            //~^ ERROR use of deprecated field `this_crate2::Deprecated2::2`: text
             = x;
         let Deprecated2
-        //~^ ERROR use of deprecated item 'this_crate2::Deprecated2': text
+        //~^ ERROR use of deprecated tuple struct `this_crate2::Deprecated2`: text
             // the patterns are all fine:
             (..) = x;
     }
diff --git a/src/test/ui/deprecation/deprecation-lint.stderr b/src/test/ui/deprecation/deprecation-lint.stderr
index 362a901d77d..03a2ec7edc9 100644
--- a/src/test/ui/deprecation/deprecation-lint.stderr
+++ b/src/test/ui/deprecation/deprecation-lint.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated item 'deprecation_lint::deprecated': text
+error: use of deprecated function `deprecation_lint::deprecated`: text
   --> $DIR/deprecation-lint.rs:17:9
    |
 LL |         deprecated();
@@ -10,727 +10,727 @@ note: the lint level is defined here
 LL | #![deny(deprecated)]
    |         ^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:22:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:24:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::deprecated_text': text
+error: use of deprecated function `deprecation_lint::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:26:9
    |
 LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:31:9
    |
-LL |         Trait::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Trait::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:33:9
    |
-LL |         <Foo as Trait>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::DeprecatedStruct': text
+error: use of deprecated struct `deprecation_lint::DeprecatedStruct`: text
   --> $DIR/deprecation-lint.rs:35:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::DeprecatedUnitStruct': text
+error: use of deprecated struct `deprecation_lint::DeprecatedUnitStruct`: text
   --> $DIR/deprecation-lint.rs:39:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Enum::DeprecatedVariant': text
+error: use of deprecated variant `deprecation_lint::Enum::DeprecatedVariant`: text
   --> $DIR/deprecation-lint.rs:41:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::DeprecatedTupleStruct': text
+error: use of deprecated struct `deprecation_lint::DeprecatedTupleStruct`: text
   --> $DIR/deprecation-lint.rs:43:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::nested::DeprecatedStruct': text
+error: use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text
   --> $DIR/deprecation-lint.rs:45:17
    |
 LL |         let _ = nested::DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::nested::DeprecatedUnitStruct': text
+error: use of deprecated struct `deprecation_lint::nested::DeprecatedUnitStruct`: text
   --> $DIR/deprecation-lint.rs:49:17
    |
 LL |         let _ = nested::DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::nested::Enum::DeprecatedVariant': text
+error: use of deprecated variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text
   --> $DIR/deprecation-lint.rs:51:17
    |
-LL |         let _ = nested::Enum::DeprecatedVariant;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   let _ = nested::Enum::DeprecatedVariant;
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::nested::DeprecatedTupleStruct': text
+error: use of deprecated struct `deprecation_lint::nested::DeprecatedTupleStruct`: text
   --> $DIR/deprecation-lint.rs:53:17
    |
-LL |         let _ = nested::DeprecatedTupleStruct (1);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   let _ = nested::DeprecatedTupleStruct (1);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::deprecated_text': text
+error: use of deprecated function `deprecation_lint::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:60:25
    |
 LL |         macro_test_arg!(deprecated_text());
    |                         ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::deprecated_text': text
+error: use of deprecated function `deprecation_lint::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:61:41
    |
 LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
    |                                         ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:66:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:68:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:70:9
    |
-LL |         Trait::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Trait::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:72:9
    |
-LL |         <Foo as Trait>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::DeprecatedTrait': text
+error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text
   --> $DIR/deprecation-lint.rs:82:10
    |
 LL |     impl DeprecatedTrait for S {}
    |          ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::DeprecatedTrait': text
+error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text
   --> $DIR/deprecation-lint.rs:83:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { }
    |                        ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated': text
+error: use of deprecated struct `deprecation_lint::Deprecated`: text
   --> $DIR/deprecation-lint.rs:114:17
    |
 LL |         let x = Deprecated {
    |                 ^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated': text
+error: use of deprecated struct `deprecation_lint::Deprecated`: text
   --> $DIR/deprecation-lint.rs:123:13
    |
 LL |         let Deprecated {
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated': text
+error: use of deprecated struct `deprecation_lint::Deprecated`: text
   --> $DIR/deprecation-lint.rs:129:13
    |
 LL |         let Deprecated
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated2': text
+error: use of deprecated struct `deprecation_lint::Deprecated2`: text
   --> $DIR/deprecation-lint.rs:133:17
    |
 LL |         let x = Deprecated2(1, 2, 3);
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated2': text
+error: use of deprecated struct `deprecation_lint::Deprecated2`: text
   --> $DIR/deprecation-lint.rs:143:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated2': text
+error: use of deprecated struct `deprecation_lint::Deprecated2`: text
   --> $DIR/deprecation-lint.rs:152:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::deprecated_mod::deprecated': text
+error: use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text
   --> $DIR/deprecation-lint.rs:163:9
    |
 LL |         deprecated_mod::deprecated();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::deprecated': text
+error: use of deprecated function `this_crate::deprecated`: text
   --> $DIR/deprecation-lint.rs:246:9
    |
 LL |         deprecated();
    |         ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:251:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:253:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::deprecated_text': text
+error: use of deprecated function `this_crate::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:255:9
    |
 LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:260:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:262:9
    |
-LL |         <Foo as Trait>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::deprecated_future': text
+error: use of deprecated function `this_crate::deprecated_future`: text
   --> $DIR/deprecation-lint.rs:265:9
    |
 LL |         deprecated_future();
    |         ^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::deprecated_future_text': text
+error: use of deprecated function `this_crate::deprecated_future_text`: text
   --> $DIR/deprecation-lint.rs:266:9
    |
 LL |         deprecated_future_text();
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::DeprecatedStruct': text
+error: use of deprecated struct `this_crate::DeprecatedStruct`: text
   --> $DIR/deprecation-lint.rs:268:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::DeprecatedUnitStruct': text
+error: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text
   --> $DIR/deprecation-lint.rs:273:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
+error: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text
   --> $DIR/deprecation-lint.rs:275:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::DeprecatedTupleStruct': text
+error: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text
   --> $DIR/deprecation-lint.rs:277:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::nested::DeprecatedStruct': text
+error: use of deprecated struct `this_crate::nested::DeprecatedStruct`: text
   --> $DIR/deprecation-lint.rs:279:17
    |
 LL |         let _ = nested::DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::nested::DeprecatedUnitStruct': text
+error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
   --> $DIR/deprecation-lint.rs:284:17
    |
 LL |         let _ = nested::DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::nested::Enum::DeprecatedVariant': text
+error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text
   --> $DIR/deprecation-lint.rs:286:17
    |
-LL |         let _ = nested::Enum::DeprecatedVariant;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   let _ = nested::Enum::DeprecatedVariant;
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::nested::DeprecatedTupleStruct': text
+error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text
   --> $DIR/deprecation-lint.rs:288:17
    |
-LL |         let _ = nested::DeprecatedTupleStruct (1);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   let _ = nested::DeprecatedTupleStruct (1);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:293:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:295:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:297:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:299:9
    |
-LL |         <Foo as Trait>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}#0::bar'
+error: use of deprecated function `this_crate::test_fn_closure_body::{{closure}}#0::bar`
   --> $DIR/deprecation-lint.rs:317:13
    |
 LL |             bar();
    |             ^^^
 
-error: use of deprecated item 'this_crate::DeprecatedTrait': text
+error: use of deprecated trait `this_crate::DeprecatedTrait`: text
   --> $DIR/deprecation-lint.rs:336:10
    |
 LL |     impl DeprecatedTrait for S { }
    |          ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::DeprecatedTrait': text
+error: use of deprecated trait `this_crate::DeprecatedTrait`: text
   --> $DIR/deprecation-lint.rs:338:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { }
    |                        ^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Deprecated': text
+error: use of deprecated struct `this_crate2::Deprecated`: text
   --> $DIR/deprecation-lint.rs:390:17
    |
 LL |         let x = Deprecated {
    |                 ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Deprecated': text
+error: use of deprecated struct `this_crate2::Deprecated`: text
   --> $DIR/deprecation-lint.rs:399:13
    |
 LL |         let Deprecated {
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Deprecated': text
+error: use of deprecated struct `this_crate2::Deprecated`: text
   --> $DIR/deprecation-lint.rs:405:13
    |
 LL |         let Deprecated
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Deprecated2': text
+error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
   --> $DIR/deprecation-lint.rs:410:17
    |
 LL |         let x = Deprecated2(1, 2, 3);
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Deprecated2': text
+error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
   --> $DIR/deprecation-lint.rs:420:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Deprecated2': text
+error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
   --> $DIR/deprecation-lint.rs:429:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated': text
+error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text
   --> $DIR/deprecation-lint.rs:18:13
    |
 LL |         foo.method_deprecated();
    |             ^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated': text
+error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text
   --> $DIR/deprecation-lint.rs:19:9
    |
 LL |         Foo::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated': text
+error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text
   --> $DIR/deprecation-lint.rs:20:9
    |
 LL |         <Foo>::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:21:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:23:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:27:13
    |
-LL |         foo.method_deprecated_text();
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   foo.method_deprecated_text();
+   |           ^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:28:9
    |
-LL |         Foo::method_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Foo::method_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::MethodTester::method_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:29:9
    |
-LL |         <Foo>::method_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::method_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:30:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:32:9
    |
-LL |         <Foo>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::DeprecatedStruct::i': text
+error: use of deprecated field `deprecation_lint::DeprecatedStruct::i`: text
   --> $DIR/deprecation-lint.rs:36:13
    |
 LL |             i: 0
    |             ^^^^
 
-error: use of deprecated item 'deprecation_lint::nested::DeprecatedStruct::i': text
+error: use of deprecated field `deprecation_lint::nested::DeprecatedStruct::i`: text
   --> $DIR/deprecation-lint.rs:46:13
    |
 LL |             i: 0
    |             ^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:65:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:67:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:69:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:71:9
    |
-LL |         <Foo>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:76:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:77:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Stable::override2': text
+error: use of deprecated field `deprecation_lint::Stable::override2`: text
   --> $DIR/deprecation-lint.rs:87:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Stable::override2': text
+error: use of deprecated field `deprecation_lint::Stable::override2`: text
   --> $DIR/deprecation-lint.rs:91:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Stable::override2': text
+error: use of deprecated field `deprecation_lint::Stable::override2`: text
   --> $DIR/deprecation-lint.rs:95:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Stable2::2': text
+error: use of deprecated field `deprecation_lint::Stable2::2`: text
   --> $DIR/deprecation-lint.rs:103:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'deprecation_lint::Stable2::2': text
+error: use of deprecated field `deprecation_lint::Stable2::2`: text
   --> $DIR/deprecation-lint.rs:108:20
    |
 LL |                    _)
    |                    ^
 
-error: use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+error: use of deprecated field `deprecation_lint::Deprecated::inherit`: text
   --> $DIR/deprecation-lint.rs:116:13
    |
 LL |             inherit: 1,
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+error: use of deprecated field `deprecation_lint::Deprecated::inherit`: text
   --> $DIR/deprecation-lint.rs:120:17
    |
 LL |         let _ = x.inherit;
    |                 ^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated::inherit': text
+error: use of deprecated field `deprecation_lint::Deprecated::inherit`: text
   --> $DIR/deprecation-lint.rs:125:13
    |
 LL |             inherit: _,
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated2::0': text
+error: use of deprecated field `deprecation_lint::Deprecated2::0`: text
   --> $DIR/deprecation-lint.rs:136:17
    |
 LL |         let _ = x.0;
    |                 ^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated2::1': text
+error: use of deprecated field `deprecation_lint::Deprecated2::1`: text
   --> $DIR/deprecation-lint.rs:138:17
    |
 LL |         let _ = x.1;
    |                 ^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated2::2': text
+error: use of deprecated field `deprecation_lint::Deprecated2::2`: text
   --> $DIR/deprecation-lint.rs:140:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'deprecation_lint::Deprecated2::0': text
+error: use of deprecated field `deprecation_lint::Deprecated2::0`: text
   --> $DIR/deprecation-lint.rs:145:14
    |
 LL |             (_,
    |              ^
 
-error: use of deprecated item 'deprecation_lint::Deprecated2::1': text
+error: use of deprecated field `deprecation_lint::Deprecated2::1`: text
   --> $DIR/deprecation-lint.rs:147:14
    |
 LL |              _,
    |              ^
 
-error: use of deprecated item 'deprecation_lint::Deprecated2::2': text
+error: use of deprecated field `deprecation_lint::Deprecated2::2`: text
   --> $DIR/deprecation-lint.rs:149:14
    |
 LL |              _)
    |              ^
 
-error: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
   --> $DIR/deprecation-lint.rs:247:13
    |
 LL |         foo.method_deprecated();
    |             ^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
   --> $DIR/deprecation-lint.rs:248:9
    |
 LL |         Foo::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
   --> $DIR/deprecation-lint.rs:249:9
    |
 LL |         <Foo>::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:250:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:252:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:256:13
    |
-LL |         foo.method_deprecated_text();
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   foo.method_deprecated_text();
+   |           ^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:257:9
    |
-LL |         Foo::method_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Foo::method_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:258:9
    |
-LL |         <Foo>::method_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::method_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:259:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:261:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::DeprecatedStruct::i': text
+error: use of deprecated field `this_crate::DeprecatedStruct::i`: text
   --> $DIR/deprecation-lint.rs:270:13
    |
 LL |             i: 0
    |             ^^^^
 
-error: use of deprecated item 'this_crate::nested::DeprecatedStruct::i': text
+error: use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text
   --> $DIR/deprecation-lint.rs:281:13
    |
 LL |             i: 0
    |             ^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:292:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:294:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:296:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:298:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/deprecation-lint.rs:303:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/deprecation-lint.rs:304:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Stable::override2': text
+error: use of deprecated field `this_crate2::Stable::override2`: text
   --> $DIR/deprecation-lint.rs:363:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Stable::override2': text
+error: use of deprecated field `this_crate2::Stable::override2`: text
   --> $DIR/deprecation-lint.rs:367:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Stable::override2': text
+error: use of deprecated field `this_crate2::Stable::override2`: text
   --> $DIR/deprecation-lint.rs:371:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Stable2::2': text
+error: use of deprecated field `this_crate2::Stable2::2`: text
   --> $DIR/deprecation-lint.rs:379:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'this_crate2::Stable2::2': text
+error: use of deprecated field `this_crate2::Stable2::2`: text
   --> $DIR/deprecation-lint.rs:384:20
    |
 LL |                    _)
    |                    ^
 
-error: use of deprecated item 'this_crate2::Deprecated::inherit': text
+error: use of deprecated field `this_crate2::Deprecated::inherit`: text
   --> $DIR/deprecation-lint.rs:392:13
    |
 LL |             inherit: 1,
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Deprecated::inherit': text
+error: use of deprecated field `this_crate2::Deprecated::inherit`: text
   --> $DIR/deprecation-lint.rs:396:17
    |
 LL |         let _ = x.inherit;
    |                 ^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Deprecated::inherit': text
+error: use of deprecated field `this_crate2::Deprecated::inherit`: text
   --> $DIR/deprecation-lint.rs:401:13
    |
 LL |             inherit: _,
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate2::Deprecated2::0': text
+error: use of deprecated field `this_crate2::Deprecated2::0`: text
   --> $DIR/deprecation-lint.rs:413:17
    |
 LL |         let _ = x.0;
    |                 ^^^
 
-error: use of deprecated item 'this_crate2::Deprecated2::1': text
+error: use of deprecated field `this_crate2::Deprecated2::1`: text
   --> $DIR/deprecation-lint.rs:415:17
    |
 LL |         let _ = x.1;
    |                 ^^^
 
-error: use of deprecated item 'this_crate2::Deprecated2::2': text
+error: use of deprecated field `this_crate2::Deprecated2::2`: text
   --> $DIR/deprecation-lint.rs:417:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'this_crate2::Deprecated2::0': text
+error: use of deprecated field `this_crate2::Deprecated2::0`: text
   --> $DIR/deprecation-lint.rs:422:14
    |
 LL |             (_,
    |              ^
 
-error: use of deprecated item 'this_crate2::Deprecated2::1': text
+error: use of deprecated field `this_crate2::Deprecated2::1`: text
   --> $DIR/deprecation-lint.rs:424:14
    |
 LL |              _,
    |              ^
 
-error: use of deprecated item 'this_crate2::Deprecated2::2': text
+error: use of deprecated field `this_crate2::Deprecated2::2`: text
   --> $DIR/deprecation-lint.rs:426:14
    |
 LL |              _)
diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.rs b/src/test/ui/deprecation/rustc_deprecation-in-future.rs
index a19363c5129..6a619bcc49c 100644
--- a/src/test/ui/deprecation/rustc_deprecation-in-future.rs
+++ b/src/test/ui/deprecation/rustc_deprecation-in-future.rs
@@ -11,5 +11,5 @@
 pub struct S;
 
 fn main() {
-    let _ = S; //~ ERROR use of item 'S' that will be deprecated in future version 99.99.99: effectively never
+    let _ = S; //~ ERROR use of unit struct `S` that will be deprecated in future version 99.99.99: effectively never
 }
diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.stderr b/src/test/ui/deprecation/rustc_deprecation-in-future.stderr
index 4aff11ad66f..e4f50d10dad 100644
--- a/src/test/ui/deprecation/rustc_deprecation-in-future.stderr
+++ b/src/test/ui/deprecation/rustc_deprecation-in-future.stderr
@@ -1,4 +1,4 @@
-error: use of item 'S' that will be deprecated in future version 99.99.99: effectively never
+error: use of unit struct `S` that will be deprecated in future version 99.99.99: effectively never
   --> $DIR/rustc_deprecation-in-future.rs:14:13
    |
 LL |     let _ = S;
diff --git a/src/test/ui/deprecation/suggestion.stderr b/src/test/ui/deprecation/suggestion.stderr
index b60d420b546..8a7cb1def90 100644
--- a/src/test/ui/deprecation/suggestion.stderr
+++ b/src/test/ui/deprecation/suggestion.stderr
@@ -1,8 +1,8 @@
-error: use of deprecated item 'Foo::deprecated': replaced by `replacement`
+error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement`
   --> $DIR/suggestion.rs:27:9
    |
 LL |     foo.deprecated();
-   |         ^^^^^^^^^^ help: replace the use of the deprecated item: `replacement`
+   |         ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement`
    |
 note: the lint level is defined here
   --> $DIR/suggestion.rs:7:9
diff --git a/src/test/ui/generator/issue-52398.rs b/src/test/ui/generator/issue-52398.rs
index 54a1912582c..ada380d116c 100644
--- a/src/test/ui/generator/issue-52398.rs
+++ b/src/test/ui/generator/issue-52398.rs
@@ -14,14 +14,14 @@ impl A {
 fn main() {
     // Test that the MIR local with type &A created for the auto-borrow adjustment
     // is caught by typeck
-    move || {
+    move || { //~ WARN unused generator that must be used
         A.test(yield);
     };
 
     // Test that the std::cell::Ref temporary returned from the `borrow` call
     // is caught by typeck
     let y = RefCell::new(true);
-    static move || {
+    static move || { //~ WARN unused generator that must be used
         yield *y.borrow();
         return "Done";
     };
diff --git a/src/test/ui/generator/issue-52398.stderr b/src/test/ui/generator/issue-52398.stderr
new file mode 100644
index 00000000000..3f8ebb5a738
--- /dev/null
+++ b/src/test/ui/generator/issue-52398.stderr
@@ -0,0 +1,24 @@
+warning: unused generator that must be used
+  --> $DIR/issue-52398.rs:17:5
+   |
+LL | /     move || {
+LL | |         A.test(yield);
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: unused generator that must be used
+  --> $DIR/issue-52398.rs:24:5
+   |
+LL | /     static move || {
+LL | |         yield *y.borrow();
+LL | |         return "Done";
+LL | |     };
+   | |______^
+   |
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/generator/issue-57084.rs b/src/test/ui/generator/issue-57084.rs
index 8aaa6a0e427..2a5c3dd0570 100644
--- a/src/test/ui/generator/issue-57084.rs
+++ b/src/test/ui/generator/issue-57084.rs
@@ -19,7 +19,7 @@ where F: Fn() -> ()
 
 fn main() {
     let data = &vec![1];
-    || {
+    || { //~ WARN unused generator that must be used
         let _to_pin = with(move || println!("{:p}", data));
         loop {
             yield
diff --git a/src/test/ui/generator/issue-57084.stderr b/src/test/ui/generator/issue-57084.stderr
new file mode 100644
index 00000000000..32a04f94dcb
--- /dev/null
+++ b/src/test/ui/generator/issue-57084.stderr
@@ -0,0 +1,16 @@
+warning: unused generator that must be used
+  --> $DIR/issue-57084.rs:22:5
+   |
+LL | /     || {
+LL | |         let _to_pin = with(move || println!("{:p}", data));
+LL | |         loop {
+LL | |             yield
+LL | |         }
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generator/match-bindings.rs b/src/test/ui/generator/match-bindings.rs
index 560d8e7103c..865904a57d4 100644
--- a/src/test/ui/generator/match-bindings.rs
+++ b/src/test/ui/generator/match-bindings.rs
@@ -9,7 +9,7 @@ enum Enum {
 }
 
 fn main() {
-    || {
+    || { //~ WARN unused generator that must be used
         loop {
             if let true = true {
                 match Enum::A(String::new()) {
diff --git a/src/test/ui/generator/match-bindings.stderr b/src/test/ui/generator/match-bindings.stderr
new file mode 100644
index 00000000000..4fd1e26f0c8
--- /dev/null
+++ b/src/test/ui/generator/match-bindings.stderr
@@ -0,0 +1,17 @@
+warning: unused generator that must be used
+  --> $DIR/match-bindings.rs:12:5
+   |
+LL | /     || {
+LL | |         loop {
+LL | |             if let true = true {
+LL | |                 match Enum::A(String::new()) {
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generator/reborrow-mut-upvar.rs b/src/test/ui/generator/reborrow-mut-upvar.rs
index 785e38a7eb8..dbd9e24e205 100644
--- a/src/test/ui/generator/reborrow-mut-upvar.rs
+++ b/src/test/ui/generator/reborrow-mut-upvar.rs
@@ -3,7 +3,7 @@
 #![feature(generators)]
 
 fn _run(bar: &mut i32) {
-    || {
+    || { //~ WARN unused generator that must be used
         {
             let _baz = &*bar;
             yield;
diff --git a/src/test/ui/generator/reborrow-mut-upvar.stderr b/src/test/ui/generator/reborrow-mut-upvar.stderr
new file mode 100644
index 00000000000..ff511b76672
--- /dev/null
+++ b/src/test/ui/generator/reborrow-mut-upvar.stderr
@@ -0,0 +1,17 @@
+warning: unused generator that must be used
+  --> $DIR/reborrow-mut-upvar.rs:6:5
+   |
+LL | /     || {
+LL | |         {
+LL | |             let _baz = &*bar;
+LL | |             yield;
+...  |
+LL | |         *bar = 2;
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generator/too-live-local-in-immovable-gen.rs b/src/test/ui/generator/too-live-local-in-immovable-gen.rs
index f299a8aa72b..7f118c88e5e 100644
--- a/src/test/ui/generator/too-live-local-in-immovable-gen.rs
+++ b/src/test/ui/generator/too-live-local-in-immovable-gen.rs
@@ -5,7 +5,7 @@
 
 fn main() {
     unsafe {
-        static move || {
+        static move || { //~ WARN unused generator that must be used
             // Tests that the generator transformation finds out that `a` is not live
             // during the yield expression. Type checking will also compute liveness
             // and it should also find out that `a` is not live.
diff --git a/src/test/ui/generator/too-live-local-in-immovable-gen.stderr b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr
new file mode 100644
index 00000000000..88dacff7b55
--- /dev/null
+++ b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr
@@ -0,0 +1,17 @@
+warning: unused generator that must be used
+  --> $DIR/too-live-local-in-immovable-gen.rs:8:9
+   |
+LL | /         static move || {
+LL | |             // Tests that the generator transformation finds out that `a` is not live
+LL | |             // during the yield expression. Type checking will also compute liveness
+LL | |             // and it should also find out that `a` is not live.
+...  |
+LL | |             &a;
+LL | |         };
+   | |__________^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generator/yield-in-args-rev.rs b/src/test/ui/generator/yield-in-args-rev.rs
index f9ab981121a..4c99bb3ef5e 100644
--- a/src/test/ui/generator/yield-in-args-rev.rs
+++ b/src/test/ui/generator/yield-in-args-rev.rs
@@ -10,7 +10,7 @@
 fn foo(_a: (), _b: &bool) {}
 
 fn bar() {
-    || {
+    || { //~ WARN unused generator that must be used
         let b = true;
         foo(yield, &b);
     };
diff --git a/src/test/ui/generator/yield-in-args-rev.stderr b/src/test/ui/generator/yield-in-args-rev.stderr
new file mode 100644
index 00000000000..a575bf88678
--- /dev/null
+++ b/src/test/ui/generator/yield-in-args-rev.stderr
@@ -0,0 +1,14 @@
+warning: unused generator that must be used
+  --> $DIR/yield-in-args-rev.rs:13:5
+   |
+LL | /     || {
+LL | |         let b = true;
+LL | |         foo(yield, &b);
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generator/yield-in-box.rs b/src/test/ui/generator/yield-in-box.rs
index d8475715c7c..65f368df9cb 100644
--- a/src/test/ui/generator/yield-in-box.rs
+++ b/src/test/ui/generator/yield-in-box.rs
@@ -6,7 +6,7 @@
 
 fn main() {
     let x = 0i32;
-    || {
+    || { //~ WARN unused generator that must be used
         let y = 2u32;
         {
             let _t = box (&x, yield 0, &y);
diff --git a/src/test/ui/generator/yield-in-box.stderr b/src/test/ui/generator/yield-in-box.stderr
new file mode 100644
index 00000000000..24de18edb0f
--- /dev/null
+++ b/src/test/ui/generator/yield-in-box.stderr
@@ -0,0 +1,17 @@
+warning: unused generator that must be used
+  --> $DIR/yield-in-box.rs:9:5
+   |
+LL | /     || {
+LL | |         let y = 2u32;
+LL | |         {
+LL | |             let _t = box (&x, yield 0, &y);
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generator/yield-in-initializer.rs b/src/test/ui/generator/yield-in-initializer.rs
index 8ff35d8ddf1..2f8754c9571 100644
--- a/src/test/ui/generator/yield-in-initializer.rs
+++ b/src/test/ui/generator/yield-in-initializer.rs
@@ -3,7 +3,7 @@
 #![feature(generators)]
 
 fn main() {
-    static || {
+    static || { //~ WARN unused generator that must be used
         loop {
             // Test that `opt` is not live across the yield, even when borrowed in a loop
             // See https://github.com/rust-lang/rust/issues/52792
diff --git a/src/test/ui/generator/yield-in-initializer.stderr b/src/test/ui/generator/yield-in-initializer.stderr
new file mode 100644
index 00000000000..e79047ae701
--- /dev/null
+++ b/src/test/ui/generator/yield-in-initializer.stderr
@@ -0,0 +1,17 @@
+warning: unused generator that must be used
+  --> $DIR/yield-in-initializer.rs:6:5
+   |
+LL | /     static || {
+LL | |         loop {
+LL | |             // Test that `opt` is not live across the yield, even when borrowed in a loop
+LL | |             // See https://github.com/rust-lang/rust/issues/52792
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generator/yield-subtype.rs b/src/test/ui/generator/yield-subtype.rs
index fe88d424dd1..cb3fc909145 100644
--- a/src/test/ui/generator/yield-subtype.rs
+++ b/src/test/ui/generator/yield-subtype.rs
@@ -8,7 +8,7 @@ fn bar<'a>() {
     let a: &'static str = "hi";
     let b: &'a str = a;
 
-    || {
+    || { //~ WARN unused generator that must be used
         yield a;
         yield b;
     };
diff --git a/src/test/ui/generator/yield-subtype.stderr b/src/test/ui/generator/yield-subtype.stderr
new file mode 100644
index 00000000000..bded36a4cda
--- /dev/null
+++ b/src/test/ui/generator/yield-subtype.stderr
@@ -0,0 +1,14 @@
+warning: unused generator that must be used
+  --> $DIR/yield-subtype.rs:11:5
+   |
+LL | /     || {
+LL | |         yield a;
+LL | |         yield b;
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
index 904efda903c..904efda903c 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
index b536e1b5548..12ad8642961 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-hair-lower-empty.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
@@ -1,155 +1,155 @@
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:12:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:12:11
    |
 LL |     m!(0, ..core::u8::MIN);
    |           ^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:15:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:15:11
    |
 LL |     m!(0, ..core::u16::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:18:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:18:11
    |
 LL |     m!(0, ..core::u32::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:21:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:21:11
    |
 LL |     m!(0, ..core::u64::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:24:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:24:11
    |
 LL |     m!(0, ..core::u128::MIN);
    |           ^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:28:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:28:11
    |
 LL |     m!(0, ..core::i8::MIN);
    |           ^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:31:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:31:11
    |
 LL |     m!(0, ..core::i16::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:34:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:34:11
    |
 LL |     m!(0, ..core::i32::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:37:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:37:11
    |
 LL |     m!(0, ..core::i64::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:40:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:40:11
    |
 LL |     m!(0, ..core::i128::MIN);
    |           ^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:44:14
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:44:14
    |
 LL |     m!(0f32, ..core::f32::NEG_INFINITY);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:47:14
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:47:14
    |
 LL |     m!(0f64, ..core::f64::NEG_INFINITY);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:51:13
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:51:13
    |
 LL |     m!('a', ..'\u{0}');
    |             ^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:12:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:12:11
    |
 LL |     m!(0, ..core::u8::MIN);
    |           ^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:15:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:15:11
    |
 LL |     m!(0, ..core::u16::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:18:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:18:11
    |
 LL |     m!(0, ..core::u32::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:21:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:21:11
    |
 LL |     m!(0, ..core::u64::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:24:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:24:11
    |
 LL |     m!(0, ..core::u128::MIN);
    |           ^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:28:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:28:11
    |
 LL |     m!(0, ..core::i8::MIN);
    |           ^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:31:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:31:11
    |
 LL |     m!(0, ..core::i16::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:34:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:34:11
    |
 LL |     m!(0, ..core::i32::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:37:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:37:11
    |
 LL |     m!(0, ..core::i64::MIN);
    |           ^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:40:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:40:11
    |
 LL |     m!(0, ..core::i128::MIN);
    |           ^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:44:14
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:44:14
    |
 LL |     m!(0f32, ..core::f32::NEG_INFINITY);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:47:14
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:47:14
    |
 LL |     m!(0f64, ..core::f64::NEG_INFINITY);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-hair-lower-empty.rs:51:13
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:51:13
    |
 LL |     m!('a', ..'\u{0}');
    |             ^^^^^^^^^
diff --git a/src/test/ui/issues/issue-1460.rs b/src/test/ui/issues/issue-1460.rs
index 143a0387e21..e663f7fd4c9 100644
--- a/src/test/ui/issues/issue-1460.rs
+++ b/src/test/ui/issues/issue-1460.rs
@@ -3,5 +3,5 @@
 // pretty-expanded FIXME #23616
 
 pub fn main() {
-    {|i: u32| if 1 == i { }};
+    {|i: u32| if 1 == i { }}; //~ WARN unused closure that must be used
 }
diff --git a/src/test/ui/issues/issue-1460.stderr b/src/test/ui/issues/issue-1460.stderr
new file mode 100644
index 00000000000..26f95f5af3d
--- /dev/null
+++ b/src/test/ui/issues/issue-1460.stderr
@@ -0,0 +1,11 @@
+warning: unused closure that must be used
+  --> $DIR/issue-1460.rs:6:5
+   |
+LL |     {|i: u32| if 1 == i { }};
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: closures are lazy and do nothing unless called
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/issues/issue-16256.rs b/src/test/ui/issues/issue-16256.rs
index e566eede8d2..eec23437bcb 100644
--- a/src/test/ui/issues/issue-16256.rs
+++ b/src/test/ui/issues/issue-16256.rs
@@ -3,5 +3,5 @@
 
 fn main() {
     let mut buf = Vec::new();
-    |c: u8| buf.push(c);
+    |c: u8| buf.push(c); //~ WARN unused closure that must be used
 }
diff --git a/src/test/ui/issues/issue-16256.stderr b/src/test/ui/issues/issue-16256.stderr
new file mode 100644
index 00000000000..9c7312461c4
--- /dev/null
+++ b/src/test/ui/issues/issue-16256.stderr
@@ -0,0 +1,11 @@
+warning: unused closure that must be used
+  --> $DIR/issue-16256.rs:6:5
+   |
+LL |     |c: u8| buf.push(c);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: closures are lazy and do nothing unless called
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/issues/issue-17337.rs b/src/test/ui/issues/issue-17337.rs
index 65f2f8fc5ac..3fd81401e00 100644
--- a/src/test/ui/issues/issue-17337.rs
+++ b/src/test/ui/issues/issue-17337.rs
@@ -13,5 +13,5 @@ impl Foo {
 
 fn main() {
     Foo
-    .foo(); //~ ERROR use of deprecated item
+    .foo(); //~ ERROR use of deprecated
 }
diff --git a/src/test/ui/issues/issue-17337.stderr b/src/test/ui/issues/issue-17337.stderr
index 4a8116b1ffd..34c2eb05fff 100644
--- a/src/test/ui/issues/issue-17337.stderr
+++ b/src/test/ui/issues/issue-17337.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated item 'Foo::foo': text
+error: use of deprecated associated function `Foo::foo`: text
   --> $DIR/issue-17337.rs:16:6
    |
 LL |     .foo();
diff --git a/src/test/ui/issues/issue-37131.rs b/src/test/ui/issues/issue-37131.rs
index aa3b6ea86bb..ac2d1d1ed8b 100644
--- a/src/test/ui/issues/issue-37131.rs
+++ b/src/test/ui/issues/issue-37131.rs
@@ -3,6 +3,7 @@
 
 // compile-flags: --target=thumbv6m-none-eabi
 // ignore-arm
+// needs-llvm-components: arm
 
 // error-pattern:target may not be installed
 fn main() { }
diff --git a/src/test/ui/issues/issue-49851/compiler-builtins-error.rs b/src/test/ui/issues/issue-49851/compiler-builtins-error.rs
index 9449376513f..ddb070ddf9f 100644
--- a/src/test/ui/issues/issue-49851/compiler-builtins-error.rs
+++ b/src/test/ui/issues/issue-49851/compiler-builtins-error.rs
@@ -1,6 +1,7 @@
 //~ ERROR 1:1: 1:1: can't find crate for `core` [E0463]
 
 // compile-flags: --target thumbv7em-none-eabihf
+// needs-llvm-components: arm
 #![deny(unsafe_code)]
 #![deny(warnings)]
 #![no_std]
diff --git a/src/test/ui/issues/issue-50993.rs b/src/test/ui/issues/issue-50993.rs
index d38eb826678..e6a9451a060 100644
--- a/src/test/ui/issues/issue-50993.rs
+++ b/src/test/ui/issues/issue-50993.rs
@@ -1,4 +1,5 @@
 // compile-flags: --crate-type dylib --target thumbv7em-none-eabihf
+// needs-llvm-components: arm
 // build-pass
 // error-pattern: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
 
diff --git a/src/test/ui/issues/issue-72574-1.rs b/src/test/ui/issues/issue-72574-1.rs
index efbb0bfb150..1b80a21793a 100644
--- a/src/test/ui/issues/issue-72574-1.rs
+++ b/src/test/ui/issues/issue-72574-1.rs
@@ -6,3 +6,5 @@ fn main() {
     }
 }
 //~^^^^ ERROR `_x @` is not allowed in a tuple
+//~| ERROR: `..` patterns are not allowed here
+//~| ERROR: mismatched types
diff --git a/src/test/ui/issues/issue-72574-1.stderr b/src/test/ui/issues/issue-72574-1.stderr
index 329f7d008d4..92ebb45e88d 100644
--- a/src/test/ui/issues/issue-72574-1.stderr
+++ b/src/test/ui/issues/issue-72574-1.stderr
@@ -10,5 +10,25 @@ help: if you don't need to use the contents of _x, discard the tuple's remaining
 LL |         (_a, ..) => {}
    |              ^^
 
-error: aborting due to previous error
+error: `..` patterns are not allowed here
+  --> $DIR/issue-72574-1.rs:4:19
+   |
+LL |         (_a, _x @ ..) => {}
+   |                   ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error[E0308]: mismatched types
+  --> $DIR/issue-72574-1.rs:4:9
+   |
+LL |     match x {
+   |           - this expression has type `({integer}, {integer}, {integer})`
+LL |         (_a, _x @ ..) => {}
+   |         ^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 2 elements
+   |
+   = note: expected tuple `({integer}, {integer}, {integer})`
+              found tuple `(_, _)`
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-72574-2.rs b/src/test/ui/issues/issue-72574-2.rs
index 0c8f6fcc508..0ad2db848b2 100644
--- a/src/test/ui/issues/issue-72574-2.rs
+++ b/src/test/ui/issues/issue-72574-2.rs
@@ -8,3 +8,5 @@ fn main() {
     }
 }
 //~^^^^ ERROR `_x @` is not allowed in a tuple struct
+//~| ERROR: `..` patterns are not allowed here
+//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr
index 6faa57bcca6..0a9c868af7a 100644
--- a/src/test/ui/issues/issue-72574-2.stderr
+++ b/src/test/ui/issues/issue-72574-2.stderr
@@ -10,5 +10,23 @@ help: if you don't need to use the contents of _x, discard the tuple's remaining
 LL |         Binder(_a, ..) => {}
    |                    ^^
 
-error: aborting due to previous error
+error: `..` patterns are not allowed here
+  --> $DIR/issue-72574-2.rs:6:25
+   |
+LL |         Binder(_a, _x @ ..) => {}
+   |                         ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/issue-72574-2.rs:6:9
+   |
+LL | struct Binder(i32, i32, i32);
+   | ----------------------------- tuple struct defined here
+...
+LL |         Binder(_a, _x @ ..) => {}
+   |         ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0023`.
diff --git a/src/test/ui/issues/issue-74539.rs b/src/test/ui/issues/issue-74539.rs
deleted file mode 100644
index 75632d11c1d..00000000000
--- a/src/test/ui/issues/issue-74539.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-enum E {
-    A(u8, u8),
-}
-
-fn main() {
-    let e = E::A(2, 3);
-    match e {
-        E::A(x @ ..) => {  //~ ERROR `x @` is not allowed in a tuple
-            x //~ ERROR cannot find value `x` in this scope
-        }
-    };
-}
diff --git a/src/test/ui/issues/issue-74539.stderr b/src/test/ui/issues/issue-74539.stderr
deleted file mode 100644
index 94526dcd7cb..00000000000
--- a/src/test/ui/issues/issue-74539.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0425]: cannot find value `x` in this scope
-  --> $DIR/issue-74539.rs:9:13
-   |
-LL |             x
-   |             ^ help: a local variable with a similar name exists: `e`
-
-error: `x @` is not allowed in a tuple struct
-  --> $DIR/issue-74539.rs:8:14
-   |
-LL |         E::A(x @ ..) => {
-   |              ^^^^^^ this is only allowed in slice patterns
-   |
-   = help: remove this and bind each tuple field independently
-help: if you don't need to use the contents of x, discard the tuple's remaining fields
-   |
-LL |         E::A(..) => {
-   |              ^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-74614.rs b/src/test/ui/issues/issue-74614.rs
index f5e8deb29fb..8b0c00b1355 100644
--- a/src/test/ui/issues/issue-74614.rs
+++ b/src/test/ui/issues/issue-74614.rs
@@ -1,3 +1,4 @@
+// compile-flags:-Zpolymorphize=on
 // build-pass
 
 fn test<T>() {
diff --git a/src/test/ui/lint/auxiliary/external_extern_fn.rs b/src/test/ui/lint/auxiliary/external_extern_fn.rs
index b2caebc6fee..c2a8cadc6b5 100644
--- a/src/test/ui/lint/auxiliary/external_extern_fn.rs
+++ b/src/test/ui/lint/auxiliary/external_extern_fn.rs
@@ -1,3 +1,3 @@
-extern {
+extern "C" {
     pub fn extern_fn(x: u8);
 }
diff --git a/src/test/ui/lint/clashing-extern-fn.rs b/src/test/ui/lint/clashing-extern-fn.rs
index 544614100ba..d6ac7ccccc7 100644
--- a/src/test/ui/lint/clashing-extern-fn.rs
+++ b/src/test/ui/lint/clashing-extern-fn.rs
@@ -3,52 +3,40 @@
 #![crate_type = "lib"]
 #![warn(clashing_extern_declarations)]
 
-extern crate external_extern_fn;
-
-extern "C" {
-    fn clash(x: u8);
-    fn no_clash(x: u8);
-}
-
-fn redeclared_different_signature() {
-    extern "C" {
-        fn clash(x: u64); //~ WARN `clash` redeclared with a different signature
+mod redeclared_different_signature {
+    mod a {
+        extern "C" {
+            fn clash(x: u8);
+        }
     }
-
-    unsafe {
-        clash(123);
-        no_clash(123);
+    mod b {
+        extern "C" {
+            fn clash(x: u64); //~ WARN `clash` redeclared with a different signature
+        }
     }
 }
 
-fn redeclared_same_signature() {
-    extern "C" {
-        fn no_clash(x: u8);
+mod redeclared_same_signature {
+    mod a {
+        extern "C" {
+            fn no_clash(x: u8);
+        }
     }
-    unsafe {
-        no_clash(123);
+    mod b {
+        extern "C" {
+            fn no_clash(x: u8);
+        }
     }
 }
 
-extern "C" {
-    fn extern_fn(x: u64);
-}
-
-fn extern_clash() {
+extern crate external_extern_fn;
+mod extern_no_clash {
+    // Should not clash with external_extern_fn::extern_fn.
     extern "C" {
-        fn extern_fn(x: u32); //~ WARN `extern_fn` redeclared with a different signature
-    }
-    unsafe {
-        extern_fn(123);
+        fn extern_fn(x: u8);
     }
 }
 
-fn extern_no_clash() {
-    unsafe {
-        external_extern_fn::extern_fn(123);
-        crate::extern_fn(123);
-    }
-}
 extern "C" {
     fn some_other_new_name(x: i16);
 
@@ -134,9 +122,9 @@ mod banana {
             weight: u32,
             length: u16,
         } // note: distinct type
-        extern "C" {
           // This should not trigger the lint because two::Banana is structurally equivalent to
           // one::Banana.
+        extern "C" {
             fn weigh_banana(count: *const Banana) -> u64;
         }
     }
@@ -180,7 +168,120 @@ mod sameish_members {
         // always be the case, for every architecture and situation. This is also a really odd
         // thing to do anyway.
         extern "C" {
-            fn draw_point(p: Point); //~ WARN `draw_point` redeclared with a different
+            fn draw_point(p: Point);
+            //~^ WARN `draw_point` redeclared with a different signature
+        }
+    }
+}
+
+mod same_sized_members_clash {
+    mod a {
+        #[repr(C)]
+        struct Point3 {
+            x: f32,
+            y: f32,
+            z: f32,
+        }
+        extern "C" { fn origin() -> Point3; }
+    }
+    mod b {
+        #[repr(C)]
+        struct Point3 {
+            x: i32,
+            y: i32,
+            z: i32, // NOTE: Incorrectly redeclared as i32
+        }
+        extern "C" { fn origin() -> Point3; }
+        //~^ WARN `origin` redeclared with a different signature
+    }
+}
+
+mod transparent {
+    #[repr(transparent)]
+    struct T(usize);
+    mod a {
+        use super::T;
+        extern "C" {
+            fn transparent() -> T;
+            fn transparent_incorrect() -> T;
+        }
+    }
+
+    mod b {
+        extern "C" {
+            // Shouldn't warn here, because repr(transparent) guarantees that T's layout is the
+            // same as just the usize.
+            fn transparent() -> usize;
+
+            // Should warn, because there's a signedness conversion here:
+            fn transparent_incorrect() -> isize;
+            //~^ WARN `transparent_incorrect` redeclared with a different signature
+        }
+    }
+}
+
+mod missing_return_type {
+    mod a {
+        extern "C" {
+            fn missing_return_type() -> usize;
+        }
+    }
+
+    mod b {
+        extern "C" {
+            // This should output a warning because we can't assume that the first declaration is
+            // the correct one -- if this one is the correct one, then calling the usize-returning
+            // version would allow reads into uninitialised memory.
+            fn missing_return_type();
+            //~^ WARN `missing_return_type` redeclared with a different signature
+        }
+    }
+}
+
+mod non_zero_and_non_null {
+    mod a {
+        extern "C" {
+            fn non_zero_usize() -> core::num::NonZeroUsize;
+            fn non_null_ptr() -> core::ptr::NonNull<usize>;
+        }
+    }
+    mod b {
+        extern "C" {
+            // If there's a clash in either of these cases you're either gaining an incorrect
+            // invariant that the value is non-zero, or you're missing out on that invariant. Both
+            // cases are warning for, from both a caller-convenience and optimisation perspective.
+            fn non_zero_usize() -> usize;
+            //~^ WARN `non_zero_usize` redeclared with a different signature
+            fn non_null_ptr() -> *const usize;
+            //~^ WARN `non_null_ptr` redeclared with a different signature
+        }
+    }
+}
+
+mod null_optimised_enums {
+    mod a {
+        extern "C" {
+            fn option_non_zero_usize() -> usize;
+            fn option_non_zero_isize() -> isize;
+            fn option_non_null_ptr() -> *const usize;
+
+            fn option_non_zero_usize_incorrect() -> usize;
+            fn option_non_null_ptr_incorrect() -> *const usize;
+        }
+    }
+    mod b {
+        extern "C" {
+            // This should be allowed, because these conversions are guaranteed to be FFI-safe (see
+            // #60300)
+            fn option_non_zero_usize() -> Option<core::num::NonZeroUsize>;
+            fn option_non_zero_isize() -> Option<core::num::NonZeroIsize>;
+            fn option_non_null_ptr() -> Option<core::ptr::NonNull<usize>>;
+
+            // However, these should be incorrect (note isize instead of usize)
+            fn option_non_zero_usize_incorrect() -> isize;
+            //~^ WARN `option_non_zero_usize_incorrect` redeclared with a different signature
+            fn option_non_null_ptr_incorrect() -> *const isize;
+            //~^ WARN `option_non_null_ptr_incorrect` redeclared with a different signature
         }
     }
 }
diff --git a/src/test/ui/lint/clashing-extern-fn.stderr b/src/test/ui/lint/clashing-extern-fn.stderr
index 96e51ab5a3e..cca0c4c59eb 100644
--- a/src/test/ui/lint/clashing-extern-fn.stderr
+++ b/src/test/ui/lint/clashing-extern-fn.stderr
@@ -1,11 +1,11 @@
 warning: `clash` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:15:9
+  --> $DIR/clashing-extern-fn.rs:14:13
    |
-LL |     fn clash(x: u8);
-   |     ---------------- `clash` previously declared here
+LL |             fn clash(x: u8);
+   |             ---------------- `clash` previously declared here
 ...
-LL |         fn clash(x: u64);
-   |         ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+LL |             fn clash(x: u64);
+   |             ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
    |
 note: the lint level is defined here
   --> $DIR/clashing-extern-fn.rs:4:9
@@ -15,20 +15,8 @@ LL | #![warn(clashing_extern_declarations)]
    = note: expected `unsafe extern "C" fn(u8)`
               found `unsafe extern "C" fn(u64)`
 
-warning: `extern_fn` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:39:9
-   |
-LL |     fn extern_fn(x: u64);
-   |     --------------------- `extern_fn` previously declared here
-...
-LL |         fn extern_fn(x: u32);
-   |         ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
-   |
-   = note: expected `unsafe extern "C" fn(u64)`
-              found `unsafe extern "C" fn(u32)`
-
 warning: `extern_link_name` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:64:9
+  --> $DIR/clashing-extern-fn.rs:52:9
    |
 LL | /     #[link_name = "extern_link_name"]
 LL | |     fn some_new_name(x: i16);
@@ -41,7 +29,7 @@ LL |           fn extern_link_name(x: u32);
               found `unsafe extern "C" fn(u32)`
 
 warning: `some_other_extern_link_name` redeclares `some_other_new_name` with a different signature
-  --> $DIR/clashing-extern-fn.rs:67:9
+  --> $DIR/clashing-extern-fn.rs:55:9
    |
 LL |       fn some_other_new_name(x: i16);
    |       ------------------------------- `some_other_new_name` previously declared here
@@ -55,7 +43,7 @@ LL | |         fn some_other_extern_link_name(x: u32);
               found `unsafe extern "C" fn(u32)`
 
 warning: `other_both_names_different` redeclares `link_name_same` with a different signature
-  --> $DIR/clashing-extern-fn.rs:71:9
+  --> $DIR/clashing-extern-fn.rs:59:9
    |
 LL | /     #[link_name = "link_name_same"]
 LL | |     fn both_names_different(x: i16);
@@ -70,7 +58,7 @@ LL | |         fn other_both_names_different(x: u32);
               found `unsafe extern "C" fn(u32)`
 
 warning: `different_mod` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:84:9
+  --> $DIR/clashing-extern-fn.rs:72:9
    |
 LL |         fn different_mod(x: u8);
    |         ------------------------ `different_mod` previously declared here
@@ -82,7 +70,7 @@ LL |         fn different_mod(x: u64);
               found `unsafe extern "C" fn(u64)`
 
 warning: `variadic_decl` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:94:9
+  --> $DIR/clashing-extern-fn.rs:82:9
    |
 LL |     fn variadic_decl(x: u8, ...);
    |     ----------------------------- `variadic_decl` previously declared here
@@ -94,7 +82,7 @@ LL |         fn variadic_decl(x: u8);
               found `unsafe extern "C" fn(u8)`
 
 warning: `weigh_banana` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:154:13
+  --> $DIR/clashing-extern-fn.rs:142:13
    |
 LL |             fn weigh_banana(count: *const Banana) -> u64;
    |             --------------------------------------------- `weigh_banana` previously declared here
@@ -106,7 +94,7 @@ LL |             fn weigh_banana(count: *const Banana) -> u64;
               found `unsafe extern "C" fn(*const banana::three::Banana) -> u64`
 
 warning: `draw_point` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:183:13
+  --> $DIR/clashing-extern-fn.rs:171:13
    |
 LL |             fn draw_point(p: Point);
    |             ------------------------ `draw_point` previously declared here
@@ -117,5 +105,89 @@ LL |             fn draw_point(p: Point);
    = note: expected `unsafe extern "C" fn(sameish_members::a::Point)`
               found `unsafe extern "C" fn(sameish_members::b::Point)`
 
-warning: 9 warnings emitted
+warning: `origin` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:194:22
+   |
+LL |         extern "C" { fn origin() -> Point3; }
+   |                      ---------------------- `origin` previously declared here
+...
+LL |         extern "C" { fn origin() -> Point3; }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> same_sized_members_clash::a::Point3`
+              found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3`
+
+warning: `transparent_incorrect` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:217:13
+   |
+LL |             fn transparent_incorrect() -> T;
+   |             -------------------------------- `transparent_incorrect` previously declared here
+...
+LL |             fn transparent_incorrect() -> isize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> transparent::T`
+              found `unsafe extern "C" fn() -> isize`
+
+warning: `missing_return_type` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:235:13
+   |
+LL |             fn missing_return_type() -> usize;
+   |             ---------------------------------- `missing_return_type` previously declared here
+...
+LL |             fn missing_return_type();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> usize`
+              found `unsafe extern "C" fn()`
+
+warning: `non_zero_usize` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:253:13
+   |
+LL |             fn non_zero_usize() -> core::num::NonZeroUsize;
+   |             ----------------------------------------------- `non_zero_usize` previously declared here
+...
+LL |             fn non_zero_usize() -> usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> std::num::NonZeroUsize`
+              found `unsafe extern "C" fn() -> usize`
+
+warning: `non_null_ptr` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:255:13
+   |
+LL |             fn non_null_ptr() -> core::ptr::NonNull<usize>;
+   |             ----------------------------------------------- `non_null_ptr` previously declared here
+...
+LL |             fn non_null_ptr() -> *const usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> std::ptr::NonNull<usize>`
+              found `unsafe extern "C" fn() -> *const usize`
+
+warning: `option_non_zero_usize_incorrect` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:281:13
+   |
+LL |             fn option_non_zero_usize_incorrect() -> usize;
+   |             ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here
+...
+LL |             fn option_non_zero_usize_incorrect() -> isize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> usize`
+              found `unsafe extern "C" fn() -> isize`
+
+warning: `option_non_null_ptr_incorrect` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:283:13
+   |
+LL |             fn option_non_null_ptr_incorrect() -> *const usize;
+   |             --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here
+...
+LL |             fn option_non_null_ptr_incorrect() -> *const isize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> *const usize`
+              found `unsafe extern "C" fn() -> *const isize`
+
+warning: 15 warnings emitted
 
diff --git a/src/test/ui/lint/issue-74883-unused-paren-baren-yield.rs b/src/test/ui/lint/issue-74883-unused-paren-baren-yield.rs
new file mode 100644
index 00000000000..02182ec2993
--- /dev/null
+++ b/src/test/ui/lint/issue-74883-unused-paren-baren-yield.rs
@@ -0,0 +1,33 @@
+#![feature(generator_trait)]
+#![feature(generators)]
+#![deny(unused_braces, unused_parens)]
+
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn main() {
+    let mut x = |_| {
+        while let Some(_) = (yield) {}
+        while let Some(_) = {yield} {}
+
+        // Only warn these cases
+        while let Some(_) = ({yield}) {} //~ ERROR: unnecessary parentheses
+        while let Some(_) = ((yield)) {} //~ ERROR: unnecessary parentheses
+        {{yield}}; //~ ERROR: unnecessary braces
+        {( yield )}; //~ ERROR: unnecessary parentheses
+
+        // FIXME: Reduce duplicate warnings.
+        // Perhaps we should tweak checks in `BlockRetValue`?
+        while let Some(_) = {(yield)} {}
+        //~^ ERROR: unnecessary braces
+        //~| ERROR: unnecessary parentheses
+        while let Some(_) = {{yield}} {}
+        //~^ ERROR: unnecessary braces
+        //~| ERROR: unnecessary braces
+
+        // FIXME: It'd be great if we could also warn them.
+        ((yield));
+        ({ yield });
+    };
+    let _ = Pin::new(&mut x).resume(Some(5));
+}
diff --git a/src/test/ui/lint/issue-74883-unused-paren-baren-yield.stderr b/src/test/ui/lint/issue-74883-unused-paren-baren-yield.stderr
new file mode 100644
index 00000000000..267cc9e031a
--- /dev/null
+++ b/src/test/ui/lint/issue-74883-unused-paren-baren-yield.stderr
@@ -0,0 +1,62 @@
+error: unnecessary parentheses around `let` scrutinee expression
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:14:29
+   |
+LL |         while let Some(_) = ({yield}) {}
+   |                             ^^^^^^^^^ help: remove these parentheses
+   |
+note: the lint level is defined here
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:24
+   |
+LL | #![deny(unused_braces, unused_parens)]
+   |                        ^^^^^^^^^^^^^
+
+error: unnecessary parentheses around `let` scrutinee expression
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:15:29
+   |
+LL |         while let Some(_) = ((yield)) {}
+   |                             ^^^^^^^^^ help: remove these parentheses
+
+error: unnecessary braces around block return value
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:16:10
+   |
+LL |         {{yield}};
+   |          ^^^^^^^ help: remove these braces
+   |
+note: the lint level is defined here
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:9
+   |
+LL | #![deny(unused_braces, unused_parens)]
+   |         ^^^^^^^^^^^^^
+
+error: unnecessary parentheses around block return value
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:17:10
+   |
+LL |         {( yield )};
+   |          ^^^^^^^^^ help: remove these parentheses
+
+error: unnecessary braces around `let` scrutinee expression
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:21:29
+   |
+LL |         while let Some(_) = {(yield)} {}
+   |                             ^^^^^^^^^ help: remove these braces
+
+error: unnecessary parentheses around block return value
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:21:30
+   |
+LL |         while let Some(_) = {(yield)} {}
+   |                              ^^^^^^^ help: remove these parentheses
+
+error: unnecessary braces around `let` scrutinee expression
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:24:29
+   |
+LL |         while let Some(_) = {{yield}} {}
+   |                             ^^^^^^^^^ help: remove these braces
+
+error: unnecessary braces around block return value
+  --> $DIR/issue-74883-unused-paren-baren-yield.rs:24:30
+   |
+LL |         while let Some(_) = {{yield}} {}
+   |                              ^^^^^^^ help: remove these braces
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs
index 4f90bd98c63..034499145b7 100644
--- a/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs
@@ -23,7 +23,7 @@ struct _ヒb;
 struct __χa;
 //~^ ERROR type `__χa` should have an upper camel case name
 
-// Besides this, we cannot have two continous underscores in the middle.
+// Besides this, we cannot have two continuous underscores in the middle.
 
 struct 对__否;
 //~^ ERROR type `对__否` should have an upper camel case name
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs
index 813e0ea5c57..0b52a5fde35 100644
--- a/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs
@@ -18,7 +18,7 @@ fn 编程() {}
 fn Ц() {}
 //~^ ERROR function `Ц` should have a snake case name
 
-// besides this, you cannot use continous underscores in the middle
+// besides this, you cannot use continuous underscores in the middle
 
 fn 分__隔() {}
 //~^ ERROR function `分__隔` should have a snake case name
diff --git a/src/test/ui/lint/lint-output-format-2.rs b/src/test/ui/lint/lint-output-format-2.rs
index 521472d99b1..985166e095d 100644
--- a/src/test/ui/lint/lint-output-format-2.rs
+++ b/src/test/ui/lint/lint-output-format-2.rs
@@ -5,11 +5,11 @@
 
 extern crate lint_output_format;
 use lint_output_format::{foo, bar};
-//~^ WARNING use of deprecated item 'lint_output_format::foo': text
+//~^ WARNING use of deprecated function `lint_output_format::foo`: text
 
 
 fn main() {
     let _x = foo();
-    //~^ WARNING use of deprecated item 'lint_output_format::foo': text
+    //~^ WARNING use of deprecated function `lint_output_format::foo`: text
     let _y = bar();
 }
diff --git a/src/test/ui/lint/lint-output-format-2.stderr b/src/test/ui/lint/lint-output-format-2.stderr
index a95fd69fb01..a36dbd61fdc 100644
--- a/src/test/ui/lint/lint-output-format-2.stderr
+++ b/src/test/ui/lint/lint-output-format-2.stderr
@@ -1,4 +1,4 @@
-warning: use of deprecated item 'lint_output_format::foo': text
+warning: use of deprecated function `lint_output_format::foo`: text
   --> $DIR/lint-output-format-2.rs:7:26
    |
 LL | use lint_output_format::{foo, bar};
@@ -6,7 +6,7 @@ LL | use lint_output_format::{foo, bar};
    |
    = note: `#[warn(deprecated)]` on by default
 
-warning: use of deprecated item 'lint_output_format::foo': text
+warning: use of deprecated function `lint_output_format::foo`: text
   --> $DIR/lint-output-format-2.rs:12:14
    |
 LL |     let _x = foo();
diff --git a/src/test/ui/lint/lint-stability-deprecated.rs b/src/test/ui/lint/lint-stability-deprecated.rs
index 4b407a29f64..a6fde11495c 100644
--- a/src/test/ui/lint/lint-stability-deprecated.rs
+++ b/src/test/ui/lint/lint-stability-deprecated.rs
@@ -22,41 +22,41 @@ mod cross_crate {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ WARN use of deprecated item 'lint_stability::deprecated'
-        foo.method_deprecated(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated'
-        Foo::method_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated'
-        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated'
-        foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
-        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
-        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
-        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
-
-        deprecated_text(); //~ WARN use of deprecated item 'lint_stability::deprecated_text': text
-        foo.method_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
-        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
-        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-
-        deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::deprecated_unstable'
-        foo.method_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable'
-        Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable'
-        <Foo>::method_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable'
-        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
-        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
-        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
-        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
-
-        deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::deprecated_unstable_text': text
-        foo.method_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
-        Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
-        <Foo>::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
-        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        deprecated(); //~ WARN use of deprecated function `lint_stability::deprecated`
+        foo.method_deprecated(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated`
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated`
+        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated`
+        foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+
+        deprecated_text(); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text
+        foo.method_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
+        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
+        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
+        foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+
+        deprecated_unstable(); //~ WARN use of deprecated function `lint_stability::deprecated_unstable`
+        foo.method_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`
+        Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`
+        <Foo>::method_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+
+        deprecated_unstable_text(); //~ WARN use of deprecated function `lint_stability::deprecated_unstable_text`: text
+        foo.method_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
+        Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
+        <Foo>::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
 
         unstable();
         foo.method_unstable();
@@ -96,38 +96,38 @@ mod cross_crate {
 
         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
-        //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
-        //~| WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+        //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
+        //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
         type A = dyn TraitWithAssociatedTypes<
             TypeUnstable = u8,
             TypeDeprecated = u16,
-            //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
-            //~| WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
-            //~| WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
+            //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`
+            //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`
+            //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`
         >;
 
-        let _ = DeprecatedStruct { //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct'
-            i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct::i'
+        let _ = DeprecatedStruct { //~ WARN use of deprecated struct `lint_stability::DeprecatedStruct`
+            i: 0 //~ WARN use of deprecated field `lint_stability::DeprecatedStruct::i`
         };
         let _ = DeprecatedUnstableStruct {
-            //~^ WARN use of deprecated item 'lint_stability::DeprecatedUnstableStruct'
-            i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedUnstableStruct::i'
+            //~^ WARN use of deprecated struct `lint_stability::DeprecatedUnstableStruct`
+            i: 0 //~ WARN use of deprecated field `lint_stability::DeprecatedUnstableStruct::i`
         };
         let _ = UnstableStruct { i: 0 };
         let _ = StableStruct { i: 0 };
 
-        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item 'lint_stability::DeprecatedUnitStruct'
-        let _ = DeprecatedUnstableUnitStruct; //~ WARN use of deprecated item 'lint_stability::DeprecatedUnstableUnitStruct'
+        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated struct `lint_stability::DeprecatedUnitStruct`
+        let _ = DeprecatedUnstableUnitStruct; //~ WARN use of deprecated struct `lint_stability::DeprecatedUnstableUnitStruct`
         let _ = UnstableUnitStruct;
         let _ = StableUnitStruct;
 
-        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item 'lint_stability::Enum::DeprecatedVariant'
-        let _ = Enum::DeprecatedUnstableVariant; //~ WARN use of deprecated item 'lint_stability::Enum::DeprecatedUnstableVariant'
+        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated variant `lint_stability::Enum::DeprecatedVariant`
+        let _ = Enum::DeprecatedUnstableVariant; //~ WARN use of deprecated variant `lint_stability::Enum::DeprecatedUnstableVariant`
         let _ = Enum::UnstableVariant;
         let _ = Enum::StableVariant;
 
-        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item 'lint_stability::DeprecatedTupleStruct'
-        let _ = DeprecatedUnstableTupleStruct (1); //~ WARN use of deprecated item 'lint_stability::DeprecatedUnstableTupleStruct'
+        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated struct `lint_stability::DeprecatedTupleStruct`
+        let _ = DeprecatedUnstableTupleStruct (1); //~ WARN use of deprecated struct `lint_stability::DeprecatedUnstableTupleStruct`
         let _ = UnstableTupleStruct (1);
         let _ = StableTupleStruct (1);
 
@@ -136,28 +136,28 @@ mod cross_crate {
         // Eventually, we will want to lint the contents of the
         // macro in the module *defining* it. Also, stability levels
         // on macros themselves are not yet linted.
-        macro_test_arg!(deprecated_text()); //~ WARN use of deprecated item 'lint_stability::deprecated_text': text
-        macro_test_arg!(deprecated_unstable_text()); //~ WARN use of deprecated item 'lint_stability::deprecated_unstable_text': text
-        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ WARN use of deprecated item 'lint_stability::deprecated_text': text
+        macro_test_arg!(deprecated_text()); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text
+        macro_test_arg!(deprecated_unstable_text()); //~ WARN use of deprecated function `lint_stability::deprecated_unstable_text`: text
+        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
-        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
-        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
-        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
-        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
-        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
-        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
-        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+        foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
         foo.trait_unstable();
         Trait::trait_unstable(&foo);
         <Foo>::trait_unstable(&foo);
@@ -173,10 +173,10 @@ mod cross_crate {
     }
 
     fn test_method_object(foo: &dyn Trait) {
-        foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
-        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+        foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+        foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
         foo.trait_unstable();
         foo.trait_unstable_text();
         foo.trait_stable();
@@ -185,9 +185,9 @@ mod cross_crate {
     struct S;
 
     impl UnstableTrait for S { }
-    impl DeprecatedTrait for S {} //~ WARN use of deprecated item 'lint_stability::DeprecatedTrait': text
+    impl DeprecatedTrait for S {} //~ WARN use of deprecated trait `lint_stability::DeprecatedTrait`: text
     trait LocalTrait : UnstableTrait { }
-    trait LocalTrait2 : DeprecatedTrait { } //~ WARN use of deprecated item 'lint_stability::DeprecatedTrait': text
+    trait LocalTrait2 : DeprecatedTrait { } //~ WARN use of deprecated trait `lint_stability::DeprecatedTrait`: text
 
     impl Trait for S {
         fn trait_stable(&self) {}
@@ -206,7 +206,7 @@ mod inheritance {
         stable_mod::unstable();
         stable_mod::stable();
 
-        unstable_mod::deprecated(); //~ WARN use of deprecated item 'inheritance::inherited_stability::unstable_mod::deprecated': text
+        unstable_mod::deprecated(); //~ WARN use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text
         unstable_mod::unstable();
 
         let _ = Unstable::UnstableVariant;
@@ -328,23 +328,23 @@ mod this_crate {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ WARN use of deprecated item 'this_crate::deprecated'
-        foo.method_deprecated(); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated'
-        Foo::method_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated'
-        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated'
-        foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
-        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
-        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
-        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
-
-        deprecated_text(); //~ WARN use of deprecated item 'this_crate::deprecated_text': text
-        foo.method_deprecated_text(); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        deprecated(); //~ WARN use of deprecated function `this_crate::deprecated`
+        foo.method_deprecated(); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated`
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated`
+        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated`
+        foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+
+        deprecated_text(); //~ WARN use of deprecated function `this_crate::deprecated_text`: text
+        foo.method_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+        foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
 
         unstable();
         foo.method_unstable();
@@ -383,34 +383,34 @@ mod this_crate {
         <Foo as Trait>::trait_stable_text(&foo);
 
         let _ = DeprecatedStruct {
-            //~^ WARN use of deprecated item 'this_crate::DeprecatedStruct'
-            i: 0 //~ WARN use of deprecated item 'this_crate::DeprecatedStruct::i'
+            //~^ WARN use of deprecated struct `this_crate::DeprecatedStruct`
+            i: 0 //~ WARN use of deprecated field `this_crate::DeprecatedStruct::i`
         };
         let _ = UnstableStruct { i: 0 };
         let _ = StableStruct { i: 0 };
 
-        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item 'this_crate::DeprecatedUnitStruct'
+        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated unit struct `this_crate::DeprecatedUnitStruct`
         let _ = UnstableUnitStruct;
         let _ = StableUnitStruct;
 
-        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item 'this_crate::Enum::DeprecatedVariant'
+        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`
         let _ = Enum::UnstableVariant;
         let _ = Enum::StableVariant;
 
-        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item 'this_crate::DeprecatedTupleStruct'
+        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`
         let _ = UnstableTupleStruct (1);
         let _ = StableTupleStruct (1);
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
-        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
-        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
-        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
         foo.trait_unstable();
         Trait::trait_unstable(&foo);
         <Foo>::trait_unstable(&foo);
@@ -426,8 +426,8 @@ mod this_crate {
     }
 
     fn test_method_object(foo: &dyn Trait) {
-        foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
-        foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+        foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+        foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
         foo.trait_unstable();
         foo.trait_unstable_text();
         foo.trait_stable();
@@ -437,7 +437,7 @@ mod this_crate {
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn test_fn_body() {
         fn fn_in_body() {}
-        fn_in_body(); //~ WARN use of deprecated item 'this_crate::test_fn_body::fn_in_body': text
+        fn_in_body(); //~ WARN use of deprecated function `this_crate::test_fn_body::fn_in_body`: text
     }
 
     impl MethodTester {
@@ -445,7 +445,7 @@ mod this_crate {
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn test_method_body(&self) {
             fn fn_in_body() {}
-            fn_in_body(); //~ WARN use of deprecated item 'this_crate::MethodTester::test_method_body::fn_in_body': text
+            fn_in_body(); //~ WARN use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text
         }
     }
 
@@ -457,9 +457,9 @@ mod this_crate {
 
     struct S;
 
-    impl DeprecatedTrait for S { } //~ WARN use of deprecated item 'this_crate::DeprecatedTrait'
+    impl DeprecatedTrait for S { } //~ WARN use of deprecated trait `this_crate::DeprecatedTrait`
 
-    trait LocalTrait : DeprecatedTrait { } //~ WARN use of deprecated item 'this_crate::DeprecatedTrait'
+    trait LocalTrait : DeprecatedTrait { } //~ WARN use of deprecated trait `this_crate::DeprecatedTrait`
 }
 
 fn main() {}
diff --git a/src/test/ui/lint/lint-stability-deprecated.stderr b/src/test/ui/lint/lint-stability-deprecated.stderr
index 801e04a7f4f..d8dd83b0d06 100644
--- a/src/test/ui/lint/lint-stability-deprecated.stderr
+++ b/src/test/ui/lint/lint-stability-deprecated.stderr
@@ -1,4 +1,4 @@
-warning: use of deprecated item 'lint_stability::deprecated': text
+warning: use of deprecated function `lint_stability::deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:25:9
    |
 LL |         deprecated();
@@ -10,643 +10,643 @@ note: the lint level is defined here
 LL | #![warn(deprecated)]
    |         ^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:30:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:32:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::deprecated_text': text
+warning: use of deprecated function `lint_stability::deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:34:9
    |
 LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:39:9
    |
-LL |         Trait::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Trait::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:41:9
    |
-LL |         <Foo as Trait>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::deprecated_unstable': text
+warning: use of deprecated function `lint_stability::deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:43:9
    |
 LL |         deprecated_unstable();
    |         ^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:48:9
    |
-LL |         Trait::trait_deprecated_unstable(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Trait::trait_deprecated_unstable(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:50:9
    |
-LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_unstable(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::deprecated_unstable_text': text
+warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:52:9
    |
 LL |         deprecated_unstable_text();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:57:9
    |
 LL | ...   Trait::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:59:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedStruct': text
+warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text
   --> $DIR/lint-stability-deprecated.rs:109:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct': text
+warning: use of deprecated struct `lint_stability::DeprecatedUnstableStruct`: text
   --> $DIR/lint-stability-deprecated.rs:112:17
    |
 LL |         let _ = DeprecatedUnstableStruct {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedUnitStruct': text
+warning: use of deprecated struct `lint_stability::DeprecatedUnitStruct`: text
   --> $DIR/lint-stability-deprecated.rs:119:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedUnstableUnitStruct': text
+warning: use of deprecated struct `lint_stability::DeprecatedUnstableUnitStruct`: text
   --> $DIR/lint-stability-deprecated.rs:120:17
    |
 LL |         let _ = DeprecatedUnstableUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Enum::DeprecatedVariant': text
+warning: use of deprecated variant `lint_stability::Enum::DeprecatedVariant`: text
   --> $DIR/lint-stability-deprecated.rs:124:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Enum::DeprecatedUnstableVariant': text
+warning: use of deprecated variant `lint_stability::Enum::DeprecatedUnstableVariant`: text
   --> $DIR/lint-stability-deprecated.rs:125:17
    |
 LL |         let _ = Enum::DeprecatedUnstableVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedTupleStruct': text
+warning: use of deprecated struct `lint_stability::DeprecatedTupleStruct`: text
   --> $DIR/lint-stability-deprecated.rs:129:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedUnstableTupleStruct': text
+warning: use of deprecated struct `lint_stability::DeprecatedUnstableTupleStruct`: text
   --> $DIR/lint-stability-deprecated.rs:130:17
    |
 LL |         let _ = DeprecatedUnstableTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::deprecated_text': text
+warning: use of deprecated function `lint_stability::deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:139:25
    |
 LL |         macro_test_arg!(deprecated_text());
    |                         ^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::deprecated_unstable_text': text
+warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:140:25
    |
 LL |         macro_test_arg!(deprecated_unstable_text());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::deprecated_text': text
+warning: use of deprecated function `lint_stability::deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:141:41
    |
 LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
    |                                         ^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:146:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:148:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:150:9
    |
-LL |         Trait::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Trait::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:152:9
    |
-LL |         <Foo as Trait>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:154:9
    |
-LL |         Trait::trait_deprecated_unstable(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Trait::trait_deprecated_unstable(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:156:9
    |
-LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_unstable(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:158:9
    |
 LL | ...   Trait::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:160:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
+warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text
   --> $DIR/lint-stability-deprecated.rs:188:10
    |
 LL |     impl DeprecatedTrait for S {}
    |          ^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
+warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text
   --> $DIR/lint-stability-deprecated.rs:190:25
    |
 LL |     trait LocalTrait2 : DeprecatedTrait { }
    |                         ^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'inheritance::inherited_stability::unstable_mod::deprecated': text
+warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:209:9
    |
 LL |         unstable_mod::deprecated();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::deprecated': text
+warning: use of deprecated function `this_crate::deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:331:9
    |
 LL |         deprecated();
    |         ^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:336:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:338:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::deprecated_text': text
+warning: use of deprecated function `this_crate::deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:340:9
    |
 LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:345:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:347:9
    |
-LL |         <Foo as Trait>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::DeprecatedStruct': text
+warning: use of deprecated struct `this_crate::DeprecatedStruct`: text
   --> $DIR/lint-stability-deprecated.rs:385:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::DeprecatedUnitStruct': text
+warning: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text
   --> $DIR/lint-stability-deprecated.rs:392:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
+warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text
   --> $DIR/lint-stability-deprecated.rs:396:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::DeprecatedTupleStruct': text
+warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text
   --> $DIR/lint-stability-deprecated.rs:400:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:407:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:409:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:411:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:413:9
    |
-LL |         <Foo as Trait>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::test_fn_body::fn_in_body': text
+warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text
   --> $DIR/lint-stability-deprecated.rs:440:9
    |
 LL |         fn_in_body();
    |         ^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::DeprecatedTrait': text
+warning: use of deprecated trait `this_crate::DeprecatedTrait`: text
   --> $DIR/lint-stability-deprecated.rs:460:10
    |
 LL |     impl DeprecatedTrait for S { }
    |          ^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::DeprecatedTrait': text
+warning: use of deprecated trait `this_crate::DeprecatedTrait`: text
   --> $DIR/lint-stability-deprecated.rs:462:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { }
    |                        ^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::MethodTester::test_method_body::fn_in_body': text
+warning: use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text
   --> $DIR/lint-stability-deprecated.rs:448:13
    |
 LL |             fn_in_body();
    |             ^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
   --> $DIR/lint-stability-deprecated.rs:98:48
    |
 LL |         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
    |                                                ^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
   --> $DIR/lint-stability-deprecated.rs:103:13
    |
 LL |             TypeDeprecated = u16,
    |             ^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:26:13
    |
 LL |         foo.method_deprecated();
    |             ^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:27:9
    |
 LL |         Foo::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:28:9
    |
 LL |         <Foo>::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:29:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:31:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:35:13
    |
-LL |         foo.method_deprecated_text();
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   foo.method_deprecated_text();
+   |           ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:36:9
    |
-LL |         Foo::method_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Foo::method_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:37:9
    |
-LL |         <Foo>::method_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::method_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:38:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:40:9
    |
-LL |         <Foo>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:44:13
    |
-LL |         foo.method_deprecated_unstable();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   foo.method_deprecated_unstable();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:45:9
    |
-LL |         Foo::method_deprecated_unstable(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Foo::method_deprecated_unstable(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:46:9
    |
-LL |         <Foo>::method_deprecated_unstable(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::method_deprecated_unstable(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:47:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:49:9
    |
-LL |         <Foo>::trait_deprecated_unstable(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::trait_deprecated_unstable(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:53:13
    |
 LL | ...   foo.method_deprecated_unstable_text();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:54:9
    |
 LL | ...   Foo::method_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:55:9
    |
 LL | ...   <Foo>::method_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:56:13
    |
-LL |         foo.trait_deprecated_unstable_text();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   foo.trait_deprecated_unstable_text();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:58:9
    |
 LL | ...   <Foo>::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedStruct::i': text
+warning: use of deprecated field `lint_stability::DeprecatedStruct::i`: text
   --> $DIR/lint-stability-deprecated.rs:110:13
    |
 LL |             i: 0
    |             ^^^^
 
-warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct::i': text
+warning: use of deprecated field `lint_stability::DeprecatedUnstableStruct::i`: text
   --> $DIR/lint-stability-deprecated.rs:114:13
    |
 LL |             i: 0
    |             ^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:145:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:147:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:149:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:151:9
    |
-LL |         <Foo>::trait_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::trait_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:153:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:155:9
    |
-LL |         <Foo>::trait_deprecated_unstable(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::trait_deprecated_unstable(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:157:13
    |
-LL |         foo.trait_deprecated_unstable_text();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   foo.trait_deprecated_unstable_text();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:159:9
    |
 LL | ...   <Foo>::trait_deprecated_unstable_text(&foo);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:176:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:177:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:178:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
+warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:179:13
    |
-LL |         foo.trait_deprecated_unstable_text();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   foo.trait_deprecated_unstable_text();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:332:13
    |
 LL |         foo.method_deprecated();
    |             ^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:333:9
    |
 LL |         Foo::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
+warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:334:9
    |
 LL |         <Foo>::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:335:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:337:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:341:13
    |
-LL |         foo.method_deprecated_text();
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   foo.method_deprecated_text();
+   |           ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:342:9
    |
-LL |         Foo::method_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   Foo::method_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
+warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:343:9
    |
-LL |         <Foo>::method_deprecated_text(&foo);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | ...   <Foo>::method_deprecated_text(&foo);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:344:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:346:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::DeprecatedStruct::i': text
+warning: use of deprecated field `this_crate::DeprecatedStruct::i`: text
   --> $DIR/lint-stability-deprecated.rs:387:13
    |
 LL |             i: 0
    |             ^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:406:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:408:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:410:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:412:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:429:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
+warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:430:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
   --> $DIR/lint-stability-deprecated.rs:98:48
    |
 LL |         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
    |                                                ^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
   --> $DIR/lint-stability-deprecated.rs:103:13
    |
 LL |             TypeDeprecated = u16,
    |             ^^^^^^^^^^^^^^^^^^^^
 
-warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
+warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
   --> $DIR/lint-stability-deprecated.rs:103:13
    |
 LL |             TypeDeprecated = u16,
diff --git a/src/test/ui/lint/lint-stability-fields-deprecated.rs b/src/test/ui/lint/lint-stability-fields-deprecated.rs
index 50e3970c7f0..14c6383806f 100644
--- a/src/test/ui/lint/lint-stability-fields-deprecated.rs
+++ b/src/test/ui/lint/lint-stability-fields-deprecated.rs
@@ -16,19 +16,19 @@ mod cross_crate {
             inherit: 1,
             override1: 2,
             override2: 3,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         };
 
         let _ = x.inherit;
         let _ = x.override1;
         let _ = x.override2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Stable {
             inherit: _,
             override1: _,
             override2: _
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         } = x;
         // all fine
         let Stable { .. } = x;
@@ -38,12 +38,12 @@ mod cross_crate {
         let _ = x.0;
         let _ = x.1;
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Stable2(_,
                    _,
                    _)
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             = x;
         // all fine
         let Stable2(..) = x;
@@ -53,19 +53,19 @@ mod cross_crate {
             inherit: 1,
             override1: 2,
             override2: 3,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         };
 
         let _ = x.inherit;
         let _ = x.override1;
         let _ = x.override2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Unstable {
             inherit: _,
             override1: _,
             override2: _
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         } = x;
 
         let Unstable
@@ -78,13 +78,13 @@ mod cross_crate {
         let _ = x.0;
         let _ = x.1;
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Unstable2
             (_,
              _,
              _)
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             = x;
         let Unstable2
             // the patterns are all fine:
@@ -92,58 +92,58 @@ mod cross_crate {
 
 
         let x = Deprecated {
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated struct
             inherit: 1,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             override1: 2,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             override2: 3,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         };
 
         let _ = x.inherit;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
         let _ = x.override1;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
         let _ = x.override2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Deprecated {
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated struct
             inherit: _,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             override1: _,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             override2: _
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         } = x;
 
         let Deprecated
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated struct
             // the patterns are all fine:
             { .. } = x;
 
         let x = Deprecated2(1, 2, 3);
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated struct
 
         let _ = x.0;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
         let _ = x.1;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Deprecated2
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated struct
             (_,
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated field
              _,
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated field
              _)
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated field
             = x;
         let Deprecated2
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated struct
             // the patterns are all fine:
             (..) = x;
     }
@@ -203,19 +203,19 @@ mod this_crate {
             inherit: 1,
             override1: 2,
             override2: 3,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         };
 
         let _ = x.inherit;
         let _ = x.override1;
         let _ = x.override2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Stable {
             inherit: _,
             override1: _,
             override2: _
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         } = x;
         // all fine
         let Stable { .. } = x;
@@ -225,12 +225,12 @@ mod this_crate {
         let _ = x.0;
         let _ = x.1;
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Stable2(_,
                    _,
                    _)
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             = x;
         // all fine
         let Stable2(..) = x;
@@ -240,19 +240,19 @@ mod this_crate {
             inherit: 1,
             override1: 2,
             override2: 3,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         };
 
         let _ = x.inherit;
         let _ = x.override1;
         let _ = x.override2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Unstable {
             inherit: _,
             override1: _,
             override2: _
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         } = x;
 
         let Unstable
@@ -265,13 +265,13 @@ mod this_crate {
         let _ = x.0;
         let _ = x.1;
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Unstable2
             (_,
              _,
              _)
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             = x;
         let Unstable2
             // the patterns are all fine:
@@ -279,58 +279,58 @@ mod this_crate {
 
 
         let x = Deprecated {
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated struct
             inherit: 1,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             override1: 2,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             override2: 3,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         };
 
         let _ = x.inherit;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
         let _ = x.override1;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
         let _ = x.override2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Deprecated {
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated struct
             inherit: _,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             override1: _,
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             override2: _
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
         } = x;
 
         let Deprecated
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated struct
             // the patterns are all fine:
             { .. } = x;
 
         let x = Deprecated2(1, 2, 3);
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated tuple struct
 
         let _ = x.0;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
         let _ = x.1;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
         let _ = x.2;
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated field
 
         let Deprecated2
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated tuple struct
             (_,
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated field
              _,
-             //~^ ERROR use of deprecated item
+             //~^ ERROR use of deprecated field
              _)
-            //~^ ERROR use of deprecated item
+            //~^ ERROR use of deprecated field
             = x;
         let Deprecated2
-        //~^ ERROR use of deprecated item
+        //~^ ERROR use of deprecated tuple struct
             // the patterns are all fine:
             (..) = x;
     }
diff --git a/src/test/ui/lint/lint-stability-fields-deprecated.stderr b/src/test/ui/lint/lint-stability-fields-deprecated.stderr
index 5210fb690e9..ec786786023 100644
--- a/src/test/ui/lint/lint-stability-fields-deprecated.stderr
+++ b/src/test/ui/lint/lint-stability-fields-deprecated.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated': text
+error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated`: text
   --> $DIR/lint-stability-fields-deprecated.rs:94:17
    |
 LL |         let x = Deprecated {
@@ -10,367 +10,367 @@ note: the lint level is defined here
 LL | #![deny(deprecated)]
    |         ^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated': text
+error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated`: text
   --> $DIR/lint-stability-fields-deprecated.rs:111:13
    |
 LL |         let Deprecated {
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated': text
+error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated`: text
   --> $DIR/lint-stability-fields-deprecated.rs:121:13
    |
 LL |         let Deprecated
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2': text
+error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:126:17
    |
 LL |         let x = Deprecated2(1, 2, 3);
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2': text
+error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:136:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2': text
+error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:145:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated': text
+error: use of deprecated struct `this_crate::Deprecated`: text
   --> $DIR/lint-stability-fields-deprecated.rs:281:17
    |
 LL |         let x = Deprecated {
    |                 ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated': text
+error: use of deprecated struct `this_crate::Deprecated`: text
   --> $DIR/lint-stability-fields-deprecated.rs:298:13
    |
 LL |         let Deprecated {
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated': text
+error: use of deprecated struct `this_crate::Deprecated`: text
   --> $DIR/lint-stability-fields-deprecated.rs:308:13
    |
 LL |         let Deprecated
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated2': text
+error: use of deprecated tuple struct `this_crate::Deprecated2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:313:17
    |
 LL |         let x = Deprecated2(1, 2, 3);
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated2': text
+error: use of deprecated tuple struct `this_crate::Deprecated2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:323:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated2': text
+error: use of deprecated tuple struct `this_crate::Deprecated2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:332:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Stable::override2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Stable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:18:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Stable::override2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Stable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:24:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Stable::override2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Stable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:30:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Stable2::2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Stable2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:40:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Stable2::2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Stable2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:45:20
    |
 LL |                    _)
    |                    ^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable::override2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Unstable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:55:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable::override2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Unstable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:61:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable::override2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Unstable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:67:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable2::2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Unstable2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:80:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Unstable2::2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Unstable2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:86:14
    |
 LL |              _)
    |              ^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::inherit': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::inherit`: text
   --> $DIR/lint-stability-fields-deprecated.rs:96:13
    |
 LL |             inherit: 1,
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override1': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:98:13
    |
 LL |             override1: 2,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:100:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::inherit': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::inherit`: text
   --> $DIR/lint-stability-fields-deprecated.rs:104:17
    |
 LL |         let _ = x.inherit;
    |                 ^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override1': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:106:17
    |
 LL |         let _ = x.override1;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:108:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::inherit': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::inherit`: text
   --> $DIR/lint-stability-fields-deprecated.rs:113:13
    |
 LL |             inherit: _,
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override1': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:115:13
    |
 LL |             override1: _,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated::override2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:117:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::0': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::0`: text
   --> $DIR/lint-stability-fields-deprecated.rs:129:17
    |
 LL |         let _ = x.0;
    |                 ^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::1': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:131:17
    |
 LL |         let _ = x.1;
    |                 ^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:133:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::0': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::0`: text
   --> $DIR/lint-stability-fields-deprecated.rs:138:14
    |
 LL |             (_,
    |              ^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::1': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:140:14
    |
 LL |              _,
    |              ^
 
-error: use of deprecated item 'cross_crate::lint_stability_fields::Deprecated2::2': text
+error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:142:14
    |
 LL |              _)
    |              ^
 
-error: use of deprecated item 'this_crate::Stable::override2': text
+error: use of deprecated field `this_crate::Stable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:205:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Stable::override2': text
+error: use of deprecated field `this_crate::Stable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:211:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Stable::override2': text
+error: use of deprecated field `this_crate::Stable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:217:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Stable2::2': text
+error: use of deprecated field `this_crate::Stable2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:227:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'this_crate::Stable2::2': text
+error: use of deprecated field `this_crate::Stable2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:232:20
    |
 LL |                    _)
    |                    ^
 
-error: use of deprecated item 'this_crate::Unstable::override2': text
+error: use of deprecated field `this_crate::Unstable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:242:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Unstable::override2': text
+error: use of deprecated field `this_crate::Unstable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:248:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Unstable::override2': text
+error: use of deprecated field `this_crate::Unstable::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:254:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Unstable2::2': text
+error: use of deprecated field `this_crate::Unstable2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:267:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'this_crate::Unstable2::2': text
+error: use of deprecated field `this_crate::Unstable2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:273:14
    |
 LL |              _)
    |              ^
 
-error: use of deprecated item 'this_crate::Deprecated::inherit': text
+error: use of deprecated field `this_crate::Deprecated::inherit`: text
   --> $DIR/lint-stability-fields-deprecated.rs:283:13
    |
 LL |             inherit: 1,
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated::override1': text
+error: use of deprecated field `this_crate::Deprecated::override1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:285:13
    |
 LL |             override1: 2,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated::override2': text
+error: use of deprecated field `this_crate::Deprecated::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:287:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated::inherit': text
+error: use of deprecated field `this_crate::Deprecated::inherit`: text
   --> $DIR/lint-stability-fields-deprecated.rs:291:17
    |
 LL |         let _ = x.inherit;
    |                 ^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated::override1': text
+error: use of deprecated field `this_crate::Deprecated::override1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:293:17
    |
 LL |         let _ = x.override1;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated::override2': text
+error: use of deprecated field `this_crate::Deprecated::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:295:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated::inherit': text
+error: use of deprecated field `this_crate::Deprecated::inherit`: text
   --> $DIR/lint-stability-fields-deprecated.rs:300:13
    |
 LL |             inherit: _,
    |             ^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated::override1': text
+error: use of deprecated field `this_crate::Deprecated::override1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:302:13
    |
 LL |             override1: _,
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated::override2': text
+error: use of deprecated field `this_crate::Deprecated::override2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:304:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
-error: use of deprecated item 'this_crate::Deprecated2::0': text
+error: use of deprecated field `this_crate::Deprecated2::0`: text
   --> $DIR/lint-stability-fields-deprecated.rs:316:17
    |
 LL |         let _ = x.0;
    |                 ^^^
 
-error: use of deprecated item 'this_crate::Deprecated2::1': text
+error: use of deprecated field `this_crate::Deprecated2::1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:318:17
    |
 LL |         let _ = x.1;
    |                 ^^^
 
-error: use of deprecated item 'this_crate::Deprecated2::2': text
+error: use of deprecated field `this_crate::Deprecated2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:320:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
-error: use of deprecated item 'this_crate::Deprecated2::0': text
+error: use of deprecated field `this_crate::Deprecated2::0`: text
   --> $DIR/lint-stability-fields-deprecated.rs:325:14
    |
 LL |             (_,
    |              ^
 
-error: use of deprecated item 'this_crate::Deprecated2::1': text
+error: use of deprecated field `this_crate::Deprecated2::1`: text
   --> $DIR/lint-stability-fields-deprecated.rs:327:14
    |
 LL |              _,
    |              ^
 
-error: use of deprecated item 'this_crate::Deprecated2::2': text
+error: use of deprecated field `this_crate::Deprecated2::2`: text
   --> $DIR/lint-stability-fields-deprecated.rs:329:14
    |
 LL |              _)
diff --git a/src/test/ui/lint/lint-stability2.rs b/src/test/ui/lint/lint-stability2.rs
index 9710d0826c7..9ae23dac61b 100644
--- a/src/test/ui/lint/lint-stability2.rs
+++ b/src/test/ui/lint/lint-stability2.rs
@@ -1,5 +1,5 @@
 // aux-build:lint_stability.rs
-// error-pattern: use of deprecated item
+// error-pattern: use of deprecated function
 
 #![deny(deprecated)]
 
diff --git a/src/test/ui/lint/lint-stability2.stderr b/src/test/ui/lint/lint-stability2.stderr
index a14bf2ec8ca..036304d25f9 100644
--- a/src/test/ui/lint/lint-stability2.stderr
+++ b/src/test/ui/lint/lint-stability2.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated item 'lint_stability::deprecated': text
+error: use of deprecated function `lint_stability::deprecated`: text
   --> $DIR/lint-stability2.rs:12:5
    |
 LL |     macro_test!();
diff --git a/src/test/ui/lint/lint-stability3.rs b/src/test/ui/lint/lint-stability3.rs
index 3d2cc6890b8..4452846ec0a 100644
--- a/src/test/ui/lint/lint-stability3.rs
+++ b/src/test/ui/lint/lint-stability3.rs
@@ -1,5 +1,5 @@
 // aux-build:lint_stability.rs
-// error-pattern: use of deprecated item
+// error-pattern: use of deprecated function
 
 #![deny(deprecated)]
 #![allow(warnings)]
diff --git a/src/test/ui/lint/lint-stability3.stderr b/src/test/ui/lint/lint-stability3.stderr
index 858ac12612c..b89a7df4938 100644
--- a/src/test/ui/lint/lint-stability3.stderr
+++ b/src/test/ui/lint/lint-stability3.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated item 'lint_stability::deprecated_text': text
+error: use of deprecated function `lint_stability::deprecated_text`: text
   --> $DIR/lint-stability3.rs:13:5
    |
 LL |     macro_test_arg_nested!(deprecated_text);
diff --git a/src/test/ui/liveness/liveness-upvars.rs b/src/test/ui/liveness/liveness-upvars.rs
index b2837e74b8c..98ea4d71ccf 100644
--- a/src/test/ui/liveness/liveness-upvars.rs
+++ b/src/test/ui/liveness/liveness-upvars.rs
@@ -27,7 +27,7 @@ pub fn f() {
     let mut c = 0;
 
     // Captured by value, but variable is dead on entry.
-    move || {
+    let _ = move || {
         c = 1; //~ WARN value captured by `c` is never read
         println!("{}", c);
     };
@@ -37,7 +37,7 @@ pub fn f() {
     };
 
     // Read and written to, but never actually used.
-    move || {
+    let _ = move || {
         c += 1; //~ WARN unused variable: `c`
     };
     let _ = async move {
@@ -45,13 +45,13 @@ pub fn f() {
                 //~| WARN unused variable: `c`
     };
 
-    move || {
+    let _ = move || {
         println!("{}", c);
         // Value is read by closure itself on later invocations.
         c += 1;
     };
     let b = Box::new(42);
-    move || {
+    let _ = move || {
         println!("{}", c);
         // Never read because this is FnOnce closure.
         c += 1; //~  WARN value assigned to `c` is never read
@@ -67,12 +67,12 @@ pub fn f() {
 pub fn nested() {
     let mut d = None;
     let mut e = None;
-    || {
-        || {
+    let _ = || {
+        let _ = || {
             d = Some("d1"); //~ WARN value assigned to `d` is never read
             d = Some("d2");
         };
-        move || {
+        let _ = move || {
             e = Some("e1"); //~  WARN value assigned to `e` is never read
                             //~| WARN unused variable: `e`
             e = Some("e2"); //~  WARN value assigned to `e` is never read
@@ -81,7 +81,7 @@ pub fn nested() {
 }
 
 pub fn g<T: Default>(mut v: T) {
-    |r| {
+    let _ = |r| {
         if r {
             v = T::default(); //~ WARN value assigned to `v` is never read
         } else {
@@ -92,7 +92,7 @@ pub fn g<T: Default>(mut v: T) {
 
 pub fn h<T: Copy + Default + std::fmt::Debug>() {
     let mut z = T::default();
-    move |b| {
+    let _ = move |b| {
         loop {
             if b {
                 z = T::default(); //~  WARN value assigned to `z` is never read
diff --git a/src/test/ui/macros/macro-deprecation.rs b/src/test/ui/macros/macro-deprecation.rs
index 9636b48c2da..a7f327cf53b 100644
--- a/src/test/ui/macros/macro-deprecation.rs
+++ b/src/test/ui/macros/macro-deprecation.rs
@@ -8,6 +8,6 @@
 macro_rules! local_deprecated{ () => () }
 
 fn main() {
-    local_deprecated!(); //~ WARN use of deprecated item 'local_deprecated': local deprecation note
-    deprecated_macro!(); //~ WARN use of deprecated item 'deprecated_macro': deprecation note
+    local_deprecated!(); //~ WARN use of deprecated macro `local_deprecated`: local deprecation note
+    deprecated_macro!(); //~ WARN use of deprecated macro `deprecated_macro`: deprecation note
 }
diff --git a/src/test/ui/macros/macro-deprecation.stderr b/src/test/ui/macros/macro-deprecation.stderr
index 0e8ecb58fe5..07849d7ce57 100644
--- a/src/test/ui/macros/macro-deprecation.stderr
+++ b/src/test/ui/macros/macro-deprecation.stderr
@@ -1,4 +1,4 @@
-warning: use of deprecated item 'local_deprecated': local deprecation note
+warning: use of deprecated macro `local_deprecated`: local deprecation note
   --> $DIR/macro-deprecation.rs:11:5
    |
 LL |     local_deprecated!();
@@ -6,7 +6,7 @@ LL |     local_deprecated!();
    |
    = note: `#[warn(deprecated)]` on by default
 
-warning: use of deprecated item 'deprecated_macro': deprecation note
+warning: use of deprecated macro `deprecated_macro`: deprecation note
   --> $DIR/macro-deprecation.rs:12:5
    |
 LL |     deprecated_macro!();
diff --git a/src/test/ui/macros/macro-stability.rs b/src/test/ui/macros/macro-stability.rs
index 755f55c28de..e2eff7c1c2d 100644
--- a/src/test/ui/macros/macro-stability.rs
+++ b/src/test/ui/macros/macro-stability.rs
@@ -22,7 +22,7 @@ fn main() {
     // unstable_macro_modern!(); // ERROR use of unstable library feature 'unstable_macros'
 
     deprecated_macro!();
-    //~^ WARN use of deprecated item 'deprecated_macro': deprecation reason
+    //~^ WARN use of deprecated macro `deprecated_macro`: deprecation reason
     local_deprecated!();
-    //~^ WARN use of deprecated item 'local_deprecated': local deprecation reason
+    //~^ WARN use of deprecated macro `local_deprecated`: local deprecation reason
 }
diff --git a/src/test/ui/macros/macro-stability.stderr b/src/test/ui/macros/macro-stability.stderr
index 9e127a3b855..34b62b4b1c3 100644
--- a/src/test/ui/macros/macro-stability.stderr
+++ b/src/test/ui/macros/macro-stability.stderr
@@ -22,7 +22,7 @@ LL |     unstable_macro!();
    |
    = help: add `#![feature(unstable_macros)]` to the crate attributes to enable
 
-warning: use of deprecated item 'deprecated_macro': deprecation reason
+warning: use of deprecated macro `deprecated_macro`: deprecation reason
   --> $DIR/macro-stability.rs:24:5
    |
 LL |     deprecated_macro!();
@@ -30,7 +30,7 @@ LL |     deprecated_macro!();
    |
    = note: `#[warn(deprecated)]` on by default
 
-warning: use of deprecated item 'local_deprecated': local deprecation reason
+warning: use of deprecated macro `local_deprecated`: local deprecation reason
   --> $DIR/macro-stability.rs:26:5
    |
 LL |     local_deprecated!();
diff --git a/src/test/ui/nll/capture-mut-ref.fixed b/src/test/ui/nll/capture-mut-ref.fixed
index 639de2813a9..2dacb26b6eb 100644
--- a/src/test/ui/nll/capture-mut-ref.fixed
+++ b/src/test/ui/nll/capture-mut-ref.fixed
@@ -8,7 +8,7 @@
 pub fn mutable_upvar() {
     let x = &mut 0;
     //~^ ERROR
-    move || {
+    let _ = move || {
         *x = 1;
     };
 }
diff --git a/src/test/ui/nll/capture-mut-ref.rs b/src/test/ui/nll/capture-mut-ref.rs
index 89f49e1ea51..56e01f7b776 100644
--- a/src/test/ui/nll/capture-mut-ref.rs
+++ b/src/test/ui/nll/capture-mut-ref.rs
@@ -8,7 +8,7 @@
 pub fn mutable_upvar() {
     let mut x = &mut 0;
     //~^ ERROR
-    move || {
+    let _ = move || {
         *x = 1;
     };
 }
diff --git a/src/test/ui/nll/issue-48623-generator.rs b/src/test/ui/nll/issue-48623-generator.rs
index ba3eccff495..08d2584ee5e 100644
--- a/src/test/ui/nll/issue-48623-generator.rs
+++ b/src/test/ui/nll/issue-48623-generator.rs
@@ -12,7 +12,7 @@ impl Drop for WithDrop {
 
 fn reborrow_from_generator(r: &mut ()) {
     let d = WithDrop;
-    move || { d; yield; &mut *r };
+    move || { d; yield; &mut *r }; //~ WARN unused generator that must be used
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/issue-48623-generator.stderr b/src/test/ui/nll/issue-48623-generator.stderr
new file mode 100644
index 00000000000..70a83e46ff0
--- /dev/null
+++ b/src/test/ui/nll/issue-48623-generator.stderr
@@ -0,0 +1,11 @@
+warning: unused generator that must be used
+  --> $DIR/issue-48623-generator.rs:15:5
+   |
+LL |     move || { d; yield; &mut *r };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: generators are lazy and do nothing unless resumed
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs
index 14797917193..993954b450e 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs
@@ -1,5 +1,5 @@
 // Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented even with promotion.
-// Currently this logic exists in HAIR match checking as opposed to borrowck.
+// Currently this logic exists in THIR match checking as opposed to borrowck.
 
 #![feature(bindings_after_at)]
 #![feature(move_ref_pattern)]
diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr
index 6e87e5c6912..2aa0824f301 100644
--- a/src/test/ui/pattern/const-pat-ice.stderr
+++ b/src/test/ui/pattern/const-pat-ice.stderr
@@ -1,4 +1,4 @@
-thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir_build/hair/pattern/_match.rs:LL:CC
+thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir_build/thir/pattern/_match.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 error: internal compiler error: unexpected panic
diff --git a/src/test/ui/pattern/issue-74539.rs b/src/test/ui/pattern/issue-74539.rs
new file mode 100644
index 00000000000..0b25f87ec53
--- /dev/null
+++ b/src/test/ui/pattern/issue-74539.rs
@@ -0,0 +1,15 @@
+enum E {
+    A(u8, u8),
+}
+
+fn main() {
+    let e = E::A(2, 3);
+    match e {
+        E::A(x @ ..) => {
+            //~^ ERROR: `x @` is not allowed in a tuple struct
+            //~| ERROR: `..` patterns are not allowed here
+            //~| ERROR: this pattern has 1 field, but the corresponding tuple variant has 2 fields
+            x
+        }
+    };
+}
diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr
new file mode 100644
index 00000000000..cbc90b5397d
--- /dev/null
+++ b/src/test/ui/pattern/issue-74539.stderr
@@ -0,0 +1,32 @@
+error: `x @` is not allowed in a tuple struct
+  --> $DIR/issue-74539.rs:8:14
+   |
+LL |         E::A(x @ ..) => {
+   |              ^^^^^^ this is only allowed in slice patterns
+   |
+   = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of x, discard the tuple's remaining fields
+   |
+LL |         E::A(..) => {
+   |              ^^
+
+error: `..` patterns are not allowed here
+  --> $DIR/issue-74539.rs:8:18
+   |
+LL |         E::A(x @ ..) => {
+   |                  ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
+  --> $DIR/issue-74539.rs:8:9
+   |
+LL |     A(u8, u8),
+   |     --------- tuple variant defined here
+...
+LL |         E::A(x @ ..) => {
+   |         ^^^^^^^^^^^^ expected 2 fields, found 1
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0023`.
diff --git a/src/test/ui/pattern/issue-74702.rs b/src/test/ui/pattern/issue-74702.rs
new file mode 100644
index 00000000000..0aeb3b217a2
--- /dev/null
+++ b/src/test/ui/pattern/issue-74702.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let (foo @ ..,) = (0, 0);
+    //~^ ERROR: `foo @` is not allowed in a tuple
+    //~| ERROR: `..` patterns are not allowed here
+    //~| ERROR: mismatched types
+    dbg!(foo);
+}
diff --git a/src/test/ui/pattern/issue-74702.stderr b/src/test/ui/pattern/issue-74702.stderr
new file mode 100644
index 00000000000..aca5c9aed96
--- /dev/null
+++ b/src/test/ui/pattern/issue-74702.stderr
@@ -0,0 +1,34 @@
+error: `foo @` is not allowed in a tuple
+  --> $DIR/issue-74702.rs:2:10
+   |
+LL |     let (foo @ ..,) = (0, 0);
+   |          ^^^^^^^^ this is only allowed in slice patterns
+   |
+   = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of foo, discard the tuple's remaining fields
+   |
+LL |     let (..,) = (0, 0);
+   |          ^^
+
+error: `..` patterns are not allowed here
+  --> $DIR/issue-74702.rs:2:16
+   |
+LL |     let (foo @ ..,) = (0, 0);
+   |                ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error[E0308]: mismatched types
+  --> $DIR/issue-74702.rs:2:9
+   |
+LL |     let (foo @ ..,) = (0, 0);
+   |         ^^^^^^^^^^^   ------ this expression has type `({integer}, {integer})`
+   |         |
+   |         expected a tuple with 2 elements, found one with 1 element
+   |
+   = note: expected tuple `({integer}, {integer})`
+              found tuple `(_,)`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/pattern/issue-74954.rs b/src/test/ui/pattern/issue-74954.rs
new file mode 100644
index 00000000000..269ec3c7abe
--- /dev/null
+++ b/src/test/ui/pattern/issue-74954.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+fn main() {
+    if let Some([b'@', filename @ ..]) = Some(b"@abc123") {
+        println!("filename {:?}", filename);
+    }
+}
diff --git a/src/test/ui/polymorphization/issue-74636.rs b/src/test/ui/polymorphization/issue-74636.rs
new file mode 100644
index 00000000000..4c532f451e3
--- /dev/null
+++ b/src/test/ui/polymorphization/issue-74636.rs
@@ -0,0 +1,16 @@
+// compile-flags:-Zpolymorphize=on
+// build-pass
+
+use std::any::TypeId;
+
+pub fn foo<T: 'static>(_: T) -> TypeId {
+    TypeId::of::<T>()
+}
+
+fn outer<T: 'static>() {
+    foo(|| ());
+}
+
+fn main() {
+    outer::<u8>();
+}
diff --git a/src/test/ui/proc-macro/attributes-on-definitions.rs b/src/test/ui/proc-macro/attributes-on-definitions.rs
index 055781d2c60..c0733c8b416 100644
--- a/src/test/ui/proc-macro/attributes-on-definitions.rs
+++ b/src/test/ui/proc-macro/attributes-on-definitions.rs
@@ -6,7 +6,7 @@
 extern crate attributes_on_definitions;
 
 attributes_on_definitions::with_attrs!();
-//~^ WARN use of deprecated item
+//~^ WARN use of deprecated
 // No errors about the use of unstable and unsafe code inside the macro.
 
 fn main() {}
diff --git a/src/test/ui/proc-macro/attributes-on-definitions.stderr b/src/test/ui/proc-macro/attributes-on-definitions.stderr
index 3e6b8f6a435..c63dd00119a 100644
--- a/src/test/ui/proc-macro/attributes-on-definitions.stderr
+++ b/src/test/ui/proc-macro/attributes-on-definitions.stderr
@@ -1,4 +1,4 @@
-warning: use of deprecated item 'attributes_on_definitions::with_attrs': test
+warning: use of deprecated macro `attributes_on_definitions::with_attrs`: test
   --> $DIR/attributes-on-definitions.rs:8:1
    |
 LL | attributes_on_definitions::with_attrs!();
diff --git a/src/test/ui/proc-macro/crt-static.rs b/src/test/ui/proc-macro/crt-static.rs
index 97f6265e308..4f11f81b00b 100644
--- a/src/test/ui/proc-macro/crt-static.rs
+++ b/src/test/ui/proc-macro/crt-static.rs
@@ -1,4 +1,4 @@
-// Test proc-macro crate can be built without addtional RUSTFLAGS
+// Test proc-macro crate can be built without additional RUSTFLAGS
 // on musl target
 // override -Ctarget-feature=-crt-static from compiletest
 // compile-flags: -Ctarget-feature=
diff --git a/src/test/ui/statics/static-promotion.rs b/src/test/ui/statics/static-promotion.rs
new file mode 100644
index 00000000000..bd8910bdb3f
--- /dev/null
+++ b/src/test/ui/statics/static-promotion.rs
@@ -0,0 +1,34 @@
+// check-pass
+
+// Use of global static variables in literal values should be allowed for
+// promotion.
+// This test is to demonstrate the issue raised in
+// https://github.com/rust-lang/rust/issues/70584
+
+// Literal values were previously promoted into local static values when
+// other global static variables are used.
+
+struct A<T: 'static>(&'static T);
+struct B<T: 'static + ?Sized> {
+    x: &'static T,
+}
+static STR: &'static [u8] = b"hi";
+static C: A<B<B<[u8]>>> = {
+    A(&B {
+        x: &B { x: STR },
+    })
+};
+
+pub struct Slice(&'static [i32]);
+
+static CONTENT: i32 = 42;
+pub static CONTENT_MAP: Slice = Slice(&[CONTENT]);
+
+pub static FOO: (i32, i32) = (42, 43);
+pub static CONTENT_MAP2: Slice = Slice(&[FOO.0]);
+
+fn main() {
+    assert_eq!(b"hi", C.0.x.x);
+    assert_eq!(&[42], CONTENT_MAP.0);
+    assert_eq!(&[42], CONTENT_MAP2.0);
+}
diff --git a/src/test/ui/suggestions/issue-61226.fixed b/src/test/ui/suggestions/issue-61226.fixed
new file mode 100644
index 00000000000..6e9d74344bc
--- /dev/null
+++ b/src/test/ui/suggestions/issue-61226.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+struct X {}
+fn main() {
+    let _ = vec![X {}]; //…
+    //~^ ERROR expected value, found struct `X`
+}
diff --git a/src/test/ui/suggestions/issue-61226.rs b/src/test/ui/suggestions/issue-61226.rs
index e83b0b4d630..695fe73418a 100644
--- a/src/test/ui/suggestions/issue-61226.rs
+++ b/src/test/ui/suggestions/issue-61226.rs
@@ -1,5 +1,6 @@
+// run-rustfix
 struct X {}
 fn main() {
-    vec![X]; //…
+    let _ = vec![X]; //…
     //~^ ERROR expected value, found struct `X`
 }
diff --git a/src/test/ui/suggestions/issue-61226.stderr b/src/test/ui/suggestions/issue-61226.stderr
index 7f6f082d7a8..cda962a9045 100644
--- a/src/test/ui/suggestions/issue-61226.stderr
+++ b/src/test/ui/suggestions/issue-61226.stderr
@@ -1,11 +1,11 @@
 error[E0423]: expected value, found struct `X`
-  --> $DIR/issue-61226.rs:3:10
+  --> $DIR/issue-61226.rs:4:18
    |
 LL | struct X {}
    | ----------- `X` defined here
 LL | fn main() {
-LL |     vec![X]; //…
-   |          ^ help: use struct literal syntax instead: `X {}`
+LL |     let _ = vec![X]; //…
+   |                  ^ help: use struct literal syntax instead: `X {}`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.fixed b/src/test/ui/suggestions/type-ascription-instead-of-method.fixed
new file mode 100644
index 00000000000..56b740b0d5c
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-method.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let _ = Box::new("foo".to_string());
+    //~^ ERROR expected type, found
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.rs b/src/test/ui/suggestions/type-ascription-instead-of-method.rs
index 361729d50c2..a603e09e7e8 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-method.rs
+++ b/src/test/ui/suggestions/type-ascription-instead-of-method.rs
@@ -1,4 +1,5 @@
+// run-rustfix
 fn main() {
-    Box:new("foo".to_string())
+    let _ = Box:new("foo".to_string());
     //~^ ERROR expected type, found
 }
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.stderr b/src/test/ui/suggestions/type-ascription-instead-of-method.stderr
index c111b4a9bc7..83bc33f410a 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-method.stderr
+++ b/src/test/ui/suggestions/type-ascription-instead-of-method.stderr
@@ -1,10 +1,10 @@
 error: expected type, found `"foo"`
-  --> $DIR/type-ascription-instead-of-method.rs:2:13
+  --> $DIR/type-ascription-instead-of-method.rs:3:21
    |
-LL |     Box:new("foo".to_string())
-   |        -    ^^^^^ expected type
-   |        |
-   |        help: maybe write a path separator here: `::`
+LL |     let _ = Box:new("foo".to_string());
+   |                -    ^^^^^ expected type
+   |                |
+   |                help: maybe write a path separator here: `::`
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
 
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-2.fixed b/src/test/ui/suggestions/type-ascription-instead-of-path-2.fixed
new file mode 100644
index 00000000000..787fcc1208e
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path-2.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+fn main() -> Result<(), ()> {
+    let _ = vec![Ok(2)].into_iter().collect::<Result<Vec<_>,_>>()?;
+    //~^ ERROR expected `::`, found `(`
+    Ok(())
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs b/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs
index 220fd1eebda..934016b3b81 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs
@@ -1,5 +1,6 @@
+// run-rustfix
 fn main() -> Result<(), ()> {
-    vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
+    let _ = vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
     //~^ ERROR expected `::`, found `(`
     Ok(())
 }
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr
index 1d1999d350f..970b220b737 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr
@@ -1,10 +1,10 @@
 error: expected `::`, found `(`
-  --> $DIR/type-ascription-instead-of-path-2.rs:2:55
+  --> $DIR/type-ascription-instead-of-path-2.rs:3:63
    |
-LL |     vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
-   |                                    -                  ^ expected `::`
-   |                                    |
-   |                                    help: maybe write a path separator here: `::`
+LL |     let _ = vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
+   |                                            -                  ^ expected `::`
+   |                                            |
+   |                                            help: maybe write a path separator here: `::`
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
 
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.fixed b/src/test/ui/suggestions/type-ascription-instead-of-variant.fixed
new file mode 100644
index 00000000000..b3247e1287d
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-variant.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let _ = Option::Some("");
+    //~^ ERROR expected type, found
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.rs b/src/test/ui/suggestions/type-ascription-instead-of-variant.rs
index b90867fef6b..6fd2c19541c 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-variant.rs
+++ b/src/test/ui/suggestions/type-ascription-instead-of-variant.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 fn main() {
     let _ = Option:Some("");
     //~^ ERROR expected type, found
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr b/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr
index f38020dcc38..f59ba78d4d3 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr
+++ b/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr
@@ -1,5 +1,5 @@
 error: expected type, found `""`
-  --> $DIR/type-ascription-instead-of-variant.rs:2:25
+  --> $DIR/type-ascription-instead-of-variant.rs:3:25
    |
 LL |     let _ = Option:Some("");
    |                   -     ^^ expected type
diff --git a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs
index 917c09801e1..bf5482056d4 100644
--- a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs
+++ b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs
@@ -7,9 +7,9 @@
 
 mod a {
     fn b() {
-        || {
+        (|| {
             #[main]
             fn c() { panic!(); }
-        };
+        })();
     }
 }
diff --git a/src/test/ui/type/ascription/issue-47666.fixed b/src/test/ui/type/ascription/issue-47666.fixed
new file mode 100644
index 00000000000..c4db747551e
--- /dev/null
+++ b/src/test/ui/type/ascription/issue-47666.fixed
@@ -0,0 +1,4 @@
+// run-rustfix
+fn main() {
+    let _ = Option::Some(vec![0, 1]); //~ ERROR expected type, found
+}
diff --git a/src/test/ui/type/ascription/issue-47666.rs b/src/test/ui/type/ascription/issue-47666.rs
index 8035de4a48a..c67202e2157 100644
--- a/src/test/ui/type/ascription/issue-47666.rs
+++ b/src/test/ui/type/ascription/issue-47666.rs
@@ -1,7 +1,4 @@
+// run-rustfix
 fn main() {
     let _ = Option:Some(vec![0, 1]); //~ ERROR expected type, found
-    //~^ ERROR expected value, found enum `Option`
-    //~| ERROR expected type, found variant `Some`
 }
-
-// This case isn't currently being handled gracefully due to the macro invocation.
diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr
index 72c7c144b53..ba393ff1a20 100644
--- a/src/test/ui/type/ascription/issue-47666.stderr
+++ b/src/test/ui/type/ascription/issue-47666.stderr
@@ -1,5 +1,5 @@
 error: expected type, found reserved keyword `box`
-  --> $DIR/issue-47666.rs:2:25
+  --> $DIR/issue-47666.rs:3:25
    |
 LL |     let _ = Option:Some(vec![0, 1]);
    |                   -     ^^^^^^^^^^
@@ -12,35 +12,5 @@ LL |     let _ = Option:Some(vec![0, 1]);
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0423]: expected value, found enum `Option`
-  --> $DIR/issue-47666.rs:2:13
-   |
-LL |     let _ = Option:Some(vec![0, 1]);
-   |             ^^^^^^
-   |
-help: try using one of the enum's variants
-   |
-LL |     let _ = std::option::Option::None:Some(vec![0, 1]);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |     let _ = std::option::Option::Some:Some(vec![0, 1]);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0573]: expected type, found variant `Some`
-  --> $DIR/issue-47666.rs:2:20
-   |
-LL |     let _ = Option:Some(vec![0, 1]);
-   |                    ^^^^^^^^^^^^^^^^ not a type
-   |
-help: try using the variant's enum
-   |
-LL |     let _ = Option:std::option::Option;
-   |                    ^^^^^^^^^^^^^^^^^^^
-help: maybe you meant to write a path separator here
-   |
-LL |     let _ = Option::Some(vec![0, 1]);
-   |                   ^^
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0423, E0573.
-For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/type/ascription/issue-54516.fixed b/src/test/ui/type/ascription/issue-54516.fixed
new file mode 100644
index 00000000000..181637b97bb
--- /dev/null
+++ b/src/test/ui/type/ascription/issue-54516.fixed
@@ -0,0 +1,7 @@
+// run-rustfix
+use std::collections::BTreeMap;
+
+fn main() {
+    println!("{}", std::mem::size_of::<BTreeMap<u32, u32>>());
+    //~^ ERROR casts cannot be followed by a function call
+}
diff --git a/src/test/ui/type/ascription/issue-54516.rs b/src/test/ui/type/ascription/issue-54516.rs
index 8d6fd2abb6d..f09ddd487d8 100644
--- a/src/test/ui/type/ascription/issue-54516.rs
+++ b/src/test/ui/type/ascription/issue-54516.rs
@@ -1,8 +1,7 @@
+// run-rustfix
 use std::collections::BTreeMap;
 
 fn main() {
     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
     //~^ ERROR casts cannot be followed by a function call
-    //~| ERROR expected value, found module `std::mem` [E0423]
-    //~| ERROR cannot find type `size_of` in this scope [E0412]
 }
diff --git a/src/test/ui/type/ascription/issue-54516.stderr b/src/test/ui/type/ascription/issue-54516.stderr
index ec08cf209c2..2c7ff6bdc48 100644
--- a/src/test/ui/type/ascription/issue-54516.stderr
+++ b/src/test/ui/type/ascription/issue-54516.stderr
@@ -1,5 +1,5 @@
 error: casts cannot be followed by a function call
-  --> $DIR/issue-54516.rs:4:20
+  --> $DIR/issue-54516.rs:5:20
    |
 LL |     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
    |                    ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,23 +8,5 @@ LL |     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
 
-error[E0423]: expected value, found module `std::mem`
-  --> $DIR/issue-54516.rs:4:20
-   |
-LL |     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
-   |                    ^^^^^^^^- help: maybe you meant to write a path separator here: `::`
-   |                    |
-   |                    not a value
-
-error[E0412]: cannot find type `size_of` in this scope
-  --> $DIR/issue-54516.rs:4:29
-   |
-LL |     println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
-   |                            -^^^^^^^ not found in this scope
-   |                            |
-   |                            help: maybe you meant to write a path separator here: `::`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0412, E0423.
-For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/type/ascription/issue-60933.fixed b/src/test/ui/type/ascription/issue-60933.fixed
new file mode 100644
index 00000000000..ac9f6a07031
--- /dev/null
+++ b/src/test/ui/type/ascription/issue-60933.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let _: usize = std::mem::size_of::<u32>();
+    //~^ ERROR casts cannot be followed by a function call
+}
diff --git a/src/test/ui/type/ascription/issue-60933.rs b/src/test/ui/type/ascription/issue-60933.rs
index bcf9f88cb41..cb093735efa 100644
--- a/src/test/ui/type/ascription/issue-60933.rs
+++ b/src/test/ui/type/ascription/issue-60933.rs
@@ -1,6 +1,5 @@
+// run-rustfix
 fn main() {
-    let u: usize = std::mem:size_of::<u32>();
+    let _: usize = std::mem:size_of::<u32>();
     //~^ ERROR casts cannot be followed by a function call
-    //~| ERROR expected value, found module `std::mem` [E0423]
-    //~| ERROR cannot find type `size_of` in this scope [E0412]
 }
diff --git a/src/test/ui/type/ascription/issue-60933.stderr b/src/test/ui/type/ascription/issue-60933.stderr
index 2006362e1bb..5c35de88e14 100644
--- a/src/test/ui/type/ascription/issue-60933.stderr
+++ b/src/test/ui/type/ascription/issue-60933.stderr
@@ -1,30 +1,12 @@
 error: casts cannot be followed by a function call
-  --> $DIR/issue-60933.rs:2:20
+  --> $DIR/issue-60933.rs:3:20
    |
-LL |     let u: usize = std::mem:size_of::<u32>();
+LL |     let _: usize = std::mem:size_of::<u32>();
    |                    ^^^^^^^^-^^^^^^^^^^^^^^
    |                            |
    |                            help: maybe write a path separator here: `::`
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
 
-error[E0423]: expected value, found module `std::mem`
-  --> $DIR/issue-60933.rs:2:20
-   |
-LL |     let u: usize = std::mem:size_of::<u32>();
-   |                    ^^^^^^^^- help: maybe you meant to write a path separator here: `::`
-   |                    |
-   |                    not a value
-
-error[E0412]: cannot find type `size_of` in this scope
-  --> $DIR/issue-60933.rs:2:29
-   |
-LL |     let u: usize = std::mem:size_of::<u32>();
-   |                            -^^^^^^^ not found in this scope
-   |                            |
-   |                            help: maybe you meant to write a path separator here: `::`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0412, E0423.
-For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/type/type-ascription-with-fn-call.fixed b/src/test/ui/type/type-ascription-with-fn-call.fixed
new file mode 100644
index 00000000000..6d96c4303c3
--- /dev/null
+++ b/src/test/ui/type/type-ascription-with-fn-call.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+#![feature(type_ascription)]
+
+fn main() {
+    f()  ;
+    f(); //~ ERROR expected type, found function
+}
+
+fn f() {}
diff --git a/src/test/ui/type/type-ascription-with-fn-call.rs b/src/test/ui/type/type-ascription-with-fn-call.rs
index 2bd2efa4d38..ed4f7c9041c 100644
--- a/src/test/ui/type/type-ascription-with-fn-call.rs
+++ b/src/test/ui/type/type-ascription-with-fn-call.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 #![feature(type_ascription)]
 
 fn main() {
diff --git a/src/test/ui/type/type-ascription-with-fn-call.stderr b/src/test/ui/type/type-ascription-with-fn-call.stderr
index eeaca5300f9..5f74724b59e 100644
--- a/src/test/ui/type/type-ascription-with-fn-call.stderr
+++ b/src/test/ui/type/type-ascription-with-fn-call.stderr
@@ -1,8 +1,8 @@
 error[E0573]: expected type, found function `f`
-  --> $DIR/type-ascription-with-fn-call.rs:5:5
+  --> $DIR/type-ascription-with-fn-call.rs:6:5
    |
 LL |     f()  :
-   |          - help: did you mean to use `;` here instead?
+   |          - help: maybe you meant to write `;` here
 LL |     f();
    |     ^^^
    |     |
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs
index e5b19db7822..470904fd391 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs
@@ -2,6 +2,7 @@
 // pretty-expanded FIXME #23616
 
 #![deny(unused_mut)]
+#![allow(unused_must_use)]
 
 // Test that mutating a mutable upvar in a capture-by-value unboxed
 // closure does not ice (issue #18238) and marks the upvar as used
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr
index 4dfd1bb3075..1254f8dbc5e 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr
@@ -1,5 +1,5 @@
 warning: unused variable: `x`
-  --> $DIR/unboxed-closures-move-mutable.rs:16:17
+  --> $DIR/unboxed-closures-move-mutable.rs:17:17
    |
 LL |         move || x += 1;
    |                 ^
@@ -8,7 +8,7 @@ LL |         move || x += 1;
    = help: did you mean to capture by reference instead?
 
 warning: unused variable: `x`
-  --> $DIR/unboxed-closures-move-mutable.rs:20:17
+  --> $DIR/unboxed-closures-move-mutable.rs:21:17
    |
 LL |         move || x += 1;
    |                 ^
diff --git a/src/test/ui/unused/unused-closure.rs b/src/test/ui/unused/unused-closure.rs
new file mode 100644
index 00000000000..637d8bb43a7
--- /dev/null
+++ b/src/test/ui/unused/unused-closure.rs
@@ -0,0 +1,40 @@
+// Test that closures and generators are "must use" types.
+// edition:2018
+
+#![feature(async_closure)]
+#![feature(const_in_array_repeat_expressions)]
+#![feature(generators)]
+#![deny(unused_must_use)]
+
+fn unused() {
+    || { //~ ERROR unused closure that must be used
+        println!("Hello!");
+    };
+
+    async {};    //~ ERROR unused implementer of `std::future::Future` that must be used
+    || async {}; //~ ERROR unused closure that must be used
+    async || {}; //~ ERROR unused closure that must be used
+
+
+    [Box::new([|| {}; 10]); 1]; //~ ERROR unused array of boxed arrays of closures that must be used
+
+    [|| { //~ ERROR unused array of generators that must be used
+        yield 42u32;
+    }; 42];
+
+    vec![|| "a"].pop().unwrap(); //~ ERROR unused closure that must be used
+
+    let b = false;
+        || true; //~ ERROR unused closure that must be used
+    println!("{}", b);
+}
+
+fn ignored() {
+    let _ = || {};
+    let _ = || yield 42;
+}
+
+fn main() {
+    unused();
+    ignored();
+}
diff --git a/src/test/ui/unused/unused-closure.stderr b/src/test/ui/unused/unused-closure.stderr
new file mode 100644
index 00000000000..9dc73fb7abe
--- /dev/null
+++ b/src/test/ui/unused/unused-closure.stderr
@@ -0,0 +1,75 @@
+error: unused closure that must be used
+  --> $DIR/unused-closure.rs:10:5
+   |
+LL | /     || {
+LL | |         println!("Hello!");
+LL | |     };
+   | |______^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-closure.rs:7:9
+   |
+LL | #![deny(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+   = note: closures are lazy and do nothing unless called
+
+error: unused implementer of `std::future::Future` that must be used
+  --> $DIR/unused-closure.rs:14:5
+   |
+LL |     async {};
+   |     ^^^^^^^^^
+   |
+   = note: futures do nothing unless you `.await` or poll them
+
+error: unused closure that must be used
+  --> $DIR/unused-closure.rs:15:5
+   |
+LL |     || async {};
+   |     ^^^^^^^^^^^^
+   |
+   = note: closures are lazy and do nothing unless called
+
+error: unused closure that must be used
+  --> $DIR/unused-closure.rs:16:5
+   |
+LL |     async || {};
+   |     ^^^^^^^^^^^^
+   |
+   = note: closures are lazy and do nothing unless called
+
+error: unused array of boxed arrays of closures that must be used
+  --> $DIR/unused-closure.rs:19:5
+   |
+LL |     [Box::new([|| {}; 10]); 1];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: closures are lazy and do nothing unless called
+
+error: unused array of generators that must be used
+  --> $DIR/unused-closure.rs:21:5
+   |
+LL | /     [|| {
+LL | |         yield 42u32;
+LL | |     }; 42];
+   | |___________^
+   |
+   = note: generators are lazy and do nothing unless resumed
+
+error: unused closure that must be used
+  --> $DIR/unused-closure.rs:25:5
+   |
+LL |     vec![|| "a"].pop().unwrap();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: closures are lazy and do nothing unless called
+
+error: unused closure that must be used
+  --> $DIR/unused-closure.rs:28:9
+   |
+LL |         || true;
+   |         ^^^^^^^^
+   |
+   = note: closures are lazy and do nothing unless called
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/unused/unused-mut-warning-captured-var.fixed b/src/test/ui/unused/unused-mut-warning-captured-var.fixed
index b67b2a7259b..c21f18015c1 100644
--- a/src/test/ui/unused/unused-mut-warning-captured-var.fixed
+++ b/src/test/ui/unused/unused-mut-warning-captured-var.fixed
@@ -5,5 +5,5 @@
 fn main() {
     let x = 1;
     //~^ ERROR: variable does not need to be mutable
-    move|| { println!("{}", x); };
+    (move|| { println!("{}", x); })();
 }
diff --git a/src/test/ui/unused/unused-mut-warning-captured-var.rs b/src/test/ui/unused/unused-mut-warning-captured-var.rs
index 8726c4f173f..3119d83a0eb 100644
--- a/src/test/ui/unused/unused-mut-warning-captured-var.rs
+++ b/src/test/ui/unused/unused-mut-warning-captured-var.rs
@@ -5,5 +5,5 @@
 fn main() {
     let mut x = 1;
     //~^ ERROR: variable does not need to be mutable
-    move|| { println!("{}", x); };
+    (move|| { println!("{}", x); })();
 }
diff --git a/src/test/ui/weird-exprs.rs b/src/test/ui/weird-exprs.rs
index d812bbd011e..916cabbfb8c 100644
--- a/src/test/ui/weird-exprs.rs
+++ b/src/test/ui/weird-exprs.rs
@@ -5,7 +5,7 @@
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
 #![allow(unreachable_code)]
-#![allow(unused_braces, unused_parens)]
+#![allow(unused_braces, unused_must_use, unused_parens)]
 
 #![recursion_limit = "256"]
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject aa6872140ab0fa10f641ab0b981d5330d419e92
+Subproject 2d5c2381e4e50484bf281fc1bfe19743aa9eb37
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index 655b1133cf7..3f8e15d9029 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -883,7 +883,7 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_
 }
 
 /// Returns `true` if a pattern is refutable.
-// TODO: should be implemented using rustc/mir_build/hair machinery
+// TODO: should be implemented using rustc/mir_build/thir machinery
 pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
     fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
         matches!(
diff --git a/src/tools/clippy/tests/ui/formatting.rs b/src/tools/clippy/tests/ui/formatting.rs
index 078811b8d88..f54b3f2bfe2 100644
--- a/src/tools/clippy/tests/ui/formatting.rs
+++ b/src/tools/clippy/tests/ui/formatting.rs
@@ -149,7 +149,7 @@ fn main() {
         1 + 2, 3 
                 - 4, 5
     ];
-    // lint if it doesnt
+    // lint if it doesn't
     let _ = &[
         -1
         -4,
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index a26c3a4acab..bd4c5949800 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -8,13 +8,14 @@ edition = "2018"
 diff = "0.1.10"
 env_logger = { version = "0.7", default-features = false }
 getopts = "0.2"
-log = "0.4"
+log = { package = "tracing", version = "0.1" }
 regex = "1.0"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 rustfix = "0.5.0"
 lazy_static = "1.0"
 walkdir = "2"
+glob = "0.3.0"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 2ab764eb920..047fbe9da14 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -1,3 +1,4 @@
+use std::collections::HashSet;
 use std::env;
 use std::fs::File;
 use std::io::prelude::*;
@@ -186,6 +187,17 @@ impl EarlyProps {
             if config.system_llvm && line.starts_with("no-system-llvm") {
                 return true;
             }
+            if let Some(needed_components) =
+                config.parse_name_value_directive(line, "needs-llvm-components")
+            {
+                let components: HashSet<_> = config.llvm_components.split_whitespace().collect();
+                if !needed_components
+                    .split_whitespace()
+                    .all(|needed_component| components.contains(needed_component))
+                {
+                    return true;
+                }
+            }
             if let Some(actual_version) = config.llvm_version {
                 if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
                     let min_version = extract_llvm_version(rest).unwrap();
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 7fbe4f2b928..940e16720f6 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -28,6 +28,7 @@ use std::path::{Path, PathBuf};
 use std::process::{Child, Command, ExitStatus, Output, Stdio};
 use std::str;
 
+use glob::glob;
 use lazy_static::lazy_static;
 use log::*;
 
@@ -177,27 +178,30 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Misma
     results
 }
 
-fn print_diff(expected: &str, actual: &str, context_size: usize) {
+fn write_diff(expected: &str, actual: &str, context_size: usize) -> String {
+    use std::fmt::Write;
+    let mut output = String::new();
     let diff_results = make_diff(expected, actual, context_size);
     for result in diff_results {
         let mut line_number = result.line_number;
         for line in result.lines {
             match line {
                 DiffLine::Expected(e) => {
-                    println!("-\t{}", e);
+                    writeln!(output, "-\t{}", e).unwrap();
                     line_number += 1;
                 }
                 DiffLine::Context(c) => {
-                    println!("{}\t{}", line_number, c);
+                    writeln!(output, "{}\t{}", line_number, c).unwrap();
                     line_number += 1;
                 }
                 DiffLine::Resulting(r) => {
-                    println!("+\t{}", r);
+                    writeln!(output, "+\t{}", r).unwrap();
                 }
             }
         }
-        println!();
+        writeln!(output, "").unwrap();
     }
+    output
 }
 
 pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
@@ -654,8 +658,12 @@ impl<'test> TestCx<'test> {
                  ------------------------------------------\n\
                  {}\n\
                  ------------------------------------------\n\
-                 \n",
-                expected, actual
+                 diff:\n\
+                 ------------------------------------------\n\
+                 {}\n",
+                expected,
+                actual,
+                write_diff(expected, actual, 3),
             ));
         }
     }
@@ -3124,22 +3132,35 @@ impl<'test> TestCx<'test> {
     fn check_mir_dump(&self) {
         let test_file_contents = fs::read_to_string(&self.testpaths.file).unwrap();
 
-        let mut test_dir = self.testpaths.file.with_extension("");
+        let test_dir = self.testpaths.file.parent().unwrap();
+        let test_crate =
+            self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace("-", "_");
 
+        let mut bit_width = String::new();
         if test_file_contents.lines().any(|l| l == "// EMIT_MIR_FOR_EACH_BIT_WIDTH") {
-            test_dir.push(get_pointer_width(&self.config.target))
+            bit_width = format!(".{}", get_pointer_width(&self.config.target));
         }
 
         if self.config.bless {
-            let _ = std::fs::remove_dir_all(&test_dir);
+            for e in
+                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()
+            {
+                std::fs::remove_file(e.unwrap()).unwrap();
+            }
         }
+
         for l in test_file_contents.lines() {
             if l.starts_with("// EMIT_MIR ") {
                 let test_name = l.trim_start_matches("// EMIT_MIR ").trim();
                 let mut test_names = test_name.split(' ');
                 // sometimes we specify two files so that we get a diff between the two files
                 let test_name = test_names.next().unwrap();
-                let expected_file;
+                let mut expected_file;
                 let from_file;
                 let to_file;
 
@@ -3147,7 +3168,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 = test_name.to_string();
+                    expected_file = format!("{}{}", test_name, bit_width);
                     assert!(
                         test_names.next().is_none(),
                         "two mir pass names specified for MIR diff"
@@ -3159,12 +3180,13 @@ impl<'test> TestCx<'test> {
                         test_names.next().is_none(),
                         "three mir pass names specified for MIR diff"
                     );
-                    expected_file = format!("{}.{}-{}.diff", test_name, first_pass, second_pass);
+                    expected_file =
+                        format!("{}{}.{}-{}.diff", test_name, bit_width, first_pass, second_pass);
                     let second_file = format!("{}.{}.mir", test_name, second_pass);
                     from_file = format!("{}.{}.mir", test_name, first_pass);
                     to_file = Some(second_file);
                 } else {
-                    expected_file = test_name.to_string();
+                    expected_file = format!("{}{}", test_name, bit_width);
                     from_file = test_name.to_string();
                     assert!(
                         test_names.next().is_none(),
@@ -3172,30 +3194,13 @@ impl<'test> TestCx<'test> {
                     );
                     to_file = None;
                 };
+                if !expected_file.starts_with(&test_crate) {
+                    expected_file = format!("{}.{}", test_crate, expected_file);
+                }
                 let expected_file = test_dir.join(expected_file);
 
                 let dumped_string = if let Some(after) = to_file {
-                    let before = self.get_mir_dump_dir().join(from_file);
-                    let after = self.get_mir_dump_dir().join(after);
-                    debug!(
-                        "comparing the contents of: {} with {}",
-                        before.display(),
-                        after.display()
-                    );
-                    let before = fs::read_to_string(before).unwrap();
-                    let after = fs::read_to_string(after).unwrap();
-                    let before = self.normalize_output(&before, &[]);
-                    let after = self.normalize_output(&after, &[]);
-                    let mut dumped_string = String::new();
-                    for result in diff::lines(&before, &after) {
-                        use std::fmt::Write;
-                        match result {
-                            diff::Result::Left(s) => writeln!(dumped_string, "- {}", s).unwrap(),
-                            diff::Result::Right(s) => writeln!(dumped_string, "+ {}", s).unwrap(),
-                            diff::Result::Both(s, _) => writeln!(dumped_string, "  {}", s).unwrap(),
-                        }
-                    }
-                    dumped_string
+                    self.diff_mir_files(from_file.into(), after.into())
                 } else {
                     let mut output_file = PathBuf::new();
                     output_file.push(self.get_mir_dump_dir());
@@ -3216,8 +3221,8 @@ impl<'test> TestCx<'test> {
                     let dumped_string = fs::read_to_string(&output_file).unwrap();
                     self.normalize_output(&dumped_string, &[])
                 };
+
                 if self.config.bless {
-                    let _ = std::fs::create_dir_all(&test_dir);
                     let _ = std::fs::remove_file(&expected_file);
                     std::fs::write(expected_file, dumped_string.as_bytes()).unwrap();
                 } else {
@@ -3229,7 +3234,7 @@ impl<'test> TestCx<'test> {
                     }
                     let expected_string = fs::read_to_string(&expected_file).unwrap();
                     if dumped_string != expected_string {
-                        print_diff(&expected_string, &dumped_string, 3);
+                        print!("{}", write_diff(&expected_string, &dumped_string, 3));
                         panic!(
                             "Actual MIR output differs from expected MIR output {}",
                             expected_file.display()
@@ -3240,6 +3245,26 @@ impl<'test> TestCx<'test> {
         }
     }
 
+    fn diff_mir_files(&self, before: PathBuf, after: PathBuf) -> String {
+        let before = self.get_mir_dump_dir().join(before);
+        let after = self.get_mir_dump_dir().join(after);
+        debug!("comparing the contents of: {} with {}", before.display(), after.display());
+        let before = fs::read_to_string(before).unwrap();
+        let after = fs::read_to_string(after).unwrap();
+        let before = self.normalize_output(&before, &[]);
+        let after = self.normalize_output(&after, &[]);
+        let mut dumped_string = String::new();
+        for result in diff::lines(&before, &after) {
+            use std::fmt::Write;
+            match result {
+                diff::Result::Left(s) => writeln!(dumped_string, "- {}", s).unwrap(),
+                diff::Result::Right(s) => writeln!(dumped_string, "+ {}", s).unwrap(),
+                diff::Result::Both(s, _) => writeln!(dumped_string, "  {}", s).unwrap(),
+            }
+        }
+        dumped_string
+    }
+
     fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) {
         let t = |file| fs::metadata(file).unwrap().modified().unwrap();
         let source_file = &self.testpaths.file;
@@ -3434,7 +3459,7 @@ impl<'test> TestCx<'test> {
                 println!("normalized {}:\n{}\n", kind, actual);
             } else {
                 println!("diff of {}:\n", kind);
-                print_diff(expected, actual, 3);
+                print!("{}", write_diff(expected, actual, 3));
             }
         }
 
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index c4292d041d0..bd9f8fb0450 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -1,7 +1,7 @@
 #![feature(rustc_private)]
 
-extern crate env_logger;
 extern crate rustc_ast;
+extern crate rustc_driver;
 extern crate rustc_span;
 
 use std::cell::RefCell;
@@ -282,7 +282,7 @@ fn parse_args() -> (OutputFormat, PathBuf) {
 }
 
 fn main() {
-    env_logger::init();
+    rustc_driver::init_env_logger("RUST_LOG");
     let (format, dst) = parse_args();
     let result = rustc_ast::with_default_session_globals(move || main_with_result(format, &dst));
     if let Err(e) = result {
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 515287f114b546a72d4a1fe8ffe1dbc20dedf13
+Subproject 55bdb3174653039f47362742f8dc941bfc086e8
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 56d2717c304..1f988f7d81b 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -17,6 +17,7 @@ const LICENSES: &[&str] = &[
     "MIT",
     "Unlicense/MIT",
     "Unlicense OR MIT",
+    "0BSD OR MIT OR Apache-2.0", // adler license
 ];
 
 /// These are exceptions to Rust's permissive licensing policy, and
@@ -36,7 +37,6 @@ const EXCEPTIONS: &[(&str, &str)] = &[
     ("ryu", "Apache-2.0 OR BSL-1.0"),       // rls/cargo/... (because of serde)
     ("bytesize", "Apache-2.0"),             // cargo
     ("im-rc", "MPL-2.0+"),                  // cargo
-    ("adler32", "BSD-3-Clause AND Zlib"),   // cargo dep that isn't used
     ("constant_time_eq", "CC0-1.0"),        // rustfmt
     ("sized-chunks", "MPL-2.0+"),           // cargo via im-rc
     ("bitmaps", "MPL-2.0+"),                // cargo via im-rc
@@ -57,7 +57,8 @@ const RESTRICTED_DEPENDENCY_CRATES: &[&str] = &["rustc_middle", "rustc_codegen_l
 /// This list is here to provide a speed-bump to adding a new dependency to
 /// rustc. Please check with the compiler team before adding an entry.
 const PERMITTED_DEPENDENCIES: &[&str] = &[
-    "adler32",
+    "addr2line",
+    "adler",
     "aho-corasick",
     "annotate-snippets",
     "ansi_term",
@@ -65,7 +66,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "atty",
     "autocfg",
     "backtrace",
-    "backtrace-sys",
     "bitflags",
     "block-buffer",
     "block-padding",
@@ -98,6 +98,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "generic-array",
     "getopts",
     "getrandom",
+    "gimli",
     "hashbrown",
     "hermit-abi",
     "humantime",
@@ -119,6 +120,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "miniz_oxide",
     "nodrop",
     "num_cpus",
+    "object",
     "once_cell",
     "opaque-debug",
     "parking_lot",
@@ -136,7 +138,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "rand_chacha",
     "rand_core",
     "rand_hc",
-    "rand_isaac",
     "rand_pcg",
     "rand_xorshift",
     "redox_syscall",
@@ -164,6 +165,9 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "termcolor",
     "termize",
     "thread_local",
+    "tracing",
+    "tracing-attributes",
+    "tracing-core",
     "typenum",
     "unicode-normalization",
     "unicode-script",
@@ -178,7 +182,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "winapi-i686-pc-windows-gnu",
     "winapi-util",
     "winapi-x86_64-pc-windows-gnu",
-    "wincolor",
 ];
 
 /// Dependency checks.
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 08b2fccd73f..19218cbd66a 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -51,6 +51,7 @@ pub mod unstable_book;
 fn filter_dirs(path: &Path) -> bool {
     let skip = [
         "src/llvm-project",
+        "library/backtrace",
         "library/stdarch",
         "src/tools/cargo",
         "src/tools/clippy",
diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs
index aa24881ac6b..11617911446 100644
--- a/src/tools/unstable-book-gen/src/main.rs
+++ b/src/tools/unstable-book-gen/src/main.rs
@@ -94,13 +94,15 @@ fn copy_recursive(from: &Path, to: &Path) {
 }
 
 fn main() {
-    let src_path_str = env::args_os().skip(1).next().expect("source path required");
-    let dest_path_str = env::args_os().skip(2).next().expect("destination path required");
+    let library_path_str = env::args_os().skip(1).next().expect("library path required");
+    let src_path_str = env::args_os().skip(2).next().expect("source path required");
+    let dest_path_str = env::args_os().skip(3).next().expect("destination path required");
+    let library_path = Path::new(&library_path_str);
     let src_path = Path::new(&src_path_str);
     let dest_path = Path::new(&dest_path_str);
 
     let lang_features = collect_lang_features(src_path, &mut false);
-    let lib_features = collect_lib_features(src_path)
+    let lib_features = collect_lib_features(library_path)
         .into_iter()
         .filter(|&(ref name, _)| !lang_features.contains_key(name))
         .collect();