about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/tracking_issue.md8
-rw-r--r--.mailmap3
-rw-r--r--CONTRIBUTING.md22
-rw-r--r--Cargo.lock83
-rw-r--r--README.md10
-rw-r--r--src/README.md4
-rw-r--r--src/bootstrap/README.md3
-rw-r--r--src/bootstrap/builder.rs10
-rw-r--r--src/bootstrap/channel.rs2
-rw-r--r--src/bootstrap/flags.rs6
-rw-r--r--src/bootstrap/format.rs3
-rw-r--r--src/bootstrap/native.rs98
-rw-r--r--src/bootstrap/test.rs11
-rw-r--r--src/bootstrap/toolstate.rs55
-rw-r--r--src/ci/docker/mingw-check/Dockerfile1
-rw-r--r--src/ci/docker/x86_64-gnu-llvm-7/Dockerfile5
-rwxr-xr-xsrc/ci/publish_toolstate.sh4
-rwxr-xr-xsrc/ci/scripts/install-msys2-packages.sh5
m---------src/doc/embedded-book0
-rw-r--r--src/doc/index.md2
m---------src/doc/reference0
-rw-r--r--src/doc/robots.txt19
m---------src/doc/rust-by-example0
-rw-r--r--src/doc/rustc/src/contributing.md4
-rw-r--r--src/doc/rustdoc/src/advanced-features.md2
-rw-r--r--src/doc/rustdoc/src/command-line-arguments.md4
-rw-r--r--src/doc/rustdoc/src/documentation-tests.md2
-rw-r--r--src/doc/rustdoc/src/what-is-rustdoc.md6
-rw-r--r--src/doc/unstable-book/src/language-features/lang-items.md23
-rw-r--r--src/liballoc/boxed.rs24
-rw-r--r--src/liballoc/collections/linked_list.rs2
-rw-r--r--src/liballoc/collections/mod.rs18
-rw-r--r--src/liballoc/string.rs11
-rw-r--r--src/liballoc/vec.rs16
-rw-r--r--src/libcore/cell.rs43
-rw-r--r--src/libcore/fmt/float.rs6
-rw-r--r--src/libcore/fmt/mod.rs18
-rw-r--r--src/libcore/fmt/num.rs27
-rw-r--r--src/libcore/hash/sip.rs53
-rw-r--r--src/libcore/intrinsics.rs72
-rw-r--r--src/libcore/iter/adapters/flatten.rs21
-rw-r--r--src/libcore/iter/adapters/mod.rs6
-rw-r--r--src/libcore/lib.rs2
-rw-r--r--src/libcore/macros/mod.rs33
-rw-r--r--src/libcore/marker.rs1
-rw-r--r--src/libcore/mem/maybe_uninit.rs12
-rw-r--r--src/libcore/mem/mod.rs77
-rw-r--r--src/libcore/num/mod.rs24
-rw-r--r--src/libcore/ops/generator.rs31
-rw-r--r--src/libcore/panicking.rs30
-rw-r--r--src/libcore/prelude/v1.rs9
-rw-r--r--src/libcore/str/pattern.rs13
-rw-r--r--src/libcore/sync/atomic.rs30
-rw-r--r--src/libcore/tests/iter.rs72
-rw-r--r--src/libcore/unicode/printable.rs173
-rw-r--r--src/libcore/unicode/unicode_data.rs734
-rw-r--r--src/libpanic_abort/lib.rs26
-rw-r--r--src/libpanic_unwind/dummy.rs4
-rw-r--r--src/libpanic_unwind/emcc.rs9
-rw-r--r--src/libpanic_unwind/gcc.rs24
-rw-r--r--src/libpanic_unwind/hermit.rs4
-rw-r--r--src/libpanic_unwind/lib.rs68
-rw-r--r--src/libpanic_unwind/miri.rs20
-rw-r--r--src/libpanic_unwind/seh.rs59
-rw-r--r--src/libproc_macro/lib.rs15
-rw-r--r--src/librustc/README.md4
-rw-r--r--src/librustc/arena.rs6
-rw-r--r--src/librustc/dep_graph/README.md2
-rw-r--r--src/librustc/dep_graph/dep_node.rs37
-rw-r--r--src/librustc/dep_graph/graph.rs51
-rw-r--r--src/librustc/hir/map/blocks.rs8
-rw-r--r--src/librustc/hir/map/collector.rs263
-rw-r--r--src/librustc/hir/map/definitions.rs188
-rw-r--r--src/librustc/hir/map/hir_id_validator.rs49
-rw-r--r--src/librustc/hir/map/mod.rs546
-rw-r--r--src/librustc/hir/mod.rs82
-rw-r--r--src/librustc/ich/hcx.rs39
-rw-r--r--src/librustc/ich/impls_hir.rs82
-rw-r--r--src/librustc/ich/impls_syntax.rs8
-rw-r--r--src/librustc/infer/canonical.rs4
-rw-r--r--src/librustc/lib.rs8
-rw-r--r--src/librustc/lint.rs2
-rw-r--r--src/librustc/middle/cstore.rs18
-rw-r--r--src/librustc/middle/dependency_format.rs2
-rw-r--r--src/librustc/middle/lang_items.rs3
-rw-r--r--src/librustc/middle/limits.rs6
-rw-r--r--src/librustc/middle/region.rs7
-rw-r--r--src/librustc/middle/stability.rs4
-rw-r--r--src/librustc/mir/interpret/allocation.rs5
-rw-r--r--src/librustc/mir/interpret/error.rs336
-rw-r--r--src/librustc/mir/interpret/mod.rs14
-rw-r--r--src/librustc/mir/interpret/pointer.rs16
-rw-r--r--src/librustc/mir/interpret/value.rs39
-rw-r--r--src/librustc/mir/mod.rs24
-rw-r--r--src/librustc/mir/mono.rs2
-rw-r--r--src/librustc/query/mod.rs50
-rw-r--r--src/librustc/traits/mod.rs4
-rw-r--r--src/librustc/traits/select.rs45
-rw-r--r--src/librustc/traits/specialization_graph.rs29
-rw-r--r--src/librustc/ty/context.rs118
-rw-r--r--src/librustc/ty/inhabitedness/mod.rs49
-rw-r--r--src/librustc/ty/instance.rs12
-rw-r--r--src/librustc/ty/layout.rs63
-rw-r--r--src/librustc/ty/mod.rs73
-rw-r--r--src/librustc/ty/print/pretty.rs400
-rw-r--r--src/librustc/ty/query/README.md4
-rw-r--r--src/librustc/ty/query/keys.rs10
-rw-r--r--src/librustc/ty/query/mod.rs14
-rw-r--r--src/librustc/ty/query/on_disk_cache.rs39
-rw-r--r--src/librustc/ty/sty.rs32
-rw-r--r--src/librustc/ty/trait_def.rs48
-rw-r--r--src/librustc/ty/util.rs7
-rw-r--r--src/librustc_ast/README.md6
-rw-r--r--src/librustc_ast/ast.rs58
-rw-r--r--src/librustc_ast/attr/mod.rs4
-rw-r--r--src/librustc_ast/lib.rs2
-rw-r--r--src/librustc_ast/mut_visit.rs24
-rw-r--r--src/librustc_ast/node_id.rs2
-rw-r--r--src/librustc_ast/token.rs10
-rw-r--r--src/librustc_ast/visit.rs18
-rw-r--r--src/librustc_ast_lowering/expr.rs2
-rw-r--r--src/librustc_ast_lowering/item.rs55
-rw-r--r--src/librustc_ast_lowering/lib.rs121
-rw-r--r--src/librustc_ast_lowering/pat.rs2
-rw-r--r--src/librustc_ast_lowering/path.rs4
-rw-r--r--src/librustc_ast_passes/ast_validation.rs128
-rw-r--r--src/librustc_ast_passes/feature_gate.rs32
-rw-r--r--src/librustc_ast_passes/lib.rs1
-rw-r--r--src/librustc_ast_passes/node_count.rs2
-rw-r--r--src/librustc_ast_passes/show_span.rs2
-rw-r--r--src/librustc_ast_pretty/pprust.rs38
-rw-r--r--src/librustc_attr/builtin.rs4
-rw-r--r--src/librustc_builtin_macros/assert.rs4
-rw-r--r--src/librustc_builtin_macros/cfg_accessible.rs54
-rw-r--r--src/librustc_builtin_macros/deriving/generic/mod.rs2
-rw-r--r--src/librustc_builtin_macros/deriving/mod.rs6
-rw-r--r--src/librustc_builtin_macros/lib.rs2
-rw-r--r--src/librustc_builtin_macros/proc_macro_harness.rs4
-rw-r--r--src/librustc_builtin_macros/source_util.rs5
-rw-r--r--src/librustc_builtin_macros/standard_library_imports.rs2
-rw-r--r--src/librustc_builtin_macros/test.rs2
-rw-r--r--src/librustc_builtin_macros/test_harness.rs6
-rw-r--r--src/librustc_builtin_macros/util.rs2
-rw-r--r--src/librustc_codegen_llvm/README.md4
-rw-r--r--src/librustc_codegen_llvm/allocator.rs21
-rw-r--r--src/librustc_codegen_llvm/asm.rs22
-rw-r--r--src/librustc_codegen_llvm/attributes.rs4
-rw-r--r--src/librustc_codegen_llvm/back/archive.rs2
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs2
-rw-r--r--src/librustc_codegen_llvm/back/write.rs4
-rw-r--r--src/librustc_codegen_llvm/base.rs2
-rw-r--r--src/librustc_codegen_llvm/builder.rs3
-rw-r--r--src/librustc_codegen_llvm/common.rs15
-rw-r--r--src/librustc_codegen_llvm/context.rs64
-rw-r--r--src/librustc_codegen_llvm/debuginfo/create_scope_map.rs16
-rw-r--r--src/librustc_codegen_llvm/debuginfo/gdb.rs2
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs12
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs16
-rw-r--r--src/librustc_codegen_llvm/debuginfo/source_loc.rs52
-rw-r--r--src/librustc_codegen_llvm/debuginfo/utils.rs8
-rw-r--r--src/librustc_codegen_llvm/declare.rs9
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs160
-rw-r--r--src/librustc_codegen_llvm/lib.rs23
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs22
-rw-r--r--src/librustc_codegen_llvm/llvm/mod.rs6
-rw-r--r--src/librustc_codegen_llvm/llvm_util.rs4
-rw-r--r--src/librustc_codegen_llvm/type_.rs2
-rw-r--r--src/librustc_codegen_ssa/README.md4
-rw-r--r--src/librustc_codegen_ssa/back/archive.rs2
-rw-r--r--src/librustc_codegen_ssa/back/link.rs37
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs6
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs4
-rw-r--r--src/librustc_codegen_ssa/back/write.rs12
-rw-r--r--src/librustc_codegen_ssa/base.rs4
-rw-r--r--src/librustc_codegen_ssa/common.rs2
-rw-r--r--src/librustc_codegen_ssa/lib.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs45
-rw-r--r--src/librustc_codegen_ssa/mir/debuginfo.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/backend.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/misc.rs3
-rw-r--r--src/librustc_codegen_utils/Cargo.toml1
-rw-r--r--src/librustc_codegen_utils/codegen_backend.rs4
-rw-r--r--src/librustc_codegen_utils/link.rs8
-rw-r--r--src/librustc_codegen_utils/symbol_names.rs2
-rw-r--r--src/librustc_data_structures/box_region.rs39
-rw-r--r--src/librustc_data_structures/frozen.rs63
-rw-r--r--src/librustc_data_structures/graph/scc/mod.rs2
-rw-r--r--src/librustc_data_structures/graph/vec_graph/mod.rs2
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_driver/Cargo.toml1
-rw-r--r--src/librustc_driver/README.md4
-rw-r--r--src/librustc_driver/lib.rs19
-rw-r--r--src/librustc_driver/pretty.rs38
-rw-r--r--src/librustc_error_codes/error_codes.rs8
-rw-r--r--src/librustc_error_codes/error_codes/E0117.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0308.md14
-rw-r--r--src/librustc_error_codes/error_codes/E0412.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0422.md3
-rw-r--r--src/librustc_error_codes/error_codes/E0423.md3
-rw-r--r--src/librustc_error_codes/error_codes/E0434.md10
-rw-r--r--src/librustc_error_codes/error_codes/E0628.md30
-rw-r--r--src/librustc_error_codes/error_codes/E0634.md20
-rw-r--r--src/librustc_error_codes/error_codes/E0693.md19
-rw-r--r--src/librustc_error_codes/error_codes/E0739.md13
-rw-r--r--src/librustc_errors/emitter.rs2
-rw-r--r--src/librustc_expand/base.rs42
-rw-r--r--src/librustc_expand/config.rs (renamed from src/librustc_parse/config.rs)25
-rw-r--r--src/librustc_expand/expand.rs284
-rw-r--r--src/librustc_expand/lib.rs6
-rw-r--r--src/librustc_expand/mbe/macro_check.rs25
-rw-r--r--src/librustc_expand/mbe/macro_parser.rs17
-rw-r--r--src/librustc_expand/mbe/macro_rules.rs53
-rw-r--r--src/librustc_expand/mbe/transcribe.rs23
-rw-r--r--src/librustc_expand/module.rs306
-rw-r--r--src/librustc_expand/mut_visit/tests.rs2
-rw-r--r--src/librustc_expand/parse/tests.rs2
-rw-r--r--src/librustc_expand/placeholders.rs52
-rw-r--r--src/librustc_expand/proc_macro.rs8
-rw-r--r--src/librustc_feature/active.rs5
-rw-r--r--src/librustc_feature/builtin_attrs.rs16
-rw-r--r--src/librustc_hir/def.rs7
-rw-r--r--src/librustc_hir/hir.rs54
-rw-r--r--src/librustc_hir/hir_id.rs47
-rw-r--r--src/librustc_hir/intravisit.rs47
-rw-r--r--src/librustc_hir/lang_items.rs1
-rw-r--r--src/librustc_hir/lib.rs6
-rw-r--r--src/librustc_hir/print.rs12
-rw-r--r--src/librustc_hir/stable_hash_impls.rs93
-rw-r--r--src/librustc_hir/target.rs4
-rw-r--r--src/librustc_hir/weak_lang_items.rs1
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs8
-rw-r--r--src/librustc_incremental/assert_module_sources.rs2
-rw-r--r--src/librustc_incremental/persist/README.md4
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs14
-rw-r--r--src/librustc_incremental/persist/file_format.rs2
-rw-r--r--src/librustc_incremental/persist/fs.rs2
-rw-r--r--src/librustc_incremental/persist/load.rs2
-rw-r--r--src/librustc_incremental/persist/save.rs2
-rw-r--r--src/librustc_incremental/persist/work_product.rs2
-rw-r--r--src/librustc_index/lib.rs3
-rw-r--r--src/librustc_index/vec.rs32
-rw-r--r--src/librustc_infer/Cargo.toml3
-rw-r--r--src/librustc_infer/infer/canonical/canonicalizer.rs12
-rw-r--r--src/librustc_infer/infer/canonical/mod.rs4
-rw-r--r--src/librustc_infer/infer/canonical/query_response.rs54
-rw-r--r--src/librustc_infer/infer/canonical/substitute.rs4
-rw-r--r--src/librustc_infer/infer/error_reporting/mod.rs102
-rw-r--r--src/librustc_infer/infer/error_reporting/need_type_info.rs12
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs11
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs12
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs19
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/util.rs78
-rw-r--r--src/librustc_infer/infer/higher_ranked/README.md6
-rw-r--r--src/librustc_infer/infer/higher_ranked/mod.rs4
-rw-r--r--src/librustc_infer/infer/lexical_region_resolve/README.md4
-rw-r--r--src/librustc_infer/infer/lexical_region_resolve/mod.rs35
-rw-r--r--src/librustc_infer/infer/mod.rs120
-rw-r--r--src/librustc_infer/infer/outlives/env.rs49
-rw-r--r--src/librustc_infer/infer/outlives/mod.rs22
-rw-r--r--src/librustc_infer/infer/region_constraints/README.md4
-rw-r--r--src/librustc_infer/lib.rs10
-rw-r--r--src/librustc_infer/traits/engine.rs10
-rw-r--r--src/librustc_infer/traits/error_reporting/mod.rs1549
-rw-r--r--src/librustc_infer/traits/mod.rs522
-rw-r--r--src/librustc_infer/traits/project.rs1507
-rw-r--r--src/librustc_infer/traits/util.rs454
-rw-r--r--src/librustc_interface/Cargo.toml1
-rw-r--r--src/librustc_interface/interface.rs8
-rw-r--r--src/librustc_interface/passes.rs48
-rw-r--r--src/librustc_interface/queries.rs4
-rw-r--r--src/librustc_interface/tests.rs14
-rw-r--r--src/librustc_interface/util.rs7
-rw-r--r--src/librustc_lint/Cargo.toml1
-rw-r--r--src/librustc_lint/builtin.rs17
-rw-r--r--src/librustc_lint/early.rs20
-rw-r--r--src/librustc_lint/internal.rs2
-rw-r--r--src/librustc_lint/late.rs8
-rw-r--r--src/librustc_lint/levels.rs6
-rw-r--r--src/librustc_lint/nonstandard_style.rs2
-rw-r--r--src/librustc_lint/passes.rs2
-rw-r--r--src/librustc_lint/types.rs50
-rw-r--r--src/librustc_lint/unused.rs11
-rw-r--r--src/librustc_metadata/Cargo.toml1
-rw-r--r--src/librustc_metadata/creader.rs13
-rw-r--r--src/librustc_metadata/dependency_format.rs8
-rw-r--r--src/librustc_metadata/lib.rs2
-rw-r--r--src/librustc_metadata/link_args.rs2
-rw-r--r--src/librustc_metadata/locator.rs6
-rw-r--r--src/librustc_metadata/native_libs.rs4
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs133
-rw-r--r--src/librustc_metadata/rmeta/decoder/cstore_impl.rs20
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs126
-rw-r--r--src/librustc_metadata/rmeta/mod.rs23
-rw-r--r--src/librustc_mir/Cargo.toml2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs8
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs8
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_name.rs2
-rw-r--r--src/librustc_mir/borrow_check/mod.rs9
-rw-r--r--src/librustc_mir/borrow_check/nll.rs2
-rw-r--r--src/librustc_mir/borrow_check/region_infer/mod.rs15
-rw-r--r--src/librustc_mir/borrow_check/region_infer/opaque_types.rs1
-rw-r--r--src/librustc_mir/borrow_check/type_check/free_region_relations.rs12
-rw-r--r--src/librustc_mir/borrow_check/type_check/liveness/trace.rs6
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs19
-rw-r--r--src/librustc_mir/borrow_check/type_check/relate_tys.rs4
-rw-r--r--src/librustc_mir/borrow_check/universal_regions.rs4
-rw-r--r--src/librustc_mir/const_eval/fn_queries.rs4
-rw-r--r--src/librustc_mir/const_eval/machine.rs4
-rw-r--r--src/librustc_mir/const_eval/mod.rs2
-rw-r--r--src/librustc_mir/dataflow/generic/cursor.rs50
-rw-r--r--src/librustc_mir/dataflow/generic/engine.rs9
-rw-r--r--src/librustc_mir/dataflow/generic/graphviz.rs2
-rw-r--r--src/librustc_mir/dataflow/generic/mod.rs32
-rw-r--r--src/librustc_mir/dataflow/generic/tests.rs4
-rw-r--r--src/librustc_mir/dataflow/impls/storage_liveness.rs18
-rw-r--r--src/librustc_mir/dataflow/mod.rs14
-rw-r--r--src/librustc_mir/interpret/eval_context.rs43
-rw-r--r--src/librustc_mir/interpret/intern.rs4
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs15
-rw-r--r--src/librustc_mir/interpret/intrinsics/type_name.rs1
-rw-r--r--src/librustc_mir/interpret/machine.rs22
-rw-r--r--src/librustc_mir/interpret/memory.rs82
-rw-r--r--src/librustc_mir/interpret/mod.rs2
-rw-r--r--src/librustc_mir/interpret/operand.rs89
-rw-r--r--src/librustc_mir/interpret/place.rs10
-rw-r--r--src/librustc_mir/interpret/terminator.rs228
-rw-r--r--src/librustc_mir/interpret/validity.rs56
-rw-r--r--src/librustc_mir/lib.rs3
-rw-r--r--src/librustc_mir/monomorphize/collector.rs8
-rw-r--r--src/librustc_mir/shim.rs33
-rw-r--r--src/librustc_mir/transform/add_retag.rs2
-rw-r--r--src/librustc_mir/transform/check_consts/ops.rs63
-rw-r--r--src/librustc_mir/transform/check_consts/qualifs.rs335
-rw-r--r--src/librustc_mir/transform/check_consts/resolver.rs31
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs7
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs7
-rw-r--r--src/librustc_mir/transform/const_prop.rs5
-rw-r--r--src/librustc_mir/transform/dump_mir.rs2
-rw-r--r--src/librustc_mir/transform/generator.rs154
-rw-r--r--src/librustc_mir/transform/inline.rs15
-rw-r--r--src/librustc_mir/transform/mod.rs5
-rw-r--r--src/librustc_mir/transform/promote_consts.rs12
-rw-r--r--src/librustc_mir/transform/simplify.rs30
-rw-r--r--src/librustc_mir/util/liveness.rs4
-rw-r--r--src/librustc_mir/util/pretty.rs12
-rw-r--r--src/librustc_mir_build/Cargo.toml1
-rw-r--r--src/librustc_mir_build/build/matches/simplify.rs7
-rw-r--r--src/librustc_mir_build/build/mod.rs4
-rw-r--r--src/librustc_mir_build/hair/cx/expr.rs9
-rw-r--r--src/librustc_mir_build/hair/cx/mod.rs1
-rw-r--r--src/librustc_mir_build/hair/pattern/_match.rs16
-rw-r--r--src/librustc_mir_build/hair/pattern/check_match.rs14
-rw-r--r--src/librustc_mir_build/hair/pattern/const_to_pat.rs13
-rw-r--r--src/librustc_mir_build/hair/pattern/mod.rs7
-rw-r--r--src/librustc_mir_build/lib.rs3
-rw-r--r--src/librustc_mir_build/lints.rs2
-rw-r--r--src/librustc_parse/lib.rs52
-rw-r--r--src/librustc_parse/parser/attr.rs231
-rw-r--r--src/librustc_parse/parser/diagnostics.rs43
-rw-r--r--src/librustc_parse/parser/expr.rs139
-rw-r--r--src/librustc_parse/parser/item.rs144
-rw-r--r--src/librustc_parse/parser/mod.rs35
-rw-r--r--src/librustc_parse/parser/module.rs306
-rw-r--r--src/librustc_parse/parser/pat.rs14
-rw-r--r--src/librustc_parse/parser/stmt.rs75
-rw-r--r--src/librustc_parse/parser/ty.rs64
-rw-r--r--src/librustc_parse/validate_attr.rs2
-rw-r--r--src/librustc_passes/Cargo.toml1
-rw-r--r--src/librustc_passes/check_attr.rs6
-rw-r--r--src/librustc_passes/check_const.rs11
-rw-r--r--src/librustc_passes/dead.rs16
-rw-r--r--src/librustc_passes/entry.rs14
-rw-r--r--src/librustc_passes/hir_stats.rs6
-rw-r--r--src/librustc_passes/intrinsicck.rs9
-rw-r--r--src/librustc_passes/lang_items.rs2
-rw-r--r--src/librustc_passes/lib_features.rs4
-rw-r--r--src/librustc_passes/liveness.rs35
-rw-r--r--src/librustc_passes/loops.rs9
-rw-r--r--src/librustc_passes/reachable.rs26
-rw-r--r--src/librustc_passes/region.rs9
-rw-r--r--src/librustc_passes/stability.rs26
-rw-r--r--src/librustc_passes/upvars.rs9
-rw-r--r--src/librustc_passes/weak_lang_items.rs11
-rw-r--r--src/librustc_plugin_impl/Cargo.toml1
-rw-r--r--src/librustc_plugin_impl/load.rs2
-rw-r--r--src/librustc_privacy/Cargo.toml1
-rw-r--r--src/librustc_privacy/lib.rs43
-rw-r--r--src/librustc_resolve/Cargo.toml1
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs95
-rw-r--r--src/librustc_resolve/check_unused.rs10
-rw-r--r--src/librustc_resolve/def_collector.rs107
-rw-r--r--src/librustc_resolve/diagnostics.rs120
-rw-r--r--src/librustc_resolve/imports.rs5
-rw-r--r--src/librustc_resolve/late.rs64
-rw-r--r--src/librustc_resolve/late/diagnostics.rs10
-rw-r--r--src/librustc_resolve/late/lifetimes.rs99
-rw-r--r--src/librustc_resolve/lib.rs152
-rw-r--r--src/librustc_resolve/macros.rs98
-rw-r--r--src/librustc_save_analysis/Cargo.toml1
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs10
-rw-r--r--src/librustc_save_analysis/lib.rs19
-rw-r--r--src/librustc_save_analysis/sig.rs8
-rw-r--r--src/librustc_save_analysis/span_utils.rs2
-rw-r--r--src/librustc_session/session.rs55
-rw-r--r--src/librustc_span/def_id.rs57
-rw-r--r--src/librustc_span/hygiene.rs32
-rw-r--r--src/librustc_span/lib.rs82
-rw-r--r--src/librustc_span/source_map.rs19
-rw-r--r--src/librustc_span/symbol.rs46
-rw-r--r--src/librustc_target/README.md4
-rw-r--r--src/librustc_target/abi/mod.rs5
-rw-r--r--src/librustc_target/lib.rs3
-rw-r--r--src/librustc_target/spec/aarch64_apple_ios.rs4
-rw-r--r--src/librustc_target/spec/aarch64_apple_tvos.rs25
-rw-r--r--src/librustc_target/spec/apple_sdk_base.rs (renamed from src/librustc_target/spec/apple_ios_base.rs)39
-rw-r--r--src/librustc_target/spec/armv7_apple_ios.rs4
-rw-r--r--src/librustc_target/spec/armv7s_apple_ios.rs4
-rw-r--r--src/librustc_target/spec/i386_apple_ios.rs4
-rw-r--r--src/librustc_target/spec/mod.rs24
-rw-r--r--src/librustc_target/spec/windows_base.rs31
-rw-r--r--src/librustc_target/spec/windows_uwp_base.rs1
-rw-r--r--src/librustc_target/spec/x86_64_apple_ios.rs4
-rw-r--r--src/librustc_target/spec/x86_64_apple_ios_macabi.rs4
-rw-r--r--src/librustc_target/spec/x86_64_apple_tvos.rs19
-rw-r--r--src/librustc_trait_selection/Cargo.toml27
-rw-r--r--src/librustc_trait_selection/infer.rs182
-rw-r--r--src/librustc_trait_selection/lib.rs32
-rw-r--r--src/librustc_trait_selection/opaque_types.rs (renamed from src/librustc_infer/infer/opaque_types/mod.rs)151
-rw-r--r--src/librustc_trait_selection/traits/auto_trait.rs (renamed from src/librustc_infer/traits/auto_trait.rs)4
-rw-r--r--src/librustc_trait_selection/traits/codegen/mod.rs (renamed from src/librustc_infer/traits/codegen/mod.rs)56
-rw-r--r--src/librustc_trait_selection/traits/coherence.rs (renamed from src/librustc_infer/traits/coherence.rs)10
-rw-r--r--src/librustc_trait_selection/traits/engine.rs14
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs1900
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs (renamed from src/librustc_infer/traits/error_reporting/on_unimplemented.rs)28
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/suggestions.rs (renamed from src/librustc_infer/traits/error_reporting/suggestions.rs)398
-rw-r--r--src/librustc_trait_selection/traits/fulfill.rs (renamed from src/librustc_infer/traits/fulfill.rs)5
-rw-r--r--src/librustc_trait_selection/traits/misc.rs (renamed from src/librustc_infer/traits/misc.rs)5
-rw-r--r--src/librustc_trait_selection/traits/mod.rs533
-rw-r--r--src/librustc_trait_selection/traits/object_safety.rs (renamed from src/librustc_infer/traits/object_safety.rs)3
-rw-r--r--src/librustc_trait_selection/traits/on_unimplemented.rs (renamed from src/librustc_infer/traits/on_unimplemented.rs)0
-rw-r--r--src/librustc_trait_selection/traits/project.rs1515
-rw-r--r--src/librustc_trait_selection/traits/query/dropck_outlives.rs (renamed from src/librustc_infer/traits/query/dropck_outlives.rs)8
-rw-r--r--src/librustc_trait_selection/traits/query/evaluate_obligation.rs (renamed from src/librustc_infer/traits/query/evaluate_obligation.rs)40
-rw-r--r--src/librustc_trait_selection/traits/query/method_autoderef.rs (renamed from src/librustc_infer/traits/query/method_autoderef.rs)0
-rw-r--r--src/librustc_trait_selection/traits/query/mod.rs (renamed from src/librustc_infer/traits/query/mod.rs)0
-rw-r--r--src/librustc_trait_selection/traits/query/normalize.rs (renamed from src/librustc_infer/traits/query/normalize.rs)13
-rw-r--r--src/librustc_trait_selection/traits/query/outlives_bounds.rs (renamed from src/librustc_infer/traits/query/outlives_bounds.rs)36
-rw-r--r--src/librustc_trait_selection/traits/query/type_op/ascribe_user_type.rs (renamed from src/librustc_infer/traits/query/type_op/ascribe_user_type.rs)0
-rw-r--r--src/librustc_trait_selection/traits/query/type_op/custom.rs (renamed from src/librustc_infer/traits/query/type_op/custom.rs)4
-rw-r--r--src/librustc_trait_selection/traits/query/type_op/eq.rs (renamed from src/librustc_infer/traits/query/type_op/eq.rs)0
-rw-r--r--src/librustc_trait_selection/traits/query/type_op/implied_outlives_bounds.rs (renamed from src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs)0
-rw-r--r--src/librustc_trait_selection/traits/query/type_op/mod.rs (renamed from src/librustc_infer/traits/query/type_op/mod.rs)2
-rw-r--r--src/librustc_trait_selection/traits/query/type_op/normalize.rs (renamed from src/librustc_infer/traits/query/type_op/normalize.rs)0
-rw-r--r--src/librustc_trait_selection/traits/query/type_op/outlives.rs (renamed from src/librustc_infer/traits/query/type_op/outlives.rs)0
-rw-r--r--src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs (renamed from src/librustc_infer/traits/query/type_op/prove_predicate.rs)0
-rw-r--r--src/librustc_trait_selection/traits/query/type_op/subtype.rs (renamed from src/librustc_infer/traits/query/type_op/subtype.rs)0
-rw-r--r--src/librustc_trait_selection/traits/select.rs (renamed from src/librustc_infer/traits/select.rs)75
-rw-r--r--src/librustc_trait_selection/traits/specialize/mod.rs (renamed from src/librustc_infer/traits/specialize/mod.rs)53
-rw-r--r--src/librustc_trait_selection/traits/specialize/specialization_graph.rs (renamed from src/librustc_infer/traits/specialize/specialization_graph.rs)0
-rw-r--r--src/librustc_trait_selection/traits/structural_match.rs (renamed from src/librustc_infer/traits/structural_match.rs)0
-rw-r--r--src/librustc_trait_selection/traits/util.rs675
-rw-r--r--src/librustc_trait_selection/traits/wf.rs (renamed from src/librustc_infer/traits/wf.rs)2
-rw-r--r--src/librustc_traits/Cargo.toml1
-rw-r--r--src/librustc_traits/dropck_outlives.rs14
-rw-r--r--src/librustc_traits/evaluate_obligation.rs6
-rw-r--r--src/librustc_traits/implied_outlives_bounds.rs12
-rw-r--r--src/librustc_traits/lowering/environment.rs4
-rw-r--r--src/librustc_traits/lowering/mod.rs14
-rw-r--r--src/librustc_traits/normalize_erasing_regions.rs3
-rw-r--r--src/librustc_traits/normalize_projection_ty.rs8
-rw-r--r--src/librustc_traits/type_op.rs18
-rw-r--r--src/librustc_ty/Cargo.toml2
-rw-r--r--src/librustc_ty/common_traits.rs2
-rw-r--r--src/librustc_ty/instance.rs72
-rw-r--r--src/librustc_ty/ty.rs9
-rw-r--r--src/librustc_typeck/Cargo.toml2
-rw-r--r--src/librustc_typeck/README.md6
-rw-r--r--src/librustc_typeck/astconv.rs33
-rw-r--r--src/librustc_typeck/check/_match.rs4
-rw-r--r--src/librustc_typeck/check/autoderef.rs8
-rw-r--r--src/librustc_typeck/check/cast.rs8
-rw-r--r--src/librustc_typeck/check/closure.rs5
-rw-r--r--src/librustc_typeck/check/coercion.rs8
-rw-r--r--src/librustc_typeck/check/compare_method.rs24
-rw-r--r--src/librustc_typeck/check/demand.rs4
-rw-r--r--src/librustc_typeck/check/dropck.rs9
-rw-r--r--src/librustc_typeck/check/expr.rs10
-rw-r--r--src/librustc_typeck/check/generator_interior.rs7
-rw-r--r--src/librustc_typeck/check/intrinsic.rs19
-rw-r--r--src/librustc_typeck/check/method/confirm.rs2
-rw-r--r--src/librustc_typeck/check/method/mod.rs7
-rw-r--r--src/librustc_typeck/check/method/probe.rs15
-rw-r--r--src/librustc_typeck/check/method/suggest.rs18
-rw-r--r--src/librustc_typeck/check/mod.rs89
-rw-r--r--src/librustc_typeck/check/op.rs3
-rw-r--r--src/librustc_typeck/check/pat.rs15
-rw-r--r--src/librustc_typeck/check/regionck.rs28
-rw-r--r--src/librustc_typeck/check/upvar.rs9
-rw-r--r--src/librustc_typeck/check/wfcheck.rs23
-rw-r--r--src/librustc_typeck/check/writeback.rs60
-rw-r--r--src/librustc_typeck/check_unused.rs2
-rw-r--r--src/librustc_typeck/coherence/builtin.rs15
-rw-r--r--src/librustc_typeck/coherence/inherent_impls_overlap.rs10
-rw-r--r--src/librustc_typeck/coherence/mod.rs18
-rw-r--r--src/librustc_typeck/coherence/orphan.rs2
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs4
-rw-r--r--src/librustc_typeck/collect.rs53
-rw-r--r--src/librustc_typeck/collect/type_of.rs12
-rw-r--r--src/librustc_typeck/constrained_generic_params.rs16
-rw-r--r--src/librustc_typeck/expr_use_visitor.rs2
-rw-r--r--src/librustc_typeck/impl_wf_check.rs16
-rw-r--r--src/librustc_typeck/impl_wf_check/min_specialization.rs409
-rw-r--r--src/librustc_typeck/lib.rs11
-rw-r--r--src/librustc_typeck/mem_categorization.rs5
-rw-r--r--src/librustc_typeck/structured_errors.rs2
-rw-r--r--src/librustc_typeck/variance/constraints.rs4
-rw-r--r--src/librustc_typeck/variance/mod.rs8
-rw-r--r--src/librustc_typeck/variance/terms.rs8
-rw-r--r--src/librustdoc/README.md4
-rw-r--r--src/librustdoc/clean/auto_trait.rs2
-rw-r--r--src/librustdoc/clean/blanket_impl.rs1
-rw-r--r--src/librustdoc/clean/inline.rs9
-rw-r--r--src/librustdoc/clean/mod.rs28
-rw-r--r--src/librustdoc/clean/types.rs14
-rw-r--r--src/librustdoc/clean/utils.rs40
-rw-r--r--src/librustdoc/config.rs82
-rw-r--r--src/librustdoc/core.rs23
-rw-r--r--src/librustdoc/html/markdown.rs8
-rw-r--r--src/librustdoc/html/render.rs108
-rw-r--r--src/librustdoc/html/render/cache.rs44
-rw-r--r--src/librustdoc/html/static/main.js130
-rw-r--r--src/librustdoc/html/static/rustdoc.css13
-rw-r--r--src/librustdoc/html/static/themes/dark.css9
-rw-r--r--src/librustdoc/html/static/themes/light.css12
-rw-r--r--src/librustdoc/html/static_files.rs56
-rw-r--r--src/librustdoc/lib.rs5
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs53
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs8
-rw-r--r--src/librustdoc/passes/mod.rs2
-rw-r--r--src/librustdoc/test.rs21
-rw-r--r--src/librustdoc/visit_ast.rs12
-rw-r--r--src/libstd/backtrace.rs91
-rw-r--r--src/libstd/error.rs3
-rw-r--r--src/libstd/future.rs5
-rw-r--r--src/libstd/io/mod.rs1
-rw-r--r--src/libstd/io/stdio.rs12
-rw-r--r--src/libstd/keyword_docs.rs71
-rw-r--r--src/libstd/lib.rs4
-rw-r--r--src/libstd/panicking.rs109
-rw-r--r--src/libstd/prelude/v1.rs9
-rw-r--r--src/libstd/sync/once.rs2
-rw-r--r--src/libstd/sys/cloudabi/io.rs1
-rw-r--r--src/libstd/sys/hermit/io.rs1
-rw-r--r--src/libstd/sys/sgx/io.rs1
-rw-r--r--src/libstd/sys/unix/io.rs1
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs23
-rw-r--r--src/libstd/sys/vxworks/io.rs1
-rw-r--r--src/libstd/sys/wasi/io.rs1
-rw-r--r--src/libstd/sys/wasm/io.rs1
-rw-r--r--src/libstd/sys/windows/c.rs5
-rw-r--r--src/libstd/sys/windows/io.rs1
-rw-r--r--src/libstd/sys/windows/time.rs2
-rw-r--r--src/libstd/sys_common/backtrace.rs2
-rw-r--r--src/libstd/sys_common/process.rs2
-rw-r--r--src/libstd/sys_common/wtf8.rs16
-rw-r--r--src/libtest/console.rs2
-rw-r--r--src/libtest/formatters/mod.rs2
-rw-r--r--src/libtest/stats.rs16
-rw-r--r--src/libtest/types.rs8
-rw-r--r--src/libunwind/build.rs9
-rw-r--r--src/rtstartup/rsbegin.rs33
-rw-r--r--src/rustllvm/RustWrapper.cpp47
-rw-r--r--src/stage0.txt2
-rw-r--r--src/test/COMPILER_TESTS.md2
-rw-r--r--src/test/codegen/catch-unwind.rs19
-rw-r--r--src/test/codegen/consts.rs4
-rw-r--r--src/test/codegen/debug-column-msvc.rs16
-rw-r--r--src/test/codegen/debug-column.rs24
-rw-r--r--src/test/codegen/remap_path_prefix/main.rs2
-rw-r--r--src/test/codegen/try-panic-abort.rs20
-rw-r--r--src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs2
-rw-r--r--src/test/incremental/change_symbol_export_status.rs6
-rw-r--r--src/test/incremental/hashes/call_expressions.rs28
-rw-r--r--src/test/incremental/hashes/closure_expressions.rs14
-rw-r--r--src/test/incremental/hashes/consts.rs18
-rw-r--r--src/test/incremental/hashes/enum_constructors.rs30
-rw-r--r--src/test/incremental/hashes/enum_defs.rs54
-rw-r--r--src/test/incremental/hashes/exported_vs_not.rs14
-rw-r--r--src/test/incremental/hashes/for_loops.rs22
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs114
-rw-r--r--src/test/incremental/hashes/if_expressions.rs16
-rw-r--r--src/test/incremental/hashes/indexing_expressions.rs56
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs52
-rw-r--r--src/test/incremental/hashes/inline_asm.rs12
-rw-r--r--src/test/incremental/hashes/let_expressions.rs24
-rw-r--r--src/test/incremental/hashes/loop_expressions.rs16
-rw-r--r--src/test/incremental/hashes/match_expressions.rs26
-rw-r--r--src/test/incremental/hashes/panic_exprs.rs18
-rw-r--r--src/test/incremental/hashes/statics.rs26
-rw-r--r--src/test/incremental/hashes/struct_constructors.rs18
-rw-r--r--src/test/incremental/hashes/struct_defs.rs168
-rw-r--r--src/test/incremental/hashes/trait_defs.rs424
-rw-r--r--src/test/incremental/hashes/trait_impls.rs156
-rw-r--r--src/test/incremental/hashes/type_defs.rs32
-rw-r--r--src/test/incremental/hashes/unary_and_binary_exprs.rs56
-rw-r--r--src/test/incremental/hashes/while_let_loops.rs18
-rw-r--r--src/test/incremental/hashes/while_loops.rs18
-rw-r--r--src/test/incremental/ich_method_call_trait_scope.rs8
-rw-r--r--src/test/incremental/ich_nested_items.rs19
-rw-r--r--src/test/incremental/ich_resolve_results.rs16
-rw-r--r--src/test/incremental/inlined_hir_34991/main.rs2
-rw-r--r--src/test/incremental/issue-69596.rs21
-rw-r--r--src/test/incremental/source_loc_macros.rs20
-rw-r--r--src/test/incremental/span_hash_stable/auxiliary/sub1.rs2
-rw-r--r--src/test/incremental/span_hash_stable/auxiliary/sub2.rs2
-rw-r--r--src/test/incremental/spans_significant_w_debuginfo.rs4
-rw-r--r--src/test/incremental/string_constant.rs2
-rw-r--r--src/test/incremental/unchecked_dirty_clean.rs8
-rw-r--r--src/test/mir-opt/const-promotion-extern-static.rs24
-rw-r--r--src/test/mir-opt/const_prop/discriminant.rs2
-rw-r--r--src/test/mir-opt/const_prop/issue-66971.rs2
-rw-r--r--src/test/mir-opt/const_prop/read_immutable_static.rs4
-rw-r--r--src/test/mir-opt/generator-tiny.rs34
-rw-r--r--src/test/mir-opt/no-drop-for-inactive-variant.rs43
-rw-r--r--src/test/mir-opt/remove_fake_borrows.rs10
-rw-r--r--src/test/mir-opt/simplify-locals-removes-unused-consts.rs24
-rw-r--r--src/test/mir-opt/storage_live_dead_in_statics.rs12
-rw-r--r--src/test/pretty/attr-literals.rs2
-rw-r--r--src/test/pretty/delimited-token-groups.rs7
-rw-r--r--src/test/pretty/issue-12590-a.rs1
-rw-r--r--src/test/pretty/issue-4264.pp44
-rw-r--r--src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs2
-rw-r--r--src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs9
-rw-r--r--src/test/run-make-fulldeps/issue-19371/foo.rs7
-rw-r--r--src/test/rustdoc-js-std/return-specific-literal.js10
-rw-r--r--src/test/rustdoc-js-std/return-specific.js10
-rw-r--r--src/test/rustdoc-ui/coverage/html.rs4
-rw-r--r--src/test/rustdoc-ui/coverage/html.stderr2
-rw-r--r--src/test/rustdoc-ui/coverage/json.rs27
-rw-r--r--src/test/rustdoc-ui/coverage/json.stdout1
-rw-r--r--src/test/rustdoc-ui/issue-61732.rs2
-rw-r--r--src/test/rustdoc-ui/issue-61732.stderr8
-rw-r--r--src/test/rustdoc/attributes.rs4
-rw-r--r--src/test/ui-fulldeps/auxiliary/linkage-visibility.rs12
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs4
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-for-crate.rs4
-rw-r--r--src/test/ui/asm/issue-69092.rs10
-rw-r--r--src/test/ui/asm/issue-69092.stderr11
-rw-r--r--src/test/ui/associated-item/associated-item-enum.stderr2
-rw-r--r--src/test/ui/async-await/async-fn-size-moved-locals.rs10
-rw-r--r--src/test/ui/async-await/async-fn-size-uninit-locals.rs10
-rw-r--r--src/test/ui/async-await/async-fn-size.rs14
-rw-r--r--src/test/ui/async-await/expansion-in-attrs.rs13
-rw-r--r--src/test/ui/async-await/issues/issue-62097.nll.stderr6
-rw-r--r--src/test/ui/async-await/issues/issue-63388-1.nll.stderr2
-rw-r--r--src/test/ui/async-await/no-const-async.stderr4
-rw-r--r--src/test/ui/auto-ref-slice-plus-ref.stderr2
-rw-r--r--src/test/ui/auto-trait-validation.stderr18
-rw-r--r--src/test/ui/binding/ambiguity-item.rs18
-rw-r--r--src/test/ui/binding/ambiguity-item.stderr41
-rw-r--r--src/test/ui/binding/const-param.rs12
-rw-r--r--src/test/ui/binding/const-param.stderr17
-rw-r--r--src/test/ui/block-result/issue-3563.stderr2
-rw-r--r--src/test/ui/coherence/coherence-negative-impls-safe.stderr7
-rw-r--r--src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs24
-rw-r--r--src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr44
-rw-r--r--src/test/ui/conditional-compilation/cfg_accessible-stuck.rs9
-rw-r--r--src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr14
-rw-r--r--src/test/ui/conditional-compilation/cfg_accessible-unstable.rs2
-rw-r--r--src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr12
-rw-r--r--src/test/ui/conditional-compilation/cfg_accessible.rs43
-rw-r--r--src/test/ui/conditional-compilation/cfg_accessible.stderr38
-rw-r--r--src/test/ui/conflicting-repr-hints.stderr2
-rw-r--r--src/test/ui/const-generics/cannot-infer-const-args.stderr2
-rw-r--r--src/test/ui/const-generics/const-generic-type_name.rs2
-rw-r--r--src/test/ui/const-generics/fn-const-param-infer.stderr12
-rw-r--r--src/test/ui/const-generics/issues/issue-62504.rs25
-rw-r--r--src/test/ui/const-generics/issues/issue-62504.stderr8
-rw-r--r--src/test/ui/const-generics/issues/issue-67739.rs18
-rw-r--r--src/test/ui/const-generics/issues/issue-67739.stderr8
-rw-r--r--src/test/ui/const-generics/raw-ptr-const-param.rs4
-rw-r--r--src/test/ui/const-generics/raw-ptr-const-param.stderr10
-rw-r--r--src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr40
-rw-r--r--src/test/ui/consts/const-eval/const_panic_libcore_main.rs2
-rw-r--r--src/test/ui/consts/const-eval/const_prop_errors.rs2
-rw-r--r--src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr4
-rw-r--r--src/test/ui/consts/const-eval/const_signed_pat.rs2
-rw-r--r--src/test/ui/consts/const-eval/double_check.rs2
-rw-r--r--src/test/ui/consts/const-eval/double_promotion.rs2
-rw-r--r--src/test/ui/consts/const-eval/duration_conversion.rs2
-rw-r--r--src/test/ui/consts/const-eval/extern_fat_pointer.rs2
-rw-r--r--src/test/ui/consts/const-eval/ice-generic-assoc-const.rs2
-rw-r--r--src/test/ui/consts/const-eval/ice-packed.rs5
-rw-r--r--src/test/ui/consts/const-eval/issue-47971.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-49296.stderr2
-rw-r--r--src/test/ui/consts/const-eval/issue-50706.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-51300.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-53157.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-53401.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-55541.rs2
-rw-r--r--src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs2
-rw-r--r--src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs2
-rw-r--r--src/test/ui/consts/const-eval/pub_const_err.rs2
-rw-r--r--src/test/ui/consts/const-eval/pub_const_err_bin.rs2
-rw-r--r--src/test/ui/consts/const-eval/simple_with_undef.rs2
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.stderr2
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.rs2
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.stderr8
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr2
-rw-r--r--src/test/ui/consts/const-eval/zst_operand_eval.rs2
-rw-r--r--src/test/ui/consts/const-int-unchecked.stderr90
-rw-r--r--src/test/ui/consts/dangling-alloc-id-ice.stderr2
-rw-r--r--src/test/ui/consts/dangling_raw_ptr.stderr2
-rw-r--r--src/test/ui/consts/miri_unleashed/abi-mismatch.stderr2
-rw-r--r--src/test/ui/consts/miri_unleashed/mutable_const.stderr2
-rw-r--r--src/test/ui/consts/offset_from_ub.stderr6
-rw-r--r--src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-40006.stderr4
-rw-r--r--src/test/ui/directory_ownership/macro-expanded-mod.rs4
-rw-r--r--src/test/ui/directory_ownership/macro-expanded-mod.stderr6
-rw-r--r--src/test/ui/directory_ownership/non-inline-mod-restriction.stderr4
-rw-r--r--src/test/ui/enum/enum-discrim-too-small2.stderr7
-rw-r--r--src/test/ui/error-codes/E0121.stderr2
-rw-r--r--src/test/ui/error-codes/E0197.stderr4
-rw-r--r--src/test/ui/error-codes/E0198.stderr7
-rw-r--r--src/test/ui/error-codes/E0396-fixed.stderr2
-rw-r--r--src/test/ui/error-codes/E0583.stderr6
-rw-r--r--src/test/ui/error-codes/E0624.rs2
-rw-r--r--src/test/ui/error-codes/E0624.stderr2
-rw-r--r--src/test/ui/explore-issue-38412.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr4
-rw-r--r--src/test/ui/fn-in-pat.rs2
-rw-r--r--src/test/ui/fn-in-pat.stderr2
-rw-r--r--src/test/ui/generator/discriminant.rs134
-rw-r--r--src/test/ui/generator/generator-yielding-or-returning-itself.rs (renamed from src/test/ui/generator-yielding-or-returning-itself.rs)0
-rw-r--r--src/test/ui/generator/generator-yielding-or-returning-itself.stderr (renamed from src/test/ui/generator-yielding-or-returning-itself.stderr)0
-rw-r--r--src/test/ui/generator/issue-69039.rs6
-rw-r--r--src/test/ui/generator/resume-arg-size.rs28
-rw-r--r--src/test/ui/generator/size-moved-locals.rs10
-rw-r--r--src/test/ui/generator/too-many-parameters.stderr1
-rw-r--r--src/test/ui/generic-associated-types/empty_generics.rs2
-rw-r--r--src/test/ui/generic-associated-types/empty_generics.stderr4
-rw-r--r--src/test/ui/hygiene/macro-metavars-legacy.rs29
-rw-r--r--src/test/ui/hygiene/macro-metavars-transparent.rs24
-rw-r--r--src/test/ui/if-attrs/else-attrs.rs2
-rw-r--r--src/test/ui/if-attrs/else-attrs.stderr19
-rw-r--r--src/test/ui/imports/issue-55884-2.stderr17
-rw-r--r--src/test/ui/imports/reexports.stderr14
-rw-r--r--src/test/ui/init-large-type.rs9
-rw-r--r--src/test/ui/init-unsafe.rs9
-rw-r--r--src/test/ui/init-unsafe.stderr11
-rw-r--r--src/test/ui/intrinsics/intrinsic-move-val.rs15
-rw-r--r--src/test/ui/intrinsics/intrinsic-uninit.rs13
-rw-r--r--src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr6
-rw-r--r--src/test/ui/issues/issue-16683.nll.stderr6
-rw-r--r--src/test/ui/issues/issue-17758.nll.stderr6
-rw-r--r--src/test/ui/issues/issue-20616-8.rs2
-rw-r--r--src/test/ui/issues/issue-20616-8.stderr4
-rw-r--r--src/test/ui/issues/issue-20616-9.rs2
-rw-r--r--src/test/ui/issues/issue-20616-9.stderr4
-rw-r--r--src/test/ui/issues/issue-21174.stderr4
-rw-r--r--src/test/ui/issues/issue-21202.rs2
-rw-r--r--src/test/ui/issues/issue-21202.stderr2
-rw-r--r--src/test/ui/issues/issue-23080-2.rs3
-rw-r--r--src/test/ui/issues/issue-23080-2.stderr11
-rw-r--r--src/test/ui/issues/issue-23080.rs3
-rw-r--r--src/test/ui/issues/issue-23080.stderr13
-rw-r--r--src/test/ui/issues/issue-28344.stderr4
-rw-r--r--src/test/ui/issues/issue-3763.rs4
-rw-r--r--src/test/ui/issues/issue-3763.stderr4
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr2
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr2
-rw-r--r--src/test/ui/issues/issue-53498.rs2
-rw-r--r--src/test/ui/issues/issue-53498.stderr2
-rw-r--r--src/test/ui/issues/issue-55587.stderr2
-rw-r--r--src/test/ui/issues/issue-63364.stderr1
-rw-r--r--src/test/ui/issues/issue-66473.rsbin113 -> 127 bytes
-rw-r--r--src/test/ui/issues/issue-66473.stderrbin2632 -> 2660 bytes
-rw-r--r--src/test/ui/json-bom-plus-crlf-multifile.stderr44
-rw-r--r--src/test/ui/json-bom-plus-crlf.stderr44
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs1
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr9
-rw-r--r--src/test/ui/label/label_break_value_illegal_uses.stderr5
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr2
-rw-r--r--src/test/ui/lint/deny-overflowing-literals.stderr1
-rw-r--r--src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs10
-rw-r--r--src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr8
-rw-r--r--src/test/ui/lint/lint-pre-expansion-extern-module.rs7
-rw-r--r--src/test/ui/lint/lint-pre-expansion-extern-module.stderr10
-rw-r--r--src/test/ui/lint/lint-range-endpoint-overflow.stderr6
-rw-r--r--src/test/ui/lint/lint-type-limits2.stderr1
-rw-r--r--src/test/ui/lint/lint-type-limits3.stderr1
-rw-r--r--src/test/ui/lint/lint-type-overflow.stderr35
-rw-r--r--src/test/ui/lint/lint-type-overflow2.stderr9
-rw-r--r--src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs3
-rw-r--r--src/test/ui/lint/type-overflow.stderr13
-rw-r--r--src/test/ui/lint/uninitialized-zeroed.stderr16
-rw-r--r--src/test/ui/lint/use_suggestion_json.stderr2
-rw-r--r--src/test/ui/macros/issue-58490.rs26
-rw-r--r--src/test/ui/macros/issue-58490.stderr14
-rw-r--r--src/test/ui/macros/macro-comma-behavior.core.stderr14
-rw-r--r--src/test/ui/macros/macro-comma-behavior.rs1
-rw-r--r--src/test/ui/macros/macro-comma-behavior.std.stderr20
-rw-r--r--src/test/ui/macros/trace-macro.stderr2
-rw-r--r--src/test/ui/match/match-fn-call.stderr4
-rw-r--r--src/test/ui/methods/method-path-in-pattern.rs12
-rw-r--r--src/test/ui/methods/method-path-in-pattern.stderr12
-rw-r--r--src/test/ui/methods/method-resolvable-path-in-pattern.rs2
-rw-r--r--src/test/ui/methods/method-resolvable-path-in-pattern.stderr2
-rw-r--r--src/test/ui/mir/issue-60390.rs8
-rw-r--r--src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr6
-rw-r--r--src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr6
-rw-r--r--src/test/ui/mod/mod_file_disambig.rs1
-rw-r--r--src/test/ui/mod/mod_file_disambig.stderr15
-rw-r--r--src/test/ui/nll/outlives-suggestion-simple.rs2
-rw-r--r--src/test/ui/nll/outlives-suggestion-simple.stderr8
-rw-r--r--src/test/ui/no-landing-pads.rs23
-rw-r--r--src/test/ui/no_owned_box_lang_item.rs1
-rw-r--r--src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs2
-rw-r--r--src/test/ui/panic-while-printing.rs24
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.rs16
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.stderr68
-rw-r--r--src/test/ui/parser/bad-interpolated-block.rs15
-rw-r--r--src/test/ui/parser/bad-interpolated-block.stderr39
-rw-r--r--src/test/ui/parser/block-no-opening-brace.rs31
-rw-r--r--src/test/ui/parser/block-no-opening-brace.stderr53
-rw-r--r--src/test/ui/parser/bounds-lifetime.rs2
-rw-r--r--src/test/ui/parser/bounds-lifetime.stderr4
-rw-r--r--src/test/ui/parser/circular_modules_main.rs2
-rw-r--r--src/test/ui/parser/circular_modules_main.stderr18
-rw-r--r--src/test/ui/parser/closure-return-syntax.rs2
-rw-r--r--src/test/ui/parser/closure-return-syntax.stderr7
-rw-r--r--src/test/ui/parser/column-offset-1-based.rs2
-rw-r--r--src/test/ui/parser/column-offset-1-based.stderr4
-rw-r--r--src/test/ui/parser/doc-comment-in-if-statement.rs3
-rw-r--r--src/test/ui/parser/doc-comment-in-if-statement.stderr19
-rw-r--r--src/test/ui/parser/fn-body-eq-expr-semi.rs23
-rw-r--r--src/test/ui/parser/fn-body-eq-expr-semi.stderr117
-rw-r--r--src/test/ui/parser/fn-header-semantic-fail.stderr10
-rw-r--r--src/test/ui/parser/issue-1655.rs3
-rw-r--r--src/test/ui/parser/issue-1655.stderr6
-rw-r--r--src/test/ui/parser/issue-5806.stderr4
-rw-r--r--src/test/ui/parser/issue-63116.stderr2
-rw-r--r--src/test/ui/parser/issue-63135.rs2
-rw-r--r--src/test/ui/parser/issue-63135.stderr18
-rw-r--r--src/test/ui/parser/issue-68730.rsbin170 -> 175 bytes
-rw-r--r--src/test/ui/parser/issue-68730.stderrbin956 -> 966 bytes
-rw-r--r--src/test/ui/parser/issue-68890-2.rs6
-rw-r--r--src/test/ui/parser/issue-68890-2.stderr22
-rw-r--r--src/test/ui/parser/issue-68890.rs2
-rw-r--r--src/test/ui/parser/issue-68890.stderr6
-rw-r--r--src/test/ui/parser/labeled-no-colon-expr.rs17
-rw-r--r--src/test/ui/parser/labeled-no-colon-expr.stderr89
-rw-r--r--src/test/ui/parser/macro/trait-object-macro-matcher.rs9
-rw-r--r--src/test/ui/parser/macro/trait-object-macro-matcher.stderr22
-rw-r--r--src/test/ui/parser/mod_file_not_exist.rs3
-rw-r--r--src/test/ui/parser/mod_file_not_exist.stderr17
-rw-r--r--src/test/ui/parser/mod_file_not_exist_windows.rs3
-rw-r--r--src/test/ui/parser/mod_file_not_exist_windows.stderr17
-rw-r--r--src/test/ui/parser/mod_file_with_path_attr.stderr4
-rw-r--r--src/test/ui/parser/regions-out-of-scope-slice.rs2
-rw-r--r--src/test/ui/parser/regions-out-of-scope-slice.stderr9
-rw-r--r--src/test/ui/parser/stripped-nested-outline-mod-pass.rs13
-rw-r--r--src/test/ui/parser/trait-object-lifetime-parens.rs4
-rw-r--r--src/test/ui/parser/trait-object-lifetime-parens.stderr14
-rw-r--r--src/test/ui/parser/trait-object-trait-parens.rs17
-rw-r--r--src/test/ui/parser/trait-object-trait-parens.stderr78
-rw-r--r--src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs2
-rw-r--r--src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr2
-rw-r--r--src/test/ui/privacy/privacy1.rs10
-rw-r--r--src/test/ui/privacy/privacy1.stderr10
-rw-r--r--src/test/ui/privacy/privacy2.stderr7
-rw-r--r--src/test/ui/privacy/private-impl-method.rs2
-rw-r--r--src/test/ui/privacy/private-impl-method.stderr2
-rw-r--r--src/test/ui/privacy/private-method-cross-crate.rs2
-rw-r--r--src/test/ui/privacy/private-method-cross-crate.stderr2
-rw-r--r--src/test/ui/privacy/private-method-inherited.rs2
-rw-r--r--src/test/ui/privacy/private-method-inherited.stderr2
-rw-r--r--src/test/ui/privacy/private-method.rs2
-rw-r--r--src/test/ui/privacy/private-method.stderr2
-rw-r--r--src/test/ui/privacy/restricted/test.stderr8
-rw-r--r--src/test/ui/proc-macro/attribute-spans-preserved.stdout2
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-unstable.rs2
-rw-r--r--src/test/ui/proc-macro/crt-static.rs16
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.stdout4
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-62325.stdout4
-rw-r--r--src/test/ui/proc-macro/dollar-crate.stdout12
-rw-r--r--src/test/ui/qualified/qualified-path-params.rs2
-rw-r--r--src/test/ui/qualified/qualified-path-params.stderr2
-rw-r--r--src/test/ui/range/issue-54505-no-std.rs4
-rw-r--r--src/test/ui/range/issue-54505-no-std.stderr12
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr58
-rw-r--r--src/test/ui/regions/regions-free-region-ordering-caller.rs6
-rw-r--r--src/test/ui/repr/repr-align-assign.stderr1
-rw-r--r--src/test/ui/resolve/raw-ident-in-path.rs5
-rw-r--r--src/test/ui/resolve/raw-ident-in-path.stderr9
-rw-r--r--src/test/ui/rfc-2091-track-caller/only-for-fns.stderr1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr8
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr6
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr6
-rw-r--r--src/test/ui/self/elision/lt-ref-self-async.nll.stderr12
-rw-r--r--src/test/ui/self/elision/lt-ref-self.nll.stderr12
-rw-r--r--src/test/ui/self/elision/ref-mut-self-async.nll.stderr12
-rw-r--r--src/test/ui/self/elision/ref-mut-self.nll.stderr12
-rw-r--r--src/test/ui/self/elision/ref-mut-struct-async.nll.stderr10
-rw-r--r--src/test/ui/self/elision/ref-mut-struct.nll.stderr10
-rw-r--r--src/test/ui/self/elision/ref-self.nll.stderr14
-rw-r--r--src/test/ui/self/elision/ref-struct-async.nll.stderr10
-rw-r--r--src/test/ui/self/elision/ref-struct.nll.stderr10
-rw-r--r--src/test/ui/shadowed/shadowed-use-visibility.stderr14
-rw-r--r--src/test/ui/span/auxiliary/transitive_dep_three.rs9
-rw-r--r--src/test/ui/span/auxiliary/transitive_dep_two.rs3
-rw-r--r--src/test/ui/span/transitive-dep-span.rs13
-rw-r--r--src/test/ui/span/transitive-dep-span.stderr19
-rw-r--r--src/test/ui/span/type-annotations-needed-expr.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/validation.stderr4
-rw-r--r--src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs6
-rw-r--r--src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs32
-rw-r--r--src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr20
-rw-r--r--src/test/ui/specialization/min_specialization/impl_specialization_trait.rs16
-rw-r--r--src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr10
-rw-r--r--src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs30
-rw-r--r--src/test/ui/specialization/min_specialization/repeated_projection_type.rs24
-rw-r--r--src/test/ui/specialization/min_specialization/repeated_projection_type.stderr11
-rw-r--r--src/test/ui/specialization/min_specialization/repeating_lifetimes.rs19
-rw-r--r--src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr11
-rw-r--r--src/test/ui/specialization/min_specialization/repeating_param.rs17
-rw-r--r--src/test/ui/specialization/min_specialization/repeating_param.stderr11
-rw-r--r--src/test/ui/specialization/min_specialization/spec-iter.rs20
-rw-r--r--src/test/ui/specialization/min_specialization/spec-reference.rs19
-rw-r--r--src/test/ui/specialization/min_specialization/specialization_marker.rs17
-rw-r--r--src/test/ui/specialization/min_specialization/specialization_marker.stderr15
-rw-r--r--src/test/ui/specialization/min_specialization/specialization_super_trait.rs18
-rw-r--r--src/test/ui/specialization/min_specialization/specialization_super_trait.stderr11
-rw-r--r--src/test/ui/specialization/min_specialization/specialization_trait.rs26
-rw-r--r--src/test/ui/specialization/min_specialization/specialization_trait.stderr29
-rw-r--r--src/test/ui/specialization/min_specialization/specialize_on_marker.rs24
-rw-r--r--src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs27
-rw-r--r--src/test/ui/specialization/min_specialization/specialize_on_static.rs18
-rw-r--r--src/test/ui/specialization/min_specialization/specialize_on_static.stderr11
-rw-r--r--src/test/ui/specialization/min_specialization/specialize_on_trait.rs20
-rw-r--r--src/test/ui/specialization/min_specialization/specialize_on_trait.stderr11
-rw-r--r--src/test/ui/static/static-method-privacy.rs2
-rw-r--r--src/test/ui/static/static-method-privacy.stderr2
-rw-r--r--src/test/ui/suggestions/const-no-type.rs2
-rw-r--r--src/test/ui/suggestions/const-no-type.stderr2
-rw-r--r--src/test/ui/suggestions/suggest-methods.stderr6
-rw-r--r--src/test/ui/syntax-trait-polarity-feature-gate.stderr4
-rw-r--r--src/test/ui/syntax-trait-polarity.stderr26
-rw-r--r--src/test/ui/test-panic-while-printing.rs24
-rw-r--r--src/test/ui/traits/trait-item-privacy.rs4
-rw-r--r--src/test/ui/traits/trait-item-privacy.stderr4
-rw-r--r--src/test/ui/traits/trait-method-private.stderr2
-rw-r--r--src/test/ui/traits/trait-safety-inherent-impl.stderr12
-rw-r--r--src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr6
-rw-r--r--src/test/ui/transmute/main.stderr3
-rw-r--r--src/test/ui/type-inference/or_else-multiple-type-params.stderr2
-rw-r--r--src/test/ui/type-inference/sort_by_key.stderr2
-rw-r--r--src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr6
-rw-r--r--src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr6
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item.stderr4
-rw-r--r--src/test/ui/ufcs/ufcs-partially-resolved.rs4
-rw-r--r--src/test/ui/ufcs/ufcs-partially-resolved.stderr12
-rw-r--r--src/test/ui/unsafe/unsafe-block-without-braces.stderr7
-rw-r--r--src/test/ui/xc-private-method.rs4
-rw-r--r--src/test/ui/xc-private-method.stderr4
-rw-r--r--src/test/ui/xc-private-method2.rs4
-rw-r--r--src/test/ui/xc-private-method2.stderr4
m---------src/tools/cargo0
m---------src/tools/clippy18
-rw-r--r--src/tools/compiletest/src/runtest.rs6
m---------src/tools/miri16
-rwxr-xr-xsrc/tools/publish_toolstate.py9
-rw-r--r--src/tools/rustdoc-js-std/tester.js26
-rw-r--r--src/tools/rustdoc-js/tester.js14
-rw-r--r--src/tools/tidy/Cargo.toml3
-rw-r--r--src/tools/tidy/src/deps.rs688
-rw-r--r--src/tools/tidy/src/main.rs9
-rw-r--r--src/tools/tidy/src/pal.rs2
-rw-r--r--triagebot.toml6
988 files changed, 18194 insertions, 13249 deletions
diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md
index f93591204cd..9457cce11af 100644
--- a/.github/ISSUE_TEMPLATE/tracking_issue.md
+++ b/.github/ISSUE_TEMPLATE/tracking_issue.md
@@ -36,11 +36,11 @@ for larger features an implementation could be broken up into multiple PRs.
 
 - [ ] Implement the RFC (cc @rust-lang/XXX -- can anyone write up mentoring
       instructions?)
-- [ ] Adjust documentation ([see instructions on rustc-guide][doc-guide])
-- [ ] Stabilization PR ([see instructions on rustc-guide][stabilization-guide])
+- [ ] Adjust documentation ([see instructions on rustc-dev-guide][doc-guide])
+- [ ] Stabilization PR ([see instructions on rustc-dev-guide][stabilization-guide])
 
-[stabilization-guide]: https://rust-lang.github.io/rustc-guide/stabilization_guide.html#stabilization-pr
-[doc-guide]: https://rust-lang.github.io/rustc-guide/stabilization_guide.html#documentation-prs
+[stabilization-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr
+[doc-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#documentation-prs
 
 ### Unresolved Questions
 <!--
diff --git a/.mailmap b/.mailmap
index ea8ef0eebf9..78c3c3019af 100644
--- a/.mailmap
+++ b/.mailmap
@@ -172,6 +172,9 @@ Mateusz Mikuła <matti@marinelayer.io> <mati865@gmail.com>
 Mateusz Mikuła <matti@marinelayer.io> <mati865@users.noreply.github.com>
 Matt Brubeck <mbrubeck@limpet.net> <mbrubeck@cs.hmc.edu>
 Matthew Auld <matthew.auld@intel.com>
+Matthew Kraai <kraai@ftbfs.org>
+Matthew Kraai <kraai@ftbfs.org> <matt.kraai@abbott.com>
+Matthew Kraai <kraai@ftbfs.org> <mkraai@its.jnj.com>
 Matthew McPherrin <matthew@mcpherrin.ca> <matt@mcpherrin.ca>
 Matthijs Hofstra <thiezz@gmail.com>
 Melody Horn <melody@boringcactus.com> <mathphreak@gmail.com>
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d6840b20c89..2843944b2e1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -19,7 +19,7 @@ hop on the [Rust Discord server][rust-discord] or [Rust Zulip server][rust-zulip
 
 As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
 
-The [rustc-guide] is your friend! It describes how the compiler works and how
+The [rustc-dev-guide] is your friend! It describes how the compiler works and how
 to contribute to it in more detail than this document.
 
 If this is your first time contributing, the [walkthrough] chapter of the guide
@@ -29,8 +29,8 @@ can give you a good example of how a typical contribution would go.
 [rust-discord]: http://discord.gg/rust-lang
 [rust-zulip]: https://rust-lang.zulipchat.com
 [coc]: https://www.rust-lang.org/conduct.html
-[rustc-guide]: https://rust-lang.github.io/rustc-guide/
-[walkthrough]: https://rust-lang.github.io/rustc-guide/walkthrough.html
+[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/
+[walkthrough]: https://rustc-dev-guide.rust-lang.org/walkthrough.html
 
 ## Feature Requests
 [feature-requests]: #feature-requests
@@ -103,12 +103,12 @@ $ RUST_BACKTRACE=1 rustc ...
 ## The Build System
 
 For info on how to configure and build the compiler, please see [this
-chapter][rustcguidebuild] of the rustc-guide. This chapter contains info for
+chapter][rustcguidebuild] of the rustc-dev-guide. This chapter contains info for
 contributions to the compiler and the standard library. It also lists some
 really useful commands to the build system (`./x.py`), which could save you a
 lot of time.
 
-[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/building/how-to-build-and-run.html
+[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
 
 ## Pull Requests
 [pull-requests]: #pull-requests
@@ -142,7 +142,7 @@ the issue in question.
 Please make sure your pull request is in compliance with Rust's style
 guidelines by running
 
-    $ python x.py test src/tools/tidy
+    $ python x.py test tidy
 
 Make this check before every pull request (and every new commit in a pull
 request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
@@ -336,9 +336,9 @@ to check small fixes. For example, `rustdoc src/doc/reference.md` will render
 reference to `doc/reference.html`. The CSS might be messed up, but you can
 verify that the HTML is right.
 
-Additionally, contributions to the [rustc-guide] are always welcome. Contributions
+Additionally, contributions to the [rustc-dev-guide] are always welcome. Contributions
 can be made directly at [the
-rust-lang/rustc-guide](https://github.com/rust-lang/rustc-guide) repo. The issue
+rust-lang/rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide) repo. The issue
 tracker in that repo is also a great way to find things that need doing. There
 are issues for beginners and advanced compiler devs alike!
 
@@ -434,7 +434,7 @@ For people new to Rust, and just starting to contribute, or even for
 more seasoned developers, some useful places to look for information
 are:
 
-* The [rustc guide] contains information about how various parts of the compiler work and how to contribute to the compiler
+* The [rustc dev guide] contains information about how various parts of the compiler work and how to contribute to the compiler
 * [Rust Forge][rustforge] contains additional documentation, including write-ups of how to achieve common tasks
 * The [Rust Internals forum][rif], a place to ask questions and
   discuss Rust's internals
@@ -448,7 +448,7 @@ are:
 * **Google!** ([search only in Rust Documentation][gsearchdocs] to find types, traits, etc. quickly)
 * Don't be afraid to ask! The Rust community is friendly and helpful.
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/about-this-guide.html
 [gdfrustc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/
 [gsearchdocs]: https://www.google.com/search?q=site:doc.rust-lang.org+your+query+here
 [rif]: http://internals.rust-lang.org
@@ -456,5 +456,5 @@ are:
 [rustforge]: https://forge.rust-lang.org/
 [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/
 [ro]: http://www.rustaceans.org/
-[rctd]: https://rust-lang.github.io/rustc-guide/tests/intro.html
+[rctd]: https://rustc-dev-guide.rust-lang.org/tests/intro.html
 [cheatsheet]: https://buildbot2.rust-lang.org/homu/
diff --git a/Cargo.lock b/Cargo.lock
index aefd40bfaa5..1b0516f7161 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -281,7 +281,7 @@ dependencies = [
 
 [[package]]
 name = "cargo"
-version = "0.44.0"
+version = "0.45.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -292,7 +292,6 @@ dependencies = [
  "clap",
  "core-foundation 0.7.0",
  "crates-io",
- "crossbeam-channel",
  "crossbeam-utils 0.7.0",
  "crypto-hash",
  "curl",
@@ -338,6 +337,7 @@ dependencies = [
  "termcolor",
  "toml",
  "unicode-width",
+ "unicode-xid 0.2.0",
  "url 2.1.0",
  "walkdir",
  "winapi 0.3.8",
@@ -386,9 +386,9 @@ dependencies = [
 
 [[package]]
 name = "cargo_metadata"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d"
+checksum = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202"
 dependencies = [
  "semver",
  "serde",
@@ -450,12 +450,11 @@ dependencies = [
 name = "clippy"
 version = "0.0.212"
 dependencies = [
- "cargo_metadata 0.9.0",
+ "cargo_metadata 0.9.1",
  "clippy-mini-macro-test",
  "clippy_lints",
  "compiletest_rs",
  "derive-new",
- "git2",
  "lazy_static 1.4.0",
  "regex",
  "rustc-workspace-hack",
@@ -474,9 +473,9 @@ version = "0.2.0"
 name = "clippy_lints"
 version = "0.0.212"
 dependencies = [
- "cargo_metadata 0.9.0",
+ "cargo_metadata 0.9.1",
  "if_chain",
- "itertools 0.8.0",
+ "itertools 0.9.0",
  "lazy_static 1.4.0",
  "matches",
  "pulldown-cmark 0.7.0",
@@ -1235,9 +1234,9 @@ dependencies = [
 
 [[package]]
 name = "git2"
-version = "0.12.0"
+version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26e07ef27260a78f7e8d218ebac2c72f2c4db50493741b190b6e8eade1da7c68"
+checksum = "b7da16ceafe24cedd9ba02c4463a2b506b6493baf4317c79c5acb553134a3c15"
 dependencies = [
  "bitflags",
  "libc",
@@ -1250,9 +1249,9 @@ dependencies = [
 
 [[package]]
 name = "git2-curl"
-version = "0.13.0"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af1754ec4170e7dcaf9bb43743bb16eddb8d827b2e0291deb6f220a6e16fe46a"
+checksum = "502d532a2d06184beb3bc869d4d90236e60934e3382c921b203fa3c33e212bd7"
 dependencies = [
  "curl",
  "git2",
@@ -1605,6 +1604,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "itertools"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
+dependencies = [
+ "either",
+]
+
+[[package]]
 name = "itoa"
 version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1770,9 +1778,9 @@ dependencies = [
 
 [[package]]
 name = "libgit2-sys"
-version = "0.11.0+0.99.0"
+version = "0.12.0+0.99.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d5d1459353d397a029fb18862166338de938e6be976606bd056cf8f1a912ecf"
+checksum = "05dff41ac39e7b653f5f1550886cf00ba52f8e7f57210b633cdeedb3de5b236c"
 dependencies = [
  "cc",
  "libc",
@@ -2124,7 +2132,7 @@ name = "miri"
 version = "0.1.0"
 dependencies = [
  "byteorder",
- "cargo_metadata 0.9.0",
+ "cargo_metadata 0.9.1",
  "colored",
  "compiletest_rs",
  "directories",
@@ -3616,6 +3624,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_hir",
  "rustc_metadata",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
 ]
@@ -3669,6 +3678,7 @@ dependencies = [
  "rustc_parse",
  "rustc_plugin_impl",
  "rustc_save_analysis",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "serialize",
@@ -3774,14 +3784,11 @@ dependencies = [
 name = "rustc_infer"
 version = "0.0.0"
 dependencies = [
- "fmt_macros",
  "graphviz",
  "log",
  "rustc",
  "rustc_ast",
- "rustc_attr",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
@@ -3826,6 +3833,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "rustc_traits",
  "rustc_ty",
  "rustc_typeck",
@@ -3860,6 +3868,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "unicode-security",
 ]
 
@@ -3897,6 +3906,7 @@ dependencies = [
  "rustc_expand",
  "rustc_hir",
  "rustc_index",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
  "serialize",
@@ -3927,8 +3937,10 @@ dependencies = [
  "rustc_infer",
  "rustc_lexer",
  "rustc_macros",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "serialize",
  "smallvec 1.0.0",
 ]
@@ -3952,6 +3964,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "serialize",
  "smallvec 1.0.0",
 ]
@@ -3992,6 +4005,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
 ]
 
 [[package]]
@@ -4004,6 +4018,7 @@ dependencies = [
  "rustc_hir",
  "rustc_lint",
  "rustc_metadata",
+ "rustc_session",
  "rustc_span",
 ]
 
@@ -4018,6 +4033,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
+ "rustc_session",
  "rustc_span",
  "rustc_typeck",
 ]
@@ -4039,7 +4055,6 @@ dependencies = [
  "rustc_expand",
  "rustc_feature",
  "rustc_hir",
- "rustc_infer",
  "rustc_metadata",
  "rustc_session",
  "rustc_span",
@@ -4060,6 +4075,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_hir",
  "rustc_parse",
+ "rustc_session",
  "rustc_span",
  "serde_json",
 ]
@@ -4120,6 +4136,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee"
 
 [[package]]
+name = "rustc_trait_selection"
+version = "0.0.0"
+dependencies = [
+ "fmt_macros",
+ "log",
+ "rustc",
+ "rustc_ast",
+ "rustc_attr",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_hir",
+ "rustc_index",
+ "rustc_infer",
+ "rustc_macros",
+ "rustc_session",
+ "rustc_span",
+ "rustc_target",
+ "smallvec 1.0.0",
+]
+
+[[package]]
 name = "rustc_traits"
 version = "0.0.0"
 dependencies = [
@@ -4132,6 +4169,7 @@ dependencies = [
  "rustc_macros",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "smallvec 1.0.0",
 ]
 
@@ -4144,8 +4182,10 @@ dependencies = [
  "rustc_data_structures",
  "rustc_hir",
  "rustc_infer",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
 ]
 
 [[package]]
@@ -4162,8 +4202,10 @@ dependencies = [
  "rustc_hir",
  "rustc_index",
  "rustc_infer",
+ "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "smallvec 1.0.0",
 ]
 
@@ -4818,10 +4860,9 @@ dependencies = [
 name = "tidy"
 version = "0.1.0"
 dependencies = [
+ "cargo_metadata 0.9.1",
  "lazy_static 1.4.0",
  "regex",
- "serde",
- "serde_json",
  "walkdir",
 ]
 
diff --git a/README.md b/README.md
index 61d3c9e1157..1cd9b8a3a2a 100644
--- a/README.md
+++ b/README.md
@@ -15,13 +15,13 @@ Read ["Installation"] from [The Book].
 ## Installing from Source
 
 _Note: If you wish to contribute to the compiler, you should read [this
-chapter][rustcguidebuild] of the rustc-guide instead of this section._
+chapter][rustcguidebuild] of the rustc-dev-guide instead of this section._
 
 The Rust build system has a Python script called `x.py` to bootstrap building
 the compiler. More information about it may be found by running `./x.py --help`
-or reading the [rustc guide][rustcguidebuild].
+or reading the [rustc dev guide][rustcguidebuild].
 
-[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/building/how-to-build-and-run.html
+[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
 
 ### Building on *nix
 1. Make sure you have installed the dependencies:
@@ -249,13 +249,13 @@ Most real-time collaboration happens in a variety of channels on the
 community, documentation, and all major contribution areas in the Rust ecosystem.
 A good place to ask for help would be the #help channel.
 
-The [rustc guide] might be a good place to start if you want to find out how
+The [rustc dev guide] might be a good place to start if you want to find out how
 various parts of the compiler work.
 
 Also, you may find the [rustdocs for the compiler itself][rustdocs] useful.
 
 [rust-discord]: https://discord.gg/rust-lang
-[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/about-this-guide.html
 [rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/
 
 ## License
diff --git a/src/README.md b/src/README.md
index 2f7cf90c5f0..b69a92a7237 100644
--- a/src/README.md
+++ b/src/README.md
@@ -3,6 +3,6 @@ This directory contains the source code of the rust project, including:
 - `libstd`
 - Various submodules for tools, like rustdoc, rls, etc.
 
-For more information on how various parts of the compiler work, see the [rustc guide].
+For more information on how various parts of the compiler work, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/about-this-guide.html
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index c501378bff5..87da7327fe6 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -55,6 +55,9 @@ The script accepts commands, flags, and arguments to determine what to do:
   # run all unit tests
   ./x.py test
 
+  # execute tool tests
+  ./x.py test tidy
+
   # execute the UI test suite
   ./x.py test src/test/ui
 
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index e4b57cddfb8..602e4511ea5 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -725,7 +725,7 @@ impl<'a> Builder<'a> {
             self.clear_if_dirty(&my_out, &rustdoc);
         }
 
-        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd).arg("-Zconfig-profile");
+        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd);
 
         let profile_var = |name: &str| {
             let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
@@ -847,13 +847,7 @@ impl<'a> Builder<'a> {
             rustflags.arg("-Zforce-unstable-if-unmarked");
         }
 
-        // cfg(bootstrap): the flag was renamed from `-Zexternal-macro-backtrace`
-        // to `-Zmacro-backtrace`, keep only the latter after beta promotion.
-        if stage == 0 {
-            rustflags.arg("-Zexternal-macro-backtrace");
-        } else {
-            rustflags.arg("-Zmacro-backtrace");
-        }
+        rustflags.arg("-Zmacro-backtrace");
 
         let want_rustdoc = self.doc_tests != DocTests::No;
 
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 504cba45570..be2b0f36d14 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -13,7 +13,7 @@ use build_helper::output;
 use crate::Build;
 
 // The version number
-pub const CFG_RELEASE_NUM: &str = "1.43.0";
+pub const CFG_RELEASE_NUM: &str = "1.44.0";
 
 pub struct GitInfo {
     inner: Option<Info>,
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 0b2ab6bbbc0..d8831c6d9e5 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -359,7 +359,7 @@ Arguments:
                 subcommand_help.push_str(
                     "\n
 Arguments:
-    This subcommand accepts a number of paths to directories to tests that
+    This subcommand accepts a number of paths to test directories that
     should be compiled and run. For example:
 
         ./x.py test src/test/ui
@@ -372,6 +372,10 @@ Arguments:
     just like `build src/libstd --stage N` it tests the compiler produced by the previous
     stage.
 
+    Execute tool tests with a tool name argument:
+
+        ./x.py test tidy
+
     If no arguments are passed then the complete artifacts for that stage are
     compiled and tested.
 
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index a4acb14ee4b..1616ae15d31 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -37,6 +37,9 @@ struct RustfmtConfig {
 }
 
 pub fn format(build: &Build, check: bool) {
+    if build.config.dry_run {
+        return;
+    }
     let mut builder = ignore::types::TypesBuilder::new();
     builder.add_defaults();
     builder.select("rust");
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index c22c2a336f1..d4d66abd520 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -11,6 +11,7 @@
 use std::env;
 use std::ffi::OsString;
 use std::fs::{self, File};
+use std::io;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
@@ -54,7 +55,6 @@ impl Step for Llvm {
             }
         }
 
-        let llvm_info = &builder.in_tree_llvm_info;
         let root = "src/llvm-project/llvm";
         let out_dir = builder.llvm_out(target);
         let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build);
@@ -65,40 +65,35 @@ impl Step for Llvm {
 
         let build_llvm_config =
             llvm_config_ret_dir.join(exe("llvm-config", &*builder.config.build));
-        let done_stamp = out_dir.join("llvm-finished-building");
 
-        if done_stamp.exists() {
-            if builder.config.llvm_skip_rebuild {
-                builder.info(
-                    "Warning: \
-                    Using a potentially stale build of LLVM; \
-                    This may not behave well.",
-                );
-                return build_llvm_config;
-            }
+        let stamp = out_dir.join("llvm-finished-building");
+        let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
 
-            if let Some(llvm_commit) = llvm_info.sha() {
-                let done_contents = t!(fs::read(&done_stamp));
+        if builder.config.llvm_skip_rebuild && stamp.path.exists() {
+            builder.info(
+                "Warning: \
+                Using a potentially stale build of LLVM; \
+                This may not behave well.",
+            );
+            return build_llvm_config;
+        }
 
-                // If LLVM was already built previously and the submodule's commit didn't change
-                // from the previous build, then no action is required.
-                if done_contents == llvm_commit.as_bytes() {
-                    return build_llvm_config;
-                }
-            } else {
+        if stamp.is_done() {
+            if stamp.hash.is_none() {
                 builder.info(
                     "Could not determine the LLVM submodule commit hash. \
                      Assuming that an LLVM rebuild is not necessary.",
                 );
                 builder.info(&format!(
                     "To force LLVM to rebuild, remove the file `{}`",
-                    done_stamp.display()
+                    stamp.path.display()
                 ));
-                return build_llvm_config;
             }
+            return build_llvm_config;
         }
 
         builder.info(&format!("Building LLVM for {}", target));
+        t!(stamp.remove());
         let _time = util::timeit(&builder);
         t!(fs::create_dir_all(&out_dir));
 
@@ -271,7 +266,7 @@ impl Step for Llvm {
 
         cfg.build();
 
-        t!(fs::write(&done_stamp, llvm_info.sha().unwrap_or("")));
+        t!(stamp.write());
 
         build_llvm_config
     }
@@ -584,17 +579,21 @@ impl Step for Sanitizers {
             return runtimes;
         }
 
-        let done_stamp = out_dir.join("sanitizers-finished-building");
-        if done_stamp.exists() {
-            builder.info(&format!(
-                "Assuming that sanitizers rebuild is not necessary. \
-                To force a rebuild, remove the file `{}`",
-                done_stamp.display()
-            ));
+        let stamp = out_dir.join("sanitizers-finished-building");
+        let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
+
+        if stamp.is_done() {
+            if stamp.hash.is_none() {
+                builder.info(&format!(
+                    "Rebuild sanitizers by removing the file `{}`",
+                    stamp.path.display()
+                ));
+            }
             return runtimes;
         }
 
         builder.info(&format!("Building sanitizers for {}", self.target));
+        t!(stamp.remove());
         let _time = util::timeit(&builder);
 
         let mut cfg = cmake::Config::new(&compiler_rt_dir);
@@ -623,8 +622,7 @@ impl Step for Sanitizers {
             cfg.build_target(&runtime.cmake_target);
             cfg.build();
         }
-
-        t!(fs::write(&done_stamp, b""));
+        t!(stamp.write());
 
         runtimes
     }
@@ -689,3 +687,41 @@ fn supported_sanitizers(
     }
     result
 }
+
+struct HashStamp {
+    path: PathBuf,
+    hash: Option<Vec<u8>>,
+}
+
+impl HashStamp {
+    fn new(path: PathBuf, hash: Option<&str>) -> Self {
+        HashStamp { path, hash: hash.map(|s| s.as_bytes().to_owned()) }
+    }
+
+    fn is_done(&self) -> bool {
+        match fs::read(&self.path) {
+            Ok(h) => self.hash.as_deref().unwrap_or(b"") == h.as_slice(),
+            Err(e) if e.kind() == io::ErrorKind::NotFound => false,
+            Err(e) => {
+                panic!("failed to read stamp file `{}`: {}", self.path.display(), e);
+            }
+        }
+    }
+
+    fn remove(&self) -> io::Result<()> {
+        match fs::remove_file(&self.path) {
+            Ok(()) => Ok(()),
+            Err(e) => {
+                if e.kind() == io::ErrorKind::NotFound {
+                    Ok(())
+                } else {
+                    Err(e)
+                }
+            }
+        }
+    }
+
+    fn write(&self) -> io::Result<()> {
+        fs::write(&self.path, self.hash.as_deref().unwrap_or(b""))
+    }
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 1b9e9a88948..aa1d1b7c424 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -607,7 +607,6 @@ impl Step for RustdocTheme {
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct RustdocJSStd {
-    pub host: Interned<String>,
     pub target: Interned<String>,
 }
 
@@ -621,13 +620,16 @@ impl Step for RustdocJSStd {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(RustdocJSStd { host: run.host, target: run.target });
+        run.builder.ensure(RustdocJSStd { target: run.target });
     }
 
     fn run(self, builder: &Builder<'_>) {
         if let Some(ref nodejs) = builder.config.nodejs {
             let mut command = Command::new(nodejs);
-            command.args(&["src/tools/rustdoc-js-std/tester.js", &*self.host]);
+            command
+                .arg(builder.src.join("src/tools/rustdoc-js-std/tester.js"))
+                .arg(builder.doc_out(self.target))
+                .arg(builder.src.join("src/test/rustdoc-js-std"));
             builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage });
             builder.run(&mut command);
         } else {
@@ -726,9 +728,6 @@ impl Step for Tidy {
         let mut cmd = builder.tool_cmd(Tool::Tidy);
         cmd.arg(builder.src.join("src"));
         cmd.arg(&builder.initial_cargo);
-        if !builder.config.vendor {
-            cmd.arg("--no-vendor");
-        }
         if builder.is_verbose() {
             cmd.arg("--verbose");
         }
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index 7cffc472930..f0e0f92af55 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -215,6 +215,9 @@ impl Step for ToolStateCheck {
                             tool, old_state, state
                         );
                     } else {
+                        // This warning only appears in the logs, which most
+                        // people won't read. It's mostly here for testing and
+                        // debugging.
                         eprintln!(
                             "warning: Tool `{}` is not test-pass (is `{}`), \
                             this should be fixed before beta is branched.",
@@ -222,6 +225,11 @@ impl Step for ToolStateCheck {
                         );
                     }
                 }
+                // `publish_toolstate.py` is responsible for updating
+                // `latest.json` and creating comments/issues warning people
+                // if there is a regression. That all happens in a separate CI
+                // job on the master branch once the PR has passed all tests
+                // on the `auto` branch.
             }
         }
 
@@ -230,7 +238,7 @@ impl Step for ToolStateCheck {
         }
 
         if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() {
-            commit_toolstate_change(&toolstates, in_beta_week);
+            commit_toolstate_change(&toolstates);
         }
     }
 
@@ -325,11 +333,11 @@ fn prepare_toolstate_config(token: &str) {
             Err(_) => false,
         };
         if !success {
-            panic!("git config key={} value={} successful (status: {:?})", key, value, status);
+            panic!("git config key={} value={} failed (status: {:?})", key, value, status);
         }
     }
 
-    // If changing anything here, then please check that src/ci/publish_toolstate.sh is up to date
+    // If changing anything here, then please check that `src/ci/publish_toolstate.sh` is up to date
     // as well.
     git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com");
     git_config("user.name", "Rust Toolstate Update");
@@ -373,14 +381,14 @@ fn read_old_toolstate() -> Vec<RepoState> {
 ///
 ///       * See <https://help.github.com/articles/about-commit-email-addresses/>
 ///           if a private email by GitHub is wanted.
-fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool) {
-    let old_toolstate = read_old_toolstate();
-
+fn commit_toolstate_change(current_toolstate: &ToolstateData) {
     let message = format!("({} CI update)", OS.expect("linux/windows only"));
     let mut success = false;
     for _ in 1..=5 {
-        // Update the toolstate results (the new commit-to-toolstate mapping) in the toolstate repo.
-        change_toolstate(&current_toolstate, &old_toolstate, in_beta_week);
+        // Upload the test results (the new commit-to-toolstate mapping) to the toolstate repo.
+        // This does *not* change the "current toolstate"; that only happens post-landing
+        // via `src/ci/docker/publish_toolstate.sh`.
+        publish_test_results(&current_toolstate);
 
         // `git commit` failing means nothing to commit.
         let status = t!(Command::new("git")
@@ -429,31 +437,12 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool
     }
 }
 
-fn change_toolstate(
-    current_toolstate: &ToolstateData,
-    old_toolstate: &[RepoState],
-    in_beta_week: bool,
-) {
-    let mut regressed = false;
-    for repo_state in old_toolstate {
-        let tool = &repo_state.tool;
-        let state = repo_state.state();
-        let new_state = current_toolstate[tool.as_str()];
-
-        if new_state != state {
-            eprintln!("The state of `{}` has changed from `{}` to `{}`", tool, state, new_state);
-            if new_state < state {
-                if !NIGHTLY_TOOLS.iter().any(|(name, _path)| name == tool) {
-                    regressed = true;
-                }
-            }
-        }
-    }
-
-    if regressed && in_beta_week {
-        std::process::exit(1);
-    }
-
+/// Updates the "history" files with the latest results.
+///
+/// These results will later be promoted to `latest.json` by the
+/// `publish_toolstate.py` script if the PR passes all tests and is merged to
+/// master.
+fn publish_test_results(current_toolstate: &ToolstateData) {
     let commit = t!(std::process::Command::new("git").arg("rev-parse").arg("HEAD").output());
     let commit = t!(String::from_utf8(commit.stdout));
 
diff --git a/src/ci/docker/mingw-check/Dockerfile b/src/ci/docker/mingw-check/Dockerfile
index b2d96aed2a9..e973ba2e33c 100644
--- a/src/ci/docker/mingw-check/Dockerfile
+++ b/src/ci/docker/mingw-check/Dockerfile
@@ -25,4 +25,5 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
            python2.7 ../x.py build --stage 0 src/tools/build-manifest && \
            python2.7 ../x.py test --stage 0 src/tools/compiletest && \
+           python2.7 ../x.py test src/tools/tidy && \
            /scripts/validate-toolstate.sh
diff --git a/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile
index dc90c286f5c..4b5d5cac516 100644
--- a/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile
@@ -16,7 +16,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config \
   zlib1g-dev \
-  xz-utils
+  xz-utils \
+  nodejs
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
@@ -28,7 +29,7 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-llvm-link-shared \
       --set rust.thin-lto-import-instr-limit=10
 
-ENV SCRIPT python2.7 ../x.py test src/tools/tidy && python2.7 ../x.py test
+ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && python2.7 ../x.py 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/publish_toolstate.sh b/src/ci/publish_toolstate.sh
index 7c43d034d8b..691df04e754 100755
--- a/src/ci/publish_toolstate.sh
+++ b/src/ci/publish_toolstate.sh
@@ -23,7 +23,9 @@ GIT_COMMIT_MSG="$(git log --format=%s -n1 HEAD)"
 cd rust-toolstate
 FAILURE=1
 for RETRY_COUNT in 1 2 3 4 5; do
-    #  The purpose is to publish the new "current" toolstate in the toolstate repo.
+    # The purpose of this is to publish the new "current" toolstate in the toolstate repo.
+    # This happens post-landing, on master.
+    # (Publishing the per-commit test results happens pre-landing in src/bootstrap/toolstate.rs).
     "$(ciCheckoutPath)/src/tools/publish_toolstate.py" "$GIT_COMMIT" \
         "$GIT_COMMIT_MSG" \
         "$MESSAGE_FILE" \
diff --git a/src/ci/scripts/install-msys2-packages.sh b/src/ci/scripts/install-msys2-packages.sh
index 843a2bf2d5e..22b9854ad5e 100755
--- a/src/ci/scripts/install-msys2-packages.sh
+++ b/src/ci/scripts/install-msys2-packages.sh
@@ -13,6 +13,7 @@ if isWindows; then
     # one way or another. The msys interpreters seem to have weird path conversions
     # baked in which break LLVM's build system one way or another, so let's use the
     # native version which keeps everything as native as possible.
-    cp C:/Python27amd64/python.exe C:/Python27amd64/python2.7.exe
-    ciCommandAddPath "C:\\Python27amd64"
+    python_home="C:/hostedtoolcache/windows/Python/2.7.17/x64"
+    cp "${python_home}/python.exe" "${python_home}/python2.7.exe"
+    ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\2.7.17\\x64"
 fi
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject b81ffb7a6f4c5aaed92786e770e99db116aa4eb
+Subproject d22a9c487c78095afc4584f1d9b4ec43529d713
diff --git a/src/doc/index.md b/src/doc/index.md
index 0a2a80e8fd6..2d10230ffcf 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -120,7 +120,7 @@ Rust. It's also sometimes called "the 'nomicon."
 
 ## The `rustc` Contribution Guide
 
-[The `rustc` Guide](https://rust-lang.github.io/rustc-guide/) documents how
+[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/) documents how
 the compiler works and how to contribute to it. This is useful if you want to build
 or modify the Rust compiler from source (e.g. to target something non-standard).
 
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 559e09caa9661043744cf7af7bd88432d966f74
+Subproject e2f11fe4d6a5ecb471c70323197da43c70cb96b
diff --git a/src/doc/robots.txt b/src/doc/robots.txt
index d119cc46473..3a2552e9a15 100644
--- a/src/doc/robots.txt
+++ b/src/doc/robots.txt
@@ -1,21 +1,6 @@
 User-agent: *
-Disallow: /0.3/
-Disallow: /0.4/
-Disallow: /0.5/
-Disallow: /0.6/
-Disallow: /0.7/
-Disallow: /0.8/
-Disallow: /0.9/
-Disallow: /0.10/
-Disallow: /0.11.0/
-Disallow: /0.12.0/
-Disallow: /1.0.0-alpha/
-Disallow: /1.0.0-alpha.2/
-Disallow: /1.0.0-beta/
-Disallow: /1.0.0-beta.2/
-Disallow: /1.0.0-beta.3/
-Disallow: /1.0.0-beta.4/
-Disallow: /1.0.0-beta.5/
+Disallow: /1.
+Disallow: /0.
 Disallow: /book/first-edition/
 Disallow: /book/second-edition/
 Disallow: /stable/book/first-edition/
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject db57f899ea2a56a544c8d280cbf033438666273
+Subproject cb369ae95ca36b841960182d26f6d5d9b2e3cc1
diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md
index 25a5c97b0a1..3b552e7cc0a 100644
--- a/src/doc/rustc/src/contributing.md
+++ b/src/doc/rustc/src/contributing.md
@@ -1,12 +1,12 @@
 # Contributing to rustc
 
 We'd love to have your help improving `rustc`! To that end, we've written [a
-whole book][rustc_guide] on its
+whole book][rustc_dev_guide] on its
 internals, how it works, and how to get started working on it. To learn
 more, you'll want to check that out.
 
 If you would like to contribute to _this_ book, you can find its source in the
 rustc source at [src/doc/rustc][rustc_book].
 
-[rustc_guide]: https://rust-lang.github.io/rustc-guide/
+[rustc_dev_guide]: https://rustc-dev-guide.rust-lang.org/
 [rustc_book]: https://github.com/rust-lang/rust/tree/master/src/doc/rustc
diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md
index 47bef3cdde1..7c12d23e649 100644
--- a/src/doc/rustdoc/src/advanced-features.md
+++ b/src/doc/rustdoc/src/advanced-features.md
@@ -4,7 +4,7 @@ The features listed on this page fall outside the rest of the main categories.
 
 ## `#[cfg(doc)]`: Documenting platform-/feature-specific information
 
-For conditional compilation, Rustdoc treats your crate the same way the compiler does: Only things
+For conditional compilation, Rustdoc treats your crate the same way the compiler does. Only things
 from the host target are available (or from the given `--target` if present), and everything else is
 "filtered out" from the crate. This can cause problems if your crate is providing different things
 on different targets and you want your documentation to reflect all the available items you
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index 2e32ce31eca..ddbe26389fd 100644
--- a/src/doc/rustdoc/src/command-line-arguments.md
+++ b/src/doc/rustdoc/src/command-line-arguments.md
@@ -79,8 +79,8 @@ Rustdoc only supports HTML output, and so this flag is redundant today.
 Using this flag looks like this:
 
 ```bash
-$ rustdoc src/lib.rs -o target\\doc
-$ rustdoc src/lib.rs --output target\\doc
+$ rustdoc src/lib.rs -o target/doc
+$ rustdoc src/lib.rs --output target/doc
 ```
 
 By default, `rustdoc`'s output appears in a directory named `doc` in
diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md
index 96fa4344b04..78181156e25 100644
--- a/src/doc/rustdoc/src/documentation-tests.md
+++ b/src/doc/rustdoc/src/documentation-tests.md
@@ -314,7 +314,7 @@ only shows the part you care about.
 `should_panic` tells `rustdoc` that the code should compile correctly, but
 not actually pass as a test.
 
-```text
+```rust
 /// ```no_run
 /// loop {
 ///     println!("Hello, world");
diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md
index bbcacb7f3d5..adcebc832bc 100644
--- a/src/doc/rustdoc/src/what-is-rustdoc.md
+++ b/src/doc/rustdoc/src/what-is-rustdoc.md
@@ -78,8 +78,8 @@ $ cargo doc
 Internally, this calls out to `rustdoc` like this:
 
 ```bash
-$ rustdoc --crate-name docs srclib.rs -o <path>\docs\target\doc -L
-dependency=<path>docs\target\debug\deps
+$ rustdoc --crate-name docs src/lib.rs -o <path>/docs/target/doc -L
+dependency=<path>/docs/target/debug/deps
 ```
 
 You can see this with `cargo doc --verbose`.
@@ -128,4 +128,4 @@ Cargo currently does not understand standalone Markdown files, unfortunately.
 ## Summary
 
 This covers the simplest use-cases of `rustdoc`. The rest of this book will
-explain all of the options that `rustdoc` has, and how to use them.
\ No newline at end of file
+explain all of the options that `rustdoc` has, and how to use them.
diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
index 6f096e582f5..25082432192 100644
--- a/src/doc/unstable-book/src/language-features/lang-items.md
+++ b/src/doc/unstable-book/src/language-features/lang-items.md
@@ -52,7 +52,6 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
 
 #[lang = "eh_personality"] extern fn rust_eh_personality() {}
 #[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } }
-#[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
 #[no_mangle] pub extern fn rust_eh_register_frames () {}
 #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
 ```
@@ -67,7 +66,7 @@ Other features provided by lang items include:
   marked with lang items; those specific four are `eq`, `ord`,
   `deref`, and `add` respectively.
 - stack unwinding and general failure; the `eh_personality`,
-  `eh_unwind_resume`, `fail` and `fail_bounds_checks` lang items.
+  `panic` and `panic_bounds_checks` lang items.
 - the traits in `std::marker` used to indicate types of
   various kinds; lang items `send`, `sync` and `copy`.
 - the marker types and variance indicators found in
@@ -130,12 +129,6 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
 pub extern fn rust_eh_personality() {
 }
 
-// This function may be needed based on the compilation target.
-#[lang = "eh_unwind_resume"]
-#[no_mangle]
-pub extern fn rust_eh_unwind_resume() {
-}
-
 #[lang = "panic_impl"]
 #[no_mangle]
 pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
@@ -173,12 +166,6 @@ pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
 pub extern fn rust_eh_personality() {
 }
 
-// This function may be needed based on the compilation target.
-#[lang = "eh_unwind_resume"]
-#[no_mangle]
-pub extern fn rust_eh_unwind_resume() {
-}
-
 #[lang = "panic_impl"]
 #[no_mangle]
 pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
@@ -211,10 +198,8 @@ compiler. When a panic happens, this controls the message that's displayed on
 the screen. While the language item's name is `panic_impl`, the symbol name is
 `rust_begin_panic`.
 
-A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume`
-flag is set in the options of the compilation target. It allows customizing the
-process of resuming unwind at the end of the landing pads. The language item's name
-is `eh_unwind_resume`.
+Finally, a `eh_catch_typeinfo` static is needed for certain targets which
+implement Rust panics on top of C++ exceptions.
 
 ## List of all language items
 
@@ -247,8 +232,6 @@ the source code.
   - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
   - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU)
   - `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
-  - `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC)
-  - `eh_catch_typeinfo`: `libpanic_unwind/seh.rs` (SEH)
   - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC)
   - `panic`: `libcore/panicking.rs`
   - `panic_bounds_check`: `libcore/panicking.rs`
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 9a7d0d9aeba..36641284a76 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -1105,29 +1105,6 @@ impl<T: ?Sized> AsMut<T> for Box<T> {
 #[stable(feature = "pin", since = "1.33.0")]
 impl<T: ?Sized> Unpin for Box<T> {}
 
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume(Pin::new(&mut *self))
-    }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume((*self).as_mut())
-    }
-}
-
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> {
     type Yield = G::Yield;
@@ -1138,7 +1115,6 @@ impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> {
     }
 }
 
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<Box<G>> {
     type Yield = G::Yield;
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index 73ae267ddab..53d4f7239b7 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -1427,7 +1427,7 @@ impl<'a, T> CursorMut<'a, T> {
     /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
     /// `CursorMut` is frozen for the lifetime of the `Cursor`.
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
-    pub fn as_cursor<'cm>(&'cm self) -> Cursor<'cm, T> {
+    pub fn as_cursor(&self) -> Cursor<'_, T> {
         Cursor { list: self.list, current: self.current, index: self.index }
     }
 }
diff --git a/src/liballoc/collections/mod.rs b/src/liballoc/collections/mod.rs
index 0bb62373fab..6b21e54f66a 100644
--- a/src/liballoc/collections/mod.rs
+++ b/src/liballoc/collections/mod.rs
@@ -42,6 +42,7 @@ pub use linked_list::LinkedList;
 pub use vec_deque::VecDeque;
 
 use crate::alloc::{Layout, LayoutErr};
+use core::fmt::Display;
 
 /// The error type for `try_reserve` methods.
 #[derive(Clone, PartialEq, Eq, Debug)]
@@ -77,6 +78,23 @@ impl From<LayoutErr> for TryReserveError {
     }
 }
 
+#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
+impl Display for TryReserveError {
+    fn fmt(
+        &self,
+        fmt: &mut core::fmt::Formatter<'_>,
+    ) -> core::result::Result<(), core::fmt::Error> {
+        fmt.write_str("memory allocation failed")?;
+        let reason = match &self {
+            TryReserveError::CapacityOverflow => {
+                " because the computed capacity exceeded the collection's maximum"
+            }
+            TryReserveError::AllocError { .. } => " because the memory allocator returned a error",
+        };
+        fmt.write_str(reason)
+    }
+}
+
 /// An intermediate trait for specialization of `Extend`.
 #[doc(hidden)]
 trait SpecExtend<I: IntoIterator> {
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index c95f79472fe..0e48f1548e6 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -2225,6 +2225,17 @@ impl From<&str> for String {
     }
 }
 
+#[stable(feature = "from_mut_str_for_string", since = "1.44.0")]
+impl From<&mut str> for String {
+    /// Converts a `&mut str` into a `String`.
+    ///
+    /// The result is allocated on the heap.
+    #[inline]
+    fn from(s: &mut str) -> String {
+        s.to_owned()
+    }
+}
+
 #[stable(feature = "from_ref_string", since = "1.35.0")]
 impl From<&String> for String {
     #[inline]
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index f661b830428..d1956270f13 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -2626,13 +2626,21 @@ impl<T: Clone> Clone for IntoIter<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<#[may_dangle] T> Drop for IntoIter<T> {
     fn drop(&mut self) {
+        struct DropGuard<'a, T>(&'a mut IntoIter<T>);
+
+        impl<T> Drop for DropGuard<'_, T> {
+            fn drop(&mut self) {
+                // RawVec handles deallocation
+                let _ = unsafe { RawVec::from_raw_parts(self.0.buf.as_ptr(), self.0.cap) };
+            }
+        }
+
+        let guard = DropGuard(self);
         // destroy the remaining elements
         unsafe {
-            ptr::drop_in_place(self.as_mut_slice());
+            ptr::drop_in_place(guard.0.as_mut_slice());
         }
-
-        // RawVec handles deallocation
-        let _ = unsafe { RawVec::from_raw_parts(self.buf.as_ptr(), self.cap) };
+        // now `guard` will be dropped and do the rest
     }
 }
 
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 9ebb3176418..a922d4f118b 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -958,6 +958,33 @@ impl<T: ?Sized> RefCell<T> {
         unsafe { &mut *self.value.get() }
     }
 
+    /// Undo the effect of leaked guards on the borrow state of the `RefCell`.
+    ///
+    /// This call is similar to [`get_mut`] but more specialized. It borrows `RefCell` mutably to
+    /// ensure no borrows exist and then resets the state tracking shared borrows. This is relevant
+    /// if some `Ref` or `RefMut` borrows have been leaked.
+    ///
+    /// [`get_mut`]: #method.get_mut
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_leak)]
+    /// use std::cell::RefCell;
+    ///
+    /// let mut c = RefCell::new(0);
+    /// std::mem::forget(c.borrow_mut());
+    ///
+    /// assert!(c.try_borrow().is_err());
+    /// c.undo_leak();
+    /// assert!(c.try_borrow().is_ok());
+    /// ```
+    #[unstable(feature = "cell_leak", issue = "69099")]
+    pub fn undo_leak(&mut self) -> &mut T {
+        *self.borrow.get_mut() = UNUSED;
+        self.get_mut()
+    }
+
     /// Immutably borrows the wrapped value, returning an error if the value is
     /// currently mutably borrowed.
     ///
@@ -1272,8 +1299,10 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// ```
     #[unstable(feature = "cell_leak", issue = "69099")]
     pub fn leak(orig: Ref<'b, T>) -> &'b T {
-        // By forgetting this Ref we ensure that the borrow counter in the RefCell never goes back
-        // to UNUSED again. No further mutable references can be created from the original cell.
+        // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to
+        // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a
+        // unique reference to the borrowed RefCell. No further mutable references can be created
+        // from the original cell.
         mem::forget(orig.borrow);
         orig.value
     }
@@ -1387,9 +1416,11 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     /// ```
     #[unstable(feature = "cell_leak", issue = "69099")]
     pub fn leak(orig: RefMut<'b, T>) -> &'b mut T {
-        // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never
-        // goes back to UNUSED again. No further references can be created from the original cell,
-        // making the current borrow the only reference for the remaining lifetime.
+        // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't
+        // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would
+        // require a unique reference to the borrowed RefCell. No further references can be created
+        // from the original cell within that lifetime, making the current borrow the only
+        // reference for the remaining lifetime.
         mem::forget(orig.borrow);
         orig.value
     }
@@ -1538,7 +1569,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 #[lang = "unsafe_cell"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(transparent)]
-#[cfg_attr(not(bootstrap), repr(no_niche))] // rust-lang/rust#68303.
+#[repr(no_niche)] // rust-lang/rust#68303.
 pub struct UnsafeCell<T: ?Sized> {
     value: T,
 }
diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs
index 5ef673009bb..52d8349bc9a 100644
--- a/src/libcore/fmt/float.rs
+++ b/src/libcore/fmt/float.rs
@@ -2,8 +2,6 @@ use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp};
 use crate::mem::MaybeUninit;
 use crate::num::flt2dec;
 
-// ignore-tidy-undocumented-unsafe
-
 // Don't inline this so callers don't use the stack space this function
 // requires unless they have to.
 #[inline(never)]
@@ -16,6 +14,7 @@ fn float_to_decimal_common_exact<T>(
 where
     T: flt2dec::DecodableFloat,
 {
+    // SAFETY: Possible undefined behavior, see FIXME(#53491)
     unsafe {
         let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64
         let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 4]>::uninit();
@@ -48,6 +47,7 @@ fn float_to_decimal_common_shortest<T>(
 where
     T: flt2dec::DecodableFloat,
 {
+    // SAFETY: Possible undefined behavior, see FIXME(#53491)
     unsafe {
         // enough for f32 and f64
         let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit();
@@ -103,6 +103,7 @@ fn float_to_exponential_common_exact<T>(
 where
     T: flt2dec::DecodableFloat,
 {
+    // SAFETY: Possible undefined behavior, see FIXME(#53491)
     unsafe {
         let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64
         let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit();
@@ -132,6 +133,7 @@ fn float_to_exponential_common_shortest<T>(
 where
     T: flt2dec::DecodableFloat,
 {
+    // SAFETY: Possible undefined behavior, see FIXME(#53491)
     unsafe {
         // enough for f32 and f64
         let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit();
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index d2cebf593ab..a93b34fc46c 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -1,7 +1,5 @@
 //! Utilities for formatting and printing strings.
 
-// ignore-tidy-undocumented-unsafe
-
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
@@ -281,6 +279,14 @@ impl<'a> ArgumentV1<'a> {
     #[doc(hidden)]
     #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {
+        // SAFETY: `mem::transmute(x)` is safe because
+        //     1. `&'b T` keeps the lifetime it originated with `'b`
+        //              (so as to not have an unbounded lifetime)
+        //     2. `&'b T` and `&'b Void` have the same memory layout
+        //              (when `T` is `Sized`, as it is here)
+        // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
+        // and `fn(&Void, &mut Formatter<'_>) -> Result` have the same ABI
+        // (as long as `T` is `Sized`)
         unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } }
     }
 
@@ -1399,6 +1405,14 @@ impl<'a> Formatter<'a> {
 
     fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result {
         fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
+            // SAFETY: This is used for `flt2dec::Part::Num` and `flt2dec::Part::Copy`.
+            // It's safe to use for `flt2dec::Part::Num` since every char `c` is between
+            // `b'0'` and `b'9'`, which means `s` is valid UTF-8.
+            // It's also probably safe in practice to use for `flt2dec::Part::Copy(buf)`
+            // since `buf` should be plain ASCII, but it's possible for someone to pass
+            // in a bad value for `buf` into `flt2dec::to_shortest_str` since it is a
+            // public function.
+            // FIXME: Determine whether this could result in UB.
             buf.write_str(unsafe { str::from_utf8_unchecked(s) })
         }
 
diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index 5dfd3a8ecdb..7d77e33d743 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -1,7 +1,5 @@
 //! Integer and floating-point number formatting
 
-// ignore-tidy-undocumented-unsafe
-
 use crate::fmt;
 use crate::mem::MaybeUninit;
 use crate::num::flt2dec;
@@ -84,6 +82,8 @@ trait GenericRadix {
             }
         }
         let buf = &buf[curr..];
+        // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
+        // valid UTF-8
         let buf = unsafe {
             str::from_utf8_unchecked(slice::from_raw_parts(MaybeUninit::first_ptr(buf), buf.len()))
         };
@@ -189,11 +189,19 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
 macro_rules! impl_Display {
     ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
         fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            // 2^128 is about 3*10^38, so 39 gives an extra byte of space
             let mut buf = [MaybeUninit::<u8>::uninit(); 39];
             let mut curr = buf.len() as isize;
             let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf);
             let lut_ptr = DEC_DIGITS_LUT.as_ptr();
 
+            // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we
+            // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show
+            // that it's OK to copy into `buf_ptr`, notice that at the beginning
+            // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at
+            // each step this is kept the same as `n` is divided. Since `n` is always
+            // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]`
+            // is safe to access.
             unsafe {
                 // need at least 16 bits for the 4-characters-at-a-time to work.
                 assert!(crate::mem::size_of::<$u>() >= 2);
@@ -206,6 +214,10 @@ macro_rules! impl_Display {
                     let d1 = (rem / 100) << 1;
                     let d2 = (rem % 100) << 1;
                     curr -= 4;
+
+                    // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
+                    // otherwise `curr < 0`. But then `n` was originally at least `10000^10`
+                    // which is `10^40 > 2^128 > n`.
                     ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                     ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                 }
@@ -232,6 +244,8 @@ macro_rules! impl_Display {
                 }
             }
 
+            // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
+            // UTF-8 since `DEC_DIGITS_LUT` is
             let buf_slice = unsafe {
                 str::from_utf8_unchecked(
                     slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize))
@@ -304,6 +318,8 @@ macro_rules! impl_Exp {
             };
 
             // 39 digits (worst case u128) + . = 40
+            // Since `curr` always decreases by the number of digits copied, this means
+            // that `curr >= 0`.
             let mut buf = [MaybeUninit::<u8>::uninit(); 40];
             let mut curr = buf.len() as isize; //index for buf
             let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf);
@@ -313,6 +329,8 @@ macro_rules! impl_Exp {
             while n >= 100 {
                 let d1 = ((n % 100) as isize) << 1;
                 curr -= 2;
+                // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since
+                // `DEC_DIGITS_LUT` has a length of 200.
                 unsafe {
                     ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                 }
@@ -324,6 +342,7 @@ macro_rules! impl_Exp {
             // decode second-to-last character
             if n >= 10 {
                 curr -= 1;
+                // SAFETY: Safe since `40 > curr >= 0` (see comment)
                 unsafe {
                     *buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0';
                 }
@@ -333,11 +352,13 @@ macro_rules! impl_Exp {
             // add decimal point iff >1 mantissa digit will be printed
             if exponent != trailing_zeros || added_precision != 0 {
                 curr -= 1;
+                // SAFETY: Safe since `40 > curr >= 0`
                 unsafe {
                     *buf_ptr.offset(curr) = b'.';
                 }
             }
 
+            // SAFETY: Safe since `40 > curr >= 0`
             let buf_slice = unsafe {
                 // decode last character
                 curr -= 1;
@@ -350,6 +371,8 @@ macro_rules! impl_Exp {
             // stores 'e' (or 'E') and the up to 2-digit exponent
             let mut exp_buf = [MaybeUninit::<u8>::uninit(); 3];
             let exp_ptr = MaybeUninit::first_ptr_mut(&mut exp_buf);
+            // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]`
+            // is contained within `exp_buf` since `len <= 3`.
             let exp_slice = unsafe {
                 *exp_ptr.offset(0) = if upper {b'E'} else {b'e'};
                 let len = if exponent < 10 {
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index aa50e7cdf57..adfbe243512 100644
--- a/src/libcore/hash/sip.rs
+++ b/src/libcore/hash/sip.rs
@@ -220,37 +220,6 @@ impl<S: Sip> Hasher<S> {
         self.state.v3 = self.k1 ^ 0x7465646279746573;
         self.ntail = 0;
     }
-
-    // Specialized write function that is only valid for buffers with len <= 8.
-    // It's used to force inlining of write_u8 and write_usize, those would normally be inlined
-    // except for composite types (that includes slices and str hashing because of delimiter).
-    // Without this extra push the compiler is very reluctant to inline delimiter writes,
-    // degrading performance substantially for the most common use cases.
-    #[inline]
-    fn short_write(&mut self, msg: &[u8]) {
-        debug_assert!(msg.len() <= 8);
-        let length = msg.len();
-        self.length += length;
-
-        let needed = 8 - self.ntail;
-        let fill = cmp::min(length, needed);
-        if fill == 8 {
-            self.tail = unsafe { load_int_le!(msg, 0, u64) };
-        } else {
-            self.tail |= unsafe { u8to64_le(msg, 0, fill) } << (8 * self.ntail);
-            if length < needed {
-                self.ntail += length;
-                return;
-            }
-        }
-        self.state.v3 ^= self.tail;
-        S::c_rounds(&mut self.state);
-        self.state.v0 ^= self.tail;
-
-        // Buffered tail is now flushed, process new input.
-        self.ntail = length - needed;
-        self.tail = unsafe { u8to64_le(msg, needed, self.ntail) };
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -280,21 +249,13 @@ impl super::Hasher for SipHasher13 {
 }
 
 impl<S: Sip> super::Hasher for Hasher<S> {
-    // see short_write comment for explanation
-    #[inline]
-    fn write_usize(&mut self, i: usize) {
-        let bytes = unsafe {
-            crate::slice::from_raw_parts(&i as *const usize as *const u8, mem::size_of::<usize>())
-        };
-        self.short_write(bytes);
-    }
-
-    // see short_write comment for explanation
-    #[inline]
-    fn write_u8(&mut self, i: u8) {
-        self.short_write(&[i]);
-    }
-
+    // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined
+    // for this type. We could add them, copy the `short_write` implementation
+    // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*`
+    // methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would
+    // greatly speed up integer hashing by those hashers, at the cost of
+    // slightly slowing down compile speeds on some benchmarks. See #69152 for
+    // details.
     #[inline]
     fn write(&mut self, msg: &[u8]) {
         let length = msg.len();
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 3c060cc6e84..f7ecbd80cbc 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1005,62 +1005,30 @@ extern "rust-intrinsic" {
 
     /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
     /// This will statically either panic, or do nothing.
+    #[cfg(bootstrap)]
     pub fn panic_if_uninhabited<T>();
 
+    /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
+    /// This will statically either panic, or do nothing.
+    #[cfg(not(bootstrap))]
+    pub fn assert_inhabited<T>();
+
     /// A guard for unsafe functions that cannot ever be executed if `T` does not permit
     /// zero-initialization: This will statically either panic, or do nothing.
     #[cfg(not(bootstrap))]
-    pub fn panic_if_zero_invalid<T>();
+    pub fn assert_zero_valid<T>();
 
     /// A guard for unsafe functions that cannot ever be executed if `T` has invalid
     /// bit patterns: This will statically either panic, or do nothing.
     #[cfg(not(bootstrap))]
-    pub fn panic_if_any_invalid<T>();
+    pub fn assert_uninit_valid<T>();
 
     /// Gets a reference to a static `Location` indicating where it was called.
     #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
     pub fn caller_location() -> &'static crate::panic::Location<'static>;
 
-    /// Creates a value initialized to zero.
-    ///
-    /// `init` is unsafe because it returns a zeroed-out datum,
-    /// which is unsafe unless `T` is `Copy`. Also, even if T is
-    /// `Copy`, an all-zero value may not correspond to any legitimate
-    /// state for the type in question.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::mem::zeroed`](../../std/mem/fn.zeroed.html).
-    #[unstable(
-        feature = "core_intrinsics",
-        reason = "intrinsics are unlikely to ever be stabilized, instead \
-                         they should be used through stabilized interfaces \
-                         in the rest of the standard library",
-        issue = "none"
-    )]
-    #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
-    pub fn init<T>() -> T;
-
-    /// Creates an uninitialized value.
-    ///
-    /// `uninit` is unsafe because there is no guarantee of what its
-    /// contents are. In particular its drop-flag may be set to any
-    /// state, which means it may claim either dropped or
-    /// undropped. In the general case one must use `ptr::write` to
-    /// initialize memory previous set to the result of `uninit`.
-    ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::mem::MaybeUninit`](../../std/mem/union.MaybeUninit.html).
-    #[unstable(
-        feature = "core_intrinsics",
-        reason = "intrinsics are unlikely to ever be stabilized, instead \
-                         they should be used through stabilized interfaces \
-                         in the rest of the standard library",
-        issue = "none"
-    )]
-    #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
-    pub fn uninit<T>() -> T;
-
     /// Moves a value out of scope without running drop glue.
+    /// This exists solely for `mem::forget_unsized`; normal `forget` uses `ManuallyDrop` instead.
     pub fn forget<T: ?Sized>(_: T);
 
     /// Reinterprets the bits of a value of one type as another type.
@@ -1865,14 +1833,16 @@ extern "rust-intrinsic" {
     #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
     pub fn discriminant_value<T>(v: &T) -> u64;
 
-    /// Rust's "try catch" construct which invokes the function pointer `f` with
-    /// the data pointer `data`.
+    /// Rust's "try catch" construct which invokes the function pointer `try_fn`
+    /// with the data pointer `data`.
     ///
-    /// The third pointer is a target-specific data pointer which is filled in
-    /// with the specifics of the exception that occurred. For examples on Unix
-    /// platforms this is a `*mut *mut T` which is filled in by the compiler and
-    /// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's
+    /// The third argument is a function called if a panic occurs. This function
+    /// takes the data pointer and a pointer to the target-specific exception
+    /// object that was caught. For more information see the compiler's
     /// source as well as std's catch implementation.
+    #[cfg(not(bootstrap))]
+    pub fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32;
+    #[cfg(bootstrap)]
     pub fn r#try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32;
 
     /// Emits a `!nontemporal` store according to LLVM (see their docs).
@@ -1884,10 +1854,12 @@ extern "rust-intrinsic" {
     pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
     /// Internal hook used by Miri to implement unwinding.
-    /// Compiles to a NOP during non-Miri codegen.
+    /// ICEs when encountered during non-Miri codegen.
+    ///
+    /// The `payload` ptr here will be exactly the one `do_catch` gets passed by `try`.
     ///
-    /// Perma-unstable: do not use
-    pub fn miri_start_panic(data: *mut (dyn crate::any::Any + crate::marker::Send)) -> ();
+    /// Perma-unstable: do not use.
+    pub fn miri_start_panic(payload: *mut u8) -> !;
 }
 
 // Some functions are defined here because they accidentally got made
diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs
index 0a7a9f26f89..4202e52448d 100644
--- a/src/libcore/iter/adapters/flatten.rs
+++ b/src/libcore/iter/adapters/flatten.rs
@@ -1,7 +1,7 @@
 use crate::fmt;
 use crate::ops::Try;
 
-use super::super::{DoubleEndedIterator, FusedIterator, Iterator};
+use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator};
 use super::Map;
 
 /// An iterator that maps each element to an iterator, and yields the elements
@@ -239,14 +239,17 @@ where
 /// this type.
 #[derive(Clone, Debug)]
 struct FlattenCompat<I, U> {
-    iter: I,
+    iter: Fuse<I>,
     frontiter: Option<U>,
     backiter: Option<U>,
 }
-impl<I, U> FlattenCompat<I, U> {
+impl<I, U> FlattenCompat<I, U>
+where
+    I: Iterator,
+{
     /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
     fn new(iter: I) -> FlattenCompat<I, U> {
-        FlattenCompat { iter, frontiter: None, backiter: None }
+        FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None }
     }
 }
 
@@ -261,8 +264,9 @@ where
     fn next(&mut self) -> Option<U::Item> {
         loop {
             if let Some(ref mut inner) = self.frontiter {
-                if let elt @ Some(_) = inner.next() {
-                    return elt;
+                match inner.next() {
+                    None => self.frontiter = None,
+                    elt @ Some(_) => return elt,
                 }
             }
             match self.iter.next() {
@@ -348,8 +352,9 @@ where
     fn next_back(&mut self) -> Option<U::Item> {
         loop {
             if let Some(ref mut inner) = self.backiter {
-                if let elt @ Some(_) = inner.next_back() {
-                    return elt;
+                match inner.next_back() {
+                    None => self.backiter = None,
+                    elt @ Some(_) => return elt,
                 }
             }
             match self.iter.next_back() {
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index 26132e36c97..3c0ddcb2bc8 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -1480,7 +1480,11 @@ where
 {
     #[inline]
     fn next_back(&mut self) -> Option<Self::Item> {
-        self.iter.next_back().or_else(|| self.peeked.take().and_then(|x| x))
+        match self.peeked.as_mut() {
+            Some(v @ Some(_)) => self.iter.next_back().or_else(|| v.take()),
+            Some(None) => None,
+            None => self.iter.next_back(),
+        }
     }
 
     #[inline]
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index a1dde1d51ef..5a731766054 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -140,7 +140,7 @@
 #![feature(associated_type_bounds)]
 #![feature(const_type_id)]
 #![feature(const_caller_location)]
-#![cfg_attr(not(bootstrap), feature(no_niche))] // rust-lang/rust#68303
+#![feature(no_niche)] // rust-lang/rust#68303
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs
index 76e58f0cc62..a0873fe6b62 100644
--- a/src/libcore/macros/mod.rs
+++ b/src/libcore/macros/mod.rs
@@ -1,3 +1,4 @@
+#[cfg(bootstrap)]
 #[doc(include = "panic.md")]
 #[macro_export]
 #[allow_internal_unstable(core_panic, track_caller)]
@@ -20,6 +21,26 @@ macro_rules! panic {
     );
 }
 
+#[cfg(not(bootstrap))]
+#[doc(include = "panic.md")]
+#[macro_export]
+#[allow_internal_unstable(core_panic, track_caller)]
+#[stable(feature = "core", since = "1.6.0")]
+macro_rules! panic {
+    () => (
+        $crate::panic!("explicit panic")
+    );
+    ($msg:expr) => (
+        $crate::panicking::panic($msg)
+    );
+    ($msg:expr,) => (
+        $crate::panic!($msg)
+    );
+    ($fmt:expr, $($arg:tt)+) => (
+        $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+))
+    );
+}
+
 /// Asserts that two expressions are equal to each other (using [`PartialEq`]).
 ///
 /// On panic, this macro will print the values of the expressions with their
@@ -1383,6 +1404,18 @@ pub(crate) mod builtin {
         /* compiler built-in */
     }
 
+    /// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise.
+    #[cfg(not(bootstrap))]
+    #[unstable(
+        feature = "cfg_accessible",
+        issue = "64797",
+        reason = "`cfg_accessible` is not fully implemented"
+    )]
+    #[rustc_builtin_macro]
+    pub macro cfg_accessible($item:item) {
+        /* compiler built-in */
+    }
+
     /// Unstable implementation detail of the `rustc` compiler, do not use.
     #[rustc_builtin_macro]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 2800f11cc01..2b908f07af8 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -90,6 +90,7 @@ impl<T: ?Sized> !Send for *mut T {}
           ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>"
 )]
 #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+#[cfg_attr(not(bootstrap), rustc_specialization_trait)]
 pub trait Sized {
     // Empty.
 }
diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs
index 58aaac21ad7..bf39d56fc11 100644
--- a/src/libcore/mem/maybe_uninit.rs
+++ b/src/libcore/mem/maybe_uninit.rs
@@ -495,7 +495,10 @@ impl<T> MaybeUninit<T> {
     #[inline(always)]
     #[rustc_diagnostic_item = "assume_init"]
     pub unsafe fn assume_init(self) -> T {
+        #[cfg(bootstrap)]
         intrinsics::panic_if_uninhabited::<T>();
+        #[cfg(not(bootstrap))]
+        intrinsics::assert_inhabited::<T>();
         ManuallyDrop::into_inner(self.value)
     }
 
@@ -559,7 +562,10 @@ impl<T> MaybeUninit<T> {
     #[unstable(feature = "maybe_uninit_extra", issue = "63567")]
     #[inline(always)]
     pub unsafe fn read(&self) -> T {
+        #[cfg(bootstrap)]
         intrinsics::panic_if_uninhabited::<T>();
+        #[cfg(not(bootstrap))]
+        intrinsics::assert_inhabited::<T>();
         self.as_ptr().read()
     }
 
@@ -621,7 +627,10 @@ impl<T> MaybeUninit<T> {
     #[unstable(feature = "maybe_uninit_ref", issue = "63568")]
     #[inline(always)]
     pub unsafe fn get_ref(&self) -> &T {
+        #[cfg(bootstrap)]
         intrinsics::panic_if_uninhabited::<T>();
+        #[cfg(not(bootstrap))]
+        intrinsics::assert_inhabited::<T>();
         &*self.value
     }
 
@@ -739,7 +748,10 @@ impl<T> MaybeUninit<T> {
     #[unstable(feature = "maybe_uninit_ref", issue = "63568")]
     #[inline(always)]
     pub unsafe fn get_mut(&mut self) -> &mut T {
+        #[cfg(bootstrap)]
         intrinsics::panic_if_uninhabited::<T>();
+        #[cfg(not(bootstrap))]
+        intrinsics::assert_inhabited::<T>();
         &mut *self.value
     }
 
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index 7d9a8bcd05b..dac9ee6a5d9 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -58,7 +58,9 @@ pub use crate::intrinsics::transmute;
 ///
 /// # Examples
 ///
-/// Leak an I/O object, never closing the file:
+/// The canonical safe use of `mem::forget` is to circumvent a value's destructor
+/// implemented by the `Drop` trait. For example, this will leak a `File`, i.e. reclaim
+/// the space taken by the variable but never close the underlying system resource:
 ///
 /// ```no_run
 /// use std::mem;
@@ -68,9 +70,40 @@ pub use crate::intrinsics::transmute;
 /// mem::forget(file);
 /// ```
 ///
-/// The practical use cases for `forget` are rather specialized and mainly come
-/// up in unsafe or FFI code. However, [`ManuallyDrop`] is usually preferred
-/// for such cases, e.g.:
+/// This is useful when the ownership of the underlying resource was previously
+/// transferred to code outside of Rust, for example by transmitting the raw
+/// file descriptor to C code.
+///
+/// # Relationship with `ManuallyDrop`
+///
+/// While `mem::forget` can also be used to transfer *memory* ownership, doing so is error-prone.
+/// [`ManuallyDrop`] should be used instead. Consider, for example, this code:
+///
+/// ```
+/// use std::mem;
+///
+/// let mut v = vec![65, 122];
+/// // Build a `String` using the contents of `v`
+/// let s = unsafe { String::from_raw_parts(v.as_mut_ptr(), v.len(), v.capacity()) };
+/// // leak `v` because its memory is now managed by `s`
+/// mem::forget(v);  // ERROR - v is invalid and must not be passed to a function
+/// assert_eq!(s, "Az");
+/// // `s` is implicitly dropped and its memory deallocated.
+/// ```
+///
+/// There are two issues with the above example:
+///
+/// * If more code were added between the construction of `String` and the invocation of
+///   `mem::forget()`, a panic within it would cause a double free because the same memory
+///   is handled by both `v` and `s`.
+/// * After calling `v.as_mut_ptr()` and transmitting the ownership of the data to `s`,
+///   the `v` value is invalid. Even when a value is just moved to `mem::forget` (which won't
+///   inspect it), some types have strict requirements on their values that
+///   make them invalid when dangling or no longer owned. Using invalid values in any
+///   way, including passing them to or returning them from functions, constitutes
+///   undefined behavior and may break the assumptions made by the compiler.
+///
+/// Switching to `ManuallyDrop` avoids both issues:
 ///
 /// ```
 /// use std::mem::ManuallyDrop;
@@ -80,24 +113,24 @@ pub use crate::intrinsics::transmute;
 /// // does not get dropped!
 /// let mut v = ManuallyDrop::new(v);
 /// // Now disassemble `v`. These operations cannot panic, so there cannot be a leak.
-/// let ptr = v.as_mut_ptr();
-/// let cap = v.capacity();
+/// let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity());
 /// // Finally, build a `String`.
-/// let s = unsafe { String::from_raw_parts(ptr, 2, cap) };
+/// let s = unsafe { String::from_raw_parts(ptr, len, cap) };
 /// assert_eq!(s, "Az");
 /// // `s` is implicitly dropped and its memory deallocated.
 /// ```
 ///
-/// Using `ManuallyDrop` here has two advantages:
+/// `ManuallyDrop` robustly prevents double-free because we disable `v`'s destructor
+/// before doing anything else. `mem::forget()` doesn't allow this because it consumes its
+/// argument, forcing us to call it only after extracting anything we need from `v`. Even
+/// if a panic were introduced between construction of `ManuallyDrop` and building the
+/// string (which cannot happen in the code as shown), it would result in a leak and not a
+/// double free. In other words, `ManuallyDrop` errs on the side of leaking instead of
+/// erring on the side of (double-)dropping.
 ///
-/// * We do not "touch" `v` after disassembling it. For some types, operations
-///   such as passing ownership (to a function like `mem::forget`) requires them to actually
-///   be fully owned right now; that is a promise we do not want to make here as we are
-///   in the process of transferring ownership to the new `String` we are building.
-/// * In case of an unexpected panic, `ManuallyDrop` is not dropped, but if the panic
-///   occurs before `mem::forget` was called we might end up dropping invalid data,
-///   or double-dropping. In other words, `ManuallyDrop` errs on the side of leaking
-///   instead of erring on the side of dropping.
+/// Also, `ManuallyDrop` prevents us from having to "touch" `v` after transferring the
+/// ownership to `s` - the final step of interacting with `v` to dispoe of it without
+/// running its destructor is entirely avoided.
 ///
 /// [drop]: fn.drop.html
 /// [uninit]: fn.uninitialized.html
@@ -490,17 +523,17 @@ pub const fn needs_drop<T>() -> bool {
 ///
 /// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
 /// ```
-#[inline]
+#[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated_in_future)]
 #[allow(deprecated)]
 #[rustc_diagnostic_item = "mem_zeroed"]
 pub unsafe fn zeroed<T>() -> T {
     #[cfg(not(bootstrap))]
-    intrinsics::panic_if_zero_invalid::<T>();
+    intrinsics::assert_zero_valid::<T>();
     #[cfg(bootstrap)]
     intrinsics::panic_if_uninhabited::<T>();
-    intrinsics::init()
+    MaybeUninit::zeroed().assume_init()
 }
 
 /// Bypasses Rust's normal memory-initialization checks by pretending to
@@ -525,7 +558,7 @@ pub unsafe fn zeroed<T>() -> T {
 /// [uninit]: union.MaybeUninit.html#method.uninit
 /// [assume_init]: union.MaybeUninit.html#method.assume_init
 /// [inv]: union.MaybeUninit.html#initialization-invariant
-#[inline]
+#[inline(always)]
 #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated_in_future)]
@@ -533,10 +566,10 @@ pub unsafe fn zeroed<T>() -> T {
 #[rustc_diagnostic_item = "mem_uninitialized"]
 pub unsafe fn uninitialized<T>() -> T {
     #[cfg(not(bootstrap))]
-    intrinsics::panic_if_any_invalid::<T>();
+    intrinsics::assert_uninit_valid::<T>();
     #[cfg(bootstrap)]
     intrinsics::panic_if_uninhabited::<T>();
-    intrinsics::uninit()
+    MaybeUninit::uninit().assume_init()
 }
 
 /// Swaps the values at two mutable locations, without deinitializing either one.
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index caffa6c509a..853092dd85e 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -2154,7 +2154,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();
 assert_eq!(bytes, ", $be_bytes, ");
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 self.to_be().to_ne_bytes()
@@ -2174,7 +2174,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();
 assert_eq!(bytes, ", $le_bytes, ");
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 self.to_le().to_ne_bytes()
@@ -2209,7 +2209,7 @@ assert_eq!(
 );
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute them to arrays of bytes
             #[allow_internal_unstable(const_fn_union)]
@@ -2251,7 +2251,7 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 Self::from_be(Self::from_ne_bytes(bytes))
@@ -2284,7 +2284,7 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 Self::from_le(Self::from_ne_bytes(bytes))
@@ -2327,7 +2327,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute to them
             #[allow_internal_unstable(const_fn_union)]
@@ -4115,7 +4115,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes();
 assert_eq!(bytes, ", $be_bytes, ");
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 self.to_be().to_ne_bytes()
@@ -4135,7 +4135,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes();
 assert_eq!(bytes, ", $le_bytes, ");
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 self.to_le().to_ne_bytes()
@@ -4170,7 +4170,7 @@ assert_eq!(
 );
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute them to arrays of bytes
             #[allow_internal_unstable(const_fn_union)]
@@ -4212,7 +4212,7 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 Self::from_be(Self::from_ne_bytes(bytes))
@@ -4245,7 +4245,7 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             #[inline]
             pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 Self::from_le(Self::from_ne_bytes(bytes))
@@ -4288,7 +4288,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
 }
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
-            #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")]
+            #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute to them
             #[allow_internal_unstable(const_fn_union)]
diff --git a/src/libcore/ops/generator.rs b/src/libcore/ops/generator.rs
index 4e43561996c..4f23620b92b 100644
--- a/src/libcore/ops/generator.rs
+++ b/src/libcore/ops/generator.rs
@@ -67,7 +67,7 @@ pub enum GeneratorState<Y, R> {
 #[lang = "generator"]
 #[unstable(feature = "generator_trait", issue = "43122")]
 #[fundamental]
-pub trait Generator<#[cfg(not(bootstrap))] R = ()> {
+pub trait Generator<R = ()> {
     /// The type of value this generator yields.
     ///
     /// This associated type corresponds to the `yield` expression and the
@@ -110,35 +110,9 @@ pub trait Generator<#[cfg(not(bootstrap))] R = ()> {
     /// been returned previously. While generator literals in the language are
     /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
     /// for all implementations of the `Generator` trait.
-    fn resume(
-        self: Pin<&mut Self>,
-        #[cfg(not(bootstrap))] arg: R,
-    ) -> GeneratorState<Self::Yield, Self::Return>;
+    fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
 }
 
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume((*self).as_mut())
-    }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
-    type Yield = G::Yield;
-    type Return = G::Return;
-
-    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
-        G::resume(Pin::new(&mut *self))
-    }
-}
-
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
     type Yield = G::Yield;
@@ -149,7 +123,6 @@ impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
     }
 }
 
-#[cfg(not(bootstrap))]
 #[unstable(feature = "generator_trait", issue = "43122")]
 impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for &mut G {
     type Yield = G::Yield;
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 61b764f2d62..3587f3f0ebf 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -32,6 +32,7 @@
 use crate::fmt;
 use crate::panic::{Location, PanicInfo};
 
+/// The underlying implementation of libcore's `panic!` macro when no formatting is used.
 #[cold]
 // never inline unless panic_immediate_abort to avoid code
 // bloat at the call sites as much as possible
@@ -49,9 +50,28 @@ pub fn panic(expr: &str) -> ! {
     // truncation and padding (even though none is used here). Using
     // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
     // output binary, saving up to a few kilobytes.
-    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), Location::caller())
+    #[cfg(not(bootstrap))]
+    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
+    #[cfg(bootstrap)]
+    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), Location::caller());
 }
 
+#[cfg(not(bootstrap))]
+#[cold]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[track_caller]
+#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
+fn panic_bounds_check(index: usize, len: usize) -> ! {
+    if cfg!(feature = "panic_immediate_abort") {
+        unsafe { super::intrinsics::abort() }
+    }
+
+    panic!("index out of bounds: the len is {} but the index is {}", len, index)
+}
+
+// For bootstrap, we need a variant with the old argument order, and a corresponding
+// `panic_fmt`.
+#[cfg(bootstrap)]
 #[cold]
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
@@ -66,10 +86,12 @@ fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! {
     )
 }
 
+/// The underlying implementation of libcore's `panic!` macro when formatting is used.
 #[cold]
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
-pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! {
+#[cfg_attr(not(bootstrap), track_caller)]
+pub fn panic_fmt(fmt: fmt::Arguments<'_>, #[cfg(bootstrap)] location: &Location<'_>) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         unsafe { super::intrinsics::abort() }
     }
@@ -81,6 +103,10 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! {
         fn panic_impl(pi: &PanicInfo<'_>) -> !;
     }
 
+    #[cfg(bootstrap)]
     let pi = PanicInfo::internal_constructor(Some(&fmt), location);
+    #[cfg(not(bootstrap))]
+    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller());
+
     unsafe { panic_impl(&pi) }
 }
diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs
index 66b5a90b77b..c91370b2719 100644
--- a/src/libcore/prelude/v1.rs
+++ b/src/libcore/prelude/v1.rs
@@ -67,3 +67,12 @@ pub use crate::{
 pub use crate::macros::builtin::{
     bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
 };
+
+#[cfg(not(bootstrap))]
+#[unstable(
+    feature = "cfg_accessible",
+    issue = "64797",
+    reason = "`cfg_accessible` is not fully implemented"
+)]
+#[doc(no_inline)]
+pub use crate::macros::builtin::cfg_accessible;
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index 6c826e5dcde..ffa418cba6c 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -365,11 +365,7 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> {
         let haystack = self.haystack.as_bytes();
         loop {
             // get the haystack up to but not including the last character searched
-            let bytes = if let Some(slice) = haystack.get(self.finger..self.finger_back) {
-                slice
-            } else {
-                return None;
-            };
+            let bytes = haystack.get(self.finger..self.finger_back)?;
             // the last byte of the utf8 encoded needle
             // SAFETY: we have an invariant that `utf8_size < 5`
             let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
@@ -575,11 +571,12 @@ macro_rules! pattern_methods {
 
         #[inline]
         fn is_suffix_of(self, haystack: &'a str) -> bool
-            where $t: ReverseSearcher<'a>
+        where
+            $t: ReverseSearcher<'a>,
         {
             ($pmap)(self).is_suffix_of(haystack)
         }
-    }
+    };
 }
 
 macro_rules! searcher_methods {
@@ -614,7 +611,7 @@ macro_rules! searcher_methods {
         fn next_reject_back(&mut self) -> Option<(usize, usize)> {
             self.0.next_reject_back()
         }
-    }
+    };
 }
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 3ba15968f89..220f221cdd3 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -2259,7 +2259,7 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering {
 }
 
 #[inline]
-unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
+unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
     match order {
         Release => intrinsics::atomic_store_rel(dst, val),
         Relaxed => intrinsics::atomic_store_relaxed(dst, val),
@@ -2270,7 +2270,7 @@ unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
 }
 
 #[inline]
-unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
+unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_load_acq(dst),
         Relaxed => intrinsics::atomic_load_relaxed(dst),
@@ -2282,7 +2282,7 @@ unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xchg_acq(dst, val),
         Release => intrinsics::atomic_xchg_rel(dst, val),
@@ -2295,7 +2295,7 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// Returns the previous value (like __sync_fetch_and_add).
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xadd_acq(dst, val),
         Release => intrinsics::atomic_xadd_rel(dst, val),
@@ -2308,7 +2308,7 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// Returns the previous value (like __sync_fetch_and_sub).
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xsub_acq(dst, val),
         Release => intrinsics::atomic_xsub_rel(dst, val),
@@ -2320,7 +2320,7 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_compare_exchange<T>(
+unsafe fn atomic_compare_exchange<T: Copy>(
     dst: *mut T,
     old: T,
     new: T,
@@ -2346,7 +2346,7 @@ unsafe fn atomic_compare_exchange<T>(
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_compare_exchange_weak<T>(
+unsafe fn atomic_compare_exchange_weak<T: Copy>(
     dst: *mut T,
     old: T,
     new: T,
@@ -2372,7 +2372,7 @@ unsafe fn atomic_compare_exchange_weak<T>(
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_and_acq(dst, val),
         Release => intrinsics::atomic_and_rel(dst, val),
@@ -2384,7 +2384,7 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_nand_acq(dst, val),
         Release => intrinsics::atomic_nand_rel(dst, val),
@@ -2396,7 +2396,7 @@ unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_or_acq(dst, val),
         Release => intrinsics::atomic_or_rel(dst, val),
@@ -2408,7 +2408,7 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xor_acq(dst, val),
         Release => intrinsics::atomic_xor_rel(dst, val),
@@ -2421,7 +2421,7 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// returns the max value (signed comparison)
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_max_acq(dst, val),
         Release => intrinsics::atomic_max_rel(dst, val),
@@ -2434,7 +2434,7 @@ unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// returns the min value (signed comparison)
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_min_acq(dst, val),
         Release => intrinsics::atomic_min_rel(dst, val),
@@ -2447,7 +2447,7 @@ unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// returns the max value (unsigned comparison)
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_umax_acq(dst, val),
         Release => intrinsics::atomic_umax_rel(dst, val),
@@ -2460,7 +2460,7 @@ unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// returns the min value (unsigned comparison)
 #[inline]
 #[cfg(target_has_atomic = "8")]
-unsafe fn atomic_umin<T>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_umin_acq(dst, val),
         Release => intrinsics::atomic_umin_rel(dst, val),
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 5b41ef35065..98e3eeb982b 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
 use core::cell::Cell;
 use core::convert::TryFrom;
 use core::iter::*;
@@ -2940,3 +2942,73 @@ fn test_partition() {
     check(xs, |&x| x < 3, 3); // small
     check(xs, |&x| x > 6, 3); // large
 }
+
+/// An iterator that panics whenever `next` or next_back` is called
+/// after `None` has already been returned. This does not violate
+/// `Iterator`'s contract. Used to test that iterator adaptors don't
+/// poll their inner iterators after exhausting them.
+struct NonFused<I> {
+    iter: I,
+    done: bool,
+}
+
+impl<I> NonFused<I> {
+    fn new(iter: I) -> Self {
+        Self { iter, done: false }
+    }
+}
+
+impl<I> Iterator for NonFused<I>
+where
+    I: Iterator,
+{
+    type Item = I::Item;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        assert!(!self.done, "this iterator has already returned None");
+        self.iter.next().or_else(|| {
+            self.done = true;
+            None
+        })
+    }
+}
+
+impl<I> DoubleEndedIterator for NonFused<I>
+where
+    I: DoubleEndedIterator,
+{
+    fn next_back(&mut self) -> Option<Self::Item> {
+        assert!(!self.done, "this iterator has already returned None");
+        self.iter.next_back().or_else(|| {
+            self.done = true;
+            None
+        })
+    }
+}
+
+#[test]
+fn test_peekable_non_fused() {
+    let mut iter = NonFused::new(empty::<i32>()).peekable();
+
+    assert_eq!(iter.peek(), None);
+    assert_eq!(iter.next_back(), None);
+}
+
+#[test]
+fn test_flatten_non_fused_outer() {
+    let mut iter = NonFused::new(once(0..2)).flatten();
+
+    assert_eq!(iter.next_back(), Some(1));
+    assert_eq!(iter.next(), Some(0));
+    assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_flatten_non_fused_inner() {
+    let mut iter = once(0..1).chain(once(1..3)).flat_map(NonFused::new);
+
+    assert_eq!(iter.next_back(), Some(2));
+    assert_eq!(iter.next(), Some(0));
+    assert_eq!(iter.next(), Some(1));
+    assert_eq!(iter.next(), None);
+}
diff --git a/src/libcore/unicode/printable.rs b/src/libcore/unicode/printable.rs
index eee9ea52ef0..9680aa14d3b 100644
--- a/src/libcore/unicode/printable.rs
+++ b/src/libcore/unicode/printable.rs
@@ -44,7 +44,7 @@ pub(crate) fn is_printable(x: char) -> bool {
     } else if x < 0x20000 {
         check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)
     } else {
-        if 0x2a6d7 <= x && x < 0x2a700 {
+        if 0x2a6de <= x && x < 0x2a700 {
             return false;
         }
         if 0x2b735 <= x && x < 0x2b740 {
@@ -59,7 +59,10 @@ pub(crate) fn is_printable(x: char) -> bool {
         if 0x2ebe1 <= x && x < 0x2f800 {
             return false;
         }
-        if 0x2fa1e <= x && x < 0xe0100 {
+        if 0x2fa1e <= x && x < 0x30000 {
+            return false;
+        }
+        if 0x3134b <= x && x < 0xe0100 {
             return false;
         }
         if 0xe01f0 <= x && x < 0x110000 {
@@ -81,7 +84,7 @@ const SINGLETONS0U: &[(u8, u8)] = &[
     (0x0a, 28),
     (0x0b, 25),
     (0x0c, 20),
-    (0x0d, 18),
+    (0x0d, 16),
     (0x0e, 13),
     (0x0f, 4),
     (0x10, 3),
@@ -96,7 +99,7 @@ const SINGLETONS0U: &[(u8, u8)] = &[
     (0x1d, 1),
     (0x1f, 22),
     (0x20, 3),
-    (0x2b, 4),
+    (0x2b, 3),
     (0x2c, 2),
     (0x2d, 11),
     (0x2e, 1),
@@ -129,29 +132,29 @@ const SINGLETONS0L: &[u8] = &[
     0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d,
     0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49,
     0x57, 0x64, 0x65, 0x8d, 0x91, 0xa9, 0xb4, 0xba,
-    0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04,
-    0x0d, 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81,
-    0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0,
-    0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf,
-    0xc5, 0xc7, 0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98,
-    0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, 0x4e, 0x4f,
-    0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1,
-    0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11,
-    0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff,
-    0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f,
-    0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e,
-    0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16, 0x17, 0x1e,
-    0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c,
-    0x5e, 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc,
-    0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75,
-    0x96, 0x97, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7,
-    0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, 0x9a,
-    0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0, 0xc1,
-    0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08,
-    0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef, 0x6e, 0x6f,
-    0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91, 0xfe,
-    0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1,
-    0xd8, 0xd9, 0xe7, 0xfe, 0xff,
+    0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d,
+    0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2,
+    0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0, 0xf1, 0x83,
+    0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7,
+    0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd,
+    0xc6, 0xce, 0xcf, 0x49, 0x4e, 0x4f, 0x57, 0x59,
+    0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7,
+    0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17,
+    0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff, 0x80, 0x0d,
+    0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e,
+    0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf,
+    0xbb, 0xbc, 0xfa, 0x16, 0x17, 0x1e, 0x1f, 0x46,
+    0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e,
+    0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1,
+    0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96, 0x2f,
+    0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf,
+    0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98,
+    0x30, 0x8f, 0x1f, 0xc0, 0xc1, 0xce, 0xff, 0x4e,
+    0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27,
+    0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f,
+    0x42, 0x45, 0x90, 0x91, 0xfe, 0xff, 0x53, 0x67,
+    0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7,
+    0xfe, 0xff,
 ];
 #[rustfmt::skip]
 const SINGLETONS1U: &[(u8, u8)] = &[
@@ -163,14 +166,15 @@ const SINGLETONS1U: &[(u8, u8)] = &[
     (0x09, 2),
     (0x0a, 5),
     (0x0b, 2),
+    (0x0e, 4),
     (0x10, 1),
-    (0x11, 4),
+    (0x11, 2),
     (0x12, 5),
     (0x13, 17),
-    (0x14, 2),
+    (0x14, 1),
     (0x15, 2),
     (0x17, 2),
-    (0x19, 4),
+    (0x19, 13),
     (0x1c, 5),
     (0x1d, 8),
     (0x24, 1),
@@ -188,32 +192,35 @@ const SINGLETONS1U: &[(u8, u8)] = &[
     (0xe8, 2),
     (0xee, 32),
     (0xf0, 4),
-    (0xf9, 6),
+    (0xf8, 2),
+    (0xf9, 2),
     (0xfa, 2),
+    (0xfb, 1),
 ];
 #[rustfmt::skip]
 const SINGLETONS1L: &[u8] = &[
     0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e,
     0x9e, 0x9f, 0x06, 0x07, 0x09, 0x36, 0x3d, 0x3e,
     0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36,
-    0x37, 0x56, 0x57, 0xbd, 0x35, 0xce, 0xcf, 0xe0,
-    0x12, 0x87, 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e,
-    0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, 0x45, 0x46,
-    0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5a, 0x5c,
-    0xb6, 0xb7, 0x1b, 0x1c, 0xa8, 0xa9, 0xd8, 0xd9,
-    0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b,
-    0x3e, 0x66, 0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee,
-    0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28, 0x55,
-    0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad,
-    0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d,
-    0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, 0xcd,
-    0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f,
-    0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28,
-    0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53,
-    0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63,
-    0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a,
-    0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x0c, 0x72,
-    0xa3, 0xa4, 0xcb, 0xcc, 0x6e, 0x6f,
+    0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd,
+    0x35, 0xe0, 0x12, 0x87, 0x89, 0x8e, 0x9e, 0x04,
+    0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
+    0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65,
+    0x5c, 0xb6, 0xb7, 0x1b, 0x1c, 0x07, 0x08, 0x0a,
+    0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9,
+    0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07,
+    0x0a, 0x3b, 0x3e, 0x66, 0x69, 0x8f, 0x92, 0x6f,
+    0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27,
+    0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7,
+    0xa8, 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c,
+    0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7,
+    0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25,
+    0x3e, 0x3f, 0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25,
+    0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c,
+    0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
+    0x60, 0x63, 0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d,
+    0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0,
+    0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93,
 ];
 #[rustfmt::skip]
 const NORMAL0: &[u8] = &[
@@ -225,7 +232,7 @@ const NORMAL0: &[u8] = &[
     0x06, 0x11,
     0x81, 0xac, 0x0e,
     0x80, 0xab, 0x35,
-    0x1e, 0x15,
+    0x28, 0x0b,
     0x80, 0xe0, 0x03,
     0x19, 0x08,
     0x01, 0x04,
@@ -237,8 +244,8 @@ const NORMAL0: &[u8] = &[
     0x11, 0x0a,
     0x50, 0x0f,
     0x12, 0x07,
-    0x55, 0x08,
-    0x02, 0x04,
+    0x55, 0x07,
+    0x03, 0x04,
     0x1c, 0x0a,
     0x09, 0x03,
     0x08, 0x03,
@@ -292,7 +299,7 @@ const NORMAL0: &[u8] = &[
     0x0b, 0x03,
     0x80, 0xac, 0x06,
     0x0a, 0x06,
-    0x1f, 0x41,
+    0x21, 0x3f,
     0x4c, 0x04,
     0x2d, 0x03,
     0x74, 0x08,
@@ -315,21 +322,19 @@ const NORMAL0: &[u8] = &[
     0x3b, 0x07,
     0x02, 0x0e,
     0x18, 0x09,
-    0x80, 0xb0, 0x30,
+    0x80, 0xb3, 0x2d,
     0x74, 0x0c,
     0x80, 0xd6, 0x1a,
     0x0c, 0x05,
     0x80, 0xff, 0x05,
-    0x80, 0xb6, 0x05,
-    0x24, 0x0c,
-    0x9b, 0xc6, 0x0a,
-    0xd2, 0x30, 0x10,
+    0x80, 0xdf, 0x0c,
+    0xee, 0x0d, 0x03,
     0x84, 0x8d, 0x03,
     0x37, 0x09,
     0x81, 0x5c, 0x14,
     0x80, 0xb8, 0x08,
-    0x80, 0xc7, 0x30,
-    0x35, 0x04,
+    0x80, 0xcb, 0x2a,
+    0x38, 0x03,
     0x0a, 0x06,
     0x38, 0x08,
     0x46, 0x08,
@@ -341,7 +346,7 @@ const NORMAL0: &[u8] = &[
     0x80, 0x83, 0x18,
     0x1c, 0x0a,
     0x16, 0x09,
-    0x48, 0x08,
+    0x4c, 0x04,
     0x80, 0x8a, 0x06,
     0xab, 0xa4, 0x0c,
     0x17, 0x04,
@@ -365,7 +370,7 @@ const NORMAL1: &[u8] = &[
     0x7b, 0x05,
     0x03, 0x04,
     0x2d, 0x03,
-    0x65, 0x04,
+    0x66, 0x03,
     0x01, 0x2f,
     0x2e, 0x80, 0x82,
     0x1d, 0x03,
@@ -410,16 +415,17 @@ const NORMAL1: &[u8] = &[
     0x33, 0x07,
     0x2e, 0x08,
     0x0a, 0x81, 0x26,
-    0x1f, 0x80, 0x81,
+    0x52, 0x4e,
     0x28, 0x08,
-    0x2a, 0x80, 0x86,
+    0x2a, 0x56,
+    0x1c, 0x14,
     0x17, 0x09,
     0x4e, 0x04,
     0x1e, 0x0f,
     0x43, 0x0e,
     0x19, 0x07,
     0x0a, 0x06,
-    0x47, 0x09,
+    0x48, 0x08,
     0x27, 0x09,
     0x75, 0x0b,
     0x3f, 0x41,
@@ -430,7 +436,7 @@ const NORMAL1: &[u8] = &[
     0x01, 0x05,
     0x10, 0x03,
     0x05, 0x80, 0x8b,
-    0x60, 0x20,
+    0x62, 0x1e,
     0x48, 0x08,
     0x0a, 0x80, 0xa6,
     0x5e, 0x22,
@@ -443,7 +449,8 @@ const NORMAL1: &[u8] = &[
     0x10, 0x80, 0xc0,
     0x3c, 0x64,
     0x53, 0x0c,
-    0x01, 0x80, 0xa0,
+    0x48, 0x09,
+    0x0a, 0x46,
     0x45, 0x1b,
     0x48, 0x08,
     0x53, 0x1d,
@@ -456,7 +463,8 @@ const NORMAL1: &[u8] = &[
     0x0a, 0x06,
     0x39, 0x07,
     0x0a, 0x81, 0x36,
-    0x19, 0x80, 0xc7,
+    0x19, 0x80, 0xb7,
+    0x01, 0x0f,
     0x32, 0x0d,
     0x83, 0x9b, 0x66,
     0x75, 0x0b,
@@ -474,9 +482,11 @@ const NORMAL1: &[u8] = &[
     0x4b, 0x04,
     0x39, 0x07,
     0x11, 0x40,
-    0x04, 0x1c,
+    0x05, 0x0b,
+    0x02, 0x0e,
     0x97, 0xf8, 0x08,
-    0x82, 0xf3, 0xa5, 0x0d,
+    0x84, 0xd6, 0x2a,
+    0x09, 0xa2, 0xf7,
     0x81, 0x1f, 0x31,
     0x03, 0x11,
     0x04, 0x08,
@@ -515,17 +525,15 @@ const NORMAL1: &[u8] = &[
     0x2c, 0x04,
     0x64, 0x0c,
     0x56, 0x0a,
-    0x0d, 0x03,
-    0x5d, 0x03,
-    0x3d, 0x39,
+    0x80, 0xae, 0x38,
     0x1d, 0x0d,
     0x2c, 0x04,
     0x09, 0x07,
     0x02, 0x0e,
     0x06, 0x80, 0x9a,
-    0x83, 0xd6, 0x0a,
+    0x83, 0xd8, 0x08,
+    0x0d, 0x03,
     0x0d, 0x03,
-    0x0b, 0x05,
     0x74, 0x0c,
     0x59, 0x07,
     0x0c, 0x14,
@@ -533,12 +541,15 @@ const NORMAL1: &[u8] = &[
     0x38, 0x08,
     0x0a, 0x06,
     0x28, 0x08,
-    0x1e, 0x52,
-    0x77, 0x03,
-    0x31, 0x03,
-    0x80, 0xa6, 0x0c,
-    0x14, 0x04,
+    0x22, 0x4e,
+    0x81, 0x54, 0x0c,
+    0x15, 0x03,
     0x03, 0x05,
+    0x07, 0x09,
+    0x19, 0x07,
+    0x07, 0x09,
     0x03, 0x0d,
-    0x06, 0x85, 0x6a,
+    0x07, 0x29,
+    0x80, 0xcb, 0x25,
+    0x0a, 0x84, 0x06,
 ];
diff --git a/src/libcore/unicode/unicode_data.rs b/src/libcore/unicode/unicode_data.rs
index da4cd4e9b1d..3e90028613c 100644
--- a/src/libcore/unicode/unicode_data.rs
+++ b/src/libcore/unicode/unicode_data.rs
@@ -1,128 +1,130 @@
 ///! This file is generated by src/tools/unicode-table-generator; do not edit manually!
 use super::range_search;
 
-pub const UNICODE_VERSION: (u32, u32, u32) = (12, 1, 0);
+pub const UNICODE_VERSION: (u32, u32, u32) = (13, 0, 0);
 
 #[rustfmt::skip]
 pub mod alphabetic {
-    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (190, 37);
-    static BITSET_CHUNKS_MAP: [u8; 187] = [
-        6, 32, 10, 18, 19, 23, 21, 12, 7, 5, 0, 20, 14, 49, 49, 49, 49, 49, 49, 36, 49, 49, 49, 49,
-        49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 47, 49, 30, 8, 49, 49, 49, 49,
-        49, 49, 49, 49, 49, 49, 45, 0, 0, 0, 0, 0, 0, 0, 0, 4, 35, 17, 31, 16, 25, 24, 26, 13, 15,
-        44, 27, 0, 0, 49, 11, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 38, 1, 49, 49, 49, 49, 49, 48,
-        42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 28, 0, 0, 0, 0, 0, 29, 0, 0, 9, 0, 33, 2, 3, 0, 0,
-        0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-        49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 41, 49, 49, 49,
-        43, 22, 49, 49, 49, 49, 40, 49, 49, 49, 49, 49, 49, 46,
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (196, 44);
+    static BITSET_CHUNKS_MAP: [u8; 196] = [
+        6, 32, 10, 18, 19, 23, 21, 12, 7, 5, 0, 20, 14, 50, 50, 50, 50, 50, 50, 37, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 50, 30, 8, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 46, 0, 0, 0, 0, 0, 0, 0, 0, 4, 36, 17, 31, 16, 25, 24, 26, 13, 15,
+        45, 27, 0, 0, 50, 11, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 39, 1, 50, 50, 50, 50, 50, 48,
+        50, 34, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 28, 0, 0, 0, 0, 0, 29, 0, 0, 9, 0, 33, 2, 3, 0, 0,
+        0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 42, 50, 50, 50,
+        43, 22, 50, 50, 50, 50, 41, 50, 50, 50, 50, 50, 50, 47, 0, 0, 0, 38, 0, 50, 50, 50, 50,
     ];
-    static BITSET_INDEX_CHUNKS: [[u8; 16]; 50] = [
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 51] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 0, 0, 248, 241, 38, 40],
-        [0, 0, 0, 0, 0, 0, 0, 0, 108, 133, 110, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 190, 200, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 248, 248, 248, 248, 248, 205, 248, 23, 134, 245, 68, 237],
-        [0, 0, 179, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 103, 99, 176, 248, 248, 248, 248, 248, 248, 248, 61, 0, 151, 217, 178],
-        [0, 145, 28, 0, 168, 221, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [48, 77, 248, 165, 201, 120, 184, 137, 91, 175, 143, 83, 206, 196, 248, 56],
-        [53, 0, 0, 0, 126, 15, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0],
-        [59, 54, 127, 199, 167, 186, 157, 114, 154, 84, 160, 115, 158, 66, 155, 21],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 0, 254, 247, 39, 68],
+        [0, 0, 0, 0, 0, 0, 0, 0, 111, 135, 113, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 195, 205, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 254, 254, 254, 254, 254, 210, 254, 25, 136, 251, 71, 243],
+        [0, 0, 182, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 107, 103, 180, 254, 254, 254, 254, 254, 254, 254, 61, 0, 155, 222, 181],
+        [0, 148, 30, 0, 172, 226, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [48, 80, 254, 169, 206, 123, 189, 139, 95, 179, 145, 86, 211, 204, 254, 56],
+        [53, 0, 0, 0, 129, 17, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0],
+        [59, 54, 185, 203, 171, 191, 161, 117, 158, 87, 164, 118, 162, 67, 159, 23],
         [62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [91, 129, 164, 101, 248, 248, 248, 79, 248, 248, 248, 248, 230, 128, 135, 117],
-        [97, 0, 220, 144, 0, 0, 212, 44, 142, 240, 30, 97, 0, 0, 0, 0],
-        [116, 247, 219, 171, 188, 248, 104, 190, 0, 0, 0, 0, 0, 0, 0, 0],
-        [141, 185, 88, 0, 149, 213, 22, 0, 0, 0, 0, 89, 0, 0, 0, 0],
-        [147, 90, 35, 82, 98, 0, 153, 0, 85, 119, 29, 45, 86, 71, 18, 0],
-        [150, 32, 248, 107, 0, 81, 0, 0, 0, 0, 227, 17, 211, 105, 231, 19],
-        [162, 41, 161, 69, 163, 173, 123, 73, 106, 14, 124, 37, 1, 187, 121, 0],
-        [172, 240, 228, 170, 248, 248, 248, 248, 248, 229, 138, 235, 234, 24, 222, 125],
-        [208, 233, 248, 74, 204, 64, 140, 232, 63, 0, 0, 0, 0, 0, 0, 0],
-        [220, 97, 202, 86, 94, 78, 203, 9, 226, 80, 46, 0, 183, 11, 174, 67],
-        [231, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248],
-        [247, 248, 248, 248, 248, 248, 248, 248, 248, 209, 225, 95, 76, 75, 180, 25],
-        [248, 5, 96, 50, 72, 87, 248, 26, 132, 0, 198, 51, 159, 42, 0, 0],
-        [248, 8, 72, 72, 49, 0, 0, 0, 0, 0, 0, 0, 194, 5, 0, 89],
-        [248, 36, 248, 7, 0, 0, 139, 31, 143, 3, 93, 0, 55, 0, 0, 0],
-        [248, 62, 248, 248, 248, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [248, 118, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [248, 236, 166, 246, 136, 239, 248, 248, 248, 248, 215, 169, 182, 207, 214, 12],
-        [248, 248, 13, 130, 248, 248, 248, 248, 57, 146, 248, 65, 218, 248, 243, 177],
-        [248, 248, 191, 111, 197, 43, 0, 0, 248, 248, 248, 248, 91, 47, 0, 0],
-        [248, 248, 244, 248, 189, 223, 152, 70, 224, 210, 248, 148, 240, 242, 68, 100],
-        [248, 248, 248, 4, 248, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [248, 248, 248, 248, 35, 195, 248, 248, 248, 248, 248, 113, 0, 0, 0, 0],
-        [248, 248, 248, 248, 131, 240, 238, 109, 0, 181, 248, 122, 102, 216, 143, 27],
-        [248, 248, 248, 248, 248, 248, 86, 0, 248, 248, 248, 248, 248, 248, 248, 248],
-        [248, 248, 248, 248, 248, 248, 248, 248, 33, 0, 0, 0, 0, 0, 0, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 97, 35, 0, 60, 65, 156, 16, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 6, 0, 0, 0, 0, 0, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 192, 248, 248, 248, 248, 248],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 20, 248, 248, 248, 248],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 72, 0, 0, 0, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 81, 248, 248, 248],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 23, 0],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 193, 112],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 39],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 65],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 92],
-        [248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248],
+        [95, 131, 168, 105, 254, 254, 254, 82, 254, 254, 254, 254, 236, 130, 137, 120],
+        [101, 0, 225, 146, 151, 2, 217, 45, 144, 246, 32, 101, 0, 0, 0, 0],
+        [119, 253, 224, 175, 193, 254, 227, 195, 0, 0, 0, 0, 0, 0, 0, 0],
+        [143, 190, 91, 0, 153, 218, 24, 0, 0, 0, 0, 92, 0, 0, 66, 0],
+        [150, 94, 37, 85, 102, 0, 157, 0, 88, 122, 31, 46, 89, 74, 20, 0],
+        [154, 34, 254, 110, 0, 84, 0, 0, 0, 0, 233, 19, 216, 108, 237, 21],
+        [166, 42, 165, 72, 167, 177, 126, 76, 109, 16, 127, 38, 1, 192, 124, 0],
+        [176, 246, 234, 174, 254, 254, 254, 254, 254, 235, 140, 241, 240, 26, 228, 128],
+        [213, 239, 254, 77, 209, 64, 142, 238, 63, 0, 0, 0, 0, 0, 0, 0],
+        [225, 101, 207, 89, 98, 81, 208, 10, 232, 83, 147, 1, 188, 13, 178, 70],
+        [237, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254],
+        [253, 254, 254, 254, 254, 254, 254, 254, 254, 214, 231, 99, 79, 78, 183, 27],
+        [254, 6, 100, 50, 75, 90, 254, 28, 134, 0, 202, 51, 163, 43, 0, 0],
+        [254, 9, 75, 75, 49, 0, 0, 0, 0, 0, 69, 0, 199, 6, 195, 93],
+        [254, 41, 254, 8, 0, 0, 141, 33, 145, 4, 97, 0, 55, 0, 0, 0],
+        [254, 62, 254, 254, 254, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [254, 121, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [254, 242, 170, 252, 138, 245, 254, 254, 254, 254, 220, 173, 186, 212, 219, 14],
+        [254, 254, 15, 132, 254, 254, 254, 254, 57, 149, 254, 65, 223, 254, 249, 187],
+        [254, 254, 196, 114, 201, 44, 0, 0, 254, 254, 254, 254, 95, 47, 0, 0],
+        [254, 254, 250, 254, 194, 229, 156, 73, 230, 215, 254, 152, 246, 248, 71, 104],
+        [254, 254, 254, 5, 254, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [254, 254, 254, 22, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [254, 254, 254, 254, 37, 200, 254, 254, 254, 254, 254, 116, 0, 0, 0, 0],
+        [254, 254, 254, 254, 133, 246, 244, 112, 0, 184, 254, 125, 106, 221, 145, 29],
+        [254, 254, 254, 254, 254, 254, 254, 0, 254, 254, 254, 254, 254, 254, 254, 254],
+        [254, 254, 254, 254, 254, 254, 254, 254, 35, 0, 0, 0, 0, 0, 0, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 101, 37, 0, 60, 65, 160, 18, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 7, 0, 0, 0, 0, 0, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 197, 254, 254, 254, 254, 254],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 35, 254, 254, 254, 254],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 84, 254, 254, 254],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 11, 0, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 25, 0],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 198, 115],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 40],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 96],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 125],
+        [254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254],
     ];
-    static BITSET: [u64; 249] = [
-        0, 1, 15, 17, 31, 63, 127, 179, 511, 1023, 2191, 4079, 4087, 8191, 8319, 16384, 65535,
-        131071, 262143, 4128527, 8388607, 8461767, 24870911, 67108863, 134217727, 276824575,
-        335544350, 486341884, 536805376, 536870911, 553648127, 1056964608, 1073692671, 1073741823,
-        1140785663, 2147483647, 2147485627, 4026540127, 4294934783, 8589934591, 47244640256,
-        64548249055, 68191066527, 68719476735, 115913785343, 137438953215, 549755813888,
-        1095220854783, 1099511627711, 1099511627775, 2199023190016, 2199023255551, 4398046511103,
-        8641373536127, 8791831609343, 8795690369023, 8796093022207, 13198434443263, 17592186044415,
-        35184321757183, 70368744112128, 88094074470339, 140737488355327, 140737488355328,
-        141836999983103, 281474976710655, 563017343310239, 1125625028935679, 1125899906842623,
-        1688915364814303, 2119858418286774, 2251795522912255, 2251799813685247, 3377704004976767,
-        3509778554814463, 3905461007941631, 4503595333443583, 4503599627370495, 8796093022142464,
-        9006649498927104, 9007192812290047, 9007199254740991, 15762594400829440, 17169970223906821,
-        17732925109967239, 18014398491652207, 18014398509481983, 20266198323101808,
-        36027697507139583, 36028792723996672, 36028792728190975, 36028797018963967,
-        72057594037927935, 90071992547409919, 143851303137705983, 144053615424700415,
-        144115188075855868, 144115188075855871, 288230371860938751, 297241973452963840,
-        301749971126844416, 319718190147960832, 576460743713488896, 576460743847706622,
-        576460748008488959, 576460752303359999, 576460752303423486, 576460752303423487,
-        790380184120328175, 1152640029630136575, 1152917029519358975, 1152921504591118335,
-        1152921504606845055, 1152921504606846975, 1153765996922689951, 2161727885562420159,
-        2251241253188403424, 2295745090394464220, 2305570330330005503, 2305843004918726656,
-        2305843004919250943, 2305843009196916483, 2305843009213693951, 3457638613854978028,
-        4323455298678290390, 4557642822898941951, 4575692405780512767, 4602678814877679616,
-        4611686017001275199, 4611686018360336384, 4611686018427322368, 4611686018427387903,
-        4656722014700830719, 6843210385291930244, 6881498031078244479, 6908521828386340863,
-        8935141660164089791, 8935423131384840192, 9168765891372858879, 9169328841326329855,
-        9187201948305063935, 9187343239835811327, 9216616637413720063, 9223372036854775807,
-        9223372041149743103, 9223934986808197120, 10371930679322607615, 10502394331027995967,
-        11241233151490523135, 13006395723845991295, 13258596753222922239, 13609596598936928288,
-        13834776580305453567, 13907115649320091647, 14082190885810440174, 14123225865944680428,
-        16212958624174047247, 16412803692974677999, 16424062692043104238, 16424062692043104239,
-        16424062692043243502, 16424625641996804079, 16429129241624174575, 16717361816799141871,
-        16717361816799216127, 16788293510930366511, 17005555242810474495, 17293822569102704639,
-        17581979622616071300, 17870283321271910397, 17870283321406070975, 17870283321406128127,
-        17978369712463020031, 18158513764145585631, 18158781978395017215, 18194542490281852927,
-        18410715276682199039, 18410715276690587772, 18428729675200069631, 18428729675200069632,
-        18433233274827440127, 18437455399478099968, 18437736874452713471, 18442240474082181119,
+    static BITSET: [u64; 255] = [
+        0, 1, 7, 15, 17, 31, 63, 127, 179, 511, 1023, 2047, 2191, 4079, 4087, 8191, 8319, 16384,
+        65535, 131071, 262143, 4128527, 4194303, 8461767, 24870911, 67108863, 134217727, 276824575,
+        335593502, 486341884, 536805376, 536870911, 553648127, 1056964608, 1073692671, 1073741823,
+        1140785663, 2147483647, 4026540127, 4294934783, 8589934591, 15032387515, 64548249055,
+        68191066527, 68719476735, 115913785343, 137438953215, 1095220854783, 1099511627711,
+        1099511627775, 2199023190016, 2199023255551, 4398046511103, 8641373536127, 8791831609343,
+        8795690369023, 8796093022207, 13198434443263, 17592186044415, 35184321757183,
+        70368744112128, 88094074470339, 140737488355327, 140737488355328, 141836999983103,
+        281474976710655, 281474976710656, 563017343310239, 844472174772224, 875211255709695,
+        1125625028935679, 1125899906842623, 1688915364814303, 2119858418286774, 2251795522912255,
+        2251799813685247, 3377704004976767, 3509778554814463, 3905461007941631, 4503595333443583,
+        4503599627370495, 8796093022142464, 9006649498927104, 9007192812290047, 9007199254740991,
+        15762594400829440, 17169970223906821, 17732925109967239, 18014398491652207,
+        18014398509481983, 20266198323101936, 36027697507139583, 36028792723996672,
+        36028792723996703, 36028792728190975, 36028797018963967, 72057594037927935,
+        90071992547409919, 143851303137705983, 144053615424700415, 144115188075855868,
+        144115188075855871, 288230371860938751, 297241973452963840, 301749971126844416,
+        319718190147960832, 576460743713488896, 576460743847706622, 576460752303359999,
+        576460752303423486, 576460752303423487, 790380184120328175, 1152640029630136575,
+        1152917029519358975, 1152921504591118335, 1152921504606845055, 1152921504606846975,
+        1153765996922689951, 2161727885562420159, 2251241253188403424, 2295745090394464220,
+        2305570330330005503, 2305843004918726656, 2305843004919250943, 2305843009196916483,
+        2305843009213693951, 3457638613854978030, 4323455298678290390, 4557642822898941951,
+        4575692405780512767, 4611686017001275199, 4611686018360336384, 4611686018427322368,
+        4611686018427387903, 4656722014700830719, 6843210385291930244, 6881498031078244479,
+        6908521828386340863, 8935141660164089791, 8935423131384840192, 9168765891372858879,
+        9169328841326329855, 9187201948305063935, 9187343239835811327, 9216616637413720063,
+        9223372036854775807, 9223372041149743103, 9223372586610589696, 9223934986808197120,
+        10371930679322607615, 10502394331027995967, 11078855083321979519, 11241233151490523135,
+        13006395723845991295, 13258596753222922239, 13609596598936928288, 13834776580305453567,
+        13907115649320091647, 14082190885810440174, 14123225865944680428, 16212958624174047247,
+        16412803692974677999, 16424062692043104238, 16424062692043104239, 16424062692043243502,
+        16424625641996804079, 16429129241624174575, 16717361816799141887, 16717361816799216127,
+        16788293510930366511, 17005555242810474495, 17293822569102704639, 17581979622616071300,
+        17870283321271910397, 17870283321406070975, 17870283321406128127, 17978369712463020031,
+        18158513764145585631, 18158781978395017215, 18194542490281852927, 18410715276682199039,
+        18428729675200069631, 18428729675200069632, 18433233274827440127, 18437455399478099968,
+        18437736870159843328, 18437736874452713471, 18437736874454812668, 18442240474082181119,
         18444492273895866367, 18445618173802708993, 18446181192473632767, 18446216308128218879,
         18446462598732840928, 18446462598732840959, 18446462598732840960, 18446462599806582783,
         18446462615912710143, 18446462667452317695, 18446463149025525759, 18446463629525450752,
-        18446463698110251007, 18446463698244468735, 18446464796682337663, 18446466966713532416,
+        18446463698244468735, 18446464796682337663, 18446466966713532671, 18446466996645134335,
         18446466996779287551, 18446471394825862144, 18446471394825863167, 18446480190918885375,
         18446498607738650623, 18446532967477018623, 18446602782178705022, 18446603336221163519,
         18446603336221196287, 18446638520593285119, 18446673709243564031, 18446708893632430079,
         18446740770879700992, 18446741595513422027, 18446741874686295551, 18446743249075830783,
         18446743798965862398, 18446744056529672000, 18446744060816261120, 18446744068886102015,
-        18446744069414584320, 18446744069414601696, 18446744069414649855, 18446744069456527359,
-        18446744069548736512, 18446744069548802046, 18446744069683019775, 18446744069951455231,
-        18446744070421282815, 18446744070446333439, 18446744070475743231, 18446744070488326143,
-        18446744071553646463, 18446744071562067967, 18446744073696837631, 18446744073701162813,
-        18446744073707454463, 18446744073709027328, 18446744073709355007, 18446744073709419615,
-        18446744073709486080, 18446744073709520895, 18446744073709543424, 18446744073709550079,
-        18446744073709550595, 18446744073709551579, 18446744073709551599, 18446744073709551614,
-        18446744073709551615,
+        18446744069414584320, 18446744069414601696, 18446744069414617087, 18446744069414649855,
+        18446744069456527359, 18446744069548736512, 18446744069548802046, 18446744069683019775,
+        18446744069951455231, 18446744070421282815, 18446744070446333439, 18446744070475743231,
+        18446744070488326143, 18446744071553646463, 18446744071562067967, 18446744073696837631,
+        18446744073701162813, 18446744073707454463, 18446744073709027328, 18446744073709355007,
+        18446744073709419615, 18446744073709486080, 18446744073709520895, 18446744073709543424,
+        18446744073709550079, 18446744073709550595, 18446744073709551579, 18446744073709551599,
+        18446744073709551614, 18446744073709551615,
     ];
 
     pub fn lookup(c: char) -> bool {
@@ -141,82 +143,83 @@ pub mod case_ignorable {
     static BITSET_LAST_CHUNK_MAP: (u16, u8) = (896, 33);
     static BITSET_CHUNKS_MAP: [u8; 125] = [
         25, 14, 21, 30, 28, 4, 17, 23, 22, 0, 0, 16, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 13, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 13, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 3, 6, 9, 0, 7, 11, 32, 31, 26, 29, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0,
-        10, 0, 8, 0, 20, 0, 12, 0, 1,
+        10, 0, 8, 0, 19, 0, 12, 0, 1,
     ];
     static BITSET_INDEX_CHUNKS: [[u8; 16]; 34] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 47, 52],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 171, 2],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 88, 134, 38],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 102, 6, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 76, 26, 0, 146, 136, 79, 43, 117],
-        [0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 58, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 165, 97, 75, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 48, 0, 114, 0, 0],
-        [0, 0, 0, 0, 0, 170, 68, 0, 0, 7, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0],
-        [0, 0, 0, 28, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 133, 0, 0, 0, 0, 15, 160, 45, 84, 51, 78, 12, 109],
-        [0, 0, 11, 0, 0, 30, 161, 90, 35, 80, 0, 69, 173, 13, 81, 129],
-        [0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 131, 0, 85, 0, 148, 0, 175, 73, 0, 0, 0, 0, 0, 0, 0],
-        [20, 4, 62, 0, 118, 0, 0, 0, 32, 154, 145, 0, 124, 89, 67, 86],
-        [25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [59, 0, 0, 150, 70, 24, 132, 60, 100, 122, 163, 99, 0, 46, 0, 66],
-        [63, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0],
-        [71, 33, 0, 178, 123, 83, 120, 137, 121, 98, 121, 167, 153, 55, 3, 18],
-        [72, 149, 36, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [104, 133, 0, 110, 174, 105, 177, 166, 0, 0, 0, 0, 0, 0, 155, 139],
-        [107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [111, 50, 106, 0, 0, 0, 0, 0, 0, 0, 172, 179, 179, 112, 9, 0],
-        [113, 0, 0, 0, 0, 0, 0, 49, 142, 34, 31, 0, 0, 0, 0, 0],
-        [116, 0, 42, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [140, 93, 37, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0],
-        [159, 0, 101, 0, 158, 10, 29, 0, 0, 0, 0, 91, 0, 0, 0, 0],
-        [162, 56, 153, 54, 125, 53, 0, 27, 115, 21, 126, 19, 108, 144, 127, 8],
-        [168, 41, 151, 5, 0, 0, 157, 39, 156, 1, 103, 0, 65, 0, 0, 0],
-        [169, 147, 130, 17, 96, 87, 143, 16, 138, 0, 0, 64, 125, 95, 0, 0],
-        [176, 179, 0, 0, 179, 179, 179, 77, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 47, 57],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 173, 3],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 90, 136, 38],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 104, 7, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 78, 27, 0, 148, 138, 81, 44, 119],
+        [0, 0, 0, 0, 0, 0, 0, 0, 154, 0, 0, 58, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 167, 99, 77, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 130, 0, 0, 0, 48, 0, 116, 0, 0],
+        [0, 0, 0, 0, 0, 172, 70, 0, 0, 8, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 67, 0, 0, 24, 0, 0],
+        [0, 0, 0, 29, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 135, 0, 0, 0, 0, 16, 162, 46, 86, 51, 80, 13, 111],
+        [0, 0, 12, 0, 0, 43, 163, 92, 35, 82, 0, 71, 175, 14, 83, 131],
+        [0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 133, 0, 87, 0, 150, 0, 178, 75, 0, 0, 0, 0, 0, 0, 0],
+        [20, 5, 61, 0, 120, 0, 0, 0, 32, 156, 176, 1, 126, 91, 69, 88],
+        [26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [62, 0, 0, 0, 137, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0],
+        [66, 0, 0, 152, 72, 25, 134, 59, 102, 124, 165, 101, 0, 64, 0, 68],
+        [73, 33, 0, 181, 125, 85, 122, 139, 123, 100, 123, 169, 155, 54, 4, 18],
+        [74, 151, 36, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [106, 135, 0, 112, 177, 107, 180, 168, 0, 0, 0, 0, 0, 0, 157, 142],
+        [109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [113, 50, 108, 0, 0, 0, 0, 0, 0, 0, 174, 182, 182, 114, 10, 0],
+        [115, 0, 0, 0, 141, 5, 0, 49, 145, 34, 31, 0, 0, 0, 0, 0],
+        [118, 0, 42, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [143, 95, 37, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0],
+        [161, 0, 103, 0, 160, 11, 30, 0, 0, 0, 0, 93, 0, 0, 0, 0],
+        [164, 55, 155, 53, 127, 52, 2, 28, 117, 21, 128, 19, 110, 147, 129, 9],
+        [170, 41, 153, 6, 0, 0, 159, 39, 158, 1, 105, 0, 65, 0, 0, 0],
+        [171, 149, 132, 17, 98, 89, 146, 23, 140, 0, 0, 63, 127, 97, 0, 0],
+        [179, 182, 0, 0, 182, 182, 182, 79, 0, 0, 0, 0, 0, 0, 0, 0],
     ];
-    static BITSET: [u64; 180] = [
-        0, 1, 3, 4, 8, 13, 15, 28, 64, 176, 191, 1016, 1792, 2047, 4080, 4096, 7680, 8192, 8193,
-        16192, 30720, 32704, 32768, 131008, 262016, 2097152, 2359296, 6030336, 8323072, 10682368,
-        33554432, 58719232, 159383552, 234881024, 243138688, 402587711, 536805376, 536879204,
-        546307648, 805306369, 1073741824, 1073741916, 2113929216, 3221225472, 3758096384,
-        4026531840, 4160749568, 4294934528, 4294967296, 4512022528, 5368709120, 17179869183,
-        47244640256, 51539615774, 51539619904, 51543810078, 51545914817, 66035122176, 412316860416,
-        412316862532, 412316893184, 1030792151040, 2199023255648, 8641373536127, 8763880767488,
-        17303886364672, 36421322670080, 65128884076547, 65970697670631, 68168642985984,
-        70093866270720, 70368739983360, 136957967529984, 140737488355328, 263882790666240,
-        281470547525648, 281470682333183, 281474976710655, 281474976710656, 281474976710657,
-        281479271675905, 562675075514368, 562949953355776, 563001509683710, 844424930131968,
-        985162418487296, 1023920203366400, 2251799813685248, 3377699721314304, 4494803534348292,
-        4503599627370678, 6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336,
-        8760633772212225, 8989057312882695, 9042383626829823, 9851624185018758, 24822575045541890,
-        28848986089586688, 30958948903026688, 35747322042253312, 53805701016846336,
-        58529202969772032, 72066390130950143, 112767012056334336, 143833713099145216,
-        189151184399892480, 216172782113783808, 220713756545974272, 288301294651703296,
-        302022650010533887, 504262420777140224, 558446353793941504, 572520102629474304,
-        593978171557150752, 1008806350890729472, 1009933895770046464, 1152921504606846976,
-        1152921504606846978, 1152921504606846982, 1153202979583561736, 1441151880758558727,
-        1715871458028158991, 1729382256910270467, 2301902359539744768, 2305843009196908767,
-        2305843009213693952, 2612078987781865472, 2771965570646540291, 3458764513820540928,
-        3731232291276455943, 4539628424389459968, 4589168020290535424, 4611404543450677248,
-        4611686018494513280, 4611686069967003678, 4671217976001691648, 6917775322003857411,
-        7421334051581067264, 8070450532247928832, 8788774672813524990, 9205357638345293827,
-        9222809086901354496, 9223091111633879040, 9223372036854775808, 9223372036854775935,
-        9223512774343131136, 9224216320050987008, 9224497932466651184, 9653465801268658176,
-        9727775195120332910, 10376293541461622786, 11526998316797657088, 11529215046068469760,
-        12103423998558208000, 12699025049277956096, 13005832773892571136, 13798747783286489088,
-        13832665517980123136, 13835058055282032640, 13835058055282163729, 13951307220663664640,
-        17870283321406128128, 17906312118425092095, 18158513697557839871, 18158513749097456062,
-        18374686479671623680, 18374686479671623682, 18444496122186563584, 18445618173802708992,
-        18446462598732840960, 18446462598733004800, 18446726481523507200, 18446744069414584320,
-        18446744069414584322, 18446744073575333888, 18446744073709027328, 18446744073709551615,
+    static BITSET: [u64; 183] = [
+        0, 1, 2, 3, 4, 8, 13, 15, 28, 64, 176, 191, 1016, 1792, 2047, 4080, 4096, 8192, 8193,
+        16192, 30720, 32704, 32768, 40448, 131008, 262016, 2097152, 2359296, 6030336, 8323072,
+        10682368, 58719232, 159383552, 234881024, 243138688, 402587711, 536805376, 536879204,
+        546307648, 805306369, 1073741824, 1073741916, 2113929216, 2181038080, 3221225472,
+        3758096384, 4026531840, 4294934528, 4294967296, 4512022528, 5368709120, 17179869183,
+        51539615774, 51539619904, 51545907230, 51545914817, 66035122176, 115964116992, 412316860416,
+        412316893184, 1030792151040, 2199023255648, 8641373536127, 8763880767488, 15397323538432,
+        17303886364672, 18004502906948, 26388279066624, 36421322670080, 65128884076547,
+        65970697670631, 68168642985984, 70093866270720, 70368739983360, 136957967529984,
+        140737488355328, 263882790666240, 281470547525648, 281470682333183, 281474976710655,
+        281474976710656, 281474976710657, 281479271675905, 562675075514368, 562949953355776,
+        563001509683710, 844424930131968, 985162418487296, 1023920203366400, 2251799813685248,
+        3377699721314304, 4494803534348292, 4503599627370678, 6755399441055744, 7881299349733376,
+        8444256867844096, 8725724278030336, 8760633772212225, 8989057312882695, 9042383626829823,
+        9851624185018758, 24822575045541890, 28848986089586688, 30958948903026688,
+        35747322042253312, 53805701016846336, 58529202969772032, 72066390130950143,
+        112767012056334336, 143833713099145216, 189151184399892480, 216172782113783808,
+        220713756545974272, 288301294651703296, 302022650010533887, 504262420777140224,
+        558446353793941504, 572520102629474304, 593978171557150752, 1008806350890729472,
+        1009933895770046464, 1152921504606846976, 1152921504606846978, 1152921504606846982,
+        1153202979583561736, 1441151880758558727, 1715871458028158991, 1729382256910270467,
+        2301902359539744768, 2305843009196908767, 2305843009213693952, 2612078987781865472,
+        2771965570646540291, 3458764513820540928, 3731232291276455943, 4539628424389459968,
+        4589168020290535424, 4611404543450677248, 4611686018494513280, 4611686069967003678,
+        4671217976001691648, 6341068275337658368, 6917775322003857411, 7421334051581067264,
+        8070450532247928832, 8788774672813524990, 9205357638345293827, 9222809086901354496,
+        9223372036854775808, 9223372036854775935, 9223512774343131136, 9224216320050987008,
+        9224497932466651184, 9653465801268658176, 9727775195120332910, 10376293541461622786,
+        11526998316797657088, 11529215046068469760, 12103423998558208000, 12699025049277956096,
+        13005832773892571136, 13798747783286489088, 13832665517980123136, 13835058055282032640,
+        13835058055282163729, 13951307220663664640, 17870283321406128128, 17906312118425092095,
+        18158513697557839871, 18158513749097456062, 18374686479671623680, 18374686479671623682,
+        18444496122186563584, 18445618173802708992, 18446462598732840960, 18446462598733004800,
+        18446463148488654848, 18446726481523507200, 18446744069414584320, 18446744069414584322,
+        18446744073575333888, 18446744073709027328, 18446744073709551615,
     ];
 
     pub fn lookup(c: char) -> bool {
@@ -264,13 +267,13 @@ pub mod cased {
     static BITSET: [u64; 63] = [
         0, 15, 24, 511, 1023, 4087, 65535, 16253055, 134217726, 536805376, 1073741823, 4294967295,
         133143986179, 4398046511103, 36009005809663, 70368744177663, 2251799813685247,
-        3509778554814463, 144115188074807295, 297241973452963840, 504403158265495676,
+        3509778554814463, 144115188074807295, 297241973452963840, 531424756029720572,
         576460743713488896, 576460743847706622, 1152921504591118335, 2295745090394464220,
         4557642822898941951, 4611686017001275199, 6908521828386340863, 8935141660164089791,
         9223934986808197120, 13605092999309557792, 16717361816799216127, 16717361816799223999,
         17005555242810474495, 17446871633794956420, 17870283321271910397, 17870283321406128127,
         18410715276682199039, 18428729675200069631, 18428729675200069632, 18437736874452713471,
-        18446462598732840959, 18446462598732840960, 18446463698110251007, 18446466996779287551,
+        18446462598732840959, 18446462598732840960, 18446464797621878783, 18446466996779287551,
         18446603336221163519, 18446603336221196287, 18446741874686295551, 18446743249075830783,
         18446744056529672000, 18446744056529682432, 18446744069414584320, 18446744069414601696,
         18446744069422972927, 18446744070475743231, 18446744071562067967, 18446744073707454463,
@@ -317,72 +320,72 @@ pub mod grapheme_extend {
     static BITSET_LAST_CHUNK_MAP: (u16, u8) = (896, 30);
     static BITSET_CHUNKS_MAP: [u8; 123] = [
         4, 15, 21, 27, 25, 3, 18, 23, 17, 0, 0, 14, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 2, 7, 10, 0, 8, 12, 29, 28, 24, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0,
-        11, 0, 9, 0, 20, 0, 13,
+        11, 0, 9, 0, 19, 0, 13,
     ];
     static BITSET_INDEX_CHUNKS: [[u8; 16]; 31] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 18, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 70, 102, 29],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 62, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 83, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 35, 66, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 35, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 45, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 130, 78, 60, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 37, 0, 90, 0, 0],
-        [0, 0, 0, 0, 0, 129, 54, 0, 0, 3, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0],
-        [0, 0, 0, 19, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 67, 0, 114, 0, 137, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 7, 0, 0, 0, 125, 5, 24, 63, 0, 55, 135, 9, 64, 100],
-        [0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [10, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [12, 0, 48, 0, 92, 0, 0, 0, 25, 119, 113, 0, 96, 71, 53, 68],
-        [46, 0, 0, 116, 57, 17, 101, 44, 81, 94, 127, 80, 0, 0, 0, 52],
-        [49, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0],
-        [56, 26, 0, 136, 95, 43, 107, 105, 93, 79, 93, 132, 128, 42, 104, 20],
-        [59, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [85, 0, 0, 87, 0, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0],
-        [89, 0, 0, 0, 0, 0, 0, 38, 110, 27, 22, 0, 0, 0, 0, 0],
-        [109, 74, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0],
-        [124, 0, 82, 0, 123, 6, 21, 0, 0, 0, 0, 72, 0, 0, 0, 0],
-        [126, 40, 118, 39, 108, 41, 0, 34, 91, 14, 97, 13, 86, 112, 98, 4],
-        [133, 32, 120, 2, 0, 0, 122, 30, 121, 1, 84, 0, 51, 0, 0, 0],
-        [134, 115, 88, 0, 77, 69, 111, 11, 106, 0, 0, 50, 108, 76, 0, 0],
-        [137, 138, 0, 0, 138, 138, 138, 62, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 20, 46],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 74, 106, 31],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 66, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 87, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 37, 70, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 37, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 0, 48, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 134, 82, 64, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 39, 0, 94, 0, 0],
+        [0, 0, 0, 0, 0, 133, 58, 0, 0, 5, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 55, 0, 0, 18, 0, 0],
+        [0, 0, 0, 21, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 71, 0, 118, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 9, 0, 0, 0, 129, 7, 26, 67, 0, 59, 140, 11, 68, 104],
+        [0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [12, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [13, 0, 50, 0, 96, 0, 0, 0, 27, 123, 139, 1, 100, 75, 57, 72],
+        [51, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0],
+        [54, 0, 0, 120, 61, 19, 105, 47, 85, 98, 131, 84, 0, 0, 0, 56],
+        [60, 28, 0, 141, 99, 45, 111, 109, 97, 83, 97, 136, 132, 44, 108, 22],
+        [63, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [89, 0, 0, 91, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0],
+        [93, 0, 0, 0, 113, 3, 0, 40, 115, 29, 24, 0, 0, 0, 0, 0],
+        [114, 78, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0],
+        [128, 0, 86, 0, 127, 8, 23, 0, 0, 0, 0, 76, 0, 0, 0, 0],
+        [130, 42, 122, 41, 112, 43, 2, 36, 95, 15, 101, 14, 90, 117, 102, 6],
+        [137, 34, 124, 4, 0, 0, 126, 32, 125, 1, 88, 0, 53, 0, 0, 0],
+        [138, 119, 92, 0, 81, 73, 116, 17, 110, 0, 0, 52, 112, 80, 0, 0],
+        [142, 143, 0, 0, 143, 143, 143, 66, 0, 0, 0, 0, 0, 0, 0, 0],
     ];
-    static BITSET: [u64; 139] = [
-        0, 1, 13, 28, 64, 182, 191, 1016, 2032, 2047, 4096, 7680, 14336, 16128, 32640, 32768,
-        131008, 262016, 491520, 8323072, 8396801, 10682368, 58719232, 100663296, 134152192,
+    static BITSET: [u64; 144] = [
+        0, 1, 2, 8, 13, 28, 64, 182, 191, 1016, 2032, 2047, 4096, 14336, 16128, 32640, 32768,
+        40448, 131008, 262016, 491520, 8323072, 8396801, 10682368, 58719232, 100663296, 134152192,
         159383552, 234881024, 243138688, 536879204, 537919040, 805306369, 1073741824, 1073741916,
         1610612736, 2153546752, 3221225472, 3758096384, 4294967296, 4512022528, 51545911364,
-        51545914817, 51548004382, 51552198686, 51556262398, 137438953472, 412316860416,
-        412316862532, 1030792151040, 2199023255648, 8641373536127, 8763880767488, 17303886364672,
-        36421322670080, 65128884076547, 65970697670631, 67755789254656, 69200441769984,
-        70093866270720, 263882790666240, 277076930199552, 281470547525648, 281470681808895,
-        281474976710655, 281479271675904, 562675075514368, 562949953355776, 844424930131968,
-        985162418487296, 1023920203366400, 2251799813685248, 3377699721314304, 4494803534348292,
-        6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336, 8760633780600833,
-        8989057312882695, 9042383626829823, 9851624185018758, 18067175067615234, 28848986089586688,
-        30958948903026688, 35747322042253312, 53805701016846336, 58529202969772032,
-        189151184399892480, 220713756545974272, 466122561432846339, 504262420777140224,
-        558446353793941504, 572520102629474304, 1009933895770046464, 1152921504606846982,
-        1152921504606851080, 1441151880758558727, 1724878657282899983, 2301902359539744768,
-        2305843009196908767, 2305843009213693952, 2310337812748042240, 3731232291276455943,
-        4589168020290535424, 4609293481125347328, 4611686018427387908, 4611686069975392286,
-        4671217976001691648, 5764607523034234882, 6341068275337658371, 7421334051581067264,
-        8788774672813524990, 9205357638345293827, 9222809086901354496, 9223090561878065152,
-        9223372036854775808, 9223372036854775935, 9224497932466651184, 9727775195120332910,
-        10376293541461622786, 11526998316797657088, 11959590285459062784, 12103423998558208000,
-        12699165786766311424, 13005832773892571136, 13798747783286489088, 13835058055282032640,
-        13835058055282163729, 13951307220663664640, 14987979559889010690, 17872468738205286400,
-        17906312118425092095, 18158513697557839871, 18158513749097456062, 18374686479671623680,
-        18374686479671623682, 18446462598732972032, 18446744056529158144, 18446744069414584320,
-        18446744073709551615,
+        51545914817, 51548004382, 51554295838, 51556262398, 68719476736, 137438953472, 412316860416,
+        1030792151040, 2199023255648, 8641373536127, 8763880767488, 17303886364672, 18004502906948,
+        26388279066624, 36421322670080, 65128884076547, 65970697670631, 67755789254656,
+        69200441769984, 70093866270720, 263882790666240, 277076930199552, 281470547525648,
+        281470681808895, 281474976710655, 281479271675904, 562675075514368, 562949953355776,
+        844424930131968, 985162418487296, 1023920203366400, 2251799813685248, 3377699721314304,
+        4494803534348292, 6755399441055744, 7881299349733376, 8444256867844096, 8725724278030336,
+        8760633780600833, 8989057312882695, 9042383626829823, 9851624185018758, 18067175067615234,
+        28848986089586688, 30958948903026688, 35747322042253312, 53805701016846336,
+        58529202969772032, 189151184399892480, 220713756545974272, 466122561432846339,
+        504262420777140224, 558446353793941504, 572520102629474304, 1009933895770046464,
+        1152921504606846982, 1152921504606851080, 1441151880758558727, 1724878657282899983,
+        2301902359539744768, 2305843009196908767, 2305843009213693952, 2310337812748042240,
+        3731232291276455943, 4589168020290535424, 4609293481125347328, 4611686018427387908,
+        4611686069975392286, 4671217976001691648, 5764607523034234882, 6341068275337658371,
+        6341349750314369024, 7421334051581067264, 8788774672813524990, 9205357638345293827,
+        9222809086901354496, 9223372036854775808, 9223372036854775935, 9224497932466651184,
+        9727775195120332910, 10376293541461622786, 11526998316797657088, 11959590285459062784,
+        12103423998558208000, 12699165786766311424, 13005832773892571136, 13798747783286489088,
+        13835058055282032640, 13835058055282163729, 13951307220663664640, 14987979559889010690,
+        17872468738205286400, 17906312118425092095, 18158513697557839871, 18158513749097456062,
+        18374686479671623680, 18374686479671623682, 18446462598732840960, 18446462598732972032,
+        18446744056529158144, 18446744069414584320, 18446744073709551615,
     ];
 
     pub fn lookup(c: char) -> bool {
@@ -430,7 +433,7 @@ pub mod lowercase {
         133143986179, 274877905920, 1099509514240, 4398046445568, 17592185782272, 36009005809663,
         46912496118442, 187649984473770, 281474972516352, 2251799813685247, 2339875276368554,
         4503599560261632, 61925590106570972, 71777214282006783, 72057592964186127,
-        144115188074807295, 297241973452963840, 504403158265495560, 576460743713488896,
+        144115188074807295, 297241973452963840, 522417556774978824, 576460743713488896,
         1152921487426978047, 1152921504590069760, 1814856824841797631, 3607524039012697088,
         4362299189061746720, 4539628424389459968, 4601013482110844927, 4611405638684049471,
         4674456033467236607, 6172933889249159850, 9223934986808197120, 10663022717737544362,
@@ -439,7 +442,7 @@ pub mod lowercase {
         12298110845996498944, 15324248332066007893, 16596095761559859497, 16717361816799215616,
         16987577794709946364, 17293822586148356092, 18158513701852807104, 18410715274543104000,
         18428729675466407935, 18446462598732840960, 18446462598732858304, 18446462598737002495,
-        18446463698110251007, 18446673704966422527, 18446726481523572736, 18446739675663105535,
+        18446464797621878783, 18446673704966422527, 18446726481523572736, 18446739675663105535,
         18446739675663106031, 18446742974197923840, 18446744056529682432, 18446744069414584320,
         18446744073709529733, 18446744073709551615,
     ];
@@ -457,56 +460,57 @@ pub mod lowercase {
 
 #[rustfmt::skip]
 pub mod n {
-    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (124, 11);
-    static BITSET_CHUNKS_MAP: [u8; 124] = [
-        30, 7, 10, 24, 18, 3, 28, 20, 23, 27, 0, 15, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 2, 12, 17, 25, 16, 22, 19, 14, 21, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        4, 1, 0, 0, 9, 0, 13, 26,
+    static BITSET_LAST_CHUNK_MAP: (u16, u8) = (127, 0);
+    static BITSET_CHUNKS_MAP: [u8; 127] = [
+        31, 8, 11, 25, 19, 4, 29, 21, 24, 28, 0, 16, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 3, 13, 18, 26, 17, 23, 20, 15, 22, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        5, 2, 0, 0, 10, 0, 14, 27, 12, 0, 1,
     ];
-    static BITSET_INDEX_CHUNKS: [[u8; 16]; 33] = [
+    static BITSET_INDEX_CHUNKS: [[u8; 16]; 34] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 48],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 42, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 21, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 46, 0, 0, 0, 2],
-        [0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 30, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 30, 0, 44, 0, 30, 0, 30, 0, 40, 0, 33],
-        [0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 36, 43, 4, 0, 0, 0, 0, 51, 22, 3, 0, 12],
-        [0, 0, 0, 6, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 61, 46, 0, 0, 0, 0, 59, 0, 0, 23, 9, 0, 0],
-        [0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 2, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0],
-        [0, 14, 0, 14, 0, 0, 0, 0, 0, 14, 0, 2, 50, 0, 0, 0],
-        [0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 25, 0, 0, 0, 14, 24, 0, 0, 0, 0, 0, 0, 0, 0, 10],
-        [0, 31, 0, 46, 64, 0, 0, 38, 0, 0, 0, 46, 0, 0, 0, 0],
-        [0, 45, 2, 0, 0, 70, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 58, 0, 30, 0, 41, 0, 30, 0, 14, 0, 14, 35, 0, 0, 0],
-        [0, 62, 29, 60, 17, 0, 54, 69, 0, 56, 19, 27, 0, 63, 28, 0],
-        [0, 65, 37, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 68, 18, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 8, 0],
-        [14, 0, 0, 0, 0, 7, 0, 16, 0, 0, 15, 0, 0, 14, 46, 0],
-        [39, 0, 0, 14, 2, 0, 0, 47, 0, 14, 0, 0, 0, 0, 0, 46],
-        [46, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [49, 0, 0, 0, 0, 0, 11, 0, 24, 20, 66, 0, 0, 0, 0, 0],
-        [72, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 49],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 43, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 22, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 47, 0, 0, 0, 2],
+        [0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 31, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 31, 0, 45, 0, 31, 0, 31, 0, 41, 0, 34],
+        [0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 37, 44, 4, 0, 0, 0, 0, 52, 23, 3, 0, 13],
+        [0, 0, 0, 7, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 35, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 62, 47, 0, 0, 0, 0, 60, 0, 0, 24, 10, 0, 5],
+        [0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 2, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0],
+        [0, 15, 0, 15, 0, 0, 0, 0, 0, 15, 0, 2, 51, 0, 0, 0],
+        [0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 26, 0, 0, 0, 15, 25, 0, 0, 0, 0, 0, 0, 0, 0, 11],
+        [0, 32, 0, 47, 65, 0, 0, 39, 0, 0, 0, 47, 0, 0, 0, 0],
+        [0, 46, 2, 0, 0, 71, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 59, 0, 31, 0, 42, 0, 31, 0, 15, 0, 15, 36, 0, 0, 0],
+        [0, 63, 30, 61, 18, 0, 55, 70, 0, 57, 20, 28, 0, 64, 29, 0],
+        [0, 66, 38, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 69, 19, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 9, 0],
+        [15, 0, 0, 0, 0, 8, 0, 17, 0, 0, 16, 0, 0, 15, 47, 0],
+        [40, 0, 0, 15, 2, 0, 0, 48, 0, 15, 0, 0, 0, 0, 0, 47],
+        [47, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [50, 0, 0, 0, 0, 0, 12, 0, 25, 21, 67, 0, 0, 0, 0, 0],
+        [73, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     ];
-    static BITSET: [u64; 73] = [
-        0, 999, 1023, 1026, 3072, 8191, 65408, 65472, 1048575, 1966080, 2097151, 3932160, 4063232,
-        8388607, 67043328, 67044351, 134152192, 264241152, 268435455, 3758096384, 4294901504,
-        17112694784, 64424509440, 549218942976, 4393751543808, 35184372023296, 140737488355327,
-        272678883688448, 279275953455104, 280925220896768, 281200098803712, 281474976448512,
-        492581209243648, 2251524935778304, 2251795518717952, 4503595332403200, 4503599627370368,
-        8708132091985919, 9007190731849728, 17732923532771328, 71212894229889024,
+    static BITSET: [u64; 74] = [
+        0, 999, 1023, 1026, 3072, 4064, 8191, 65408, 65472, 1048575, 1966080, 2097151, 3932160,
+        4063232, 8388607, 67043328, 67044351, 134152192, 264241152, 268435455, 3758096384,
+        4294901504, 17112694784, 64424509440, 549218942976, 4393751543808, 35184372023296,
+        140737488355327, 272678883688448, 279275953455104, 280925220896768, 281200098803712,
+        281474976448512, 492581209243648, 2251524935778304, 2251795518717952, 4503595332403200,
+        4503599627370368, 8708132091985919, 9007190731849728, 17732923532771328, 71212894229889024,
         144114915328655360, 144115183780888576, 144115188075855871, 284007976623144960,
         284008251501051904, 287948901175001088, 287948901242044416, 287953294926544896,
         504407547722072192, 1152640029630136320, 1152921496016912384, 2305840810190438400,
@@ -541,28 +545,28 @@ pub mod uppercase {
     static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 10, 0, 38, 46, 44, 2],
-        [0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 51, 24, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 0, 0, 60, 62, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 54, 0, 0, 0, 0, 0, 43, 43, 40, 43, 56, 23, 34, 35],
-        [0, 0, 57, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 9, 0, 38, 46, 44, 28],
+        [0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 51, 23, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 0, 0, 60, 62, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [0, 0, 54, 0, 0, 0, 0, 0, 43, 43, 40, 43, 56, 22, 34, 35],
+        [0, 0, 57, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [0, 0, 66, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 30],
-        [0, 11, 0, 12, 50, 37, 36, 45, 47, 6, 0, 0, 0, 49, 18, 53],
-        [15, 0, 60, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [22, 52, 43, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [25, 39, 42, 41, 59, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        [58, 65, 29, 17, 48, 63, 31, 20, 55, 61, 64, 32, 28, 21, 16, 4],
+        [0, 0, 66, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 30],
+        [0, 10, 0, 11, 50, 37, 36, 45, 47, 5, 0, 0, 0, 49, 17, 53],
+        [14, 0, 60, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [21, 52, 43, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [24, 39, 42, 41, 59, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        [58, 65, 29, 16, 48, 63, 31, 19, 55, 61, 64, 32, 27, 20, 15, 3],
     ];
     static BITSET: [u64; 67] = [
-        0, 8, 116, 1023, 1024, 8383, 21882, 65535, 1048575, 8388607, 89478485, 134217726,
-        2139095039, 4294967295, 17179869183, 1099511627775, 2199023190016, 4398046445568,
-        17575006099264, 23456248059221, 70368743129088, 140737484161024, 140737488355327,
-        280378317225728, 281470681743392, 281474976710655, 1169903278445909, 2251799813685247,
-        9007198986305536, 17977448100528131, 18014398509481983, 288230371856744511,
+        0, 8, 1023, 1024, 8383, 21882, 65535, 1048575, 8388607, 89478485, 134217726, 2139095039,
+        4294967295, 17179869183, 1099511627775, 2199023190016, 4398046445568, 17575006099264,
+        23456248059221, 70368743129088, 140737484161024, 140737488355327, 280378317225728,
+        281470681743392, 281474976710655, 1169903278445909, 2251799813685247, 9007198986305536,
+        9007199254741748, 17977448100528131, 18014398509481983, 288230371856744511,
         576460735123554305, 576460743713488896, 1080863910568919040, 1080897995681042176,
         1274187559846268630, 3122495741643543722, 6148633210533183488, 6148914689804861440,
         6148914690880001365, 6148914691236506283, 6148914691236516865, 6148914691236517205,
@@ -1202,20 +1206,21 @@ pub mod conversions {
         ('\u{a7ba}', ['\u{a7bb}', '\u{0}', '\u{0}']), ('\u{a7bc}', ['\u{a7bd}', '\u{0}', '\u{0}']),
         ('\u{a7be}', ['\u{a7bf}', '\u{0}', '\u{0}']), ('\u{a7c2}', ['\u{a7c3}', '\u{0}', '\u{0}']),
         ('\u{a7c4}', ['\u{a794}', '\u{0}', '\u{0}']), ('\u{a7c5}', ['\u{282}', '\u{0}', '\u{0}']),
-        ('\u{a7c6}', ['\u{1d8e}', '\u{0}', '\u{0}']), ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']),
-        ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']), ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']),
-        ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']), ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']),
-        ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']), ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']),
-        ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']), ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']),
-        ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']), ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']),
-        ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']), ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']),
-        ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']), ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']),
-        ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']), ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']),
-        ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']), ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']),
-        ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']), ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']),
-        ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']), ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']),
-        ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']), ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']),
-        ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']),
+        ('\u{a7c6}', ['\u{1d8e}', '\u{0}', '\u{0}']), ('\u{a7c7}', ['\u{a7c8}', '\u{0}', '\u{0}']),
+        ('\u{a7c9}', ['\u{a7ca}', '\u{0}', '\u{0}']), ('\u{a7f5}', ['\u{a7f6}', '\u{0}', '\u{0}']),
+        ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']), ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']),
+        ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']), ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']),
+        ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']), ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']),
+        ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']), ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']),
+        ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']), ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']),
+        ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']), ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']),
+        ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']), ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']),
+        ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']), ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']),
+        ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']), ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']),
+        ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']), ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']),
+        ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']), ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']),
+        ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']), ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']),
+        ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']), ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']),
         ('\u{10400}', ['\u{10428}', '\u{0}', '\u{0}']),
         ('\u{10401}', ['\u{10429}', '\u{0}', '\u{0}']),
         ('\u{10402}', ['\u{1042a}', '\u{0}', '\u{0}']),
@@ -2052,51 +2057,52 @@ pub mod conversions {
         ('\u{a7b7}', ['\u{a7b6}', '\u{0}', '\u{0}']), ('\u{a7b9}', ['\u{a7b8}', '\u{0}', '\u{0}']),
         ('\u{a7bb}', ['\u{a7ba}', '\u{0}', '\u{0}']), ('\u{a7bd}', ['\u{a7bc}', '\u{0}', '\u{0}']),
         ('\u{a7bf}', ['\u{a7be}', '\u{0}', '\u{0}']), ('\u{a7c3}', ['\u{a7c2}', '\u{0}', '\u{0}']),
-        ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']), ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']),
-        ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']), ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']),
-        ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']), ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']),
-        ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']), ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']),
-        ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']), ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']),
-        ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']), ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']),
-        ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']), ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']),
-        ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']), ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']),
-        ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']), ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']),
-        ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']), ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']),
-        ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']), ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']),
-        ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']), ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']),
-        ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']), ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']),
-        ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']), ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']),
-        ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']), ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']),
-        ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']), ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']),
-        ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']), ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']),
-        ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']), ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']),
-        ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']), ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']),
-        ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']), ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']),
-        ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']), ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']),
-        ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']), ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']),
-        ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']), ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']),
-        ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']), ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']),
-        ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']), ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']),
-        ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']), ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']),
-        ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']), ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']),
-        ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']), ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']),
-        ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']), ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']),
-        ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']), ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']),
-        ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']), ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']),
-        ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']), ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']),
-        ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']), ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']),
-        ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']), ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']),
-        ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']), ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']),
-        ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']), ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']),
-        ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']), ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']),
-        ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']), ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']),
-        ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']), ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']),
-        ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']), ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']),
-        ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']), ('\u{fb00}', ['F', 'F', '\u{0}']),
-        ('\u{fb01}', ['F', 'I', '\u{0}']), ('\u{fb02}', ['F', 'L', '\u{0}']),
-        ('\u{fb03}', ['F', 'F', 'I']), ('\u{fb04}', ['F', 'F', 'L']),
-        ('\u{fb05}', ['S', 'T', '\u{0}']), ('\u{fb06}', ['S', 'T', '\u{0}']),
-        ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']),
+        ('\u{a7c8}', ['\u{a7c7}', '\u{0}', '\u{0}']), ('\u{a7ca}', ['\u{a7c9}', '\u{0}', '\u{0}']),
+        ('\u{a7f6}', ['\u{a7f5}', '\u{0}', '\u{0}']), ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']),
+        ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']), ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']),
+        ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']), ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']),
+        ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']), ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']),
+        ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']), ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']),
+        ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']), ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']),
+        ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']), ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']),
+        ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']), ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']),
+        ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']), ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']),
+        ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']), ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']),
+        ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']), ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']),
+        ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']), ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']),
+        ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']), ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']),
+        ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']), ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']),
+        ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']), ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']),
+        ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']), ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']),
+        ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']), ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']),
+        ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']), ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']),
+        ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']), ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']),
+        ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']), ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']),
+        ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']), ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']),
+        ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']), ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']),
+        ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']), ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']),
+        ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']), ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']),
+        ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']), ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']),
+        ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']), ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']),
+        ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']), ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']),
+        ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']), ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']),
+        ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']), ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']),
+        ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']), ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']),
+        ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']), ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']),
+        ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']), ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']),
+        ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']), ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']),
+        ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']), ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']),
+        ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']), ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']),
+        ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']), ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']),
+        ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']), ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']),
+        ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']), ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']),
+        ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']), ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']),
+        ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']), ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']),
+        ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']), ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']),
+        ('\u{fb00}', ['F', 'F', '\u{0}']), ('\u{fb01}', ['F', 'I', '\u{0}']),
+        ('\u{fb02}', ['F', 'L', '\u{0}']), ('\u{fb03}', ['F', 'F', 'I']),
+        ('\u{fb04}', ['F', 'F', 'L']), ('\u{fb05}', ['S', 'T', '\u{0}']),
+        ('\u{fb06}', ['S', 'T', '\u{0}']), ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']),
         ('\u{fb14}', ['\u{544}', '\u{535}', '\u{0}']),
         ('\u{fb15}', ['\u{544}', '\u{53b}', '\u{0}']),
         ('\u{fb16}', ['\u{54e}', '\u{546}', '\u{0}']),
diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs
index db7c250e211..f44a875c9d0 100644
--- a/src/libpanic_abort/lib.rs
+++ b/src/libpanic_abort/lib.rs
@@ -18,17 +18,11 @@
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
 
-// Rust's "try" function, but if we're aborting on panics we just call the
-// function as there's nothing else we need to do here.
+use core::any::Any;
+
 #[rustc_std_internal_symbol]
-pub unsafe extern "C" fn __rust_maybe_catch_panic(
-    f: fn(*mut u8),
-    data: *mut u8,
-    _data_ptr: *mut usize,
-    _vtable_ptr: *mut usize,
-) -> u32 {
-    f(data);
-    0
+pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) {
+    unreachable!()
 }
 
 // "Leak" the payload and shim to the relevant abort on the platform in
@@ -92,7 +86,7 @@ pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 {
 // binaries, but it should never be called as we don't link in an unwinding
 // runtime at all.
 pub mod personalities {
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     #[cfg(not(any(
         all(target_arch = "wasm32", not(target_os = "emscripten"),),
         all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",),
@@ -101,7 +95,7 @@ pub mod personalities {
 
     // On x86_64-pc-windows-gnu we use our own personality function that needs
     // to return `ExceptionContinueSearch` as we're passing on all our frames.
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86_64"))]
     pub extern "C" fn rust_eh_personality(
         _record: usize,
@@ -117,16 +111,16 @@ pub mod personalities {
     //
     // Note that we don't execute landing pads, so this is never called, so it's
     // body is empty.
-    #[no_mangle]
-    #[cfg(all(target_os = "windows", target_env = "gnu"))]
+    #[rustc_std_internal_symbol]
+    #[cfg(all(bootstrap, target_os = "windows", target_env = "gnu"))]
     pub extern "C" fn rust_eh_unwind_resume() {}
 
     // These two are called by our startup objects on i686-pc-windows-gnu, but
     // they don't need to do anything so the bodies are nops.
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
     pub extern "C" fn rust_eh_register_frames() {}
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
     pub extern "C" fn rust_eh_unregister_frames() {}
 }
diff --git a/src/libpanic_unwind/dummy.rs b/src/libpanic_unwind/dummy.rs
index 86756326387..4667ede2baa 100644
--- a/src/libpanic_unwind/dummy.rs
+++ b/src/libpanic_unwind/dummy.rs
@@ -6,10 +6,6 @@ use alloc::boxed::Box;
 use core::any::Any;
 use core::intrinsics;
 
-pub fn payload() -> *mut u8 {
-    core::ptr::null_mut()
-}
-
 pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
     intrinsics::abort()
 }
diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs
index 9161d49959c..a0bdb1481c6 100644
--- a/src/libpanic_unwind/emcc.rs
+++ b/src/libpanic_unwind/emcc.rs
@@ -6,8 +6,6 @@
 //! Emscripten's runtime always implements those APIs and does not
 //! implement libunwind.
 
-#![allow(private_no_mangle_fns)]
-
 use alloc::boxed::Box;
 use core::any::Any;
 use core::mem;
@@ -48,15 +46,11 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo {
     name: b"rust_panic\0".as_ptr(),
 };
 
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
-
 struct Exception {
     // This needs to be an Option because the object's lifetime follows C++
     // semantics: when catch_unwind moves the Box out of the exception it must
     // still leave the exception object in a valid state because its destructor
-    // is still going to be called by __cxa_end_catch..
+    // is still going to be called by __cxa_end_catch.
     data: Option<Box<dyn Any + Send>>,
 }
 
@@ -98,7 +92,6 @@ extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> DestructorRet {
 }
 
 #[lang = "eh_personality"]
-#[no_mangle]
 unsafe extern "C" fn rust_eh_personality(
     version: c_int,
     actions: uw::_Unwind_Action,
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index 591ff9d7fdc..1622442a5eb 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -35,20 +35,9 @@
 //!
 //! Once stack has been unwound down to the handler frame level, unwinding stops
 //! and the last personality routine transfers control to the catch block.
-//!
-//! ## `eh_personality` and `eh_unwind_resume`
-//!
-//! These language items are used by the compiler when generating unwind info.
-//! The first one is the personality routine described above. The second one
-//! allows compilation target to customize the process of resuming unwind at the
-//! end of the landing pads. `eh_unwind_resume` is used only if
-//! `custom_unwind_resume` flag in the target options is set.
-
-#![allow(private_no_mangle_fns)]
 
 use alloc::boxed::Box;
 use core::any::Any;
-use core::ptr;
 
 use crate::dwarf::eh::{self, EHAction, EHContext};
 use libc::{c_int, uintptr_t};
@@ -83,10 +72,6 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     }
 }
 
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
-
 pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
     let exception = Box::from_raw(ptr as *mut Exception);
     exception.cause
@@ -143,7 +128,6 @@ cfg_if::cfg_if! {
         //
         // iOS uses the default routine instead since it uses SjLj unwinding.
         #[lang = "eh_personality"]
-        #[no_mangle]
         unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
                                                  exception_object: *mut uw::_Unwind_Exception,
                                                  context: *mut uw::_Unwind_Context)
@@ -277,7 +261,6 @@ cfg_if::cfg_if! {
                 // On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind
                 // handler data (aka LSDA) uses GCC-compatible encoding.
                 #[lang = "eh_personality"]
-                #[no_mangle]
                 #[allow(nonstandard_style)]
                 unsafe extern "C" fn rust_eh_personality(exceptionRecord: *mut uw::EXCEPTION_RECORD,
                         establisherFrame: uw::LPVOID,
@@ -293,7 +276,6 @@ cfg_if::cfg_if! {
             } else {
                 // The personality routine for most of our targets.
                 #[lang = "eh_personality"]
-                #[no_mangle]
                 unsafe extern "C" fn rust_eh_personality(version: c_int,
                         actions: uw::_Unwind_Action,
                         exception_class: uw::_Unwind_Exception_Class,
@@ -329,8 +311,8 @@ unsafe fn find_eh_action(
     eh::find_eh_action(lsda, &eh_context, foreign_exception)
 }
 
-// See docs in the `unwind` module.
 #[cfg(all(
+    bootstrap,
     target_os = "windows",
     any(target_arch = "x86", target_arch = "x86_64"),
     target_env = "gnu"
@@ -364,12 +346,12 @@ pub mod eh_frame_registry {
         fn __deregister_frame_info(eh_frame_begin: *const u8, object: *mut u8);
     }
 
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern "C" fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8) {
         __register_frame_info(eh_frame_begin, object);
     }
 
-    #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern "C" fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8) {
         __deregister_frame_info(eh_frame_begin, object);
     }
diff --git a/src/libpanic_unwind/hermit.rs b/src/libpanic_unwind/hermit.rs
index 2f53df2861d..6bded4dd499 100644
--- a/src/libpanic_unwind/hermit.rs
+++ b/src/libpanic_unwind/hermit.rs
@@ -6,10 +6,6 @@ use alloc::boxed::Box;
 use core::any::Any;
 use core::ptr;
 
-pub fn payload() -> *mut u8 {
-    ptr::null_mut()
-}
-
 pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
     extern "C" {
         pub fn __rust_abort() -> !;
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index 6383ae39fb6..0a2a0e9e045 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -22,42 +22,56 @@
 #![feature(libc)]
 #![feature(nll)]
 #![feature(panic_unwind)]
-#![feature(raw)]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(unwind_attributes)]
 #![feature(abi_thiscall)]
+#![feature(rustc_attrs)]
+#![feature(raw)]
 #![panic_runtime]
 #![feature(panic_runtime)]
+// `real_imp` is unused with Miri, so silence warnings.
+#![cfg_attr(miri, allow(dead_code))]
 
 use alloc::boxed::Box;
-use core::intrinsics;
-use core::mem;
+use core::any::Any;
 use core::panic::BoxMeUp;
-use core::raw;
 
 cfg_if::cfg_if! {
     if #[cfg(target_os = "emscripten")] {
         #[path = "emcc.rs"]
-        mod imp;
+        mod real_imp;
     } else if #[cfg(target_arch = "wasm32")] {
         #[path = "dummy.rs"]
-        mod imp;
+        mod real_imp;
     } else if #[cfg(target_os = "hermit")] {
         #[path = "hermit.rs"]
-        mod imp;
+        mod real_imp;
     } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {
         #[path = "dummy.rs"]
-        mod imp;
+        mod real_imp;
     } else if #[cfg(target_env = "msvc")] {
         #[path = "seh.rs"]
-        mod imp;
+        mod real_imp;
     } else {
         // Rust runtime's startup objects depend on these symbols, so make them public.
         #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
-        pub use imp::eh_frame_registry::*;
+        pub use real_imp::eh_frame_registry::*;
         #[path = "gcc.rs"]
+        mod real_imp;
+    }
+}
+
+cfg_if::cfg_if! {
+    if #[cfg(miri)] {
+        // Use the Miri runtime.
+        // We still need to also load the normal runtime above, as rustc expects certain lang
+        // items from there to be defined.
+        #[path = "miri.rs"]
         mod imp;
+    } else {
+        // Use the real runtime.
+        use real_imp as imp;
     }
 }
 
@@ -69,44 +83,18 @@ extern "C" {
 
 mod dwarf;
 
-// Entry point for catching an exception, implemented using the `try` intrinsic
-// in the compiler.
-//
-// The interaction between the `payload` function and the compiler is pretty
-// hairy and tightly coupled, for more information see the compiler's
-// implementation of this.
-#[no_mangle]
-pub unsafe extern "C" fn __rust_maybe_catch_panic(
-    f: fn(*mut u8),
-    data: *mut u8,
-    data_ptr: *mut usize,
-    vtable_ptr: *mut usize,
-) -> u32 {
-    let mut payload = imp::payload();
-    if intrinsics::r#try(f, data, &mut payload as *mut _ as *mut _) == 0 {
-        0
-    } else {
-        let obj = mem::transmute::<_, raw::TraitObject>(imp::cleanup(payload));
-        *data_ptr = obj.data as usize;
-        *vtable_ptr = obj.vtable as usize;
-        1
-    }
+#[rustc_std_internal_symbol]
+pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) {
+    Box::into_raw(imp::cleanup(payload))
 }
 
 // Entry point for raising an exception, just delegates to the platform-specific
 // implementation.
-#[no_mangle]
+#[rustc_std_internal_symbol]
 #[unwind(allowed)]
 pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 {
     let payload = payload as *mut &mut dyn BoxMeUp;
     let payload = (*payload).take_box();
 
-    // Miri panic support: cfg'd out of normal builds just to be sure.
-    // When going through normal codegen, `miri_start_panic` is a NOP, so the
-    // Miri-enabled sysroot still supports normal unwinding. But when executed in
-    // Miri, this line initiates unwinding.
-    #[cfg(miri)]
-    core::intrinsics::miri_start_panic(payload);
-
     imp::panic(Box::from_raw(payload))
 }
diff --git a/src/libpanic_unwind/miri.rs b/src/libpanic_unwind/miri.rs
new file mode 100644
index 00000000000..9d92b2b2f32
--- /dev/null
+++ b/src/libpanic_unwind/miri.rs
@@ -0,0 +1,20 @@
+//! Unwinding panics for Miri.
+use alloc::boxed::Box;
+use core::any::Any;
+
+// The type of the payload that the Miri engine propagates through unwinding for us.
+// Must be pointer-sized.
+type Payload = Box<Box<dyn Any + Send>>;
+
+pub unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 {
+    // The payload we pass to `miri_start_panic` will be exactly the argument we get
+    // in `cleanup` below. So we just box it up once, to get something pointer-sized.
+    let payload_box: Payload = Box::new(payload);
+    core::intrinsics::miri_start_panic(Box::into_raw(payload_box) as *mut u8)
+}
+
+pub unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> {
+    // Recover the underlying `Box`.
+    let payload_box: Payload = Box::from_raw(payload_box as *mut _);
+    *payload_box
+}
diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs
index 6f507e85e74..10b765a5b41 100644
--- a/src/libpanic_unwind/seh.rs
+++ b/src/libpanic_unwind/seh.rs
@@ -45,14 +45,20 @@
 //! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions
 
 #![allow(nonstandard_style)]
-#![allow(private_no_mangle_fns)]
 
 use alloc::boxed::Box;
 use core::any::Any;
-use core::mem;
-use core::raw;
+use core::mem::{self, ManuallyDrop};
 use libc::{c_int, c_uint, c_void};
 
+struct Exception {
+    // This needs to be an Option because we catch the exception by reference
+    // and its destructor is executed by the C++ runtime. When we take the Box
+    // out of the exception, we need to leave the exception in a valid state
+    // for its destructor to run without double-dropping the Box.
+    data: Option<Box<dyn Any + Send>>,
+}
+
 // First up, a whole bunch of type definitions. There's a few platform-specific
 // oddities here, and a lot that's just blatantly copied from LLVM. The purpose
 // of all this is to implement the `panic` function below through a call to
@@ -167,6 +173,9 @@ pub struct _TypeDescriptor {
 
 // Note that we intentionally ignore name mangling rules here: we don't want C++
 // to be able to catch Rust panics by simply declaring a `struct rust_panic`.
+//
+// When modifying, make sure that the type name string exactly matches
+// the one used in src/librustc_codegen_llvm/intrinsic.rs.
 const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
 
 static mut THROW_INFO: _ThrowInfo = _ThrowInfo {
@@ -183,7 +192,7 @@ static mut CATCHABLE_TYPE: _CatchableType = _CatchableType {
     properties: 0,
     pType: ptr!(0),
     thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 },
-    sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int,
+    sizeOrOffset: mem::size_of::<Exception>() as c_int,
     copyFunction: ptr!(0),
 };
 
@@ -199,12 +208,12 @@ extern "C" {
     static TYPE_INFO_VTABLE: *const u8;
 }
 
-// We use #[lang = "eh_catch_typeinfo"] here as this is the type descriptor which
-// we'll use in LLVM's `catchpad` instruction which ends up also being passed as
-// an argument to the C++ personality function.
+// This type descriptor is only used when throwing an exception. The catch part
+// is handled by the try intrinsic, which generates its own TypeDescriptor.
 //
-// Again, I'm not entirely sure what this is describing, it just seems to work.
-#[cfg_attr(not(test), lang = "eh_catch_typeinfo")]
+// This is fine since the MSVC runtime uses string comparison on the type name
+// to match TypeDescriptors rather than pointer equality.
+#[cfg_attr(bootstrap, lang = "eh_catch_typeinfo")]
 static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
     pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _,
     spare: core::ptr::null_mut(),
@@ -226,16 +235,16 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
 // because Box<dyn Any> isn't clonable.
 macro_rules! define_cleanup {
     ($abi:tt) => {
-        unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) {
-            if (*e)[0] != 0 {
-                cleanup(*e);
+        unsafe extern $abi fn exception_cleanup(e: *mut Exception) {
+            if let Exception { data: Some(b) } = e.read() {
+                drop(b);
                 super::__rust_drop_panic();
             }
         }
         #[unwind(allowed)]
-        unsafe extern $abi fn exception_copy(_dest: *mut [u64; 2],
-                                             _src: *mut [u64; 2])
-                                             -> *mut [u64; 2] {
+        unsafe extern $abi fn exception_copy(_dest: *mut Exception,
+                                             _src: *mut Exception)
+                                             -> *mut Exception {
             panic!("Rust panics cannot be copied");
         }
     }
@@ -255,12 +264,11 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     // need to otherwise transfer `data` to the heap. We just pass a stack
     // pointer to this function.
     //
-    // The first argument is the payload being thrown (our two pointers), and
-    // the second argument is the type information object describing the
-    // exception (constructed above).
-    let ptrs = mem::transmute::<_, raw::TraitObject>(data);
-    let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64];
-    let throw_ptr = ptrs.as_mut_ptr() as *mut _;
+    // The ManuallyDrop is needed here since we don't want Exception to be
+    // dropped when unwinding. Instead it will be dropped by exception_cleanup
+    // which is invoked by the C++ runtime.
+    let mut exception = ManuallyDrop::new(Exception { data: Some(data) });
+    let throw_ptr = &mut exception as *mut _ as *mut _;
 
     // This... may seems surprising, and justifiably so. On 32-bit MSVC the
     // pointers between these structure are just that, pointers. On 64-bit MSVC,
@@ -308,12 +316,9 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _);
 }
 
-pub fn payload() -> [u64; 2] {
-    [0; 2]
-}
-
-pub unsafe fn cleanup(payload: [u64; 2]) -> Box<dyn Any + Send> {
-    mem::transmute(raw::TraitObject { data: payload[0] as *mut _, vtable: payload[1] as *mut _ })
+pub unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> {
+    let exception = &mut *(payload as *mut Exception);
+    exception.data.take().unwrap()
 }
 
 // This is required by the compiler to exist (e.g., it's a lang item), but
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index c51db695a5b..8f16e3c08ec 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -26,7 +26,8 @@
 #![feature(in_band_lifetimes)]
 #![feature(optin_builtin_traits)]
 #![feature(rustc_attrs)]
-#![feature(specialization)]
+#![cfg_attr(bootstrap, feature(specialization))]
+#![cfg_attr(not(bootstrap), feature(min_specialization))]
 #![recursion_limit = "256"]
 
 #[unstable(feature = "proc_macro_internals", issue = "27812")]
@@ -41,7 +42,7 @@ pub use diagnostic::{Diagnostic, Level, MultiSpan};
 use std::ops::{Bound, RangeBounds};
 use std::path::PathBuf;
 use std::str::FromStr;
-use std::{fmt, iter, mem};
+use std::{error, fmt, iter, mem};
 
 /// The main type provided by this crate, representing an abstract stream of
 /// tokens, or, more specifically, a sequence of token trees.
@@ -66,6 +67,16 @@ pub struct LexError {
     _inner: (),
 }
 
+#[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")]
+impl fmt::Display for LexError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("cannot parse string into token stream")
+    }
+}
+
+#[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")]
+impl error::Error for LexError {}
+
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 impl !Send for LexError {}
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
diff --git a/src/librustc/README.md b/src/librustc/README.md
index c0e5c542bdc..de58f546cd3 100644
--- a/src/librustc/README.md
+++ b/src/librustc/README.md
@@ -1,3 +1,3 @@
-For more information about how rustc works, see the [rustc guide].
+For more information about how rustc works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index 0384a9f7815..72258c0537a 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -161,6 +161,12 @@ macro_rules! arena_types {
             [] type_binding: rustc_hir::TypeBinding<$tcx>,
             [] variant: rustc_hir::Variant<$tcx>,
             [] where_predicate: rustc_hir::WherePredicate<$tcx>,
+
+            // HIR query types
+            [few] indexed_hir: rustc::hir::map::IndexedHir<$tcx>,
+            [few] hir_definitions: rustc::hir::map::definitions::Definitions,
+            [] hir_owner: rustc::hir::HirOwner<$tcx>,
+            [] hir_owner_items: rustc::hir::HirOwnerItems<$tcx>,
         ], $tcx);
     )
 }
diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md
index 91a06e452e5..b9d91cd35a8 100644
--- a/src/librustc/dep_graph/README.md
+++ b/src/librustc/dep_graph/README.md
@@ -1,4 +1,4 @@
 To learn more about how dependency tracking works in rustc, see the [rustc
 guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/query.html
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 5cbaa5a42f6..b32fa2cda80 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -35,7 +35,7 @@
 //! "infer" some properties for each kind of `DepNode`:
 //!
 //! * Whether a `DepNode` of a given kind has any parameters at all. Some
-//!   `DepNode`s, like `AllLocalTraitImpls`, represent global concepts with only one value.
+//!   `DepNode`s could represent global concepts with only one value.
 //! * Whether it is possible, in principle, to reconstruct a query key from a
 //!   given `DepNode`. Many `DepKind`s only require a single `DefId` parameter,
 //!   in which case it is possible to map the node's fingerprint back to the
@@ -63,7 +63,7 @@ use crate::ty::subst::SubstsRef;
 use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::HirId;
 use rustc_span::symbol::Symbol;
 use std::fmt;
@@ -179,7 +179,7 @@ macro_rules! define_dep_nodes {
             $(
                 #[inline(always)]
                 #[allow(unreachable_code, non_snake_case)]
-                pub fn $variant<'tcx>(_tcx: TyCtxt<'tcx>, $(arg: $tuple_arg_ty)*) -> DepNode {
+                pub fn $variant(_tcx: TyCtxt<'_>, $(arg: $tuple_arg_ty)*) -> DepNode {
                     // tuple args
                     $({
                         erase!($tuple_arg_ty);
@@ -223,8 +223,8 @@ macro_rules! define_dep_nodes {
             /// Construct a DepNode from the given DepKind and DefPathHash. This
             /// method will assert that the given DepKind actually requires a
             /// single DefId/DefPathHash parameter.
-            pub fn from_def_path_hash(kind: DepKind,
-                                      def_path_hash: DefPathHash)
+            pub fn from_def_path_hash(def_path_hash: DefPathHash,
+                                      kind: DepKind)
                                       -> DepNode {
                 debug_assert!(kind.can_reconstruct_query_key() && kind.has_params());
                 DepNode {
@@ -280,7 +280,7 @@ macro_rules! define_dep_nodes {
                 }
 
                 if kind.has_params() {
-                    Ok(def_path_hash.to_dep_node(kind))
+                    Ok(DepNode::from_def_path_hash(def_path_hash, kind))
                 } else {
                     Ok(DepNode::new_no_params(kind))
                 }
@@ -337,28 +337,13 @@ impl fmt::Debug for DepNode {
     }
 }
 
-impl DefPathHash {
-    pub fn to_dep_node(self, kind: DepKind) -> DepNode {
-        DepNode::from_def_path_hash(kind, self)
-    }
-}
-
 rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
     // We use this for most things when incr. comp. is turned off.
     [] Null,
 
-    // Represents the body of a function or method. The def-id is that of the
-    // function/method.
-    [eval_always] HirBody(DefId),
-
-    // Represents the HIR node with the given node-id
-    [eval_always] Hir(DefId),
-
     // Represents metadata from an extern crate.
     [eval_always] CrateMetadata(CrateNum),
 
-    [eval_always] AllLocalTraitImpls,
-
     [anon] TraitSelect,
 
     [] CompileCodegenUnit(Symbol),
@@ -428,19 +413,19 @@ impl<'tcx> DepNodeParams<'tcx> for DefId {
     }
 }
 
-impl<'tcx> DepNodeParams<'tcx> for DefIndex {
+impl<'tcx> DepNodeParams<'tcx> for LocalDefId {
     const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
 
     fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
-        tcx.hir().definitions().def_path_hash(*self).0
+        self.to_def_id().to_fingerprint(tcx)
     }
 
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
-        tcx.def_path_str(DefId::local(*self))
+        self.to_def_id().to_debug_str(tcx)
     }
 
     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
-        dep_node.extract_def_id(tcx).map(|id| id.index)
+        dep_node.extract_def_id(tcx).map(|id| id.expect_local())
     }
 }
 
@@ -492,7 +477,7 @@ impl<'tcx> DepNodeParams<'tcx> for HirId {
     fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
         let HirId { owner, local_id } = *self;
 
-        let def_path_hash = tcx.def_path_hash(DefId::local(owner));
+        let def_path_hash = tcx.def_path_hash(owner.to_def_id());
         let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into());
 
         def_path_hash.0.combine(local_id)
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index d5cde703411..f60d20b8cb7 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -174,7 +174,7 @@ impl DepGraph {
     /// what state they have access to. In particular, we want to
     /// prevent implicit 'leaks' of tracked state into the task (which
     /// could then be read without generating correct edges in the
-    /// dep-graph -- see the [rustc guide] for more details on
+    /// dep-graph -- see the [rustc dev guide] for more details on
     /// the dep-graph). To this end, the task function gets exactly two
     /// pieces of state: the context `cx` and an argument `arg`. Both
     /// of these bits of state must be of some type that implements
@@ -194,7 +194,7 @@ impl DepGraph {
     /// - If you need 3+ arguments, use a tuple for the
     ///   `arg` parameter.
     ///
-    /// [rustc guide]: https://rust-lang.github.io/rustc-guide/incremental-compilation.html
+    /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html
     pub fn with_task<'a, C, A, R>(
         &self,
         key: DepNode,
@@ -225,28 +225,6 @@ impl DepGraph {
         )
     }
 
-    /// Creates a new dep-graph input with value `input`
-    pub fn input_task<'a, C, R>(&self, key: DepNode, cx: C, input: R) -> (R, DepNodeIndex)
-    where
-        C: DepGraphSafe + StableHashingContextProvider<'a>,
-        R: for<'b> HashStable<StableHashingContext<'b>>,
-    {
-        fn identity_fn<C, A>(_: C, arg: A) -> A {
-            arg
-        }
-
-        self.with_task_impl(
-            key,
-            cx,
-            input,
-            true,
-            identity_fn,
-            |_| None,
-            |data, key, fingerprint, _| data.alloc_node(key, SmallVec::new(), fingerprint),
-            hash_result::<R>,
-        )
-    }
-
     fn with_task_impl<'a, C, A, R>(
         &self,
         key: DepNode,
@@ -676,18 +654,25 @@ impl DepGraph {
                             continue;
                         }
                     } else {
+                        // FIXME: This match is just a workaround for incremental bugs and should
+                        // be removed. https://github.com/rust-lang/rust/issues/62649 is one such
+                        // bug that must be fixed before removing this.
                         match dep_dep_node.kind {
-                            DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => {
+                            DepKind::hir_owner
+                            | DepKind::hir_owner_items
+                            | DepKind::CrateMetadata => {
                                 if let Some(def_id) = dep_dep_node.extract_def_id(tcx) {
                                     if def_id_corresponds_to_hir_dep_node(tcx, def_id) {
-                                        // The `DefPath` has corresponding node,
-                                        // and that node should have been marked
-                                        // either red or green in `data.colors`.
-                                        bug!(
-                                            "DepNode {:?} should have been \
+                                        if dep_dep_node.kind == DepKind::CrateMetadata {
+                                            // The `DefPath` has corresponding node,
+                                            // and that node should have been marked
+                                            // either red or green in `data.colors`.
+                                            bug!(
+                                                "DepNode {:?} should have been \
                                              pre-marked as red or green but wasn't.",
-                                            dep_dep_node
-                                        );
+                                                dep_dep_node
+                                            );
+                                        }
                                     } else {
                                         // This `DefPath` does not have a
                                         // corresponding `DepNode` (e.g. a
@@ -917,7 +902,7 @@ impl DepGraph {
 
 fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    def_id.index == hir_id.owner
+    def_id.index == hir_id.owner.local_def_index
 }
 
 /// A "work product" is an intermediate result that we save into the
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 618f9a018d1..7024e86f95d 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -51,7 +51,7 @@ impl MaybeFnLike for hir::Item<'_> {
 impl MaybeFnLike for hir::ImplItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            hir::ImplItemKind::Method(..) => true,
+            hir::ImplItemKind::Fn(..) => true,
             _ => false,
         }
     }
@@ -60,7 +60,7 @@ impl MaybeFnLike for hir::ImplItem<'_> {
 impl MaybeFnLike for hir::TraitItem<'_> {
     fn is_fn_like(&self) -> bool {
         match self.kind {
-            hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true,
+            hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true,
             _ => false,
         }
     }
@@ -239,13 +239,13 @@ impl<'a> FnLikeNode<'a> {
                 _ => bug!("item FnLikeNode that is not fn-like"),
             },
             Node::TraitItem(ti) => match ti.kind {
-                hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+                hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                     method(ti.hir_id, ti.ident, sig, None, body, ti.span, &ti.attrs)
                 }
                 _ => bug!("trait method FnLikeNode that is not fn-like"),
             },
             Node::ImplItem(ii) => match ii.kind {
-                hir::ImplItemKind::Method(ref sig, body) => {
+                hir::ImplItemKind::Fn(ref sig, body) => {
                     method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
                 }
                 _ => bug!("impl method FnLikeNode that is not fn-like"),
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index ebd335ab355..de0cc61118f 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -1,19 +1,19 @@
-use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex};
+use crate::arena::Arena;
 use crate::hir::map::definitions::{self, DefPathHash};
-use crate::hir::map::{Entry, HirEntryMap, Map};
+use crate::hir::map::{Entry, HirOwnerData, Map};
+use crate::hir::{HirItem, HirOwner, HirOwnerItems};
 use crate::ich::StableHashingContext;
 use crate::middle::cstore::CrateStore;
-use rustc_ast::ast::NodeId;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
 use rustc_hir::def_id::CRATE_DEF_INDEX;
-use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE};
+use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::*;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{Idx, IndexVec};
 use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::source_map::SourceMap;
 use rustc_span::{Span, Symbol, DUMMY_SP};
@@ -22,76 +22,57 @@ use std::iter::repeat;
 
 /// A visitor that walks over the HIR and collects `Node`s into a HIR map.
 pub(super) struct NodeCollector<'a, 'hir> {
+    arena: &'hir Arena<'hir>,
+
     /// The crate
     krate: &'hir Crate<'hir>,
 
     /// Source map
     source_map: &'a SourceMap,
 
-    /// The node map
-    map: HirEntryMap<'hir>,
+    map: IndexVec<LocalDefId, HirOwnerData<'hir>>,
+
     /// The parent of this node
     parent_node: hir::HirId,
 
-    // These fields keep track of the currently relevant DepNodes during
-    // the visitor's traversal.
-    current_dep_node_owner: DefIndex,
-    current_signature_dep_index: DepNodeIndex,
-    current_full_dep_index: DepNodeIndex,
-    currently_in_body: bool,
+    current_dep_node_owner: LocalDefId,
 
-    dep_graph: &'a DepGraph,
     definitions: &'a definitions::Definitions,
-    hir_to_node_id: &'a FxHashMap<HirId, NodeId>,
 
     hcx: StableHashingContext<'a>,
 
-    // We are collecting `DepNode::HirBody` hashes here so we can compute the
-    // crate hash from then later on.
+    // We are collecting HIR hashes here so we can compute the
+    // crate hash from them later on.
     hir_body_nodes: Vec<(DefPathHash, Fingerprint)>,
 }
 
-fn input_dep_node_and_hash(
-    dep_graph: &DepGraph,
+fn insert_vec_map<K: Idx, V: Clone>(map: &mut IndexVec<K, Option<V>>, k: K, v: V) {
+    let i = k.index();
+    let len = map.len();
+    if i >= len {
+        map.extend(repeat(None).take(i - len + 1));
+    }
+    map[k] = Some(v);
+}
+
+fn hash(
     hcx: &mut StableHashingContext<'_>,
-    dep_node: DepNode,
     input: impl for<'a> HashStable<StableHashingContext<'a>>,
-) -> (DepNodeIndex, Fingerprint) {
-    let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1;
-
-    let hash = if dep_graph.is_fully_enabled() {
-        dep_graph.fingerprint_of(dep_node_index)
-    } else {
-        let mut stable_hasher = StableHasher::new();
-        input.hash_stable(hcx, &mut stable_hasher);
-        stable_hasher.finish()
-    };
-
-    (dep_node_index, hash)
+) -> Fingerprint {
+    let mut stable_hasher = StableHasher::new();
+    input.hash_stable(hcx, &mut stable_hasher);
+    stable_hasher.finish()
 }
 
-fn alloc_hir_dep_nodes(
-    dep_graph: &DepGraph,
+fn hash_body(
     hcx: &mut StableHashingContext<'_>,
     def_path_hash: DefPathHash,
     item_like: impl for<'a> HashStable<StableHashingContext<'a>>,
     hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>,
-) -> (DepNodeIndex, DepNodeIndex) {
-    let sig = dep_graph
-        .input_task(
-            def_path_hash.to_dep_node(DepKind::Hir),
-            &mut *hcx,
-            HirItemLike { item_like: &item_like, hash_bodies: false },
-        )
-        .1;
-    let (full, hash) = input_dep_node_and_hash(
-        dep_graph,
-        hcx,
-        def_path_hash.to_dep_node(DepKind::HirBody),
-        HirItemLike { item_like: &item_like, hash_bodies: true },
-    );
+) -> Fingerprint {
+    let hash = hash(hcx, HirItemLike { item_like: &item_like });
     hir_body_nodes.push((def_path_hash, hash));
-    (sig, full)
+    hash
 }
 
 fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
@@ -112,24 +93,19 @@ fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
     pub(super) fn root(
         sess: &'a Session,
+        arena: &'hir Arena<'hir>,
         krate: &'hir Crate<'hir>,
-        dep_graph: &'a DepGraph,
         definitions: &'a definitions::Definitions,
-        hir_to_node_id: &'a FxHashMap<HirId, NodeId>,
         mut hcx: StableHashingContext<'a>,
     ) -> NodeCollector<'a, 'hir> {
-        let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX);
+        let root_mod_def_path_hash =
+            definitions.def_path_hash(LocalDefId { local_def_index: CRATE_DEF_INDEX });
 
         let mut hir_body_nodes = Vec::new();
 
-        // Allocate `DepNode`s for the root module.
-        let (root_mod_sig_dep_index, root_mod_full_dep_index) = {
+        let hash = {
             let Crate {
-                ref module,
-                // Crate attributes are not copied over to the root `Mod`, so hash
-                // them explicitly here.
-                ref attrs,
-                span,
+                ref item,
                 // These fields are handled separately:
                 exported_macros: _,
                 non_exported_macro_attrs: _,
@@ -143,45 +119,26 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
                 proc_macros: _,
             } = *krate;
 
-            alloc_hir_dep_nodes(
-                dep_graph,
-                &mut hcx,
-                root_mod_def_path_hash,
-                (module, attrs, span),
-                &mut hir_body_nodes,
-            )
+            hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes)
         };
 
-        {
-            dep_graph.input_task(
-                DepNode::new_no_params(DepKind::AllLocalTraitImpls),
-                &mut hcx,
-                &krate.trait_impls,
-            );
-        }
-
         let mut collector = NodeCollector {
+            arena,
             krate,
             source_map: sess.source_map(),
-            map: IndexVec::from_elem_n(IndexVec::new(), definitions.def_index_count()),
             parent_node: hir::CRATE_HIR_ID,
-            current_signature_dep_index: root_mod_sig_dep_index,
-            current_full_dep_index: root_mod_full_dep_index,
-            current_dep_node_owner: CRATE_DEF_INDEX,
-            currently_in_body: false,
-            dep_graph,
+            current_dep_node_owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
             definitions,
-            hir_to_node_id,
             hcx,
             hir_body_nodes,
+            map: (0..definitions.def_index_count())
+                .map(|_| HirOwnerData { signature: None, with_bodies: None })
+                .collect(),
         };
         collector.insert_entry(
             hir::CRATE_HIR_ID,
-            Entry {
-                parent: hir::CRATE_HIR_ID,
-                dep_node: root_mod_sig_dep_index,
-                node: Node::Crate,
-            },
+            Entry { parent: hir::CRATE_HIR_ID, node: Node::Crate(&krate.item) },
+            hash,
         );
 
         collector
@@ -192,7 +149,13 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
         crate_disambiguator: CrateDisambiguator,
         cstore: &dyn CrateStore,
         commandline_args_hash: u64,
-    ) -> (HirEntryMap<'hir>, Svh) {
+    ) -> (IndexVec<LocalDefId, HirOwnerData<'hir>>, Svh) {
+        // Insert bodies into the map
+        for (id, body) in self.krate.bodies.iter() {
+            let bodies = &mut self.map[id.hir_id.owner].with_bodies.as_mut().unwrap().bodies;
+            assert!(bodies.insert(id.hir_id.local_id, body).is_none());
+        }
+
         self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
 
         let node_hashes = self.hir_body_nodes.iter().fold(
@@ -213,7 +176,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
             .source_map
             .files()
             .iter()
-            .filter(|source_file| CrateNum::from_u32(source_file.crate_of_origin) == LOCAL_CRATE)
+            .filter(|source_file| source_file.cnum == LOCAL_CRATE)
             .map(|source_file| source_file.name_hash)
             .collect();
 
@@ -232,37 +195,58 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
         (self.map, svh)
     }
 
-    fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) {
-        debug!("hir_map: {:?} => {:?}", id, entry);
-        let local_map = &mut self.map[id.owner];
+    fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>, hash: Fingerprint) {
         let i = id.local_id.as_u32() as usize;
-        let len = local_map.len();
-        if i >= len {
-            local_map.extend(repeat(None).take(i - len + 1));
+
+        let arena = self.arena;
+
+        let data = &mut self.map[id.owner];
+
+        if data.with_bodies.is_none() {
+            data.with_bodies = Some(arena.alloc(HirOwnerItems {
+                hash,
+                items: IndexVec::new(),
+                bodies: FxHashMap::default(),
+            }));
+        }
+
+        let items = data.with_bodies.as_mut().unwrap();
+
+        if i == 0 {
+            // Overwrite the dummy hash with the real HIR owner hash.
+            items.hash = hash;
+
+            // FIXME: feature(impl_trait_in_bindings) broken and trigger this assert
+            //assert!(data.signature.is_none());
+
+            data.signature =
+                Some(self.arena.alloc(HirOwner { parent: entry.parent, node: entry.node }));
+        } else {
+            assert_eq!(entry.parent.owner, id.owner);
+            insert_vec_map(
+                &mut items.items,
+                id.local_id,
+                HirItem { parent: entry.parent.local_id, node: entry.node },
+            );
         }
-        local_map[id.local_id] = Some(entry);
     }
 
     fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
-        let entry = Entry {
-            parent: self.parent_node,
-            dep_node: if self.currently_in_body {
-                self.current_full_dep_index
-            } else {
-                self.current_signature_dep_index
-            },
-            node,
-        };
+        self.insert_with_hash(span, hir_id, node, Fingerprint::ZERO)
+    }
+
+    fn insert_with_hash(&mut self, span: Span, hir_id: HirId, node: Node<'hir>, hash: Fingerprint) {
+        let entry = Entry { parent: self.parent_node, node };
 
         // Make sure that the DepNode of some node coincides with the HirId
         // owner of that node.
         if cfg!(debug_assertions) {
-            let node_id = self.hir_to_node_id[&hir_id];
+            let node_id = self.definitions.hir_to_node_id(hir_id);
             assert_eq!(self.definitions.node_to_hir_id(node_id), hir_id);
 
             if hir_id.owner != self.current_dep_node_owner {
-                let node_str = match self.definitions.opt_def_index(node_id) {
-                    Some(def_index) => self.definitions.def_path(def_index).to_string_no_crate(),
+                let node_str = match self.definitions.opt_local_def_id(node_id) {
+                    Some(def_id) => self.definitions.def_path(def_id).to_string_no_crate(),
                     None => format!("{:?}", node),
                 };
 
@@ -287,7 +271,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
             }
         }
 
-        self.insert_entry(hir_id, entry);
+        self.insert_entry(hir_id, entry, hash);
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) {
@@ -299,37 +283,22 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
 
     fn with_dep_node_owner<
         T: for<'b> HashStable<StableHashingContext<'b>>,
-        F: FnOnce(&mut Self),
+        F: FnOnce(&mut Self, Fingerprint),
     >(
         &mut self,
-        dep_node_owner: DefIndex,
+        dep_node_owner: LocalDefId,
         item_like: &T,
         f: F,
     ) {
         let prev_owner = self.current_dep_node_owner;
-        let prev_signature_dep_index = self.current_signature_dep_index;
-        let prev_full_dep_index = self.current_full_dep_index;
-        let prev_in_body = self.currently_in_body;
 
         let def_path_hash = self.definitions.def_path_hash(dep_node_owner);
 
-        let (signature_dep_index, full_dep_index) = alloc_hir_dep_nodes(
-            self.dep_graph,
-            &mut self.hcx,
-            def_path_hash,
-            item_like,
-            &mut self.hir_body_nodes,
-        );
-        self.current_signature_dep_index = signature_dep_index;
-        self.current_full_dep_index = full_dep_index;
+        let hash = hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes);
 
         self.current_dep_node_owner = dep_node_owner;
-        self.currently_in_body = false;
-        f(self);
-        self.currently_in_body = prev_in_body;
+        f(self, hash);
         self.current_dep_node_owner = prev_owner;
-        self.current_full_dep_index = prev_full_dep_index;
-        self.current_signature_dep_index = prev_signature_dep_index;
     }
 }
 
@@ -340,7 +309,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     /// deep walking so that we walk nested items in the context of
     /// their outer items.
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         panic!("`visit_nested_xxx` must be manually implemented in this visitor");
     }
 
@@ -358,10 +327,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 
     fn visit_nested_body(&mut self, id: BodyId) {
-        let prev_in_body = self.currently_in_body;
-        self.currently_in_body = true;
         self.visit_body(self.krate.body(id));
-        self.currently_in_body = prev_in_body;
     }
 
     fn visit_param(&mut self, param: &'hir Param<'hir>) {
@@ -376,10 +342,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         debug!("visit_item: {:?}", i);
         debug_assert_eq!(
             i.hir_id.owner,
-            self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap()
+            self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(i.hir_id)).unwrap()
         );
-        self.with_dep_node_owner(i.hir_id.owner, i, |this| {
-            this.insert(i.span, i.hir_id, Node::Item(i));
+        self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| {
+            this.insert_with_hash(i.span, i.hir_id, Node::Item(i), hash);
             this.with_parent(i.hir_id, |this| {
                 if let ItemKind::Struct(ref struct_def, _) = i.kind {
                     // If this is a tuple or unit-like struct, register the constructor.
@@ -408,10 +374,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
         debug_assert_eq!(
             ti.hir_id.owner,
-            self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap()
+            self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(ti.hir_id)).unwrap()
         );
-        self.with_dep_node_owner(ti.hir_id.owner, ti, |this| {
-            this.insert(ti.span, ti.hir_id, Node::TraitItem(ti));
+        self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| {
+            this.insert_with_hash(ti.span, ti.hir_id, Node::TraitItem(ti), hash);
 
             this.with_parent(ti.hir_id, |this| {
                 intravisit::walk_trait_item(this, ti);
@@ -422,10 +388,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
         debug_assert_eq!(
             ii.hir_id.owner,
-            self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap()
+            self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(ii.hir_id)).unwrap()
         );
-        self.with_dep_node_owner(ii.hir_id.owner, ii, |this| {
-            this.insert(ii.span, ii.hir_id, Node::ImplItem(ii));
+        self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| {
+            this.insert_with_hash(ii.span, ii.hir_id, Node::ImplItem(ii), hash);
 
             this.with_parent(ii.hir_id, |this| {
                 intravisit::walk_impl_item(this, ii);
@@ -541,11 +507,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 
     fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) {
-        let node_id = self.hir_to_node_id[&macro_def.hir_id];
-        let def_index = self.definitions.opt_def_index(node_id).unwrap();
-
-        self.with_dep_node_owner(def_index, macro_def, |this| {
-            this.insert(macro_def.span, macro_def.hir_id, Node::MacroDef(macro_def));
+        self.with_dep_node_owner(macro_def.hir_id.owner, macro_def, |this, hash| {
+            this.insert_with_hash(
+                macro_def.span,
+                macro_def.hir_id,
+                Node::MacroDef(macro_def),
+                hash,
+            );
         });
     }
 
@@ -584,11 +552,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 }
 
-// This is a wrapper structure that allows determining if span values within
-// the wrapped item should be hashed or not.
 struct HirItemLike<T> {
     item_like: T,
-    hash_bodies: bool,
 }
 
 impl<'hir, T> HashStable<StableHashingContext<'hir>> for HirItemLike<T>
@@ -596,7 +561,7 @@ where
     T: HashStable<StableHashingContext<'hir>>,
 {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) {
-        hcx.while_hashing_hir_bodies(self.hash_bodies, |hcx| {
+        hcx.while_hashing_hir_bodies(true, |hcx| {
             self.item_like.hash_stable(hcx, hasher);
         });
     }
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index e1b5ec041db..aa4742ea891 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -5,22 +5,21 @@
 //! expressions) that are mostly just leftovers.
 
 use rustc_ast::ast;
-use rustc_ast::node_id::NodeMap;
-use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::IndexVec;
 use rustc_session::CrateDisambiguator;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
-use std::borrow::Borrow;
 use std::fmt::Write;
 use std::hash::Hash;
 
+pub use rustc_hir::def_id::DefPathHash;
+
 /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
 /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
 /// stores the `DefIndex` of its parent.
@@ -78,21 +77,29 @@ impl DefPathTable {
 #[derive(Clone, Default)]
 pub struct Definitions {
     table: DefPathTable,
-    node_to_def_index: NodeMap<DefIndex>,
-    def_index_to_node: IndexVec<DefIndex, ast::NodeId>,
-    pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
+
+    def_id_to_span: IndexVec<LocalDefId, Span>,
+
+    // FIXME(eddyb) don't go through `ast::NodeId` to convert between `HirId`
+    // and `LocalDefId` - ideally all `LocalDefId`s would be HIR owners.
+    node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
+    def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
+
+    pub(super) node_id_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
+    /// The reverse mapping of `node_id_to_hir_id`.
+    pub(super) hir_id_to_node_id: FxHashMap<hir::HirId, ast::NodeId>,
+
     /// If `ExpnId` is an ID of some macro expansion,
     /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
     parent_modules_of_macro_defs: FxHashMap<ExpnId, DefId>,
-    /// Item with a given `DefIndex` was defined during macro expansion with ID `ExpnId`.
-    expansions_that_defined: FxHashMap<DefIndex, ExpnId>,
-    next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>,
-    def_index_to_span: FxHashMap<DefIndex, Span>,
+    /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
+    expansions_that_defined: FxHashMap<LocalDefId, ExpnId>,
+    next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>,
     /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
     /// we know what parent node that fragment should be attached to thanks to this table.
-    invocation_parents: FxHashMap<ExpnId, DefIndex>,
+    invocation_parents: FxHashMap<ExpnId, LocalDefId>,
     /// Indices of unnamed struct or variant fields with unresolved attributes.
-    placeholder_field_indices: NodeMap<usize>,
+    placeholder_field_indices: FxHashMap<ast::NodeId, usize>,
 }
 
 /// A unique identifier that we can use to lookup a definition
@@ -282,28 +289,6 @@ pub enum DefPathData {
     ImplTrait,
 }
 
-#[derive(
-    Copy,
-    Clone,
-    Hash,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Debug,
-    RustcEncodable,
-    RustcDecodable,
-    HashStable
-)]
-pub struct DefPathHash(pub Fingerprint);
-
-impl Borrow<Fingerprint> for DefPathHash {
-    #[inline]
-    fn borrow(&self) -> &Fingerprint {
-        &self.0
-    }
-}
-
 impl Definitions {
     pub fn def_path_table(&self) -> &DefPathTable {
         &self.table
@@ -314,13 +299,13 @@ impl Definitions {
         self.table.index_to_key.len()
     }
 
-    pub fn def_key(&self, index: DefIndex) -> DefKey {
-        self.table.def_key(index)
+    pub fn def_key(&self, id: LocalDefId) -> DefKey {
+        self.table.def_key(id.local_def_index)
     }
 
     #[inline(always)]
-    pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
-        self.table.def_path_hash(index)
+    pub fn def_path_hash(&self, id: LocalDefId) -> DefPathHash {
+        self.table.def_path_hash(id.local_def_index)
     }
 
     /// Returns the path from the crate root to `index`. The root
@@ -328,29 +313,27 @@ impl Definitions {
     /// empty vector for the crate root). For an inlined item, this
     /// will be the path of the item in the external crate (but the
     /// path will begin with the path to the external crate).
-    pub fn def_path(&self, index: DefIndex) -> DefPath {
-        DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p))
-    }
-
-    #[inline]
-    pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
-        self.node_to_def_index.get(&node).copied()
+    pub fn def_path(&self, id: LocalDefId) -> DefPath {
+        DefPath::make(LOCAL_CRATE, id.local_def_index, |index| {
+            self.def_key(LocalDefId { local_def_index: index })
+        })
     }
 
     #[inline]
-    pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
-        self.opt_def_index(node).map(DefId::local)
+    pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<LocalDefId> {
+        self.node_id_to_def_id.get(&node).copied()
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     #[inline]
     pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
-        self.opt_local_def_id(node).unwrap()
+        self.opt_local_def_id(node).unwrap().to_def_id()
     }
 
     #[inline]
     pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
-        if def_id.krate == LOCAL_CRATE {
-            let node_id = self.def_index_to_node[def_id.index];
+        if let Some(def_id) = def_id.as_local() {
+            let node_id = self.def_id_to_node_id[def_id];
             if node_id != ast::DUMMY_NODE_ID {
                 return Some(node_id);
             }
@@ -360,34 +343,36 @@ impl Definitions {
 
     #[inline]
     pub fn as_local_hir_id(&self, def_id: DefId) -> Option<hir::HirId> {
-        if def_id.krate == LOCAL_CRATE {
-            let hir_id = self.def_index_to_hir_id(def_id.index);
+        if let Some(def_id) = def_id.as_local() {
+            let hir_id = self.local_def_id_to_hir_id(def_id);
             if hir_id != hir::DUMMY_HIR_ID { Some(hir_id) } else { None }
         } else {
             None
         }
     }
 
+    // FIXME(eddyb) rename to `hir_id_to_node_id`.
+    #[inline]
+    pub fn hir_to_node_id(&self, hir_id: hir::HirId) -> ast::NodeId {
+        self.hir_id_to_node_id[&hir_id]
+    }
+
+    // FIXME(eddyb) rename to `node_id_to_hir_id`.
     #[inline]
     pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
-        self.node_to_hir_id[node_id]
+        self.node_id_to_hir_id[node_id]
     }
 
     #[inline]
-    pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> hir::HirId {
-        let node_id = self.def_index_to_node[def_index];
-        self.node_to_hir_id[node_id]
+    pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId {
+        let node_id = self.def_id_to_node_id[id];
+        self.node_id_to_hir_id[node_id]
     }
 
-    /// Retrieves the span of the given `DefId` if `DefId` is in the local crate, the span exists
-    /// and it's not `DUMMY_SP`.
+    /// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
     #[inline]
     pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
-        if def_id.krate == LOCAL_CRATE {
-            self.def_index_to_span.get(&def_id.index).copied()
-        } else {
-            None
-        }
+        if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None }
     }
 
     /// Adds a root definition (no parent) and a few other reserved definitions.
@@ -395,7 +380,7 @@ impl Definitions {
         &mut self,
         crate_name: &str,
         crate_disambiguator: CrateDisambiguator,
-    ) -> DefIndex {
+    ) -> LocalDefId {
         let key = DefKey {
             parent: None,
             disambiguated_data: DisambiguatedDefPathData {
@@ -408,36 +393,38 @@ impl Definitions {
         let def_path_hash = key.compute_stable_hash(parent_hash);
 
         // Create the definition.
-        let root_index = self.table.allocate(key, def_path_hash);
-        assert_eq!(root_index, CRATE_DEF_INDEX);
-        assert!(self.def_index_to_node.is_empty());
-        self.def_index_to_node.push(ast::CRATE_NODE_ID);
-        self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index);
-        self.set_invocation_parent(ExpnId::root(), root_index);
+        let root = LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) };
+        assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
+
+        assert_eq!(self.def_id_to_node_id.push(ast::CRATE_NODE_ID), root);
+        assert_eq!(self.def_id_to_span.push(rustc_span::DUMMY_SP), root);
 
-        root_index
+        self.node_id_to_def_id.insert(ast::CRATE_NODE_ID, root);
+        self.set_invocation_parent(ExpnId::root(), root);
+
+        root
     }
 
     /// Adds a definition with a parent definition.
     pub fn create_def_with_parent(
         &mut self,
-        parent: DefIndex,
+        parent: LocalDefId,
         node_id: ast::NodeId,
         data: DefPathData,
         expn_id: ExpnId,
         span: Span,
-    ) -> DefIndex {
+    ) -> LocalDefId {
         debug!(
             "create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
             parent, node_id, data
         );
 
         assert!(
-            !self.node_to_def_index.contains_key(&node_id),
+            !self.node_id_to_def_id.contains_key(&node_id),
             "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
             node_id,
             data,
-            self.table.def_key(self.node_to_def_index[&node_id])
+            self.table.def_key(self.node_id_to_def_id[&node_id].local_def_index),
         );
 
         // The root node must be created with `create_root_def()`.
@@ -452,52 +439,55 @@ impl Definitions {
         };
 
         let key = DefKey {
-            parent: Some(parent),
+            parent: Some(parent.local_def_index),
             disambiguated_data: DisambiguatedDefPathData { data, disambiguator },
         };
 
-        let parent_hash = self.table.def_path_hash(parent);
+        let parent_hash = self.table.def_path_hash(parent.local_def_index);
         let def_path_hash = key.compute_stable_hash(parent_hash);
 
         debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
 
         // Create the definition.
-        let index = self.table.allocate(key, def_path_hash);
-        assert_eq!(index.index(), self.def_index_to_node.len());
-        self.def_index_to_node.push(node_id);
+        let def_id = LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) };
+
+        assert_eq!(self.def_id_to_node_id.push(node_id), def_id);
+        assert_eq!(self.def_id_to_span.push(span), def_id);
 
-        // Some things for which we allocate `DefIndex`es don't correspond to
+        // Some things for which we allocate `LocalDefId`s don't correspond to
         // anything in the AST, so they don't have a `NodeId`. For these cases
-        // we don't need a mapping from `NodeId` to `DefIndex`.
+        // we don't need a mapping from `NodeId` to `LocalDefId`.
         if node_id != ast::DUMMY_NODE_ID {
-            debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
-            self.node_to_def_index.insert(node_id, index);
+            debug!("create_def_with_parent: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
+            self.node_id_to_def_id.insert(node_id, def_id);
         }
 
         if expn_id != ExpnId::root() {
-            self.expansions_that_defined.insert(index, expn_id);
-        }
-
-        // The span is added if it isn't dummy.
-        if !span.is_dummy() {
-            self.def_index_to_span.insert(index, span);
+            self.expansions_that_defined.insert(def_id, expn_id);
         }
 
-        index
+        def_id
     }
 
     /// Initializes the `ast::NodeId` to `HirId` mapping once it has been generated during
     /// AST to HIR lowering.
     pub fn init_node_id_to_hir_id_mapping(&mut self, mapping: IndexVec<ast::NodeId, hir::HirId>) {
         assert!(
-            self.node_to_hir_id.is_empty(),
+            self.node_id_to_hir_id.is_empty(),
             "trying to initialize `NodeId` -> `HirId` mapping twice"
         );
-        self.node_to_hir_id = mapping;
+        self.node_id_to_hir_id = mapping;
+
+        // Build the reverse mapping of `node_id_to_hir_id`.
+        self.hir_id_to_node_id = self
+            .node_id_to_hir_id
+            .iter_enumerated()
+            .map(|(node_id, &hir_id)| (hir_id, node_id))
+            .collect();
     }
 
-    pub fn expansion_that_defined(&self, index: DefIndex) -> ExpnId {
-        self.expansions_that_defined.get(&index).copied().unwrap_or(ExpnId::root())
+    pub fn expansion_that_defined(&self, id: LocalDefId) -> ExpnId {
+        self.expansions_that_defined.get(&id).copied().unwrap_or(ExpnId::root())
     }
 
     pub fn parent_module_of_macro_def(&self, expn_id: ExpnId) -> DefId {
@@ -508,13 +498,13 @@ impl Definitions {
         self.parent_modules_of_macro_defs.insert(expn_id, module);
     }
 
-    pub fn invocation_parent(&self, invoc_id: ExpnId) -> DefIndex {
+    pub fn invocation_parent(&self, invoc_id: ExpnId) -> LocalDefId {
         self.invocation_parents[&invoc_id]
     }
 
-    pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: DefIndex) {
+    pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: LocalDefId) {
         let old_parent = self.invocation_parents.insert(invoc_id, parent);
-        assert!(old_parent.is_none(), "parent `DefIndex` is reset for an invocation");
+        assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
     }
 
     pub fn placeholder_field_index(&self, node_id: ast::NodeId) -> usize {
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index a4f9193c0eb..e3386a2a910 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -1,18 +1,20 @@
 use crate::hir::map::Map;
+use crate::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ItemLocalId};
 
-pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) {
-    hir_map.dep_graph.assert_ignored();
+pub fn check_crate(tcx: TyCtxt<'_>) {
+    tcx.dep_graph.assert_ignored();
 
     let errors = Lock::new(Vec::new());
+    let hir_map = tcx.hir();
 
-    par_iter(&hir_map.krate.modules).for_each(|(module_id, _)| {
+    par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| {
         let local_def_id = hir_map.local_def_id(*module_id);
         hir_map.visit_item_likes_in_module(
             local_def_id,
@@ -24,27 +26,27 @@ pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) {
 
     if !errors.is_empty() {
         let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2);
-        sess.delay_span_bug(rustc_span::DUMMY_SP, &message);
+        tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, &message);
     }
 }
 
 struct HirIdValidator<'a, 'hir> {
-    hir_map: &'a Map<'hir>,
-    owner_def_index: Option<DefIndex>,
+    hir_map: Map<'hir>,
+    owner: Option<LocalDefId>,
     hir_ids_seen: FxHashSet<ItemLocalId>,
     errors: &'a Lock<Vec<String>>,
 }
 
 struct OuterVisitor<'a, 'hir> {
-    hir_map: &'a Map<'hir>,
+    hir_map: Map<'hir>,
     errors: &'a Lock<Vec<String>>,
 }
 
 impl<'a, 'hir> OuterVisitor<'a, 'hir> {
-    fn new_inner_visitor(&self, hir_map: &'a Map<'hir>) -> HirIdValidator<'a, 'hir> {
+    fn new_inner_visitor(&self, hir_map: Map<'hir>) -> HirIdValidator<'a, 'hir> {
         HirIdValidator {
             hir_map,
-            owner_def_index: None,
+            owner: None,
             hir_ids_seen: Default::default(),
             errors: self.errors,
         }
@@ -76,12 +78,12 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
     }
 
     fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, hir_id: HirId, walk: F) {
-        assert!(self.owner_def_index.is_none());
-        let owner_def_index = self.hir_map.local_def_id(hir_id).index;
-        self.owner_def_index = Some(owner_def_index);
+        assert!(self.owner.is_none());
+        let owner = self.hir_map.local_def_id(hir_id).expect_local();
+        self.owner = Some(owner);
         walk(self);
 
-        if owner_def_index == CRATE_DEF_INDEX {
+        if owner.local_def_index == CRATE_DEF_INDEX {
             return;
         }
 
@@ -103,27 +105,26 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
             let mut missing_items = Vec::with_capacity(missing.len());
 
             for local_id in missing {
-                let hir_id =
-                    HirId { owner: owner_def_index, local_id: ItemLocalId::from_u32(local_id) };
+                let hir_id = HirId { owner, local_id: ItemLocalId::from_u32(local_id) };
 
                 trace!("missing hir id {:#?}", hir_id);
 
                 missing_items.push(format!(
-                    "[local_id: {}, node:{}]",
+                    "[local_id: {}, owner: {}]",
                     local_id,
-                    self.hir_map.node_to_string(hir_id)
+                    self.hir_map.def_path(owner).to_string_no_crate()
                 ));
             }
             self.error(|| {
                 format!(
                     "ItemLocalIds not assigned densely in {}. \
                 Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}",
-                    self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(),
+                    self.hir_map.def_path(owner).to_string_no_crate(),
                     max,
                     missing_items,
                     self.hir_ids_seen
                         .iter()
-                        .map(|&local_id| HirId { owner: owner_def_index, local_id })
+                        .map(|&local_id| HirId { owner, local_id })
                         .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h)))
                         .collect::<Vec<_>>()
                 )
@@ -135,12 +136,12 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
 impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
     type Map = Map<'hir>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
         intravisit::NestedVisitorMap::OnlyBodies(self.hir_map)
     }
 
     fn visit_id(&mut self, hir_id: HirId) {
-        let owner = self.owner_def_index.expect("no owner_def_index");
+        let owner = self.owner.expect("no owner");
 
         if hir_id == hir::DUMMY_HIR_ID {
             self.error(|| {
@@ -157,8 +158,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
                 format!(
                     "HirIdValidator: The recorded owner of {} is {} instead of {}",
                     self.hir_map.node_to_string(hir_id),
-                    self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(),
-                    self.hir_map.def_path(DefId::local(owner)).to_string_no_crate()
+                    self.hir_map.def_path(hir_id.owner).to_string_no_crate(),
+                    self.hir_map.def_path(owner).to_string_no_crate()
                 )
             });
         }
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 0f129904b43..36cb19c6c37 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -3,14 +3,13 @@ pub use self::definitions::{
     DefKey, DefPath, DefPathData, DefPathHash, Definitions, DisambiguatedDefPathData,
 };
 
-use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex};
-use crate::middle::cstore::CrateStoreDyn;
+use crate::hir::{HirOwner, HirOwnerItems};
 use crate::ty::query::Providers;
+use crate::ty::TyCtxt;
 use rustc_ast::ast::{self, Name, NodeId};
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::print::Nested;
@@ -26,131 +25,125 @@ pub mod blocks;
 mod collector;
 pub mod definitions;
 mod hir_id_validator;
+pub use hir_id_validator::check_crate;
 
 /// Represents an entry and its parent `HirId`.
 #[derive(Copy, Clone, Debug)]
 pub struct Entry<'hir> {
     parent: HirId,
-    dep_node: DepNodeIndex,
     node: Node<'hir>,
 }
 
 impl<'hir> Entry<'hir> {
     fn parent_node(self) -> Option<HirId> {
         match self.node {
-            Node::Crate | Node::MacroDef(_) => None,
+            Node::Crate(_) | Node::MacroDef(_) => None,
             _ => Some(self.parent),
         }
     }
+}
 
-    fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> {
-        match self.node {
-            Node::Item(ref item) => match item.kind {
-                ItemKind::Fn(ref sig, _, _) => Some(&sig.decl),
-                _ => None,
-            },
-
-            Node::TraitItem(ref item) => match item.kind {
-                TraitItemKind::Method(ref sig, _) => Some(&sig.decl),
-                _ => None,
-            },
+fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
+    match node {
+        Node::Item(ref item) => match item.kind {
+            ItemKind::Fn(ref sig, _, _) => Some(&sig.decl),
+            _ => None,
+        },
 
-            Node::ImplItem(ref item) => match item.kind {
-                ImplItemKind::Method(ref sig, _) => Some(&sig.decl),
-                _ => None,
-            },
+        Node::TraitItem(ref item) => match item.kind {
+            TraitItemKind::Fn(ref sig, _) => Some(&sig.decl),
+            _ => None,
+        },
 
-            Node::Expr(ref expr) => match expr.kind {
-                ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl),
-                _ => None,
-            },
+        Node::ImplItem(ref item) => match item.kind {
+            ImplItemKind::Fn(ref sig, _) => Some(&sig.decl),
+            _ => None,
+        },
 
+        Node::Expr(ref expr) => match expr.kind {
+            ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl),
             _ => None,
-        }
-    }
+        },
 
-    fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> {
-        match &self.node {
-            Node::Item(item) => match &item.kind {
-                ItemKind::Fn(sig, _, _) => Some(sig),
-                _ => None,
-            },
+        _ => None,
+    }
+}
 
-            Node::TraitItem(item) => match &item.kind {
-                TraitItemKind::Method(sig, _) => Some(sig),
-                _ => None,
-            },
+fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> {
+    match &node {
+        Node::Item(item) => match &item.kind {
+            ItemKind::Fn(sig, _, _) => Some(sig),
+            _ => None,
+        },
 
-            Node::ImplItem(item) => match &item.kind {
-                ImplItemKind::Method(sig, _) => Some(sig),
-                _ => None,
-            },
+        Node::TraitItem(item) => match &item.kind {
+            TraitItemKind::Fn(sig, _) => Some(sig),
+            _ => None,
+        },
 
+        Node::ImplItem(item) => match &item.kind {
+            ImplItemKind::Fn(sig, _) => Some(sig),
             _ => None,
-        }
-    }
+        },
 
-    fn associated_body(self) -> Option<BodyId> {
-        match self.node {
-            Node::Item(item) => match item.kind {
-                ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => {
-                    Some(body)
-                }
-                _ => None,
-            },
+        _ => None,
+    }
+}
 
-            Node::TraitItem(item) => match item.kind {
-                TraitItemKind::Const(_, Some(body))
-                | TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body),
-                _ => None,
-            },
+fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
+    match node {
+        Node::Item(item) => match item.kind {
+            ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => {
+                Some(body)
+            }
+            _ => None,
+        },
 
-            Node::ImplItem(item) => match item.kind {
-                ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body),
-                _ => None,
-            },
+        Node::TraitItem(item) => match item.kind {
+            TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)) => {
+                Some(body)
+            }
+            _ => None,
+        },
 
-            Node::AnonConst(constant) => Some(constant.body),
+        Node::ImplItem(item) => match item.kind {
+            ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body) => Some(body),
+            _ => None,
+        },
 
-            Node::Expr(expr) => match expr.kind {
-                ExprKind::Closure(.., body, _, _) => Some(body),
-                _ => None,
-            },
+        Node::AnonConst(constant) => Some(constant.body),
 
+        Node::Expr(expr) => match expr.kind {
+            ExprKind::Closure(.., body, _, _) => Some(body),
             _ => None,
-        }
-    }
+        },
 
-    fn is_body_owner(self, hir_id: HirId) -> bool {
-        match self.associated_body() {
-            Some(b) => b.hir_id == hir_id,
-            None => false,
-        }
+        _ => None,
     }
 }
 
-/// This type is effectively a `HashMap<HirId, Entry<'hir>>`,
-/// but it is implemented as 2 layers of arrays.
-/// - first we have `A = IndexVec<DefIndex, B>` mapping `DefIndex`s to an inner value
-/// - which is `B = IndexVec<ItemLocalId, Option<Entry<'hir>>` which gives you the `Entry`.
-pub(super) type HirEntryMap<'hir> = IndexVec<DefIndex, IndexVec<ItemLocalId, Option<Entry<'hir>>>>;
-
-/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s.
-#[derive(Clone)]
-pub struct Map<'hir> {
-    krate: &'hir Crate<'hir>,
+fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool {
+    match associated_body(node) {
+        Some(b) => b.hir_id == hir_id,
+        None => false,
+    }
+}
 
-    pub dep_graph: DepGraph,
+pub(super) struct HirOwnerData<'hir> {
+    pub(super) signature: Option<&'hir HirOwner<'hir>>,
+    pub(super) with_bodies: Option<&'hir mut HirOwnerItems<'hir>>,
+}
 
+pub struct IndexedHir<'hir> {
     /// The SVH of the local crate.
     pub crate_hash: Svh,
 
-    map: HirEntryMap<'hir>,
-
-    definitions: Definitions,
+    pub(super) map: IndexVec<LocalDefId, HirOwnerData<'hir>>,
+}
 
-    /// The reverse mapping of `node_to_hir_id`.
-    hir_to_node_id: FxHashMap<HirId, NodeId>,
+#[derive(Copy, Clone)]
+pub struct Map<'hir> {
+    pub(super) tcx: TyCtxt<'hir>,
 }
 
 /// An iterator that walks up the ancestor tree of a given `HirId`.
@@ -186,53 +179,28 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
 }
 
 impl<'hir> Map<'hir> {
-    /// This is used internally in the dependency tracking system.
-    /// Use the `krate` method to ensure your dependency on the
-    /// crate is tracked.
-    pub fn untracked_krate(&self) -> &Crate<'hir> {
-        &self.krate
+    pub fn krate(&self) -> &'hir Crate<'hir> {
+        self.tcx.hir_crate(LOCAL_CRATE)
     }
 
     #[inline]
-    fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> {
-        let local_map = self.map.get(id.owner)?;
-        local_map.get(id.local_id)?.as_ref()
-    }
-
-    /// Registers a read in the dependency graph of the AST node with
-    /// the given `id`. This needs to be called each time a public
-    /// function returns the HIR for a node -- in other words, when it
-    /// "reveals" the content of a node to the caller (who might not
-    /// otherwise have had access to those contents, and hence needs a
-    /// read recorded). If the function just returns a DefId or
-    /// HirId, no actual content was returned, so no read is needed.
-    pub fn read(&self, hir_id: HirId) {
-        if let Some(entry) = self.lookup(hir_id) {
-            self.dep_graph.read_index(entry.dep_node);
-        } else {
-            bug!("called `HirMap::read()` with invalid `HirId`: {:?}", hir_id)
-        }
+    pub fn definitions(&self) -> &'hir Definitions {
+        &self.tcx.definitions
     }
 
-    #[inline]
-    pub fn definitions(&self) -> &Definitions {
-        &self.definitions
-    }
-
-    pub fn def_key(&self, def_id: DefId) -> DefKey {
-        assert!(def_id.is_local());
-        self.definitions.def_key(def_id.index)
+    pub fn def_key(&self, def_id: LocalDefId) -> DefKey {
+        self.tcx.definitions.def_key(def_id)
     }
 
     pub fn def_path_from_hir_id(&self, id: HirId) -> Option<DefPath> {
-        self.opt_local_def_id(id).map(|def_id| self.def_path(def_id))
+        self.opt_local_def_id(id).map(|def_id| self.def_path(def_id.expect_local()))
     }
 
-    pub fn def_path(&self, def_id: DefId) -> DefPath {
-        assert!(def_id.is_local());
-        self.definitions.def_path(def_id.index)
+    pub fn def_path(&self, def_id: LocalDefId) -> DefPath {
+        self.tcx.definitions.def_path(def_id)
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     #[inline]
     pub fn local_def_id_from_node_id(&self, node: NodeId) -> DefId {
         self.opt_local_def_id_from_node_id(node).unwrap_or_else(|| {
@@ -245,6 +213,7 @@ impl<'hir> Map<'hir> {
         })
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     #[inline]
     pub fn local_def_id(&self, hir_id: HirId) -> DefId {
         self.opt_local_def_id(hir_id).unwrap_or_else(|| {
@@ -259,46 +228,41 @@ impl<'hir> Map<'hir> {
     #[inline]
     pub fn opt_local_def_id(&self, hir_id: HirId) -> Option<DefId> {
         let node_id = self.hir_to_node_id(hir_id);
-        self.definitions.opt_local_def_id(node_id)
+        self.opt_local_def_id_from_node_id(node_id)
     }
 
     #[inline]
     pub fn opt_local_def_id_from_node_id(&self, node: NodeId) -> Option<DefId> {
-        self.definitions.opt_local_def_id(node)
+        Some(self.tcx.definitions.opt_local_def_id(node)?.to_def_id())
     }
 
     #[inline]
     pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
-        self.definitions.as_local_node_id(def_id)
+        self.tcx.definitions.as_local_node_id(def_id)
     }
 
     #[inline]
     pub fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
-        self.definitions.as_local_hir_id(def_id)
+        self.tcx.definitions.as_local_hir_id(def_id)
     }
 
     #[inline]
     pub fn hir_to_node_id(&self, hir_id: HirId) -> NodeId {
-        self.hir_to_node_id[&hir_id]
+        self.tcx.definitions.hir_to_node_id(hir_id)
     }
 
     #[inline]
     pub fn node_to_hir_id(&self, node_id: NodeId) -> HirId {
-        self.definitions.node_to_hir_id(node_id)
-    }
-
-    #[inline]
-    pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> HirId {
-        self.definitions.def_index_to_hir_id(def_index)
+        self.tcx.definitions.node_to_hir_id(node_id)
     }
 
     #[inline]
     pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
-        self.definitions.def_index_to_hir_id(def_id.to_def_id().index)
+        self.tcx.definitions.local_def_id_to_hir_id(def_id)
     }
 
     pub fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
-        let node = if let Some(node) = self.find(hir_id) { node } else { return None };
+        let node = self.find(hir_id)?;
 
         Some(match node {
             Node::Item(item) => match item.kind {
@@ -326,12 +290,12 @@ impl<'hir> Map<'hir> {
             },
             Node::TraitItem(item) => match item.kind {
                 TraitItemKind::Const(..) => DefKind::AssocConst,
-                TraitItemKind::Method(..) => DefKind::Method,
+                TraitItemKind::Fn(..) => DefKind::AssocFn,
                 TraitItemKind::Type(..) => DefKind::AssocTy,
             },
             Node::ImplItem(item) => match item.kind {
                 ImplItemKind::Const(..) => DefKind::AssocConst,
-                ImplItemKind::Method(..) => DefKind::Method,
+                ImplItemKind::Fn(..) => DefKind::AssocFn,
                 ImplItemKind::TyAlias(..) => DefKind::AssocTy,
                 ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy,
             },
@@ -362,7 +326,7 @@ impl<'hir> Map<'hir> {
             | Node::Lifetime(_)
             | Node::Visibility(_)
             | Node::Block(_)
-            | Node::Crate => return None,
+            | Node::Crate(_) => return None,
             Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
             Node::GenericParam(param) => match param.kind {
                 GenericParamKind::Lifetime { .. } => return None,
@@ -373,54 +337,58 @@ impl<'hir> Map<'hir> {
     }
 
     fn find_entry(&self, id: HirId) -> Option<Entry<'hir>> {
-        self.lookup(id).cloned()
+        Some(self.get_entry(id))
     }
 
-    pub fn item(&self, id: HirId) -> &'hir Item<'hir> {
-        self.read(id);
+    fn get_entry(&self, id: HirId) -> Entry<'hir> {
+        if id.local_id == ItemLocalId::from_u32(0) {
+            let owner = self.tcx.hir_owner(id.owner);
+            Entry { parent: owner.parent, node: owner.node }
+        } else {
+            let owner = self.tcx.hir_owner_items(id.owner);
+            let item = owner.items[id.local_id].as_ref().unwrap();
+            Entry { parent: HirId { owner: id.owner, local_id: item.parent }, node: item.node }
+        }
+    }
 
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.item(id)
+    pub fn item(&self, id: HirId) -> &'hir Item<'hir> {
+        match self.find(id).unwrap() {
+            Node::Item(item) => item,
+            _ => bug!(),
+        }
     }
 
     pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
-        self.read(id.hir_id);
-
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.trait_item(id)
+        match self.find(id.hir_id).unwrap() {
+            Node::TraitItem(item) => item,
+            _ => bug!(),
+        }
     }
 
     pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        self.read(id.hir_id);
-
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.impl_item(id)
+        match self.find(id.hir_id).unwrap() {
+            Node::ImplItem(item) => item,
+            _ => bug!(),
+        }
     }
 
     pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
-        self.read(id.hir_id);
-
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.body(id)
+        self.tcx.hir_owner_items(id.hir_id.owner).bodies.get(&id.hir_id.local_id).unwrap()
     }
 
     pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
-        if let Some(entry) = self.find_entry(hir_id) {
-            entry.fn_decl()
+        if let Some(node) = self.find(hir_id) {
+            fn_decl(node)
         } else {
-            bug!("no entry for hir_id `{}`", hir_id)
+            bug!("no node for hir_id `{}`", hir_id)
         }
     }
 
     pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> {
-        if let Some(entry) = self.find_entry(hir_id) {
-            entry.fn_sig()
+        if let Some(node) = self.find(hir_id) {
+            fn_sig(node)
         } else {
-            bug!("no entry for hir_id `{}`", hir_id)
+            bug!("no node for hir_id `{}`", hir_id)
         }
     }
 
@@ -429,10 +397,11 @@ impl<'hir> Map<'hir> {
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
     pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> HirId {
         let parent = self.get_parent_node(hir_id);
-        assert!(self.lookup(parent).map_or(false, |e| e.is_body_owner(hir_id)));
+        assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)));
         parent
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
         self.local_def_id(self.body_owner(id))
     }
@@ -440,14 +409,8 @@ impl<'hir> Map<'hir> {
     /// Given a `HirId`, returns the `BodyId` associated with it,
     /// if the node is a body owner, otherwise returns `None`.
     pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option<BodyId> {
-        if let Some(entry) = self.find_entry(hir_id) {
-            if self.dep_graph.is_fully_enabled() {
-                let hir_id_owner = hir_id.owner;
-                let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
-                self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
-            }
-
-            entry.associated_body()
+        if let Some(node) = self.find(hir_id) {
+            associated_body(node)
         } else {
             bug!("no entry for id `{}`", hir_id)
         }
@@ -472,8 +435,8 @@ impl<'hir> Map<'hir> {
             | Node::AnonConst(_) => BodyOwnerKind::Const,
             Node::Ctor(..)
             | Node::Item(&Item { kind: ItemKind::Fn(..), .. })
-            | Node::TraitItem(&TraitItem { kind: TraitItemKind::Method(..), .. })
-            | Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => BodyOwnerKind::Fn,
+            | Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. })
+            | Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), .. }) => BodyOwnerKind::Fn,
             Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m),
             Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure,
             node => bug!("{:#?} is not a body node", node),
@@ -499,29 +462,24 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn trait_impls(&self, trait_did: DefId) -> &'hir [HirId] {
-        self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls));
-
-        // N.B., intentionally bypass `self.krate()` so that we
-        // do not trigger a read of the whole krate here
-        self.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
+        self.tcx.all_local_trait_impls(LOCAL_CRATE).get(&trait_did).map_or(&[], |xs| &xs[..])
     }
 
     /// Gets the attributes on the crate. This is preferable to
     /// invoking `krate.attrs` because it registers a tighter
     /// dep-graph access.
     pub fn krate_attrs(&self) -> &'hir [ast::Attribute] {
-        let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX);
-
-        self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
-        &self.krate.attrs
+        match self.get_entry(CRATE_HIR_ID).node {
+            Node::Crate(item) => item.attrs,
+            _ => bug!(),
+        }
     }
 
     pub fn get_module(&self, module: DefId) -> (&'hir Mod<'hir>, Span, HirId) {
         let hir_id = self.as_local_hir_id(module).unwrap();
-        self.read(hir_id);
-        match self.find_entry(hir_id).unwrap().node {
+        match self.get_entry(hir_id).node {
             Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id),
-            Node::Crate => (&self.krate.module, self.krate.span, hir_id),
+            Node::Crate(item) => (&item.module, item.span, hir_id),
             node => panic!("not a module: {:?}", node),
         }
     }
@@ -530,15 +488,7 @@ impl<'hir> Map<'hir> {
     where
         V: ItemLikeVisitor<'hir>,
     {
-        let hir_id = self.as_local_hir_id(module).unwrap();
-
-        // Read the module so we'll be re-executed if new items
-        // appear immediately under in the module. If some new item appears
-        // in some nested item in the module, we'll be re-executed due to reads
-        // in the expect_* calls the loops below
-        self.read(hir_id);
-
-        let module = &self.krate.modules[&hir_id];
+        let module = self.tcx.hir_module_items(module.expect_local());
 
         for id in &module.items {
             visitor.visit_item(self.expect_item(*id));
@@ -555,12 +505,11 @@ impl<'hir> Map<'hir> {
 
     /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
     pub fn get(&self, id: HirId) -> Node<'hir> {
-        // read recorded by `find`
         self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id))
     }
 
     pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
-        self.as_local_hir_id(id).map(|id| self.get(id)) // read recorded by `get`
+        self.as_local_hir_id(id).map(|id| self.get(id))
     }
 
     pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
@@ -584,13 +533,8 @@ impl<'hir> Map<'hir> {
 
     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
     pub fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
-        let result = self
-            .find_entry(hir_id)
-            .and_then(|entry| if let Node::Crate = entry.node { None } else { Some(entry.node) });
-        if result.is_some() {
-            self.read(hir_id);
-        }
-        result
+        let node = self.get_entry(hir_id).node;
+        if let Node::Crate(..) = node { None } else { Some(node) }
     }
 
     /// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there
@@ -604,13 +548,7 @@ impl<'hir> Map<'hir> {
     /// from a node to the root of the HIR (unless you get back the same ID here,
     /// which can happen if the ID is not in the map itself or is just weird).
     pub fn get_parent_node(&self, hir_id: HirId) -> HirId {
-        if self.dep_graph.is_fully_enabled() {
-            let hir_id_owner = hir_id.owner;
-            let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
-            self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
-        }
-
-        self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id)
+        self.get_entry(hir_id).parent_node().unwrap_or(hir_id)
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
@@ -655,9 +593,9 @@ impl<'hir> Map<'hir> {
 
     /// Whether `hir_id` corresponds to a `mod` or a crate.
     pub fn is_hir_id_module(&self, hir_id: HirId) -> bool {
-        match self.lookup(hir_id) {
-            Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. })
-            | Some(Entry { node: Node::Crate, .. }) => true,
+        match self.get_entry(hir_id) {
+            Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }
+            | Entry { node: Node::Crate(..), .. } => true,
             _ => false,
         }
     }
@@ -734,7 +672,7 @@ impl<'hir> Map<'hir> {
     pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
         for (hir_id, node) in self.parent_iter(hir_id) {
             match node {
-                Node::Crate
+                Node::Crate(_)
                 | Node::Item(_)
                 | Node::ForeignItem(_)
                 | Node::TraitItem(_)
@@ -800,11 +738,11 @@ impl<'hir> Map<'hir> {
                     _ => false,
                 },
                 Node::TraitItem(ti) => match ti.kind {
-                    TraitItemKind::Method(..) => true,
+                    TraitItemKind::Fn(..) => true,
                     _ => false,
                 },
                 Node::ImplItem(ii) => match ii.kind {
-                    ImplItemKind::Method(..) => true,
+                    ImplItemKind::Fn(..) => true,
                     _ => false,
                 },
                 Node::Block(_) => true,
@@ -836,6 +774,7 @@ impl<'hir> Map<'hir> {
         scope
     }
 
+    // FIXME(eddyb) this function can and should return `LocalDefId`.
     pub fn get_parent_did(&self, id: HirId) -> DefId {
         self.local_def_id(self.get_parent_item(id))
     }
@@ -847,7 +786,6 @@ impl<'hir> Map<'hir> {
                 node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), ..
             } = entry
             {
-                self.read(hir_id); // reveals some of the content of a node
                 return nm.abi;
             }
         }
@@ -856,7 +794,6 @@ impl<'hir> Map<'hir> {
 
     pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> {
         match self.find(id) {
-            // read recorded by `find`
             Some(Node::Item(item)) => item,
             _ => bug!("expected item, found {}", self.node_to_string(id)),
         }
@@ -906,7 +843,6 @@ impl<'hir> Map<'hir> {
 
     pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> {
         match self.find(id) {
-            // read recorded by find
             Some(Node::Expr(expr)) => expr,
             _ => bug!("expected expr, found {}", self.node_to_string(id)),
         }
@@ -938,7 +874,6 @@ impl<'hir> Map<'hir> {
     /// Given a node ID, gets a list of attributes associated with the AST
     /// corresponding to the node-ID.
     pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
-        self.read(id); // reveals attributes on the node
         let attrs = match self.find_entry(id).map(|entry| entry.node) {
             Some(Node::Param(a)) => Some(&a.attrs[..]),
             Some(Node::Local(l)) => Some(&l.attrs[..]),
@@ -955,53 +890,13 @@ impl<'hir> Map<'hir> {
             // Unit/tuple structs/variants take the attributes straight from
             // the struct/variant definition.
             Some(Node::Ctor(..)) => return self.attrs(self.get_parent_item(id)),
-            Some(Node::Crate) => Some(&self.krate.attrs[..]),
+            Some(Node::Crate(item)) => Some(&item.attrs[..]),
             _ => None,
         };
         attrs.unwrap_or(&[])
     }
 
-    /// Returns an iterator that yields all the hir ids in the map.
-    fn all_ids<'a>(&'a self) -> impl Iterator<Item = HirId> + 'a {
-        // This code is a bit awkward because the map is implemented as 2 levels of arrays,
-        // see the comment on `HirEntryMap`.
-        // Iterate over all the indices and return a reference to
-        // local maps and their index given that they exist.
-        self.map.iter_enumerated().flat_map(move |(owner, local_map)| {
-            // Iterate over each valid entry in the local map.
-            local_map.iter_enumerated().filter_map(move |(i, entry)| {
-                entry.map(move |_| {
-                    // Reconstruct the `HirId` based on the 3 indices we used to find it.
-                    HirId { owner, local_id: i }
-                })
-            })
-        })
-    }
-
-    /// Returns an iterator that yields the node id's with paths that
-    /// match `parts`.  (Requires `parts` is non-empty.)
-    ///
-    /// For example, if given `parts` equal to `["bar", "quux"]`, then
-    /// the iterator will produce node id's for items with paths
-    /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
-    /// any other such items it can find in the map.
-    pub fn nodes_matching_suffix<'a>(
-        &'a self,
-        parts: &'a [String],
-    ) -> impl Iterator<Item = NodeId> + 'a {
-        let nodes = NodesMatchingSuffix {
-            map: self,
-            item_name: parts.last().unwrap(),
-            in_which: &parts[..parts.len() - 1],
-        };
-
-        self.all_ids()
-            .filter(move |hir| nodes.matches_suffix(*hir))
-            .map(move |hir| self.hir_to_node_id(hir))
-    }
-
     pub fn span(&self, hir_id: HirId) -> Span {
-        self.read(hir_id); // reveals span from node
         match self.find_entry(hir_id).map(|entry| entry.node) {
             Some(Node::Param(param)) => param.span,
             Some(Node::Item(item)) => item.span,
@@ -1034,7 +929,7 @@ impl<'hir> Map<'hir> {
             Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v),
             Some(Node::Local(local)) => local.span,
             Some(Node::MacroDef(macro_def)) => macro_def.span,
-            Some(Node::Crate) => self.krate.span,
+            Some(Node::Crate(item)) => item.span,
             None => bug!("hir::map::Map::span: id not in map: {:?}", hir_id),
         }
     }
@@ -1082,82 +977,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
     }
 }
 
-pub struct NodesMatchingSuffix<'a> {
-    map: &'a Map<'a>,
-    item_name: &'a String,
-    in_which: &'a [String],
-}
-
-impl<'a> NodesMatchingSuffix<'a> {
-    /// Returns `true` only if some suffix of the module path for parent
-    /// matches `self.in_which`.
-    ///
-    /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
-    /// returns true if parent's path ends with the suffix
-    /// `x_0::x_1::...::x_k`.
-    fn suffix_matches(&self, parent: HirId) -> bool {
-        let mut cursor = parent;
-        for part in self.in_which.iter().rev() {
-            let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) {
-                None => return false,
-                Some((node_id, name)) => (node_id, name),
-            };
-            if mod_name.as_str() != *part {
-                return false;
-            }
-            cursor = self.map.get_parent_item(mod_id);
-        }
-        return true;
-
-        // Finds the first mod in parent chain for `id`, along with
-        // that mod's name.
-        //
-        // If `id` itself is a mod named `m` with parent `p`, then
-        // returns `Some(id, m, p)`.  If `id` has no mod in its parent
-        // chain, then returns `None`.
-        fn find_first_mod_parent(map: &Map<'_>, mut id: HirId) -> Option<(HirId, Name)> {
-            loop {
-                if let Node::Item(item) = map.find(id)? {
-                    if item_is_mod(&item) {
-                        return Some((id, item.ident.name));
-                    }
-                }
-                let parent = map.get_parent_item(id);
-                if parent == id {
-                    return None;
-                }
-                id = parent;
-            }
-
-            fn item_is_mod(item: &Item<'_>) -> bool {
-                match item.kind {
-                    ItemKind::Mod(_) => true,
-                    _ => false,
-                }
-            }
-        }
-    }
-
-    // We are looking at some node `n` with a given name and parent
-    // id; do their names match what I am seeking?
-    fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool {
-        name.as_str() == *self.item_name && self.suffix_matches(parent_of_n)
-    }
-
-    fn matches_suffix(&self, hir: HirId) -> bool {
-        let name = match self.map.find_entry(hir).map(|entry| entry.node) {
-            Some(Node::Item(n)) => n.name(),
-            Some(Node::ForeignItem(n)) => n.name(),
-            Some(Node::TraitItem(n)) => n.name(),
-            Some(Node::ImplItem(n)) => n.name(),
-            Some(Node::Variant(n)) => n.name(),
-            Some(Node::Field(n)) => n.name(),
-            _ => return false,
-        };
-        self.matches_names(self.map.get_parent_item(hir), name)
-    }
-}
-
 trait Named {
     fn name(&self) -> Name;
 }
@@ -1199,39 +1018,24 @@ impl Named for ImplItem<'_> {
     }
 }
 
-pub fn map_crate<'hir>(
-    sess: &rustc_session::Session,
-    cstore: &CrateStoreDyn,
-    krate: &'hir Crate<'hir>,
-    dep_graph: DepGraph,
-    definitions: Definitions,
-) -> Map<'hir> {
-    let _prof_timer = sess.prof.generic_activity("build_hir_map");
-
-    // Build the reverse mapping of `node_to_hir_id`.
-    let hir_to_node_id = definitions
-        .node_to_hir_id
-        .iter_enumerated()
-        .map(|(node_id, &hir_id)| (hir_id, node_id))
-        .collect();
+pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx IndexedHir<'tcx> {
+    assert_eq!(cnum, LOCAL_CRATE);
+
+    let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map");
 
     let (map, crate_hash) = {
-        let hcx = crate::ich::StableHashingContext::new(sess, krate, &definitions, cstore);
+        let hcx = tcx.create_stable_hashing_context();
 
         let mut collector =
-            NodeCollector::root(sess, krate, &dep_graph, &definitions, &hir_to_node_id, hcx);
-        intravisit::walk_crate(&mut collector, krate);
+            NodeCollector::root(tcx.sess, &**tcx.arena, tcx.untracked_crate, &tcx.definitions, hcx);
+        intravisit::walk_crate(&mut collector, tcx.untracked_crate);
 
-        let crate_disambiguator = sess.local_crate_disambiguator();
-        let cmdline_args = sess.opts.dep_tracking_hash();
-        collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args)
+        let crate_disambiguator = tcx.sess.local_crate_disambiguator();
+        let cmdline_args = tcx.sess.opts.dep_tracking_hash();
+        collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args)
     };
 
-    let map = Map { krate, dep_graph, crate_hash, map, hir_to_node_id, definitions };
-
-    sess.time("validate_HIR_map", || {
-        hir_id_validator::check_crate(&map, sess);
-    });
+    let map = tcx.arena.alloc(IndexedHir { crate_hash, map });
 
     map
 }
@@ -1300,7 +1104,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
             ImplItemKind::Const(..) => {
                 format!("assoc const {} in {}{}", ii.ident, path_str(), id_str)
             }
-            ImplItemKind::Method(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str),
+            ImplItemKind::Fn(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str),
             ImplItemKind::TyAlias(_) => {
                 format!("assoc type {} in {}{}", ii.ident, path_str(), id_str)
             }
@@ -1311,7 +1115,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
         Some(Node::TraitItem(ti)) => {
             let kind = match ti.kind {
                 TraitItemKind::Const(..) => "assoc constant",
-                TraitItemKind::Method(..) => "trait method",
+                TraitItemKind::Fn(..) => "trait method",
                 TraitItemKind::Type(..) => "assoc type",
             };
 
@@ -1342,7 +1146,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
         Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str),
         Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str),
         Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str),
-        Some(Node::Crate) => String::from("root_crate"),
+        Some(Node::Crate(..)) => String::from("root_crate"),
         None => format!("unknown node{}", id_str),
     }
 }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 1aa3b27bd1a..0042b6a3bd4 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1,62 +1,86 @@
-//! HIR datatypes. See the [rustc guide] for more info.
+//! HIR datatypes. See the [rustc dev guide] for more info.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 
 pub mod exports;
 pub mod map;
 
+use crate::ich::StableHashingContext;
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::print;
-use rustc_hir::Crate;
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
+use rustc_hir::Body;
 use rustc_hir::HirId;
-use std::ops::Deref;
+use rustc_hir::ItemLocalId;
+use rustc_hir::Node;
+use rustc_index::vec::IndexVec;
 
-/// A wrapper type which allows you to access HIR.
-#[derive(Clone)]
-pub struct Hir<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    map: &'tcx map::Map<'tcx>,
+pub struct HirOwner<'tcx> {
+    parent: HirId,
+    node: Node<'tcx>,
 }
 
-impl<'tcx> Hir<'tcx> {
-    pub fn krate(&self) -> &'tcx Crate<'tcx> {
-        self.tcx.hir_crate(LOCAL_CRATE)
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for HirOwner<'tcx> {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        let HirOwner { parent, node } = self;
+        hcx.while_hashing_hir_bodies(false, |hcx| {
+            parent.hash_stable(hcx, hasher);
+            node.hash_stable(hcx, hasher);
+        });
     }
 }
 
-impl<'tcx> Deref for Hir<'tcx> {
-    type Target = &'tcx map::Map<'tcx>;
+#[derive(Clone)]
+pub struct HirItem<'tcx> {
+    parent: ItemLocalId,
+    node: Node<'tcx>,
+}
 
-    #[inline(always)]
-    fn deref(&self) -> &Self::Target {
-        &self.map
-    }
+pub struct HirOwnerItems<'tcx> {
+    hash: Fingerprint,
+    items: IndexVec<ItemLocalId, Option<HirItem<'tcx>>>,
+    bodies: FxHashMap<ItemLocalId, &'tcx Body<'tcx>>,
 }
 
-impl<'hir> print::PpAnn for Hir<'hir> {
-    fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) {
-        self.map.nested(state, nested)
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for HirOwnerItems<'tcx> {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        // We ignore the `items` and `bodies` fields since these refer to information included in
+        // `hash` which is hashed in the collector and used for the crate hash.
+        let HirOwnerItems { hash, items: _, bodies: _ } = *self;
+        hash.hash_stable(hcx, hasher);
     }
 }
 
 impl<'tcx> TyCtxt<'tcx> {
     #[inline(always)]
-    pub fn hir(self) -> Hir<'tcx> {
-        Hir { tcx: self, map: &self.hir_map }
+    pub fn hir(self) -> map::Map<'tcx> {
+        map::Map { tcx: self }
     }
 
-    pub fn parent_module(self, id: HirId) -> DefId {
-        self.parent_module_from_def_id(DefId::local(id.owner))
+    pub fn parent_module(self, id: HirId) -> LocalDefId {
+        self.parent_module_from_def_id(id.owner)
     }
 }
 
 pub fn provide(providers: &mut Providers<'_>) {
     providers.parent_module_from_def_id = |tcx, id| {
         let hir = tcx.hir();
-        hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id).unwrap()))
+        hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id.to_def_id()).unwrap()))
+            .expect_local()
+    };
+    providers.hir_crate = |tcx, _| tcx.untracked_crate;
+    providers.index_hir = map::index_hir;
+    providers.hir_module_items = |tcx, id| {
+        let hir = tcx.hir();
+        let module = hir.as_local_hir_id(id.to_def_id()).unwrap();
+        &tcx.untracked_crate.modules[&module]
+    };
+    providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature.unwrap();
+    providers.hir_owner_items = |tcx, id| {
+        tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_ref().map(|items| &**items).unwrap()
     };
-    providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate();
     map::provide(providers);
 }
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index f28e26ef2c3..ba3763f6ee0 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -1,16 +1,15 @@
-use crate::hir::map::definitions::Definitions;
-use crate::hir::map::DefPathHash;
+use crate::hir::map::definitions::{DefPathHash, Definitions};
 use crate::ich::{self, CachingSourceMapView};
 use crate::middle::cstore::CrateStore;
-use crate::session::Session;
 use crate::ty::{fast_reject, TyCtxt};
 
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, DefIndex};
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, SourceFile};
@@ -124,16 +123,16 @@ impl<'a> StableHashingContext<'a> {
 
     #[inline]
     pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
-        if def_id.is_local() {
-            self.definitions.def_path_hash(def_id.index)
+        if let Some(def_id) = def_id.as_local() {
+            self.local_def_path_hash(def_id)
         } else {
             self.cstore.def_path_hash(def_id)
         }
     }
 
     #[inline]
-    pub fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash {
-        self.definitions.def_path_hash(def_index)
+    pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
+        self.definitions.def_path_hash(def_id)
     }
 
     #[inline]
@@ -164,15 +163,6 @@ impl<'a> StableHashingContext<'a> {
         }
         IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name))
     }
-
-    pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) {
-        let prev_hash_node_ids = self.node_id_hashing_mode;
-        self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
-
-        f(self);
-
-        self.node_id_hashing_mode = prev_hash_node_ids;
-    }
 }
 
 /// Something that can provide a stable hashing context.
@@ -206,19 +196,6 @@ impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> {
 
 impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {}
 
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::HirId {
-    type KeyType = (DefPathHash, hir::ItemLocalId);
-
-    #[inline]
-    fn to_stable_hash_key(
-        &self,
-        hcx: &StableHashingContext<'a>,
-    ) -> (DefPathHash, hir::ItemLocalId) {
-        let def_path_hash = hcx.local_def_path_hash(self.owner);
-        (def_path_hash, self.local_id)
-    }
-}
-
 impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
     fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
         panic!("Node IDs should not appear in incremental state");
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index eadc9ddeee6..1722b29266a 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -105,6 +105,20 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
             }
         }
     }
+
+    fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) {
+        let prev_hash_node_ids = self.node_id_hashing_mode;
+        self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
+
+        f(self);
+
+        self.node_id_hashing_mode = prev_hash_node_ids;
+    }
+
+    #[inline]
+    fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
+        self.local_def_path_hash(def_id)
+    }
 }
 
 impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId {
@@ -158,59 +172,6 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::ItemLocalId {
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem<'_> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let hir::TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self;
-
-        hcx.hash_hir_item_like(|hcx| {
-            ident.name.hash_stable(hcx, hasher);
-            attrs.hash_stable(hcx, hasher);
-            generics.hash_stable(hcx, hasher);
-            kind.hash_stable(hcx, hasher);
-            span.hash_stable(hcx, hasher);
-        });
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem<'_> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let hir::ImplItem {
-            hir_id: _,
-            ident,
-            ref vis,
-            defaultness,
-            ref attrs,
-            ref generics,
-            ref kind,
-            span,
-        } = *self;
-
-        hcx.hash_hir_item_like(|hcx| {
-            ident.name.hash_stable(hcx, hasher);
-            vis.hash_stable(hcx, hasher);
-            defaultness.hash_stable(hcx, hasher);
-            attrs.hash_stable(hcx, hasher);
-            generics.hash_stable(hcx, hasher);
-            kind.hash_stable(hcx, hasher);
-            span.hash_stable(hcx, hasher);
-        });
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for hir::Item<'_> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let hir::Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self;
-
-        hcx.hash_hir_item_like(|hcx| {
-            ident.name.hash_stable(hcx, hasher);
-            attrs.hash_stable(hcx, hasher);
-            kind.hash_stable(hcx, hasher);
-            vis.hash_stable(hcx, hasher);
-            span.hash_stable(hcx, hasher);
-        });
-    }
-}
-
 impl<'a> HashStable<StableHashingContext<'a>> for hir::Body<'_> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let hir::Body { params, value, generator_kind } = self;
@@ -236,21 +197,6 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::BodyId {
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for hir::def_id::DefIndex {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::def_id::DefIndex {
-    type KeyType = DefPathHash;
-
-    #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
-        hcx.local_def_path_hash(*self)
-    }
-}
-
 impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index daff8a0f182..c5a4b53b10d 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -5,7 +5,6 @@ use crate::ich::StableHashingContext;
 
 use rustc_ast::ast;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_span::SourceFile;
 
 use smallvec::SmallVec;
@@ -59,7 +58,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
             name_hash,
             name_was_remapped,
             unmapped_path: _,
-            crate_of_origin,
+            cnum,
             // Do not hash the source as it is not encoded
             src: _,
             src_hash,
@@ -75,9 +74,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
         (name_hash as u64).hash_stable(hcx, hasher);
         name_was_remapped.hash_stable(hcx, hasher);
 
-        DefId { krate: CrateNum::from_u32(crate_of_origin), index: CRATE_DEF_INDEX }
-            .hash_stable(hcx, hasher);
-
         src_hash.hash_stable(hcx, hasher);
 
         // We only hash the relative position within this source_file
@@ -101,6 +97,8 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
         for &char_pos in normalized_pos.iter() {
             stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher);
         }
+
+        cnum.hash_stable(hcx, hasher);
     }
 }
 
diff --git a/src/librustc/infer/canonical.rs b/src/librustc/infer/canonical.rs
index 76d0d57e233..5f7e8c84965 100644
--- a/src/librustc/infer/canonical.rs
+++ b/src/librustc/infer/canonical.rs
@@ -17,9 +17,9 @@
 //! `instantiate_query_result` method.
 //!
 //! For a more detailed look at what is happening here, check
-//! out the [chapter in the rustc guide][c].
+//! out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::MemberConstraint;
 use crate::ty::subst::GenericArg;
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 055d70effc6..8d0f604de6d 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -14,9 +14,9 @@
 //!   (or `tcx`), which is the central context during most of
 //!   compilation, containing the interners and other things.
 //!
-//! For more information about how rustc works, see the [rustc guide].
+//! For more information about how rustc works, see the [rustc dev guide].
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
 //!
 //! # Note
 //!
@@ -26,6 +26,9 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(const_transmute)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
@@ -80,7 +83,6 @@ pub mod infer;
 pub mod lint;
 pub mod middle;
 pub mod mir;
-pub use rustc_session as session;
 pub mod traits;
 pub mod ty;
 
diff --git a/src/librustc/lint.rs b/src/librustc/lint.rs
index dcc8dcbf219..d4d01a716db 100644
--- a/src/librustc/lint.rs
+++ b/src/librustc/lint.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir::HirId;
-pub use rustc_session::lint::{builtin, Level, Lint, LintId, LintPass};
+use rustc_session::lint::{builtin, Level, Lint, LintId};
 use rustc_session::{DiagnosticMessageId, Session};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 42d56c65462..9f5a56903aa 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -2,10 +2,9 @@
 //! are *mostly* used as a part of that interface, but these should
 //! probably get a better home if someone can find one.
 
-use crate::hir::map as hir_map;
-use crate::hir::map::definitions::{DefKey, DefPathTable};
-use crate::session::search_paths::PathKind;
-use crate::session::CrateDisambiguator;
+pub use self::NativeLibraryKind::*;
+
+use crate::hir::map::definitions::{DefKey, DefPath, DefPathHash, DefPathTable};
 use crate::ty::TyCtxt;
 
 use rustc_ast::ast;
@@ -14,15 +13,16 @@ use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{self, MetadataRef};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_macros::HashStable;
+use rustc_session::search_paths::PathKind;
+pub use rustc_session::utils::NativeLibraryKind;
+use rustc_session::CrateDisambiguator;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::spec::Target;
+
 use std::any::Any;
 use std::path::{Path, PathBuf};
 
-pub use self::NativeLibraryKind::*;
-pub use rustc_session::utils::NativeLibraryKind;
-
 // lonely orphan structs and enums looking for a better home
 
 /// Where a crate came from on the local filesystem. One of these three options
@@ -197,8 +197,8 @@ pub trait CrateStore {
 
     // resolve
     fn def_key(&self, def: DefId) -> DefKey;
-    fn def_path(&self, def: DefId) -> hir_map::DefPath;
-    fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash;
+    fn def_path(&self, def: DefId) -> DefPath;
+    fn def_path_hash(&self, def: DefId) -> DefPathHash;
     fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable;
 
     // "queries" used in resolve that aren't tracked for incremental compilation
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 6ece51fe866..ee5f822d313 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -4,7 +4,7 @@
 //! For all the gory details, see the provider of the `dependency_formats`
 //! query.
 
-use crate::session::config;
+use rustc_session::config;
 
 /// A list of dependencies for a certain crate type.
 ///
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index c8e284be6fc..36560371587 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -57,8 +57,7 @@ pub fn whitelisted(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
     // symbols. Other panic runtimes ensure that the relevant symbols are
     // available to link things together, but they're never exercised.
     if tcx.sess.panic_strategy() != PanicStrategy::Unwind {
-        return lang_item == LangItem::EhPersonalityLangItem
-            || lang_item == LangItem::EhUnwindResumeLangItem;
+        return lang_item == LangItem::EhPersonalityLangItem;
     }
 
     false
diff --git a/src/librustc/middle/limits.rs b/src/librustc/middle/limits.rs
index 22e4f5ea222..6de53c703e1 100644
--- a/src/librustc/middle/limits.rs
+++ b/src/librustc/middle/limits.rs
@@ -5,13 +5,13 @@
 //! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
 //! just peeks and looks for that attribute.
 
-use crate::session::Session;
-use core::num::IntErrorKind;
 use rustc::bug;
 use rustc_ast::ast;
+use rustc_data_structures::sync::Once;
+use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 
-use rustc_data_structures::sync::Once;
+use std::num::IntErrorKind;
 
 pub fn update_limits(sess: &Session, krate: &ast::Crate) {
     update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 1d043f5dcde..2735c4afca2 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -2,14 +2,13 @@
 //! the parent links in the region hierarchy.
 //!
 //! For more information about how MIR-based region-checking works,
-//! see the [rustc guide].
+//! see the [rustc dev guide].
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/borrowck.html
 
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::ty::{self, DefIdTree, TyCtxt};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -594,7 +593,7 @@ impl<'tcx> ScopeTree {
                               region scope tree for {:?} / {:?}",
                             param_owner,
                             self.root_parent.map(|id| tcx.hir().local_def_id(id)),
-                            self.root_body.map(|hir_id| DefId::local(hir_id.owner))
+                            self.root_body.map(|hir_id| hir_id.owner)
                         ),
                     );
                 }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index cf917daef83..46525bdedad 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -3,7 +3,6 @@
 
 pub use self::StabilityLevel::*;
 
-use crate::session::{DiagnosticMessageId, Session};
 use crate::ty::{self, TyCtxt};
 use rustc_ast::ast::CRATE_NODE_ID;
 use rustc_attr::{self as attr, ConstStability, Deprecation, RustcDeprecation, Stability};
@@ -17,6 +16,7 @@ use rustc_hir::{self, HirId};
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
 use rustc_session::lint::{BuiltinLintDiagnostics, Lint, LintBuffer};
 use rustc_session::parse::feature_err_issue;
+use rustc_session::{DiagnosticMessageId, Session};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{MultiSpan, Span};
 
@@ -250,7 +250,7 @@ pub enum EvalResult {
 fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, mut def_id: DefId) -> bool {
     // Check if `def_id` is a trait method.
     match tcx.def_kind(def_id) {
-        Some(DefKind::Method) | Some(DefKind::AssocTy) | Some(DefKind::AssocConst) => {
+        Some(DefKind::AssocFn) | Some(DefKind::AssocTy) | Some(DefKind::AssocConst) => {
             if let ty::TraitContainer(trait_def_id) = tcx.associated_item(def_id).container {
                 // Trait methods do not declare visibility (even
                 // for visibility info in cstore). Use containing
diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs
index 546ba586d30..9474f05b55d 100644
--- a/src/librustc/mir/interpret/allocation.rs
+++ b/src/librustc/mir/interpret/allocation.rs
@@ -41,6 +41,7 @@ pub struct Allocation<Tag = (), Extra = ()> {
     /// The size of the allocation. Currently, must always equal `bytes.len()`.
     pub size: Size,
     /// The alignment of the allocation to detect unaligned reads.
+    /// (`Align` guarantees that this is a power of two.)
     pub align: Align,
     /// `true` if the allocation is mutable.
     /// Also used by codegen to determine if a static should be put into mutable memory,
@@ -314,7 +315,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
                 &self.get_bytes(cx, ptr, size_with_null)?[..size]
             }
             // This includes the case where `offset` is out-of-bounds to begin with.
-            None => throw_unsup!(UnterminatedCString(ptr.erase_tag())),
+            None => throw_ub!(UnterminatedCString(ptr.erase_tag())),
         })
     }
 
@@ -573,7 +574,7 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
     fn check_defined(&self, ptr: Pointer<Tag>, size: Size) -> InterpResult<'tcx> {
         self.undef_mask
             .is_range_defined(ptr.offset, ptr.offset + size)
-            .or_else(|idx| throw_unsup!(ReadUndefBytes(idx)))
+            .or_else(|idx| throw_ub!(InvalidUndefBytes(Some(Pointer::new(ptr.alloc_id, idx)))))
     }
 
     pub fn mark_definedness(&mut self, ptr: Pointer<Tag>, size: Size, new_state: bool) {
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index b46095927b7..ff107a5f1e2 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -1,19 +1,20 @@
-use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};
+use super::{AllocId, CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};
 
 use crate::hir::map::definitions::DefPathData;
-use crate::mir;
 use crate::mir::interpret::ConstValue;
 use crate::ty::layout::{Align, LayoutError, Size};
 use crate::ty::query::TyCtxtAt;
+use crate::ty::tls;
 use crate::ty::{self, layout, Ty};
 
 use backtrace::Backtrace;
+use rustc_data_structures::sync::Lock;
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_macros::HashStable;
-use rustc_span::{Pos, Span};
-use rustc_target::spec::abi::Abi;
-use std::{any::Any, env, fmt};
+use rustc_session::CtfeBacktrace;
+use rustc_span::{def_id::DefId, Pos, Span};
+use std::{any::Any, fmt};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
 pub enum ErrorHandled {
@@ -257,21 +258,25 @@ impl From<ErrorHandled> for InterpErrorInfo<'_> {
 
 impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
     fn from(kind: InterpError<'tcx>) -> Self {
-        let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
-            // Matching `RUST_BACKTRACE` -- we treat "0" the same as "not present".
-            Ok(ref val) if val != "0" => {
-                let mut backtrace = Backtrace::new_unresolved();
+        let capture_backtrace = tls::with_context_opt(|ctxt| {
+            if let Some(ctxt) = ctxt {
+                *Lock::borrow(&ctxt.tcx.sess.ctfe_backtrace)
+            } else {
+                CtfeBacktrace::Disabled
+            }
+        });
 
-                if val == "immediate" {
-                    // Print it now.
-                    print_backtrace(&mut backtrace);
-                    None
-                } else {
-                    Some(Box::new(backtrace))
-                }
+        let backtrace = match capture_backtrace {
+            CtfeBacktrace::Disabled => None,
+            CtfeBacktrace::Capture => Some(Box::new(Backtrace::new_unresolved())),
+            CtfeBacktrace::Immediate => {
+                // Print it now.
+                let mut backtrace = Backtrace::new_unresolved();
+                print_backtrace(&mut backtrace);
+                None
             }
-            _ => None,
         };
+
         InterpErrorInfo { kind, backtrace }
     }
 }
@@ -289,6 +294,8 @@ pub enum InvalidProgramInfo<'tcx> {
     TypeckError,
     /// An error occurred during layout computation.
     Layout(layout::LayoutError<'tcx>),
+    /// An invalid transmute happened.
+    TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
 }
 
 impl fmt::Debug for InvalidProgramInfo<'_> {
@@ -299,6 +306,11 @@ impl fmt::Debug for InvalidProgramInfo<'_> {
             ReferencedConstant => write!(f, "referenced constant has errors"),
             TypeckError => write!(f, "encountered constants with type errors, stopping evaluation"),
             Layout(ref err) => write!(f, "{}", err),
+            TransmuteSizeDiff(from_ty, to_ty) => write!(
+                f,
+                "tried to transmute from {:?} to {:?}, but their sizes differed",
+                from_ty, to_ty
+            ),
         }
     }
 }
@@ -314,7 +326,10 @@ pub enum UndefinedBehaviorInfo {
     /// An enum discriminant was set to a value which was outside the range of valid values.
     InvalidDiscriminant(ScalarMaybeUndef),
     /// A slice/array index projection went out-of-bounds.
-    BoundsCheckFailed { len: u64, index: u64 },
+    BoundsCheckFailed {
+        len: u64,
+        index: u64,
+    },
     /// Something was divided by 0 (x / 0).
     DivisionByZero,
     /// Something was "remainded" by 0 (x % 0).
@@ -323,6 +338,43 @@ pub enum UndefinedBehaviorInfo {
     PointerArithOverflow,
     /// Invalid metadata in a wide pointer (using `str` to avoid allocations).
     InvalidMeta(&'static str),
+    /// Reading a C string that does not end within its allocation.
+    UnterminatedCString(Pointer),
+    /// Dereferencing a dangling pointer after it got freed.
+    PointerUseAfterFree(AllocId),
+    /// Used a pointer outside the bounds it is valid for.
+    PointerOutOfBounds {
+        ptr: Pointer,
+        msg: CheckInAllocMsg,
+        allocation_size: Size,
+    },
+    /// Used a pointer with bad alignment.
+    AlignmentCheckFailed {
+        required: Align,
+        has: Align,
+    },
+    /// Using an integer as a pointer in the wrong way.
+    InvalidIntPointerUsage(u64),
+    /// Writing to read-only memory.
+    WriteToReadOnly(AllocId),
+    /// Using a pointer-not-to-a-function as function pointer.
+    InvalidFunctionPointer(Pointer),
+    // Trying to access the data behind a function pointer.
+    DerefFunctionPointer(AllocId),
+    /// The value validity check found a problem.
+    /// Should only be thrown by `validity.rs` and always point out which part of the value
+    /// is the problem.
+    ValidationFailure(String),
+    /// Using a non-boolean `u8` as bool.
+    InvalidBool(u8),
+    /// Using a non-character `u32` as character.
+    InvalidChar(u32),
+    /// Using uninitialized data where it is not allowed.
+    InvalidUndefBytes(Option<Pointer>),
+    /// Working with a local that is not currently live.
+    DeadLocal,
+    /// Trying to read from the return place of a function.
+    ReadFromReturnPlace,
 }
 
 impl fmt::Debug for UndefinedBehaviorInfo {
@@ -341,6 +393,50 @@ impl fmt::Debug for UndefinedBehaviorInfo {
             RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
             PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
             InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
+            UnterminatedCString(p) => write!(
+                f,
+                "reading a null-terminated string starting at {:?} with no null found before end of allocation",
+                p,
+            ),
+            PointerUseAfterFree(a) => {
+                write!(f, "pointer to {:?} was dereferenced after this allocation got freed", a)
+            }
+            PointerOutOfBounds { ptr, msg, allocation_size } => write!(
+                f,
+                "{} failed: pointer must be in-bounds at offset {}, \
+                           but is outside bounds of {} which has size {}",
+                msg,
+                ptr.offset.bytes(),
+                ptr.alloc_id,
+                allocation_size.bytes()
+            ),
+            InvalidIntPointerUsage(0) => write!(f, "invalid use of NULL pointer"),
+            InvalidIntPointerUsage(i) => write!(f, "invalid use of {} as a pointer", i),
+            AlignmentCheckFailed { required, has } => write!(
+                f,
+                "accessing memory with alignment {}, but alignment {} is required",
+                has.bytes(),
+                required.bytes()
+            ),
+            WriteToReadOnly(a) => write!(f, "writing to {:?} which is read-only", a),
+            InvalidFunctionPointer(p) => {
+                write!(f, "using {:?} as function pointer but it does not point to a function", p)
+            }
+            DerefFunctionPointer(a) => write!(f, "accessing {:?} which contains a function", a),
+            ValidationFailure(ref err) => write!(f, "type validation failed: {}", err),
+            InvalidBool(b) => write!(f, "interpreting an invalid 8-bit value as a bool: {}", b),
+            InvalidChar(c) => write!(f, "interpreting an invalid 32-bit value as a char: {}", c),
+            InvalidUndefBytes(Some(p)) => write!(
+                f,
+                "reading uninitialized memory at {:?}, but this operation requires initialized memory",
+                p
+            ),
+            InvalidUndefBytes(None) => write!(
+                f,
+                "using uninitialized data, but this operation requires initialized memory"
+            ),
+            DeadLocal => write!(f, "accessing a dead local variable"),
+            ReadFromReturnPlace => write!(f, "tried to read from the return place"),
         }
     }
 }
@@ -352,203 +448,45 @@ impl fmt::Debug for UndefinedBehaviorInfo {
 ///
 /// Currently, we also use this as fall-back error kind for errors that have not been
 /// categorized yet.
-pub enum UnsupportedOpInfo<'tcx> {
+pub enum UnsupportedOpInfo {
     /// Free-form case. Only for errors that are never caught!
     Unsupported(String),
-
     /// When const-prop encounters a situation it does not support, it raises this error.
     /// This must not allocate for performance reasons (hence `str`, not `String`).
     ConstPropUnsupported(&'static str),
-
-    // -- Everything below is not categorized yet --
-    FunctionAbiMismatch(Abi, Abi),
-    FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
-    FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
-    FunctionArgCountMismatch,
-    UnterminatedCString(Pointer),
-    DanglingPointerDeref,
-    DoubleFree,
-    InvalidMemoryAccess,
-    InvalidFunctionPointer,
-    InvalidBool,
-    PointerOutOfBounds {
-        ptr: Pointer,
-        msg: CheckInAllocMsg,
-        allocation_size: Size,
-    },
-    InvalidNullPointerUsage,
+    /// Accessing an unsupported foreign static.
+    ReadForeignStatic(DefId),
+    /// Could not find MIR for a function.
+    NoMirFor(DefId),
+    /// Modified a static during const-eval.
+    /// FIXME: move this to `ConstEvalErrKind` through a machine hook.
+    ModifiedStatic,
+    /// Encountered a pointer where we needed raw bytes.
     ReadPointerAsBytes,
+    /// Encountered raw bytes where we needed a pointer.
     ReadBytesAsPointer,
-    ReadForeignStatic,
-    InvalidPointerMath,
-    ReadUndefBytes(Size),
-    DeadLocal,
-    InvalidBoolOp(mir::BinOp),
-    UnimplementedTraitSelection,
-    CalledClosureAsFunction,
-    NoMirFor(String),
-    DerefFunctionPointer,
-    ExecuteMemory,
-    InvalidChar(u128),
-    OutOfTls,
-    TlsOutOfBounds,
-    AlignmentCheckFailed {
-        required: Align,
-        has: Align,
-    },
-    ValidationFailure(String),
-    VtableForArgumentlessMethod,
-    ModifiedConstantMemory,
-    ModifiedStatic,
-    TypeNotPrimitive(Ty<'tcx>),
-    ReallocatedWrongMemoryKind(String, String),
-    DeallocatedWrongMemoryKind(String, String),
-    ReallocateNonBasePtr,
-    DeallocateNonBasePtr,
-    IncorrectAllocationInformation(Size, Size, Align, Align),
-    HeapAllocZeroBytes,
-    HeapAllocNonPowerOfTwoAlignment(u64),
-    ReadFromReturnPointer,
-    PathNotFound(Vec<String>),
-    TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
 }
 
-impl fmt::Debug for UnsupportedOpInfo<'tcx> {
+impl fmt::Debug for UnsupportedOpInfo {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use UnsupportedOpInfo::*;
         match self {
-            PointerOutOfBounds { ptr, msg, allocation_size } => write!(
-                f,
-                "{} failed: pointer must be in-bounds at offset {}, \
-                           but is outside bounds of allocation {} which has size {}",
-                msg,
-                ptr.offset.bytes(),
-                ptr.alloc_id,
-                allocation_size.bytes()
-            ),
-            ValidationFailure(ref err) => write!(f, "type validation failed: {}", err),
-            NoMirFor(ref func) => write!(f, "no MIR for `{}`", func),
-            FunctionAbiMismatch(caller_abi, callee_abi) => write!(
-                f,
-                "tried to call a function with ABI {:?} using caller ABI {:?}",
-                callee_abi, caller_abi
-            ),
-            FunctionArgMismatch(caller_ty, callee_ty) => write!(
-                f,
-                "tried to call a function with argument of type {:?} \
-                           passing data of type {:?}",
-                callee_ty, caller_ty
-            ),
-            TransmuteSizeDiff(from_ty, to_ty) => write!(
-                f,
-                "tried to transmute from {:?} to {:?}, but their sizes differed",
-                from_ty, to_ty
-            ),
-            FunctionRetMismatch(caller_ty, callee_ty) => write!(
-                f,
-                "tried to call a function with return type {:?} \
-                           passing return place of type {:?}",
-                callee_ty, caller_ty
-            ),
-            FunctionArgCountMismatch => {
-                write!(f, "tried to call a function with incorrect number of arguments")
-            }
-            ReallocatedWrongMemoryKind(ref old, ref new) => {
-                write!(f, "tried to reallocate memory from `{}` to `{}`", old, new)
-            }
-            DeallocatedWrongMemoryKind(ref old, ref new) => {
-                write!(f, "tried to deallocate `{}` memory but gave `{}` as the kind", old, new)
-            }
-            InvalidChar(c) => {
-                write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c)
-            }
-            AlignmentCheckFailed { required, has } => write!(
-                f,
-                "tried to access memory with alignment {}, but alignment {} is required",
-                has.bytes(),
-                required.bytes()
-            ),
-            TypeNotPrimitive(ty) => write!(f, "expected primitive type, got {}", ty),
-            PathNotFound(ref path) => write!(f, "cannot find path {:?}", path),
-            IncorrectAllocationInformation(size, size2, align, align2) => write!(
-                f,
-                "incorrect alloc info: expected size {} and align {}, \
-                           got size {} and align {}",
-                size.bytes(),
-                align.bytes(),
-                size2.bytes(),
-                align2.bytes()
-            ),
-            InvalidMemoryAccess => write!(f, "tried to access memory through an invalid pointer"),
-            DanglingPointerDeref => write!(f, "dangling pointer was dereferenced"),
-            DoubleFree => write!(f, "tried to deallocate dangling pointer"),
-            InvalidFunctionPointer => {
-                write!(f, "tried to use a function pointer after offsetting it")
-            }
-            InvalidBool => write!(f, "invalid boolean value read"),
-            InvalidNullPointerUsage => write!(f, "invalid use of NULL pointer"),
-            ReadPointerAsBytes => write!(
-                f,
-                "a raw memory access tried to access part of a pointer value as raw \
-                    bytes"
-            ),
-            ReadBytesAsPointer => {
-                write!(f, "a memory access tried to interpret some bytes as a pointer")
-            }
-            ReadForeignStatic => write!(f, "tried to read from foreign (extern) static"),
-            InvalidPointerMath => write!(
-                f,
-                "attempted to do invalid arithmetic on pointers that would leak base \
-                    addresses, e.g., comparing pointers into different allocations"
-            ),
-            DeadLocal => write!(f, "tried to access a dead local variable"),
-            DerefFunctionPointer => write!(f, "tried to dereference a function pointer"),
-            ExecuteMemory => write!(f, "tried to treat a memory pointer as a function pointer"),
-            OutOfTls => write!(f, "reached the maximum number of representable TLS keys"),
-            TlsOutOfBounds => write!(f, "accessed an invalid (unallocated) TLS key"),
-            CalledClosureAsFunction => {
-                write!(f, "tried to call a closure through a function pointer")
+            Unsupported(ref msg) => write!(f, "{}", msg),
+            ConstPropUnsupported(ref msg) => {
+                write!(f, "Constant propagation encountered an unsupported situation: {}", msg)
             }
-            VtableForArgumentlessMethod => {
-                write!(f, "tried to call a vtable function without arguments")
+            ReadForeignStatic(did) => {
+                write!(f, "tried to read from foreign (extern) static {:?}", did)
             }
-            ModifiedConstantMemory => write!(f, "tried to modify constant memory"),
+            NoMirFor(did) => write!(f, "could not load MIR for {:?}", did),
             ModifiedStatic => write!(
                 f,
                 "tried to modify a static's initial value from another static's \
                     initializer"
             ),
-            ReallocateNonBasePtr => write!(
-                f,
-                "tried to reallocate with a pointer not to the beginning of an \
-                    existing object"
-            ),
-            DeallocateNonBasePtr => write!(
-                f,
-                "tried to deallocate with a pointer not to the beginning of an \
-                    existing object"
-            ),
-            HeapAllocZeroBytes => write!(f, "tried to re-, de- or allocate zero bytes on the heap"),
-            ReadFromReturnPointer => write!(f, "tried to read from the return pointer"),
-            UnimplementedTraitSelection => {
-                write!(f, "there were unresolved type arguments during trait selection")
-            }
-            InvalidBoolOp(_) => write!(f, "invalid boolean operation"),
-            UnterminatedCString(_) => write!(
-                f,
-                "attempted to get length of a null-terminated string, but no null \
-                    found before end of allocation"
-            ),
-            ReadUndefBytes(_) => write!(f, "attempted to read undefined bytes"),
-            HeapAllocNonPowerOfTwoAlignment(_) => write!(
-                f,
-                "tried to re-, de-, or allocate heap memory with alignment that is \
-                    not a power of two"
-            ),
-            Unsupported(ref msg) => write!(f, "{}", msg),
-            ConstPropUnsupported(ref msg) => {
-                write!(f, "Constant propagation encountered an unsupported situation: {}", msg)
-            }
+
+            ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",),
+            ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"),
         }
     }
 }
@@ -583,7 +521,7 @@ pub enum InterpError<'tcx> {
     UndefinedBehavior(UndefinedBehaviorInfo),
     /// The program did something the interpreter does not support (some of these *might* be UB
     /// but the interpreter is not sure).
-    Unsupported(UnsupportedOpInfo<'tcx>),
+    Unsupported(UnsupportedOpInfo),
     /// The program was invalid (ill-typed, bad MIR, not sufficiently monomorphized, ...).
     InvalidProgram(InvalidProgramInfo<'tcx>),
     /// The program exhausted the interpreter's resources (stack/heap too big,
@@ -599,7 +537,7 @@ pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
 impl fmt::Display for InterpError<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Forward `Display` to `Debug`.
-        write!(f, "{:?}", self)
+        fmt::Debug::fmt(self, f)
     }
 }
 
@@ -624,7 +562,7 @@ impl InterpError<'_> {
         match self {
             InterpError::MachineStop(_)
             | InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
-            | InterpError::Unsupported(UnsupportedOpInfo::ValidationFailure(_))
+            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_))
             | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
             | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true,
             _ => false,
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 64c07b431db..0b5bb7f3c03 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -161,7 +161,13 @@ pub struct AllocId(pub u64);
 
 impl fmt::Debug for AllocId {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "alloc{}", self.0)
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
+impl fmt::Display for AllocId {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "alloc{}", self.0)
     }
 }
 
@@ -351,12 +357,6 @@ impl<'s> AllocDecodingSession<'s> {
     }
 }
 
-impl fmt::Display for AllocId {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.0)
-    }
-}
-
 /// An allocation in the global (tcx-managed) memory can be either a function pointer,
 /// a static, or a "real" allocation with some data in it.
 #[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)]
diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs
index cc3c50b7899..2cbe25f9674 100644
--- a/src/librustc/mir/interpret/pointer.rs
+++ b/src/librustc/mir/interpret/pointer.rs
@@ -213,20 +213,4 @@ impl<'tcx, Tag> Pointer<Tag> {
     pub fn erase_tag(self) -> Pointer {
         Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
     }
-
-    /// Test if the pointer is "inbounds" of an allocation of the given size.
-    /// A pointer is "inbounds" even if its offset is equal to the size; this is
-    /// a "one-past-the-end" pointer.
-    #[inline(always)]
-    pub fn check_inbounds_alloc(
-        self,
-        allocation_size: Size,
-        msg: CheckInAllocMsg,
-    ) -> InterpResult<'tcx, ()> {
-        if self.offset > allocation_size {
-            throw_unsup!(PointerOutOfBounds { ptr: self.erase_tag(), msg, allocation_size })
-        } else {
-            Ok(())
-        }
-    }
 }
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 9dc0b24cd2f..04fe70b36c1 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -272,11 +272,13 @@ impl<'tcx, Tag> Scalar<Tag> {
 
     #[inline]
     pub fn from_bool(b: bool) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: b as u128, size: 1 }
     }
 
     #[inline]
     pub fn from_char(c: char) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: c as u128, size: 4 }
     }
 
@@ -299,21 +301,25 @@ impl<'tcx, Tag> Scalar<Tag> {
 
     #[inline]
     pub fn from_u8(i: u8) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: i as u128, size: 1 }
     }
 
     #[inline]
     pub fn from_u16(i: u16) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: i as u128, size: 2 }
     }
 
     #[inline]
     pub fn from_u32(i: u32) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: i as u128, size: 4 }
     }
 
     #[inline]
     pub fn from_u64(i: u64) -> Self {
+        // Guaranteed to be truncated and does not need sign extension.
         Scalar::Raw { data: i as u128, size: 8 }
     }
 
@@ -342,6 +348,26 @@ impl<'tcx, Tag> Scalar<Tag> {
     }
 
     #[inline]
+    pub fn from_i8(i: i8) -> Self {
+        Self::from_int(i, Size::from_bits(8))
+    }
+
+    #[inline]
+    pub fn from_i16(i: i16) -> Self {
+        Self::from_int(i, Size::from_bits(16))
+    }
+
+    #[inline]
+    pub fn from_i32(i: i32) -> Self {
+        Self::from_int(i, Size::from_bits(32))
+    }
+
+    #[inline]
+    pub fn from_i64(i: i64) -> Self {
+        Self::from_int(i, Size::from_bits(64))
+    }
+
+    #[inline]
     pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self {
         Self::from_int(i, cx.data_layout().pointer_size)
     }
@@ -429,10 +455,11 @@ impl<'tcx, Tag> Scalar<Tag> {
     }
 
     pub fn to_bool(self) -> InterpResult<'tcx, bool> {
-        match self {
-            Scalar::Raw { data: 0, size: 1 } => Ok(false),
-            Scalar::Raw { data: 1, size: 1 } => Ok(true),
-            _ => throw_unsup!(InvalidBool),
+        let val = self.to_u8()?;
+        match val {
+            0 => Ok(false),
+            1 => Ok(true),
+            _ => throw_ub!(InvalidBool(val)),
         }
     }
 
@@ -440,7 +467,7 @@ impl<'tcx, Tag> Scalar<Tag> {
         let val = self.to_u32()?;
         match ::std::char::from_u32(val) {
             Some(c) => Ok(c),
-            None => throw_unsup!(InvalidChar(val as u128)),
+            None => throw_ub!(InvalidChar(val)),
         }
     }
 
@@ -583,7 +610,7 @@ impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
     pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> {
         match self {
             ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
-            ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::ZERO)),
+            ScalarMaybeUndef::Undef => throw_ub!(InvalidUndefBytes(None)),
         }
     }
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index b2413f5a2c8..9018cd2656f 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1,6 +1,6 @@
-//! MIR datatypes and passes. See the [rustc guide] for more info.
+//! MIR datatypes and passes. See the [rustc dev guide] for more info.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 
 use crate::mir::interpret::{GlobalAlloc, Scalar};
 use crate::mir::visit::MirVisitable;
@@ -403,7 +403,7 @@ pub enum ClearCrossCrate<T> {
 }
 
 impl<T> ClearCrossCrate<T> {
-    pub fn as_ref(&'a self) -> ClearCrossCrate<&'a T> {
+    pub fn as_ref(&self) -> ClearCrossCrate<&T> {
         match self {
             ClearCrossCrate::Clear => ClearCrossCrate::Clear,
             ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
@@ -2503,7 +2503,7 @@ impl UserTypeProjection {
 
     pub(crate) fn variant(
         mut self,
-        adt_def: &'tcx AdtDef,
+        adt_def: &AdtDef,
         variant_index: VariantIdx,
         field: Field,
     ) -> Self {
@@ -2562,15 +2562,15 @@ impl<'tcx> Debug for Constant<'tcx> {
 
 impl<'tcx> Display for Constant<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
+        use crate::ty::print::PrettyPrinter;
         write!(fmt, "const ")?;
-        // FIXME make the default pretty printing of raw pointers more detailed. Here we output the
-        // debug representation of raw pointers, so that the raw pointers in the mir dump output are
-        // detailed and just not '{pointer}'.
-        if let ty::RawPtr(_) = self.literal.ty.kind {
-            write!(fmt, "{:?} : {}", self.literal.val, self.literal.ty)
-        } else {
-            write!(fmt, "{}", self.literal)
-        }
+        ty::tls::with(|tcx| {
+            let literal = tcx.lift(&self.literal).unwrap();
+            let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS);
+            cx.print_alloc_ids = true;
+            cx.pretty_print_const(literal, true)?;
+            Ok(())
+        })
     }
 }
 
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index 4f8efc1607e..27d82d25803 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -1,6 +1,5 @@
 use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId};
 use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
-use crate::session::config::OptLevel;
 use crate::ty::print::obsolete::DefPathBasedNames;
 use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
 use rustc_attr::InlineAttr;
@@ -9,6 +8,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::HirId;
+use rustc_session::config::OptLevel;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
 use std::fmt;
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 11e9acf3a39..de35c6d87e6 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -11,7 +11,7 @@ use crate::ty::query::queries;
 use crate::ty::query::QueryDescription;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 
 use rustc_span::symbol::Symbol;
 use std::borrow::Cow;
@@ -55,6 +55,40 @@ rustc_queries! {
             desc { "get the crate HIR" }
         }
 
+        // The indexed HIR. This can be conveniently accessed by `tcx.hir()`.
+        // Avoid calling this query directly.
+        query index_hir(_: CrateNum) -> &'tcx map::IndexedHir<'tcx> {
+            eval_always
+            no_hash
+            desc { "index HIR" }
+        }
+
+        // The items in a module.
+        // This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
+        // Avoid calling this query directly.
+        query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems {
+            eval_always
+            desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
+        }
+
+        // An HIR item with a `LocalDefId` that can own other HIR items which do
+        // not themselves have a `LocalDefId`.
+        // This can be conveniently accessed by methods on `tcx.hir()`.
+        // Avoid calling this query directly.
+        query hir_owner(key: LocalDefId) -> &'tcx HirOwner<'tcx> {
+            eval_always
+            desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) }
+        }
+
+        // The HIR items which do not themselves have a `LocalDefId` and are
+        // owned by another HIR item with a `LocalDefId`.
+        // This can be conveniently accessed by methods on `tcx.hir()`.
+        // Avoid calling this query directly.
+        query hir_owner_items(key: LocalDefId) -> &'tcx HirOwnerItems<'tcx> {
+            eval_always
+            desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
+        }
+
         /// Records the type of every item.
         query type_of(key: DefId) -> Ty<'tcx> {
             cache_on_disk_if { key.is_local() }
@@ -104,8 +138,9 @@ rustc_queries! {
             desc { "computing the lint levels for items in this crate" }
         }
 
-        query parent_module_from_def_id(_: DefId) -> DefId {
+        query parent_module_from_def_id(key: LocalDefId) -> LocalDefId {
             eval_always
+            desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) }
         }
     }
 
@@ -653,6 +688,9 @@ rustc_queries! {
     }
 
     TypeChecking {
+        query all_local_trait_impls(key: CrateNum) -> &'tcx BTreeMap<DefId, Vec<hir::HirId>> {
+            desc { "local trait impls" }
+        }
         query trait_impls_of(key: DefId) -> &'tcx ty::trait_def::TraitImpls {
             desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) }
         }
@@ -757,7 +795,7 @@ rustc_queries! {
         query specializes(_: (DefId, DefId)) -> bool {
             desc { "computing whether impls specialize one another" }
         }
-        query in_scope_traits_map(_: DefIndex)
+        query in_scope_traits_map(_: LocalDefId)
             -> Option<&'tcx FxHashMap<ItemLocalId, StableVec<TraitCandidate>>> {
             eval_always
             desc { "traits in scope at a block" }
@@ -914,15 +952,15 @@ rustc_queries! {
         query resolve_lifetimes(_: CrateNum) -> &'tcx ResolveLifetimes {
             desc { "resolving lifetimes" }
         }
-        query named_region_map(_: DefIndex) ->
+        query named_region_map(_: LocalDefId) ->
             Option<&'tcx FxHashMap<ItemLocalId, Region>> {
             desc { "looking up a named region" }
         }
-        query is_late_bound_map(_: DefIndex) ->
+        query is_late_bound_map(_: LocalDefId) ->
             Option<&'tcx FxHashSet<ItemLocalId>> {
             desc { "testing if a region is late bound" }
         }
-        query object_lifetime_defaults_map(_: DefIndex)
+        query object_lifetime_defaults_map(_: LocalDefId)
             -> Option<&'tcx FxHashMap<ItemLocalId, Vec<ObjectLifetimeDefault>>> {
             desc { "looking up lifetime defaults for a region" }
         }
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 4e02a1744ff..6ebcc8b0754 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -1,6 +1,6 @@
-//! Trait Resolution. See the [rustc guide] for more information on how this works.
+//! Trait Resolution. See the [rustc dev guide] for more information on how this works.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
 
 pub mod query;
 pub mod select;
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index ac3d0049c0c..d316d7659e2 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1,6 +1,6 @@
-//! Candidate selection. See the [rustc guide] for more information on how this works.
+//! Candidate selection. See the [rustc dev guide] for more information on how this works.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html#selection
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
 
 use self::EvaluationResult::*;
 
@@ -288,3 +288,44 @@ impl<T: Clone> WithDepNode<T> {
         self.cached_value.clone()
     }
 }
+
+#[derive(Clone, Debug)]
+pub enum IntercrateAmbiguityCause {
+    DownstreamCrate { trait_desc: String, self_desc: Option<String> },
+    UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> },
+    ReservationImpl { message: String },
+}
+
+impl IntercrateAmbiguityCause {
+    /// Emits notes when the overlap is caused by complex intercrate ambiguities.
+    /// See #23980 for details.
+    pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
+        err.note(&self.intercrate_ambiguity_hint());
+    }
+
+    pub fn intercrate_ambiguity_hint(&self) -> String {
+        match self {
+            &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
+                let self_desc = if let &Some(ref ty) = self_desc {
+                    format!(" for type `{}`", ty)
+                } else {
+                    String::new()
+                };
+                format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
+            }
+            &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
+                let self_desc = if let &Some(ref ty) = self_desc {
+                    format!(" for type `{}`", ty)
+                } else {
+                    String::new()
+                };
+                format!(
+                    "upstream crates may add a new impl of trait `{}`{} \
+                     in future versions",
+                    trait_desc, self_desc
+                )
+            }
+            &IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(),
+        }
+    }
+}
diff --git a/src/librustc/traits/specialization_graph.rs b/src/librustc/traits/specialization_graph.rs
index d481e578fc1..1847326a742 100644
--- a/src/librustc/traits/specialization_graph.rs
+++ b/src/librustc/traits/specialization_graph.rs
@@ -4,6 +4,7 @@ use crate::ty::{self, TyCtxt};
 use rustc_ast::ast::Ident;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_errors::ErrorReported;
 use rustc_hir::def_id::{DefId, DefIdMap};
 
 /// A per-trait graph of impls in specialization order. At the moment, this
@@ -23,17 +24,20 @@ use rustc_hir::def_id::{DefId, DefIdMap};
 ///   has at most one parent.
 #[derive(RustcEncodable, RustcDecodable, HashStable)]
 pub struct Graph {
-    // All impls have a parent; the "root" impls have as their parent the `def_id`
-    // of the trait.
+    /// All impls have a parent; the "root" impls have as their parent the `def_id`
+    /// of the trait.
     pub parent: DefIdMap<DefId>,
 
-    // The "root" impls are found by looking up the trait's def_id.
+    /// The "root" impls are found by looking up the trait's def_id.
     pub children: DefIdMap<Children>,
+
+    /// Whether an error was emitted while constructing the graph.
+    pub has_errored: bool,
 }
 
 impl Graph {
     pub fn new() -> Graph {
-        Graph { parent: Default::default(), children: Default::default() }
+        Graph { parent: Default::default(), children: Default::default(), has_errored: false }
     }
 
     /// The parent of a given impl, which is the `DefId` of the trait when the
@@ -179,17 +183,22 @@ impl<'tcx> Ancestors<'tcx> {
 }
 
 /// Walk up the specialization ancestors of a given impl, starting with that
-/// impl itself.
+/// impl itself. Returns `None` if an error was reported while building the
+/// specialization graph.
 pub fn ancestors(
     tcx: TyCtxt<'tcx>,
     trait_def_id: DefId,
     start_from_impl: DefId,
-) -> Ancestors<'tcx> {
+) -> Result<Ancestors<'tcx>, ErrorReported> {
     let specialization_graph = tcx.specialization_graph_of(trait_def_id);
-    Ancestors {
-        trait_def_id,
-        specialization_graph,
-        current_source: Some(Node::Impl(start_from_impl)),
+    if specialization_graph.has_errored {
+        Err(ErrorReported)
+    } else {
+        Ok(Ancestors {
+            trait_def_id,
+            specialization_graph,
+            current_source: Some(Node::Impl(start_from_impl)),
+        })
     }
 }
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 48ef81c1d5b..742d57fb58a 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -5,6 +5,7 @@ use crate::dep_graph::DepGraph;
 use crate::dep_graph::{self, DepConstructor};
 use crate::hir::exports::Export;
 use crate::hir::map as hir_map;
+use crate::hir::map::definitions::Definitions;
 use crate::hir::map::{DefPathData, DefPathHash};
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
@@ -22,7 +23,6 @@ use crate::mir::{
 };
 use crate::traits;
 use crate::traits::{Clause, Clauses, Goal, GoalKind, Goals};
-use crate::ty::free_region_map::FreeRegionMap;
 use crate::ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
 use crate::ty::query;
 use crate::ty::steal::Steal;
@@ -55,7 +55,7 @@ use rustc_data_structures::stable_hasher::{
 use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
 use rustc_hir::{HirId, Node, TraitCandidate};
 use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet};
 use rustc_index::vec::{Idx, IndexVec};
@@ -205,13 +205,13 @@ fn validate_hir_id_for_typeck_tables(
     mut_access: bool,
 ) {
     if let Some(local_id_root) = local_id_root {
-        if hir_id.owner != local_id_root.index {
+        if hir_id.owner.to_def_id() != local_id_root {
             ty::tls::with(|tcx| {
                 bug!(
                     "node {} with HirId::owner {:?} cannot be placed in \
                      TypeckTables with local_id_root {:?}",
                     tcx.hir().node_to_string(hir_id),
-                    DefId::local(hir_id.owner),
+                    hir_id.owner,
                     local_id_root
                 )
             });
@@ -415,11 +415,6 @@ pub struct TypeckTables<'tcx> {
     /// this field will be set to `true`.
     pub tainted_by_errors: bool,
 
-    /// Stores the free-region relationships that were deduced from
-    /// its where-clauses and parameter types. These are then
-    /// read-again by borrowck.
-    pub free_region_map: FreeRegionMap<'tcx>,
-
     /// All the opaque types that are restricted to concrete types
     /// by this function.
     pub concrete_opaque_types: FxHashMap<DefId, ResolvedOpaqueTy<'tcx>>,
@@ -455,7 +450,6 @@ impl<'tcx> TypeckTables<'tcx> {
             coercion_casts: Default::default(),
             used_trait_imports: Lrc::new(Default::default()),
             tainted_by_errors: false,
-            free_region_map: Default::default(),
             concrete_opaque_types: Default::default(),
             upvar_list: Default::default(),
             generator_interior_types: Default::default(),
@@ -611,7 +605,7 @@ impl<'tcx> TypeckTables<'tcx> {
         }
 
         match self.type_dependent_defs().get(expr.hir_id) {
-            Some(Ok((DefKind::Method, _))) => true,
+            Some(Ok((DefKind::AssocFn, _))) => true,
             _ => false,
         }
     }
@@ -718,7 +712,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
 
             ref used_trait_imports,
             tainted_by_errors,
-            ref free_region_map,
             ref concrete_opaque_types,
             ref upvar_list,
             ref generator_interior_types,
@@ -739,10 +732,12 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
 
                 let local_id_root = local_id_root.expect("trying to hash invalid TypeckTables");
 
-                let var_owner_def_id =
-                    DefId { krate: local_id_root.krate, index: var_path.hir_id.owner };
+                let var_owner_def_id = DefId {
+                    krate: local_id_root.krate,
+                    index: var_path.hir_id.owner.local_def_index,
+                };
                 let closure_def_id =
-                    DefId { krate: local_id_root.krate, index: closure_expr_id.to_def_id().index };
+                    DefId { krate: local_id_root.krate, index: closure_expr_id.local_def_index };
                 (
                     hcx.def_path_hash(var_owner_def_id),
                     var_path.hir_id.local_id,
@@ -756,7 +751,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
             coercion_casts.hash_stable(hcx, hasher);
             used_trait_imports.hash_stable(hcx, hasher);
             tainted_by_errors.hash_stable(hcx, hasher);
-            free_region_map.hash_stable(hcx, hasher);
             concrete_opaque_types.hash_stable(hcx, hasher);
             upvar_list.hash_stable(hcx, hasher);
             generator_interior_types.hash_stable(hcx, hasher);
@@ -916,9 +910,9 @@ pub struct FreeRegionInfo {
 /// The central data structure of the compiler. It stores references
 /// to the various **arenas** and also houses the results of the
 /// various **compiler queries** that have been performed. See the
-/// [rustc guide] for more details.
+/// [rustc dev guide] for more details.
 ///
-/// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html
+/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
 #[derive(Copy, Clone)]
 #[rustc_diagnostic_item = "TyCtxt"]
 pub struct TyCtxt<'tcx> {
@@ -938,7 +932,7 @@ pub struct GlobalCtxt<'tcx> {
 
     interners: CtxtInterners<'tcx>,
 
-    cstore: Box<CrateStoreDyn>,
+    pub(crate) cstore: Box<CrateStoreDyn>,
 
     pub sess: &'tcx Session,
 
@@ -966,13 +960,13 @@ pub struct GlobalCtxt<'tcx> {
 
     /// Map indicating what traits are in scope for places where this
     /// is relevant; generated by resolve.
-    trait_map: FxHashMap<DefIndex, FxHashMap<ItemLocalId, StableVec<TraitCandidate>>>,
+    trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, StableVec<TraitCandidate>>>,
 
     /// Export map produced by name resolution.
     export_map: FxHashMap<DefId, Vec<Export<hir::HirId>>>,
 
-    /// This should usually be accessed with the `tcx.hir()` method.
-    pub(crate) hir_map: hir_map::Map<'tcx>,
+    pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>,
+    pub(crate) definitions: &'tcx Definitions,
 
     /// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate
     /// as well as all upstream crates. Only populated in incremental mode.
@@ -1116,7 +1110,9 @@ impl<'tcx> TyCtxt<'tcx> {
         extern_providers: ty::query::Providers<'tcx>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         resolutions: ty::ResolverOutputs,
-        hir: hir_map::Map<'tcx>,
+        krate: &'tcx hir::Crate<'tcx>,
+        definitions: &'tcx Definitions,
+        dep_graph: DepGraph,
         on_disk_query_result_cache: query::OnDiskCache<'tcx>,
         crate_name: &str,
         output_filenames: &OutputFilenames,
@@ -1128,7 +1124,6 @@ impl<'tcx> TyCtxt<'tcx> {
         let common_types = CommonTypes::new(&interners);
         let common_lifetimes = CommonLifetimes::new(&interners);
         let common_consts = CommonConsts::new(&interners, &common_types);
-        let dep_graph = hir.dep_graph.clone();
         let cstore = resolutions.cstore;
         let crates = cstore.crates_untracked();
         let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0);
@@ -1139,7 +1134,7 @@ impl<'tcx> TyCtxt<'tcx> {
             let def_path_tables = crates
                 .iter()
                 .map(|&cnum| (cnum, cstore.def_path_table(cnum)))
-                .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table())));
+                .chain(iter::once((LOCAL_CRATE, definitions.def_path_table())));
 
             // Precompute the capacity of the hashmap so we don't have to
             // re-allocate when populating it.
@@ -1159,11 +1154,11 @@ impl<'tcx> TyCtxt<'tcx> {
 
         let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
         for (k, v) in resolutions.trait_map {
-            let hir_id = hir.node_to_hir_id(k);
+            let hir_id = definitions.node_to_hir_id(k);
             let map = trait_map.entry(hir_id.owner).or_default();
             let v = v
                 .into_iter()
-                .map(|tc| tc.map_import_ids(|id| hir.definitions().node_to_hir_id(id)))
+                .map(|tc| tc.map_import_ids(|id| definitions.node_to_hir_id(id)))
                 .collect();
             map.insert(hir_id.local_id, StableVec::new(v));
         }
@@ -1185,28 +1180,31 @@ impl<'tcx> TyCtxt<'tcx> {
                 .export_map
                 .into_iter()
                 .map(|(k, v)| {
-                    let exports: Vec<_> =
-                        v.into_iter().map(|e| e.map_id(|id| hir.node_to_hir_id(id))).collect();
+                    let exports: Vec<_> = v
+                        .into_iter()
+                        .map(|e| e.map_id(|id| definitions.node_to_hir_id(id)))
+                        .collect();
                     (k, exports)
                 })
                 .collect(),
             maybe_unused_trait_imports: resolutions
                 .maybe_unused_trait_imports
                 .into_iter()
-                .map(|id| hir.local_def_id_from_node_id(id))
+                .map(|id| definitions.local_def_id(id))
                 .collect(),
             maybe_unused_extern_crates: resolutions
                 .maybe_unused_extern_crates
                 .into_iter()
-                .map(|(id, sp)| (hir.local_def_id_from_node_id(id), sp))
+                .map(|(id, sp)| (definitions.local_def_id(id), sp))
                 .collect(),
             glob_map: resolutions
                 .glob_map
                 .into_iter()
-                .map(|(id, names)| (hir.local_def_id_from_node_id(id), names))
+                .map(|(id, names)| (definitions.local_def_id(id), names))
                 .collect(),
             extern_prelude: resolutions.extern_prelude,
-            hir_map: hir,
+            untracked_crate: krate,
+            definitions,
             def_path_hash_to_def_id,
             queries: query::Queries::new(providers, extern_providers, on_disk_query_result_cache),
             rcache: Default::default(),
@@ -1265,7 +1263,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn def_key(self, id: DefId) -> hir_map::DefKey {
-        if id.is_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) }
+        if let Some(id) = id.as_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) }
     }
 
     /// Converts a `DefId` into its fully expanded `DefPath` (every
@@ -1274,7 +1272,11 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Note that if `id` is not local to this crate, the result will
     ///  be a non-local `DefPath`.
     pub fn def_path(self, id: DefId) -> hir_map::DefPath {
-        if id.is_local() { self.hir().def_path(id) } else { self.cstore.def_path(id) }
+        if let Some(id) = id.as_local() {
+            self.hir().def_path(id)
+        } else {
+            self.cstore.def_path(id)
+        }
     }
 
     /// Returns whether or not the crate with CrateNum 'cnum'
@@ -1285,8 +1287,8 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline]
     pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash {
-        if def_id.is_local() {
-            self.hir().definitions().def_path_hash(def_id.index)
+        if let Some(def_id) = def_id.as_local() {
+            self.definitions.def_path_hash(def_id)
         } else {
             self.cstore.def_path_hash(def_id)
         }
@@ -1333,9 +1335,9 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline(always)]
     pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> {
-        let krate = self.gcx.hir_map.untracked_krate();
+        let krate = self.gcx.untracked_crate;
 
-        StableHashingContext::new(self.sess, krate, self.hir().definitions(), &*self.cstore)
+        StableHashingContext::new(self.sess, krate, self.definitions, &*self.cstore)
     }
 
     // This method makes sure that we have a DepNode and a Fingerprint for
@@ -1515,20 +1517,21 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
     pub fn article_and_description(&self, def_id: DefId) -> (&'static str, &'static str) {
-        match self.def_key(def_id).disambiguated_data.data {
-            DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => {
-                let kind = self.def_kind(def_id).unwrap();
-                (kind.article(), kind.descr(def_id))
-            }
-            DefPathData::ClosureExpr => match self.generator_kind(def_id) {
-                None => ("a", "closure"),
-                Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"),
-                Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"),
-            },
-            DefPathData::LifetimeNs(..) => ("a", "lifetime"),
-            DefPathData::Impl => ("an", "implementation"),
-            _ => bug!("article_and_description called on def_id {:?}", def_id),
-        }
+        self.def_kind(def_id)
+            .map(|def_kind| (def_kind.article(), def_kind.descr(def_id)))
+            .unwrap_or_else(|| match self.def_key(def_id).disambiguated_data.data {
+                DefPathData::ClosureExpr => match self.generator_kind(def_id) {
+                    None => ("a", "closure"),
+                    Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"),
+                    Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"),
+                },
+                DefPathData::LifetimeNs(..) => ("a", "lifetime"),
+                DefPathData::Impl => ("an", "implementation"),
+                DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => {
+                    unreachable!()
+                }
+                _ => bug!("article_and_description called on def_id {:?}", def_id),
+            })
     }
 }
 
@@ -2750,18 +2753,15 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
     };
 
     providers.lookup_stability = |tcx, id| {
-        assert_eq!(id.krate, LOCAL_CRATE);
-        let id = tcx.hir().definitions().def_index_to_hir_id(id.index);
+        let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
         tcx.stability().local_stability(id)
     };
     providers.lookup_const_stability = |tcx, id| {
-        assert_eq!(id.krate, LOCAL_CRATE);
-        let id = tcx.hir().definitions().def_index_to_hir_id(id.index);
+        let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
         tcx.stability().local_const_stability(id)
     };
     providers.lookup_deprecation_entry = |tcx, id| {
-        assert_eq!(id.krate, LOCAL_CRATE);
-        let id = tcx.hir().definitions().def_index_to_hir_id(id.index);
+        let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
         tcx.stability().local_deprecation_entry(id)
     };
     providers.extern_mod_stmt_cnum = |tcx, id| {
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 144e3bc9c8b..b166c4dea0c 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -90,30 +90,46 @@ impl<'tcx> TyCtxt<'tcx> {
     /// ```
     /// This code should only compile in modules where the uninhabitedness of Foo is
     /// visible.
-    pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool {
+    pub fn is_ty_uninhabited_from(
+        self,
+        module: DefId,
+        ty: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
         // To check whether this type is uninhabited at all (not just from the
         // given node), you could check whether the forest is empty.
         // ```
         // forest.is_empty()
         // ```
-        ty.uninhabited_from(self).contains(self, module)
+        ty.uninhabited_from(self, param_env).contains(self, module)
     }
 
-    pub fn is_ty_uninhabited_from_any_module(self, ty: Ty<'tcx>) -> bool {
-        !ty.uninhabited_from(self).is_empty()
+    pub fn is_ty_uninhabited_from_any_module(
+        self,
+        ty: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
+        !ty.uninhabited_from(self, param_env).is_empty()
     }
 }
 
 impl<'tcx> AdtDef {
     /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
-    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest {
+    fn uninhabited_from(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        substs: SubstsRef<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> DefIdForest {
         // Non-exhaustive ADTs from other crates are always considered inhabited.
         if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
             DefIdForest::empty()
         } else {
             DefIdForest::intersection(
                 tcx,
-                self.variants.iter().map(|v| v.uninhabited_from(tcx, substs, self.adt_kind())),
+                self.variants
+                    .iter()
+                    .map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)),
             )
         }
     }
@@ -126,6 +142,7 @@ impl<'tcx> VariantDef {
         tcx: TyCtxt<'tcx>,
         substs: SubstsRef<'tcx>,
         adt_kind: AdtKind,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> DefIdForest {
         let is_enum = match adt_kind {
             // For now, `union`s are never considered uninhabited.
@@ -140,7 +157,7 @@ impl<'tcx> VariantDef {
         } else {
             DefIdForest::union(
                 tcx,
-                self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum)),
+                self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum, param_env)),
             )
         }
     }
@@ -153,8 +170,9 @@ impl<'tcx> FieldDef {
         tcx: TyCtxt<'tcx>,
         substs: SubstsRef<'tcx>,
         is_enum: bool,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> DefIdForest {
-        let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx);
+        let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env);
         // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
         // `Visibility::Invisible` so we need to override `self.vis` if we're
         // dealing with an enum.
@@ -176,20 +194,21 @@ impl<'tcx> FieldDef {
 
 impl<'tcx> TyS<'tcx> {
     /// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
-    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest {
+    fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> DefIdForest {
         match self.kind {
-            Adt(def, substs) => def.uninhabited_from(tcx, substs),
+            Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env),
 
             Never => DefIdForest::full(tcx),
 
-            Tuple(ref tys) => {
-                DefIdForest::union(tcx, tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx)))
-            }
+            Tuple(ref tys) => DefIdForest::union(
+                tcx,
+                tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)),
+            ),
 
-            Array(ty, len) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
+            Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
                 // If the array is definitely non-empty, it's uninhabited if
                 // the type of its elements is uninhabited.
-                Some(n) if n != 0 => ty.uninhabited_from(tcx),
+                Some(n) if n != 0 => ty.uninhabited_from(tcx, param_env),
                 _ => DefIdForest::empty(),
             },
 
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 78fcc494f6c..13d58ea73ac 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -39,6 +39,10 @@ pub enum InstanceDef<'tcx> {
 
     /// `<fn() as FnTrait>::call_*`
     /// `DefId` is `FnTrait::call_*`.
+    ///
+    /// NB: the (`fn` pointer) type must currently be monomorphic to avoid double substitution
+    /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
+    // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     FnPtrShim(DefId, Ty<'tcx>),
 
     /// `<dyn Trait as Trait>::fn`, "direct calls" of which are implicitly
@@ -57,9 +61,17 @@ pub enum InstanceDef<'tcx> {
     /// The `DefId` is for `core::ptr::drop_in_place`.
     /// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop
     /// glue.
+    ///
+    /// NB: the type must currently be monomorphic to avoid double substitution
+    /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
+    // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     DropGlue(DefId, Option<Ty<'tcx>>),
 
     ///`<T as Clone>::clone` shim.
+    ///
+    /// NB: the type must currently be monomorphic to avoid double substitution
+    /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
+    // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     CloneShim(DefId, Ty<'tcx>),
 }
 
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index dedb3035ced..6d28796b348 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1,30 +1,28 @@
-use crate::session::{self, DataTypeKind};
+use crate::ich::StableHashingContext;
+use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
+use crate::ty::subst::Subst;
 use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
 
 use rustc_ast::ast::{self, Ident, IntTy, UintTy};
 use rustc_attr as attr;
-use rustc_span::DUMMY_SP;
-
-use std::cmp;
-use std::fmt;
-use std::iter;
-use std::mem;
-use std::ops::Bound;
-
-use crate::ich::StableHashingContext;
-use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
-use crate::ty::subst::Subst;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
-
+use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
+use rustc_span::DUMMY_SP;
 use rustc_target::abi::call::{
     ArgAbi, ArgAttribute, ArgAttributes, Conv, FnAbi, PassMode, Reg, RegKind,
 };
 pub use rustc_target::abi::*;
 use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec};
 
+use std::cmp;
+use std::fmt;
+use std::iter;
+use std::mem;
+use std::ops::Bound;
+
 pub trait IntegerExt {
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
     fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
@@ -782,8 +780,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     present_first @ Some(_) => present_first,
                     // Uninhabited because it has no variants, or only absent ones.
                     None if def.is_enum() => return tcx.layout_raw(param_env.and(tcx.types.never)),
-                    // if it's a struct, still compute a layout so that we can still compute the
-                    // field offsets
+                    // If it's a struct, still compute a layout so that we can still compute the
+                    // field offsets.
                     None => Some(VariantIdx::new(0)),
                 };
 
@@ -1409,12 +1407,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
         // locals as part of the prefix. We compute the layout of all of
         // these fields at once to get optimal packing.
         let discr_index = substs.as_generator().prefix_tys(def_id, tcx).count();
-        // FIXME(eddyb) set the correct vaidity range for the discriminant.
-        let discr_layout = self.layout_of(substs.as_generator().discr_ty(tcx))?;
-        let discr = match &discr_layout.abi {
-            Abi::Scalar(s) => s.clone(),
-            _ => bug!(),
-        };
+
+        // `info.variant_fields` already accounts for the reserved variants, so no need to add them.
+        let max_discr = (info.variant_fields.len() - 1) as u128;
+        let discr_int = Integer::fit_unsigned(max_discr);
+        let discr_int_ty = discr_int.to_ty(tcx, false);
+        let discr = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr };
+        let discr_layout = self.tcx.intern_layout(LayoutDetails::scalar(self, discr.clone()));
+        let discr_layout = TyLayout { ty: discr_int_ty, details: discr_layout };
+
         let promoted_layouts = ineligible_locals
             .iter()
             .map(|local| subst_field(info.field_tys[local]))
@@ -1648,7 +1649,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         if min_size < field_end {
                             min_size = field_end;
                         }
-                        session::FieldInfo {
+                        FieldInfo {
                             name: name.to_string(),
                             offset: offset.bytes(),
                             size: field_layout.size.bytes(),
@@ -1658,13 +1659,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                 })
                 .collect();
 
-            session::VariantInfo {
+            VariantInfo {
                 name: n.map(|n| n.to_string()),
-                kind: if layout.is_unsized() {
-                    session::SizeKind::Min
-                } else {
-                    session::SizeKind::Exact
-                },
+                kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
                 align: layout.align.abi.bytes(),
                 size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() },
                 fields: field_info,
@@ -1990,7 +1987,15 @@ where
 {
     fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
         let details = match this.variants {
-            Variants::Single { index } if index == variant_index => this.details,
+            Variants::Single { index }
+                // If all variants but one are uninhabited, the variant layout is the enum layout.
+                if index == variant_index &&
+                // Don't confuse variants of uninhabited enums with the enum itself.
+                // For more details see https://github.com/rust-lang/rust/issues/69763.
+                this.fields != FieldPlacement::Union(0) =>
+            {
+                this.details
+            }
 
             Variants::Single { index } => {
                 // Deny calling for_variant more than once for non-Single enums.
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 7bcd63b9655..9e3853c51af 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -9,7 +9,6 @@ pub use self::Variance::*;
 use crate::arena::Arena;
 use crate::hir::exports::ExportMap;
 use crate::hir::map as hir_map;
-
 use crate::ich::Fingerprint;
 use crate::ich::StableHashingContext;
 use crate::infer::canonical::Canonical;
@@ -19,7 +18,6 @@ use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
 use crate::mir::interpret::ErrorHandled;
 use crate::mir::GeneratorLayout;
 use crate::mir::ReadOnlyBodyAndCache;
-use crate::session::DataTypeKind;
 use crate::traits::{self, Reveal};
 use crate::ty;
 use crate::ty::layout::VariantIdx;
@@ -42,6 +40,7 @@ use rustc_hir::{Constness, GlobMap, Node, TraitMap};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_serialize::{self, Encodable, Encoder};
+use rustc_session::DataTypeKind;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
@@ -230,7 +229,7 @@ impl AssocItem {
     pub fn def_kind(&self) -> DefKind {
         match self.kind {
             AssocKind::Const => DefKind::AssocConst,
-            AssocKind::Method => DefKind::Method,
+            AssocKind::Method => DefKind::AssocFn,
             AssocKind::Type => DefKind::AssocTy,
             AssocKind::OpaqueTy => DefKind::AssocOpaqueTy,
         }
@@ -385,7 +384,9 @@ impl Visibility {
                 Res::Err => Visibility::Public,
                 def => Visibility::Restricted(def.def_id()),
             },
-            hir::VisibilityKind::Inherited => Visibility::Restricted(tcx.parent_module(id)),
+            hir::VisibilityKind::Inherited => {
+                Visibility::Restricted(tcx.parent_module(id).to_def_id())
+            }
         }
     }
 
@@ -554,24 +555,26 @@ bitflags! {
         /// Does this have [ConstKind::Placeholder]?
         const HAS_CT_PLACEHOLDER        = 1 << 8;
 
+        /// `true` if there are "names" of regions and so forth
+        /// that are local to a particular fn/inferctxt
+        const HAS_FREE_LOCAL_REGIONS    = 1 << 9;
+
         /// `true` if there are "names" of types and regions and so forth
         /// that are local to a particular fn
         const HAS_FREE_LOCAL_NAMES      = TypeFlags::HAS_TY_PARAM.bits
-                                        | TypeFlags::HAS_RE_PARAM.bits
                                         | TypeFlags::HAS_CT_PARAM.bits
                                         | TypeFlags::HAS_TY_INFER.bits
-                                        | TypeFlags::HAS_RE_INFER.bits
                                         | TypeFlags::HAS_CT_INFER.bits
                                         | TypeFlags::HAS_TY_PLACEHOLDER.bits
-                                        | TypeFlags::HAS_RE_PLACEHOLDER.bits
-                                        | TypeFlags::HAS_CT_PLACEHOLDER.bits;
+                                        | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                        | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
 
         /// Does this have [Projection] or [UnnormalizedProjection]?
-        const HAS_TY_PROJECTION         = 1 << 9;
+        const HAS_TY_PROJECTION         = 1 << 10;
         /// Does this have [Opaque]?
-        const HAS_TY_OPAQUE             = 1 << 10;
+        const HAS_TY_OPAQUE             = 1 << 11;
         /// Does this have [ConstKind::Unevaluated]?
-        const HAS_CT_PROJECTION         = 1 << 11;
+        const HAS_CT_PROJECTION         = 1 << 12;
 
         /// Could this type be normalized further?
         const HAS_PROJECTION            = TypeFlags::HAS_TY_PROJECTION.bits
@@ -580,21 +583,21 @@ bitflags! {
 
         /// Present if the type belongs in a local type context.
         /// Set for placeholders and inference variables that are not "Fresh".
-        const KEEP_IN_LOCAL_TCX         = 1 << 12;
+        const KEEP_IN_LOCAL_TCX         = 1 << 13;
 
         /// Is an error type reachable?
-        const HAS_TY_ERR                = 1 << 13;
+        const HAS_TY_ERR                = 1 << 14;
 
         /// Does this have any region that "appears free" in the type?
         /// Basically anything but [ReLateBound] and [ReErased].
-        const HAS_FREE_REGIONS          = 1 << 14;
+        const HAS_FREE_REGIONS          = 1 << 15;
 
         /// Does this have any [ReLateBound] regions? Used to check
         /// if a global bound is safe to evaluate.
-        const HAS_RE_LATE_BOUND         = 1 << 15;
+        const HAS_RE_LATE_BOUND         = 1 << 16;
 
         /// Does this have any [ReErased] regions?
-        const HAS_RE_ERASED             = 1 << 16;
+        const HAS_RE_ERASED             = 1 << 17;
 
         /// Flags representing the nominal content of a type,
         /// computed by FlagsComputation. If you add a new nominal
@@ -608,6 +611,7 @@ bitflags! {
                                         | TypeFlags::HAS_TY_PLACEHOLDER.bits
                                         | TypeFlags::HAS_RE_PLACEHOLDER.bits
                                         | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                        | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
                                         | TypeFlags::HAS_TY_PROJECTION.bits
                                         | TypeFlags::HAS_TY_OPAQUE.bits
                                         | TypeFlags::HAS_CT_PROJECTION.bits
@@ -1697,7 +1701,7 @@ rustc_index::newtype_index! {
 }
 
 impl UniverseIndex {
-    pub const ROOT: UniverseIndex = UniverseIndex::from_u32_const(0);
+    pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0);
 
     /// Returns the "next" universe index in order -- this new index
     /// is considered to extend all previous universes. This
@@ -2872,7 +2876,7 @@ impl<'tcx> TyCtxt<'tcx> {
             }
         } else {
             match self.def_kind(def_id).expect("no def for `DefId`") {
-                DefKind::AssocConst | DefKind::Method | DefKind::AssocTy => true,
+                DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => true,
                 _ => false,
             }
         };
@@ -3051,7 +3055,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// `DefId` of the impl that the method belongs to; otherwise, returns `None`.
     pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         let item = if def_id.krate != LOCAL_CRATE {
-            if let Some(DefKind::Method) = self.def_kind(def_id) {
+            if let Some(DefKind::AssocFn) = self.def_kind(def_id) {
                 Some(self.associated_item(def_id))
             } else {
                 None
@@ -3083,7 +3087,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool {
         // We could use `Ident::eq` here, but we deliberately don't. The name
         // comparison fails frequently, and we want to avoid the expensive
-        // `modern()` calls required for the span comparison whenever possible.
+        // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible.
         use_name.name == def_name.name
             && use_name
                 .span
@@ -3092,14 +3096,14 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     fn expansion_that_defined(self, scope: DefId) -> ExpnId {
-        match scope.krate {
-            LOCAL_CRATE => self.hir().definitions().expansion_that_defined(scope.index),
-            _ => ExpnId::root(),
+        match scope.as_local() {
+            Some(scope) => self.hir().definitions().expansion_that_defined(scope),
+            None => ExpnId::root(),
         }
     }
 
     pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident {
-        ident.span.modernize_and_adjust(self.expansion_that_defined(scope));
+        ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope));
         ident
     }
 
@@ -3109,12 +3113,14 @@ impl<'tcx> TyCtxt<'tcx> {
         scope: DefId,
         block: hir::HirId,
     ) -> (Ident, DefId) {
-        let scope = match ident.span.modernize_and_adjust(self.expansion_that_defined(scope)) {
-            Some(actual_expansion) => {
-                self.hir().definitions().parent_module_of_macro_def(actual_expansion)
-            }
-            None => self.parent_module(block),
-        };
+        let scope =
+            match ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope))
+            {
+                Some(actual_expansion) => {
+                    self.hir().definitions().parent_module_of_macro_def(actual_expansion)
+                }
+                None => self.parent_module(block).to_def_id(),
+            };
         (ident, scope)
     }
 
@@ -3142,8 +3148,11 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
     context::provide(providers);
     erase_regions::provide(providers);
     layout::provide(providers);
-    *providers =
-        ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, ..*providers };
+    *providers = ty::query::Providers {
+        trait_impls_of: trait_def::trait_impls_of_provider,
+        all_local_trait_impls: trait_def::all_local_trait_impls,
+        ..*providers
+    };
 }
 
 /// A map for the local crate mapping each type to a vector of its
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 05dcc9e85ac..cb01d821c18 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -1,7 +1,7 @@
 use crate::hir::map::{DefPathData, DisambiguatedDefPathData};
 use crate::middle::cstore::{ExternCrate, ExternCrateSource};
 use crate::middle::region;
-use crate::mir::interpret::{sign_extend, truncate, ConstValue, Scalar};
+use crate::mir::interpret::{sign_extend, truncate, AllocId, ConstValue, Pointer, Scalar};
 use crate::ty::layout::{Integer, IntegerExt, Size};
 use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
 use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
@@ -17,6 +17,7 @@ use rustc_span::symbol::{kw, Symbol};
 use rustc_target::spec::abi::Abi;
 
 use std::cell::Cell;
+use std::char;
 use std::collections::BTreeMap;
 use std::fmt::{self, Write as _};
 use std::ops::{Deref, DerefMut};
@@ -210,6 +211,21 @@ pub trait PrettyPrinter<'tcx>:
         Ok(self)
     }
 
+    /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument
+    fn typed_value(
+        mut self,
+        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        t: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        conversion: &str,
+    ) -> Result<Self::Const, Self::Error> {
+        self.write_str("{")?;
+        self = f(self)?;
+        self.write_str(conversion)?;
+        self = t(self)?;
+        self.write_str("}")?;
+        Ok(self)
+    }
+
     /// Prints `<...>` around what `f` prints.
     fn generic_delimiters(
         self,
@@ -517,14 +533,7 @@ pub trait PrettyPrinter<'tcx>:
             ty::Error => p!(write("[type error]")),
             ty::Param(ref param_ty) => p!(write("{}", param_ty)),
             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
-                ty::BoundTyKind::Anon => {
-                    if debruijn == ty::INNERMOST {
-                        p!(write("^{}", bound_ty.var.index()))
-                    } else {
-                        p!(write("^{}_{}", debruijn.index(), bound_ty.var.index()))
-                    }
-                }
-
+                ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
                 ty::BoundTyKind::Param(p) => p!(write("{}", p)),
             },
             ty::Adt(def, substs) => {
@@ -689,7 +698,7 @@ pub trait PrettyPrinter<'tcx>:
                     // array length anon const, rustc will (with debug assertions) print the
                     // constant's path. Which will end up here again.
                     p!(write("_"));
-                } else if let Some(n) = sz.try_eval_usize(self.tcx(), ty::ParamEnv::empty()) {
+                } else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) {
                     p!(write("{}", n));
                 } else {
                     p!(write("_"));
@@ -702,6 +711,18 @@ pub trait PrettyPrinter<'tcx>:
         Ok(self)
     }
 
+    fn pretty_print_bound_var(
+        &mut self,
+        debruijn: ty::DebruijnIndex,
+        var: ty::BoundVar,
+    ) -> Result<(), Self::Error> {
+        if debruijn == ty::INNERMOST {
+            write!(self, "^{}", var.index())
+        } else {
+            write!(self, "^{}_{}", debruijn.index(), var.index())
+        }
+    }
+
     fn infer_ty_name(&self, _: ty::TyVid) -> Option<String> {
         None
     }
@@ -842,16 +863,23 @@ pub trait PrettyPrinter<'tcx>:
 
         macro_rules! print_underscore {
             () => {{
-                p!(write("_"));
                 if print_ty {
-                    p!(write(": "), print(ct.ty));
+                    self = self.typed_value(
+                        |mut this| {
+                            write!(this, "_")?;
+                            Ok(this)
+                        },
+                        |this| this.print_type(ct.ty),
+                        ": ",
+                    )?;
+                } else {
+                    write!(self, "_")?;
                 }
             }};
         }
 
-        match (ct.val, &ct.ty.kind) {
-            (_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)),
-            (ty::ConstKind::Unevaluated(did, substs, promoted), _) => {
+        match ct.val {
+            ty::ConstKind::Unevaluated(did, substs, promoted) => {
                 if let Some(promoted) = promoted {
                     p!(print_value_path(did, substs));
                     p!(write("::{:?}", promoted));
@@ -876,49 +904,73 @@ pub trait PrettyPrinter<'tcx>:
                     }
                 }
             }
-            (ty::ConstKind::Infer(..), _) => print_underscore!(),
-            (ty::ConstKind::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
-            (ty::ConstKind::Value(value), _) => {
+            ty::ConstKind::Infer(..) => print_underscore!(),
+            ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
+            ty::ConstKind::Value(value) => {
                 return self.pretty_print_const_value(value, ct.ty, print_ty);
             }
 
-            _ => {
-                // fallback
-                p!(write("{:?}", ct.val));
-                if print_ty {
-                    p!(write(": "), print(ct.ty));
-                }
+            ty::ConstKind::Bound(debruijn, bound_var) => {
+                self.pretty_print_bound_var(debruijn, bound_var)?
             }
+            ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
         };
         Ok(self)
     }
 
-    fn pretty_print_const_value(
+    fn pretty_print_const_scalar(
         mut self,
-        ct: ConstValue<'tcx>,
+        scalar: Scalar,
         ty: Ty<'tcx>,
         print_ty: bool,
     ) -> Result<Self::Const, Self::Error> {
         define_scoped_cx!(self);
 
-        if self.tcx().sess.verbose() {
-            p!(write("ConstValue({:?}: {:?})", ct, ty));
-            return Ok(self);
-        }
-
-        let u8 = self.tcx().types.u8;
-
-        match (ct, &ty.kind) {
-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) => {
-                p!(write("{}", if data == 0 { "false" } else { "true" }))
-            }
-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) => {
+        match (scalar, &ty.kind) {
+            // Byte strings (&[u8; N])
+            (
+                Scalar::Ptr(ptr),
+                ty::Ref(
+                    _,
+                    ty::TyS {
+                        kind:
+                            ty::Array(
+                                ty::TyS { kind: ty::Uint(ast::UintTy::U8), .. },
+                                ty::Const {
+                                    val:
+                                        ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw {
+                                            data,
+                                            ..
+                                        })),
+                                    ..
+                                },
+                            ),
+                        ..
+                    },
+                    _,
+                ),
+            ) => {
+                let byte_str = self
+                    .tcx()
+                    .alloc_map
+                    .lock()
+                    .unwrap_memory(ptr.alloc_id)
+                    .get_bytes(&self.tcx(), ptr, Size::from_bytes(*data as u64))
+                    .unwrap();
+                p!(pretty_print_byte_str(byte_str));
+            }
+            // Bool
+            (Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")),
+            (Scalar::Raw { data: 1, .. }, ty::Bool) => p!(write("true")),
+            // Float
+            (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F32)) => {
                 p!(write("{}f32", Single::from_bits(data)))
             }
-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F64)) => {
+            (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F64)) => {
                 p!(write("{}f64", Double::from_bits(data)))
             }
-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => {
+            // Int
+            (Scalar::Raw { data, .. }, ty::Uint(ui)) => {
                 let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size();
                 let max = truncate(u128::MAX, bit_size);
 
@@ -926,93 +978,191 @@ pub trait PrettyPrinter<'tcx>:
                 if data == max {
                     p!(write("std::{}::MAX", ui_str))
                 } else {
-                    p!(write("{}{}", data, ui_str))
+                    if print_ty { p!(write("{}{}", data, ui_str)) } else { p!(write("{}", data)) }
                 };
             }
-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => {
-                let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size().bits() as u128;
+            (Scalar::Raw { data, .. }, ty::Int(i)) => {
+                let size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size();
+                let bit_size = size.bits() as u128;
                 let min = 1u128 << (bit_size - 1);
                 let max = min - 1;
 
-                let ty = self.tcx().lift(&ty).unwrap();
-                let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
                 let i_str = i.name_str();
                 match data {
                     d if d == min => p!(write("std::{}::MIN", i_str)),
                     d if d == max => p!(write("std::{}::MAX", i_str)),
-                    _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)),
+                    _ => {
+                        let data = sign_extend(data, size) as i128;
+                        if print_ty {
+                            p!(write("{}{}", data, i_str))
+                        } else {
+                            p!(write("{}", data))
+                        }
+                    }
                 }
             }
-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => {
-                p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()))
-            }
-            (ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")),
-            (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => {
+            // Char
+            (Scalar::Raw { data, .. }, ty::Char) if char::from_u32(data as u32).is_some() => {
+                p!(write("{:?}", char::from_u32(data as u32).unwrap()))
+            }
+            // Raw pointers
+            (Scalar::Raw { data, .. }, ty::RawPtr(_)) => {
+                self = self.typed_value(
+                    |mut this| {
+                        write!(this, "0x{:x}", data)?;
+                        Ok(this)
+                    },
+                    |this| this.print_type(ty),
+                    " as ",
+                )?;
+            }
+            (Scalar::Ptr(ptr), ty::FnPtr(_)) => {
                 let instance = {
                     let alloc_map = self.tcx().alloc_map.lock();
                     alloc_map.unwrap_fn(ptr.alloc_id)
                 };
-                p!(print_value_path(instance.def_id(), instance.substs));
-            }
-            _ => {
-                let printed = if let ty::Ref(_, ref_ty, _) = ty.kind {
-                    let byte_str = match (ct, &ref_ty.kind) {
-                        (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
-                            let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
-                            Some(
-                                self.tcx()
-                                    .alloc_map
-                                    .lock()
-                                    .unwrap_memory(ptr.alloc_id)
-                                    .get_bytes(&self.tcx(), ptr, Size::from_bytes(n))
-                                    .unwrap(),
-                            )
-                        }
-                        (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
-                            // The `inspect` here is okay since we checked the bounds, and there are
-                            // no relocations (we have an active slice reference here). We don't use
-                            // this result to affect interpreter execution.
-                            Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
-                        }
-                        _ => None,
-                    };
-
-                    if let Some(byte_str) = byte_str {
-                        p!(write("b\""));
-                        for &c in byte_str {
-                            for e in std::ascii::escape_default(c) {
-                                self.write_char(e as char)?;
-                            }
-                        }
-                        p!(write("\""));
-                        true
-                    } else if let (ConstValue::Slice { data, start, end }, ty::Str) =
-                        (ct, &ref_ty.kind)
-                    {
-                        // The `inspect` here is okay since we checked the bounds, and there are no
-                        // relocations (we have an active `str` reference here). We don't use this
-                        // result to affect interpreter execution.
-                        let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
-                        let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
-                        p!(write("{:?}", s));
-                        true
+                self = self.typed_value(
+                    |this| this.print_value_path(instance.def_id(), instance.substs),
+                    |this| this.print_type(ty),
+                    " as ",
+                )?;
+            }
+            // For function type zsts just printing the path is enough
+            (Scalar::Raw { size: 0, .. }, ty::FnDef(d, s)) => p!(print_value_path(*d, s)),
+            // Empty tuples are frequently occurring, so don't print the fallback.
+            (Scalar::Raw { size: 0, .. }, ty::Tuple(ts)) if ts.is_empty() => p!(write("()")),
+            // Zero element arrays have a trivial representation.
+            (
+                Scalar::Raw { size: 0, .. },
+                ty::Array(
+                    _,
+                    ty::Const {
+                        val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: 0, .. })),
+                        ..
+                    },
+                ),
+            ) => p!(write("[]")),
+            // Nontrivial types with scalar bit representation
+            (Scalar::Raw { data, size }, _) => {
+                let print = |mut this: Self| {
+                    if size == 0 {
+                        write!(this, "transmute(())")?;
                     } else {
-                        false
+                        write!(this, "transmute(0x{:01$x})", data, size as usize * 2)?;
                     }
+                    Ok(this)
+                };
+                self = if print_ty {
+                    self.typed_value(print, |this| this.print_type(ty), ": ")?
                 } else {
-                    false
+                    print(self)?
                 };
-                if !printed {
-                    // fallback
-                    p!(write("{:?}", ct));
-                    if print_ty {
-                        p!(write(": "), print(ty));
-                    }
-                }
             }
-        };
+            // Any pointer values not covered by a branch above
+            (Scalar::Ptr(p), _) => {
+                self = self.pretty_print_const_pointer(p, ty, print_ty)?;
+            }
+        }
         Ok(self)
     }
+
+    /// This is overridden for MIR printing because we only want to hide alloc ids from users, not
+    /// from MIR where it is actually useful.
+    fn pretty_print_const_pointer(
+        mut self,
+        _: Pointer,
+        ty: Ty<'tcx>,
+        print_ty: bool,
+    ) -> Result<Self::Const, Self::Error> {
+        if print_ty {
+            self.typed_value(
+                |mut this| {
+                    this.write_str("&_")?;
+                    Ok(this)
+                },
+                |this| this.print_type(ty),
+                ": ",
+            )
+        } else {
+            self.write_str("&_")?;
+            Ok(self)
+        }
+    }
+
+    fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> {
+        define_scoped_cx!(self);
+        p!(write("b\""));
+        for &c in byte_str {
+            for e in std::ascii::escape_default(c) {
+                self.write_char(e as char)?;
+            }
+        }
+        p!(write("\""));
+        Ok(self)
+    }
+
+    fn pretty_print_const_value(
+        mut self,
+        ct: ConstValue<'tcx>,
+        ty: Ty<'tcx>,
+        print_ty: bool,
+    ) -> Result<Self::Const, Self::Error> {
+        define_scoped_cx!(self);
+
+        if self.tcx().sess.verbose() {
+            p!(write("ConstValue({:?}: {:?})", ct, ty));
+            return Ok(self);
+        }
+
+        let u8_type = self.tcx().types.u8;
+
+        match (ct, &ty.kind) {
+            (ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty),
+            (
+                ConstValue::Slice { data, start, end },
+                ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _),
+            ) if *t == u8_type => {
+                // The `inspect` here is okay since we checked the bounds, and there are
+                // no relocations (we have an active slice reference here). We don't use
+                // this result to affect interpreter execution.
+                let byte_str = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
+                self.pretty_print_byte_str(byte_str)
+            }
+            (
+                ConstValue::Slice { data, start, end },
+                ty::Ref(_, ty::TyS { kind: ty::Str, .. }, _),
+            ) => {
+                // The `inspect` here is okay since we checked the bounds, and there are no
+                // relocations (we have an active `str` reference here). We don't use this
+                // result to affect interpreter execution.
+                let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
+                let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
+                p!(write("{:?}", s));
+                Ok(self)
+            }
+            (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
+                let n = n.val.try_to_bits(self.tcx().data_layout.pointer_size).unwrap();
+                // cast is ok because we already checked for pointer size (32 or 64 bit) above
+                let n = Size::from_bytes(n as u64);
+                let ptr = Pointer::new(AllocId(0), offset);
+
+                let byte_str = alloc.get_bytes(&self.tcx(), ptr, n).unwrap();
+                p!(write("*"));
+                p!(pretty_print_byte_str(byte_str));
+                Ok(self)
+            }
+            // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
+            // their fields instead of just dumping the memory.
+            _ => {
+                // fallback
+                p!(write("{:?}", ct));
+                if print_ty {
+                    p!(write(": "), print(ty));
+                }
+                Ok(self)
+            }
+        }
+    }
 }
 
 // HACK(eddyb) boxed to avoid moving around a large struct by-value.
@@ -1024,6 +1174,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
 
     empty_path: bool,
     in_value: bool,
+    pub print_alloc_ids: bool,
 
     used_region_names: FxHashSet<Symbol>,
     region_index: usize,
@@ -1054,6 +1205,7 @@ impl<F> FmtPrinter<'a, 'tcx, F> {
             fmt,
             empty_path: false,
             in_value: ns == Namespace::ValueNS,
+            print_alloc_ids: false,
             used_region_names: Default::default(),
             region_index: 0,
             binder_depth: 0,
@@ -1326,6 +1478,22 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
         self.pretty_in_binder(value)
     }
 
+    fn typed_value(
+        mut self,
+        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        t: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        conversion: &str,
+    ) -> Result<Self::Const, Self::Error> {
+        self.write_str("{")?;
+        self = f(self)?;
+        self.write_str(conversion)?;
+        let was_in_value = std::mem::replace(&mut self.in_value, false);
+        self = t(self)?;
+        self.in_value = was_in_value;
+        self.write_str("}")?;
+        Ok(self)
+    }
+
     fn generic_delimiters(
         mut self,
         f: impl FnOnce(Self) -> Result<Self, Self::Error>,
@@ -1382,6 +1550,28 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
             ty::ReStatic | ty::ReEmpty(_) | ty::ReClosureBound(_) => true,
         }
     }
+
+    fn pretty_print_const_pointer(
+        self,
+        p: Pointer,
+        ty: Ty<'tcx>,
+        print_ty: bool,
+    ) -> Result<Self::Const, Self::Error> {
+        let print = |mut this: Self| {
+            define_scoped_cx!(this);
+            if this.print_alloc_ids {
+                p!(write("{:?}", p));
+            } else {
+                p!(write("&_"));
+            }
+            Ok(this)
+        };
+        if print_ty {
+            self.typed_value(print, |this| this.print_type(ty), ": ")
+        } else {
+            print(self)
+        }
+    }
 }
 
 // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
diff --git a/src/librustc/ty/query/README.md b/src/librustc/ty/query/README.md
index 4b5e08cecd9..8ec07b9fdeb 100644
--- a/src/librustc/ty/query/README.md
+++ b/src/librustc/ty/query/README.md
@@ -1,3 +1,3 @@
-For more information about how the query system works, see the [rustc guide].
+For more information about how the query system works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/query.html
diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs
index 09fb307a1ce..6073d3a545f 100644
--- a/src/librustc/ty/query/keys.rs
+++ b/src/librustc/ty/query/keys.rs
@@ -7,7 +7,7 @@ use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::query::caches::DefaultCacheSelector;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, Ty, TyCtxt};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -84,14 +84,14 @@ impl Key for CrateNum {
     }
 }
 
-impl Key for DefIndex {
+impl Key for LocalDefId {
     type CacheSelector = DefaultCacheSelector;
 
     fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
+        self.to_def_id().query_crate()
     }
-    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
-        DUMMY_SP
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.to_def_id().default_span(tcx)
     }
 }
 
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 8adb828fbeb..7ac8358c78a 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -1,5 +1,7 @@
 use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams};
 use crate::hir::exports::Export;
+use crate::hir::map;
+use crate::hir::{HirOwner, HirOwnerItems};
 use crate::infer::canonical::{self, Canonical};
 use crate::lint::LintLevelMap;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
@@ -17,8 +19,6 @@ use crate::mir::interpret::GlobalId;
 use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue};
 use crate::mir::interpret::{LitToConstError, LitToConstInput};
 use crate::mir::mono::CodegenUnit;
-use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
-use crate::session::CrateDisambiguator;
 use crate::traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
     CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
@@ -44,9 +44,11 @@ use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
 use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate};
 use rustc_index::vec::IndexVec;
+use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
+use rustc_session::CrateDisambiguator;
 use rustc_target::spec::PanicStrategy;
 
 use rustc_ast::ast;
@@ -54,6 +56,7 @@ use rustc_attr as attr;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 use std::borrow::Cow;
+use std::collections::BTreeMap;
 use std::convert::TryFrom;
 use std::ops::Deref;
 use std::sync::Arc;
@@ -144,7 +147,7 @@ rustc_query_append! { [define_queries!][<'tcx>] }
 ///
 /// When you implement a new query, it will likely have a corresponding new
 /// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
-/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
+/// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
 /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
 /// add it to the "We don't have enough information to reconstruct..." group in
 /// the match below.
@@ -176,10 +179,7 @@ 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.
-        DepKind::AllLocalTraitImpls |
         DepKind::CrateMetadata |
-        DepKind::HirBody |
-        DepKind::Hir |
 
         // These are anonymous nodes.
         DepKind::TraitSelect |
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 9c1db7c5f2b..781abea75d9 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -3,7 +3,6 @@ use crate::hir::map::definitions::DefPathHash;
 use crate::ich::{CachingSourceMapView, Fingerprint};
 use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use crate::mir::{self, interpret};
-use crate::session::{CrateDisambiguator, Session};
 use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
@@ -12,13 +11,13 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once};
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_errors::Diagnostic;
-use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_serialize::{
     opaque, Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder,
     UseSpecializedDecodable, UseSpecializedEncodable,
 };
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::hygiene::{ExpnId, SyntaxContext};
 use rustc_span::source_map::{SourceMap, StableSourceFileId};
 use rustc_span::{BytePos, SourceFile, Span, DUMMY_SP};
@@ -657,26 +656,7 @@ impl<'a, 'tcx> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx> {
 impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for CacheDecoder<'a, 'tcx> {
     #[inline]
     fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
-        Ok(LocalDefId::from_def_id(DefId::decode(self)?))
-    }
-}
-
-impl<'a, 'tcx> SpecializedDecoder<hir::HirId> for CacheDecoder<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<hir::HirId, Self::Error> {
-        // Load the `DefPathHash` which is what we encoded the `DefIndex` as.
-        let def_path_hash = DefPathHash::decode(self)?;
-
-        // Use the `DefPathHash` to map to the current `DefId`.
-        let def_id = self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash];
-
-        debug_assert!(def_id.is_local());
-
-        // The `ItemLocalId` needs no remapping.
-        let local_id = hir::ItemLocalId::decode(self)?;
-
-        // Reconstruct the `HirId` and look up the corresponding `NodeId` in the
-        // context of the current session.
-        Ok(hir::HirId { owner: def_id.index, local_id })
+        Ok(DefId::decode(self)?.expect_local())
     }
 }
 
@@ -873,21 +853,6 @@ where
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<hir::HirId> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-{
-    #[inline]
-    fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> {
-        let hir::HirId { owner, local_id } = *id;
-
-        let def_path_hash = self.tcx.hir().definitions().def_path_hash(owner);
-
-        def_path_hash.encode(self)?;
-        local_id.encode(self)
-    }
-}
-
 impl<'a, 'tcx, E> SpecializedEncoder<DefId> for CacheEncoder<'a, 'tcx, E>
 where
     E: 'a + TyEncoder,
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 47bf7822b1f..e265a2f8257 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1396,11 +1396,11 @@ pub type Region<'tcx> = &'tcx RegionKind;
 /// the inference variable is supposed to satisfy the relation
 /// *for every value of the placeholder region*. To ensure that doesn't
 /// happen, you can use `leak_check`. This is more clearly explained
-/// by the [rustc guide].
+/// by the [rustc dev guide].
 ///
 /// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
 /// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
-/// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html
+/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
 #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
 pub enum RegionKind {
     /// Region bound in a type or fn declaration which will be
@@ -1743,42 +1743,42 @@ impl RegionKind {
         }
     }
 
-    pub fn keep_in_local_tcx(&self) -> bool {
-        if let ty::ReVar(..) = self { true } else { false }
-    }
-
     pub fn type_flags(&self) -> TypeFlags {
         let mut flags = TypeFlags::empty();
 
-        if self.keep_in_local_tcx() {
-            flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
-        }
-
         match *self {
             ty::ReVar(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_INFER;
+                flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
             }
             ty::RePlaceholder(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
             }
-            ty::ReLateBound(..) => {
-                flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
-            }
             ty::ReEarlyBound(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_PARAM;
             }
-            ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => {
+            ty::ReFree { .. } | ty::ReScope { .. } => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
             }
-            ty::ReErased => {
-                flags = flags | TypeFlags::HAS_RE_ERASED;
+            ty::ReEmpty(_) | ty::ReStatic => {
+                flags = flags | TypeFlags::HAS_FREE_REGIONS;
             }
             ty::ReClosureBound(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
             }
+            ty::ReLateBound(..) => {
+                flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
+            }
+            ty::ReErased => {
+                flags = flags | TypeFlags::HAS_RE_ERASED;
+            }
         }
 
         debug!("type_flags({:?}) = {:?}", self, flags);
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index 0cf1c397648..b0287be6529 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -5,11 +5,14 @@ use crate::ty::fast_reject;
 use crate::ty::fold::TypeFoldable;
 use crate::ty::{Ty, TyCtxt};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::HirId;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_errors::ErrorReported;
 use rustc_macros::HashStable;
+use std::collections::BTreeMap;
 
 /// A trait's definition with type information.
 #[derive(HashStable)]
@@ -33,11 +36,33 @@ pub struct TraitDef {
     /// and thus `impl`s of it are allowed to overlap.
     pub is_marker: bool,
 
+    /// Used to determine whether the standard library is allowed to specialize
+    /// on this trait.
+    pub specialization_kind: TraitSpecializationKind,
+
     /// The ICH of this trait's DefPath, cached here so it doesn't have to be
     /// recomputed all the time.
     pub def_path_hash: DefPathHash,
 }
 
+/// Whether this trait is treated specially by the standard library
+/// specialization lint.
+#[derive(HashStable, PartialEq, Clone, Copy, RustcEncodable, RustcDecodable)]
+pub enum TraitSpecializationKind {
+    /// The default. Specializing on this trait is not allowed.
+    None,
+    /// Specializing on this trait is allowed because it doesn't have any
+    /// methods. For example `Sized` or `FusedIterator`.
+    /// Applies to traits with the `rustc_unsafe_specialization_marker`
+    /// attribute.
+    Marker,
+    /// Specializing on this trait is allowed because all of the impls of this
+    /// trait are "always applicable". Always applicable means that if
+    /// `X<'x>: T<'y>` for any lifetimes, then `for<'a, 'b> X<'a>: T<'b>`.
+    /// Applies to traits with the `rustc_specialization_trait` attribute.
+    AlwaysApplicable,
+}
+
 #[derive(Default)]
 pub struct TraitImpls {
     blanket_impls: Vec<DefId>,
@@ -52,16 +77,25 @@ impl<'tcx> TraitDef {
         paren_sugar: bool,
         has_auto_impl: bool,
         is_marker: bool,
+        specialization_kind: TraitSpecializationKind,
         def_path_hash: DefPathHash,
     ) -> TraitDef {
-        TraitDef { def_id, unsafety, paren_sugar, has_auto_impl, is_marker, def_path_hash }
+        TraitDef {
+            def_id,
+            unsafety,
+            paren_sugar,
+            has_auto_impl,
+            is_marker,
+            specialization_kind,
+            def_path_hash,
+        }
     }
 
     pub fn ancestors(
         &self,
         tcx: TyCtxt<'tcx>,
         of_impl: DefId,
-    ) -> specialization_graph::Ancestors<'tcx> {
+    ) -> Result<specialization_graph::Ancestors<'tcx>, ErrorReported> {
         specialization_graph::ancestors(tcx, self.def_id, of_impl)
     }
 }
@@ -146,6 +180,14 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 }
 
+// Query provider for `all_local_trait_impls`.
+pub(super) fn all_local_trait_impls<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    krate: CrateNum,
+) -> &'tcx BTreeMap<DefId, Vec<HirId>> {
+    &tcx.hir_crate(krate).trait_impls
+}
+
 // Query provider for `trait_impls_of`.
 pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> &TraitImpls {
     let mut impls = TraitImpls::default();
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index fcebedb2601..69daa2da1fd 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -346,12 +346,7 @@ impl<'tcx> TyCtxt<'tcx> {
         adt_did: DefId,
         validate: &mut dyn FnMut(Self, DefId) -> Result<(), ErrorReported>,
     ) -> Option<ty::Destructor> {
-        let drop_trait = if let Some(def_id) = self.lang_items().drop_trait() {
-            def_id
-        } else {
-            return None;
-        };
-
+        let drop_trait = self.lang_items().drop_trait()?;
         self.ensure().coherent_trait(drop_trait);
 
         let mut dtor_did = None;
diff --git a/src/librustc_ast/README.md b/src/librustc_ast/README.md
index d62e5a5ece0..dd407dba1f4 100644
--- a/src/librustc_ast/README.md
+++ b/src/librustc_ast/README.md
@@ -3,7 +3,7 @@ The `rustc_ast` crate contains those things concerned purely with syntax
 lexer, macro expander, and utilities for traversing ASTs.
 
 For more information about how these things work in rustc, see the
-rustc guide:
+rustc dev guide:
 
-- [Parsing](https://rust-lang.github.io/rustc-guide/the-parser.html)
-- [Macro Expansion](https://rust-lang.github.io/rustc-guide/macro-expansion.html)
+- [Parsing](https://rustc-dev-guide.rust-lang.org/the-parser.html)
+- [Macro Expansion](https://rustc-dev-guide.rust-lang.org/macro-expansion.html)
diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index 88a96dc6c69..e3077b9897c 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -14,7 +14,7 @@
 //! - [`Generics`], [`GenericParam`], [`WhereClause`]: Metadata associated with generic parameters.
 //! - [`EnumDef`] and [`Variant`]: Enum declaration.
 //! - [`Lit`] and [`LitKind`]: Literal expressions.
-//! - [`MacroDef`], [`MacStmtStyle`], [`Mac`], [`MacDelimeter`]: Macro definition and invocation.
+//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`], [`MacDelimeter`]: Macro definition and invocation.
 //! - [`Attribute`]: Metadata associated with item.
 //! - [`UnOp`], [`UnOpKind`], [`BinOp`], [`BinOpKind`]: Unary and binary operators.
 
@@ -513,7 +513,7 @@ impl Pat {
                 TyKind::Path(None, Path::from_ident(*ident))
             }
             PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
-            PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
+            PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
             // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.
             PatKind::Ref(pat, mutbl) => {
                 pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?
@@ -567,7 +567,7 @@ impl Pat {
             | PatKind::Range(..)
             | PatKind::Ident(..)
             | PatKind::Path(..)
-            | PatKind::Mac(_) => {}
+            | PatKind::MacCall(_) => {}
         }
     }
 
@@ -682,7 +682,7 @@ pub enum PatKind {
     Paren(P<Pat>),
 
     /// A macro pattern; pre-expansion.
-    Mac(Mac),
+    MacCall(MacCall),
 }
 
 #[derive(
@@ -881,9 +881,9 @@ impl Stmt {
     pub fn add_trailing_semicolon(mut self) -> Self {
         self.kind = match self.kind {
             StmtKind::Expr(expr) => StmtKind::Semi(expr),
-            StmtKind::Mac(mac) => {
-                StmtKind::Mac(mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs)))
-            }
+            StmtKind::MacCall(mac) => StmtKind::MacCall(
+                mac.map(|(mac, _style, attrs)| (mac, MacStmtStyle::Semicolon, attrs)),
+            ),
             kind => kind,
         };
         self
@@ -917,7 +917,7 @@ pub enum StmtKind {
     /// Just a trailing semi-colon.
     Empty,
     /// Macro.
-    Mac(P<(Mac, MacStmtStyle, AttrVec)>),
+    MacCall(P<(MacCall, MacStmtStyle, AttrVec)>),
 }
 
 #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
@@ -1057,7 +1057,7 @@ impl Expr {
         let kind = match &self.kind {
             // Trivial conversions.
             ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
-            ExprKind::Mac(mac) => TyKind::Mac(mac.clone()),
+            ExprKind::MacCall(mac) => TyKind::MacCall(mac.clone()),
 
             ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?,
 
@@ -1127,7 +1127,7 @@ impl Expr {
             ExprKind::Continue(..) => ExprPrecedence::Continue,
             ExprKind::Ret(..) => ExprPrecedence::Ret,
             ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
-            ExprKind::Mac(..) => ExprPrecedence::Mac,
+            ExprKind::MacCall(..) => ExprPrecedence::Mac,
             ExprKind::Struct(..) => ExprPrecedence::Struct,
             ExprKind::Repeat(..) => ExprPrecedence::Repeat,
             ExprKind::Paren(..) => ExprPrecedence::Paren,
@@ -1259,7 +1259,7 @@ pub enum ExprKind {
     InlineAsm(P<InlineAsm>),
 
     /// A macro invocation; pre-expansion.
-    Mac(Mac),
+    MacCall(MacCall),
 
     /// A struct literal expression.
     ///
@@ -1345,13 +1345,13 @@ pub enum Movability {
 /// Represents a macro invocation. The `path` indicates which macro
 /// is being invoked, and the `args` are arguments passed to it.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct Mac {
+pub struct MacCall {
     pub path: Path,
     pub args: P<MacArgs>,
     pub prior_type_ascription: Option<(Span, bool)>,
 }
 
-impl Mac {
+impl MacCall {
     pub fn span(&self) -> Span {
         self.path.span.to(self.args.span().unwrap_or(self.path.span))
     }
@@ -1446,11 +1446,11 @@ impl MacDelimiter {
 }
 
 /// Represents a macro definition.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub struct MacroDef {
     pub body: P<MacArgs>,
     /// `true` if macro was defined with `macro_rules`.
-    pub legacy: bool,
+    pub macro_rules: bool,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, Eq, PartialEq)]
@@ -1881,7 +1881,7 @@ pub enum TyKind {
     /// Inferred type of a `self` or `&self` argument in a method.
     ImplicitSelf,
     /// A macro in the type position.
-    Mac(Mac),
+    MacCall(MacCall),
     /// Placeholder for a kind that has failed to be defined.
     Err,
     /// Placeholder for a `va_list`.
@@ -2118,14 +2118,14 @@ pub enum ImplPolarity {
     /// `impl Trait for Type`
     Positive,
     /// `impl !Trait for Type`
-    Negative,
+    Negative(Span),
 }
 
 impl fmt::Debug for ImplPolarity {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             ImplPolarity::Positive => "positive".fmt(f),
-            ImplPolarity::Negative => "negative".fmt(f),
+            ImplPolarity::Negative(_) => "negative".fmt(f),
         }
     }
 }
@@ -2153,7 +2153,7 @@ impl FnRetTy {
 /// Module declaration.
 ///
 /// E.g., `mod foo;` or `mod foo { .. }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
 pub struct Mod {
     /// A span from the first token past `{` to the last token until `}`.
     /// For `mod foo;`, the inner span ranges from the first token
@@ -2574,7 +2574,7 @@ pub enum ItemKind {
     /// A macro invocation.
     ///
     /// E.g., `foo!(..)`.
-    Mac(Mac),
+    MacCall(MacCall),
 
     /// A macro definition.
     MacroDef(MacroDef),
@@ -2586,7 +2586,7 @@ impl ItemKind {
         match self {
             Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
             | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a",
-            ExternCrate(..) | ForeignMod(..) | Mac(..) | Enum(..) | Impl { .. } => "an",
+            ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
         }
     }
 
@@ -2606,7 +2606,7 @@ impl ItemKind {
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::Mac(..) => "item macro invocation",
+            ItemKind::MacCall(..) => "item macro invocation",
             ItemKind::MacroDef(..) => "macro definition",
             ItemKind::Impl { .. } => "implementation",
         }
@@ -2648,14 +2648,14 @@ pub enum AssocItemKind {
     /// An associated type.
     TyAlias(Defaultness, Generics, GenericBounds, Option<P<Ty>>),
     /// A macro expanding to associated items.
-    Macro(Mac),
+    MacCall(MacCall),
 }
 
 impl AssocItemKind {
     pub fn defaultness(&self) -> Defaultness {
         match *self {
             Self::Const(def, ..) | Self::Fn(def, ..) | Self::TyAlias(def, ..) => def,
-            Self::Macro(..) => Defaultness::Final,
+            Self::MacCall(..) => Defaultness::Final,
         }
     }
 }
@@ -2666,7 +2666,7 @@ impl From<AssocItemKind> for ItemKind {
             AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c),
             AssocItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d),
             AssocItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d),
-            AssocItemKind::Macro(a) => ItemKind::Mac(a),
+            AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
         }
     }
 }
@@ -2679,7 +2679,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
             ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
             ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d),
             ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d),
-            ItemKind::Mac(a) => AssocItemKind::Macro(a),
+            ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
             _ => return Err(item_kind),
         })
     }
@@ -2695,7 +2695,7 @@ pub enum ForeignItemKind {
     /// A foreign type.
     TyAlias(Defaultness, Generics, GenericBounds, Option<P<Ty>>),
     /// A macro expanding to foreign items.
-    Macro(Mac),
+    MacCall(MacCall),
 }
 
 impl From<ForeignItemKind> for ItemKind {
@@ -2704,7 +2704,7 @@ impl From<ForeignItemKind> for ItemKind {
             ForeignItemKind::Static(a, b, c) => ItemKind::Static(a, b, c),
             ForeignItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d),
             ForeignItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d),
-            ForeignItemKind::Macro(a) => ItemKind::Mac(a),
+            ForeignItemKind::MacCall(a) => ItemKind::MacCall(a),
         }
     }
 }
@@ -2717,7 +2717,7 @@ impl TryFrom<ItemKind> for ForeignItemKind {
             ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c),
             ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d),
             ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d),
-            ItemKind::Mac(a) => ForeignItemKind::Macro(a),
+            ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
             _ => return Err(item_kind),
         })
     }
diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs
index 52a59e82ae2..249311851fb 100644
--- a/src/librustc_ast/attr/mod.rs
+++ b/src/librustc_ast/attr/mod.rs
@@ -679,7 +679,7 @@ impl HasAttrs for StmtKind {
             StmtKind::Local(ref local) => local.attrs(),
             StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(),
             StmtKind::Empty | StmtKind::Item(..) => &[],
-            StmtKind::Mac(ref mac) => {
+            StmtKind::MacCall(ref mac) => {
                 let (_, _, ref attrs) = **mac;
                 attrs.attrs()
             }
@@ -691,7 +691,7 @@ impl HasAttrs for StmtKind {
             StmtKind::Local(local) => local.visit_attrs(f),
             StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f),
             StmtKind::Empty | StmtKind::Item(..) => {}
-            StmtKind::Mac(mac) => {
+            StmtKind::MacCall(mac) => {
                 let (_mac, _style, attrs) = mac.deref_mut();
                 attrs.visit_attrs(f);
             }
diff --git a/src/librustc_ast/lib.rs b/src/librustc_ast/lib.rs
index adb96356aae..2594cc536ac 100644
--- a/src/librustc_ast/lib.rs
+++ b/src/librustc_ast/lib.rs
@@ -7,7 +7,9 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
 #![feature(bool_to_option)]
 #![feature(box_syntax)]
+#![feature(const_if_match)]
 #![feature(const_fn)] // For the `transmute` in `P::new`
+#![feature(const_panic)]
 #![feature(const_transmute)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
diff --git a/src/librustc_ast/mut_visit.rs b/src/librustc_ast/mut_visit.rs
index dedc74eea92..aa2968b3cbe 100644
--- a/src/librustc_ast/mut_visit.rs
+++ b/src/librustc_ast/mut_visit.rs
@@ -202,7 +202,7 @@ pub trait MutVisitor: Sized {
         noop_visit_local(l, self);
     }
 
-    fn visit_mac(&mut self, _mac: &mut Mac) {
+    fn visit_mac(&mut self, _mac: &mut MacCall) {
         panic!("visit_mac disabled by default");
         // N.B., see note about macros above. If you really want a visitor that
         // works on macros, use this definition in your trait impl:
@@ -482,7 +482,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
             vis.visit_id(id);
             visit_vec(bounds, |bound| vis.visit_param_bound(bound));
         }
-        TyKind::Mac(mac) => vis.visit_mac(mac),
+        TyKind::MacCall(mac) => vis.visit_mac(mac),
     }
     vis.visit_span(span);
 }
@@ -584,14 +584,14 @@ pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_visit_mac<T: MutVisitor>(mac: &mut Mac, vis: &mut T) {
-    let Mac { path, args, prior_type_ascription: _ } = mac;
+pub fn noop_visit_mac<T: MutVisitor>(mac: &mut MacCall, vis: &mut T) {
+    let MacCall { path, args, prior_type_ascription: _ } = mac;
     vis.visit_path(path);
     visit_mac_args(args, vis);
 }
 
 pub fn noop_visit_macro_def<T: MutVisitor>(macro_def: &mut MacroDef, vis: &mut T) {
-    let MacroDef { body, legacy: _ } = macro_def;
+    let MacroDef { body, macro_rules: _ } = macro_def;
     visit_mac_args(body, vis);
 }
 
@@ -926,7 +926,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
             vis.visit_generics(generics);
             visit_bounds(bounds, vis);
         }
-        ItemKind::Mac(m) => vis.visit_mac(m),
+        ItemKind::MacCall(m) => vis.visit_mac(m),
         ItemKind::MacroDef(def) => vis.visit_macro_def(def),
     }
 }
@@ -955,7 +955,7 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
         }
-        AssocItemKind::Macro(mac) => visitor.visit_mac(mac),
+        AssocItemKind::MacCall(mac) => visitor.visit_mac(mac),
     }
     visitor.visit_span(span);
     smallvec![item]
@@ -1043,7 +1043,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
         }
-        ForeignItemKind::Macro(mac) => visitor.visit_mac(mac),
+        ForeignItemKind::MacCall(mac) => visitor.visit_mac(mac),
     }
     visitor.visit_span(span);
     smallvec![item]
@@ -1082,7 +1082,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
             visit_vec(elems, |elem| vis.visit_pat(elem))
         }
         PatKind::Paren(inner) => vis.visit_pat(inner),
-        PatKind::Mac(mac) => vis.visit_mac(mac),
+        PatKind::MacCall(mac) => vis.visit_mac(mac),
     }
     vis.visit_span(span);
 }
@@ -1219,7 +1219,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { kind, id, span, attrs }: &mut Expr,
             }
             visit_vec(inputs, |(_c, expr)| vis.visit_expr(expr));
         }
-        ExprKind::Mac(mac) => vis.visit_mac(mac),
+        ExprKind::MacCall(mac) => vis.visit_mac(mac),
         ExprKind::Struct(path, fields, expr) => {
             vis.visit_path(path);
             fields.flat_map_in_place(|field| vis.flat_map_field(field));
@@ -1275,11 +1275,11 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
         StmtKind::Expr(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Expr).collect(),
         StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(),
         StmtKind::Empty => smallvec![StmtKind::Empty],
-        StmtKind::Mac(mut mac) => {
+        StmtKind::MacCall(mut mac) => {
             let (mac_, _semi, attrs) = mac.deref_mut();
             vis.visit_mac(mac_);
             visit_thin_attrs(attrs, vis);
-            smallvec![StmtKind::Mac(mac)]
+            smallvec![StmtKind::MacCall(mac)]
         }
     }
 }
diff --git a/src/librustc_ast/node_id.rs b/src/librustc_ast/node_id.rs
index 58d2334a7b1..cd562c48e91 100644
--- a/src/librustc_ast/node_id.rs
+++ b/src/librustc_ast/node_id.rs
@@ -12,7 +12,7 @@ rustc_index::newtype_index! {
 rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeId);
 
 /// `NodeId` used to represent the root of the crate.
-pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0);
+pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
 
 /// When parsing and doing expansions, we initially give all AST nodes this AST
 /// node value. Then later, in the renumber pass, we renumber them to have
diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs
index b67b7d346f7..3fc6444168e 100644
--- a/src/librustc_ast/token.rs
+++ b/src/librustc_ast/token.rs
@@ -535,6 +535,16 @@ impl Token {
         false
     }
 
+    // Is the token an interpolated block (`$b:block`)?
+    pub fn is_whole_block(&self) -> bool {
+        if let Interpolated(ref nt) = self.kind {
+            if let NtBlock(..) = **nt {
+                return true;
+            }
+        }
+        false
+    }
+
     /// Returns `true` if the token is either the `mut` or `const` keyword.
     pub fn is_mutability(&self) -> bool {
         self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)
diff --git a/src/librustc_ast/visit.rs b/src/librustc_ast/visit.rs
index 1436c84b9c1..39028b7583c 100644
--- a/src/librustc_ast/visit.rs
+++ b/src/librustc_ast/visit.rs
@@ -168,7 +168,7 @@ pub trait Visitor<'ast>: Sized {
     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
         walk_lifetime(self, lifetime)
     }
-    fn visit_mac(&mut self, _mac: &'ast Mac) {
+    fn visit_mac(&mut self, _mac: &'ast MacCall) {
         panic!("visit_mac disabled by default");
         // N.B., see note about macros above.
         // if you really want a visitor that
@@ -350,7 +350,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
         }
-        ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
+        ItemKind::MacCall(ref mac) => visitor.visit_mac(mac),
         ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
@@ -418,7 +418,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
         }
         TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
-        TyKind::Mac(ref mac) => visitor.visit_mac(mac),
+        TyKind::MacCall(ref mac) => visitor.visit_mac(mac),
         TyKind::Never | TyKind::CVarArgs => {}
     }
 }
@@ -521,7 +521,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
         PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => {
             walk_list!(visitor, visit_pat, elems);
         }
-        PatKind::Mac(ref mac) => visitor.visit_mac(mac),
+        PatKind::MacCall(ref mac) => visitor.visit_mac(mac),
     }
 }
 
@@ -545,7 +545,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
         }
-        ForeignItemKind::Macro(mac) => {
+        ForeignItemKind::MacCall(mac) => {
             visitor.visit_mac(mac);
         }
     }
@@ -650,7 +650,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
         }
-        AssocItemKind::Macro(mac) => {
+        AssocItemKind::MacCall(mac) => {
             visitor.visit_mac(mac);
         }
     }
@@ -679,7 +679,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
         StmtKind::Item(ref item) => visitor.visit_item(item),
         StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr),
         StmtKind::Empty => {}
-        StmtKind::Mac(ref mac) => {
+        StmtKind::MacCall(ref mac) => {
             let (ref mac, _, ref attrs) = **mac;
             visitor.visit_mac(mac);
             for attr in attrs.iter() {
@@ -689,7 +689,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
     }
 }
 
-pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a Mac) {
+pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) {
     visitor.visit_path(&mac.path, DUMMY_NODE_ID);
 }
 
@@ -811,7 +811,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         ExprKind::Ret(ref optional_expression) => {
             walk_list!(visitor, visit_expr, optional_expression);
         }
-        ExprKind::Mac(ref mac) => visitor.visit_mac(mac),
+        ExprKind::MacCall(ref mac) => visitor.visit_mac(mac),
         ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression),
         ExprKind::InlineAsm(ref ia) => {
             for &(_, ref input) in &ia.inputs {
diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs
index 7038387caa9..a4cbae51966 100644
--- a/src/librustc_ast_lowering/expr.rs
+++ b/src/librustc_ast_lowering/expr.rs
@@ -198,7 +198,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 return self.lower_expr_for(e, pat, head, body, opt_label);
             }
             ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr),
-            ExprKind::Mac(_) => panic!("Shouldn't exist here"),
+            ExprKind::MacCall(_) => panic!("Shouldn't exist here"),
         };
 
         hir::Expr {
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 46aad99f131..94ae2a0973a 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -6,11 +6,12 @@ use rustc::bug;
 use rustc_ast::ast::*;
 use rustc_ast::attr;
 use rustc_ast::node_id::NodeMap;
+use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
 use rustc_span::source_map::{respan, DesugaringKind};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -114,7 +115,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             _ => &[],
         };
         let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
-            hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()),
+            hir::GenericParamKind::Lifetime { .. } => Some(param.name.normalize_to_macros_2_0()),
             _ => None,
         });
         self.in_scope_lifetimes.extend(lt_def_names);
@@ -219,18 +220,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let mut vis = self.lower_visibility(&i.vis, None);
         let attrs = self.lower_attrs(&i.attrs);
 
-        if let ItemKind::MacroDef(ref def) = i.kind {
-            if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
-                let body = self.lower_token_stream(def.body.inner_tokens());
+        if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind {
+            if !macro_rules || attr::contains_name(&i.attrs, sym::macro_export) {
                 let hir_id = self.lower_node_id(i.id);
+                let body = P(self.lower_mac_args(body));
                 self.exported_macros.push(hir::MacroDef {
-                    name: ident.name,
+                    ident,
                     vis,
                     attrs,
                     hir_id,
                     span: i.span,
-                    body,
-                    legacy: def.legacy,
+                    ast: MacroDef { body, macro_rules },
                 });
             } else {
                 self.non_exported_macro_attrs.extend(attrs.iter().cloned());
@@ -269,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 hir::ItemKind::Const(ty, body_id)
             }
             ItemKind::Fn(_, FnSig { ref decl, header }, ref generics, ref body) => {
-                let fn_def_id = self.resolver.definitions().local_def_id(id);
+                let fn_def_id = self.resolver.definitions().local_def_id(id).expect_local();
                 self.with_new_scopes(|this| {
                     this.current_item = Some(ident.span);
 
@@ -287,7 +287,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         AnonymousLifetimeMode::PassThrough,
                         |this, idty| {
                             let ret_id = asyncness.opt_return_id();
-                            this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id)
+                            this.lower_fn_decl(
+                                &decl,
+                                Some((fn_def_id.to_def_id(), idty)),
+                                true,
+                                ret_id,
+                            )
                         },
                     );
                     let sig = hir::FnSig { decl, header: this.lower_fn_header(header) };
@@ -351,7 +356,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self_ty: ref ty,
                 items: ref impl_items,
             } => {
-                let def_id = self.resolver.definitions().local_def_id(id);
+                let def_id = self.resolver.definitions().local_def_id(id).expect_local();
 
                 // Lower the "impl header" first. This ordering is important
                 // for in-band lifetimes! Consider `'a` here:
@@ -426,7 +431,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self.lower_generics(generics, ImplTraitContext::disallowed()),
                 self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
             ),
-            ItemKind::MacroDef(..) | ItemKind::Mac(..) => {
+            ItemKind::MacroDef(..) | ItemKind::MacCall(..) => {
                 bug!("`TyMac` should have been expanded by now")
             }
         }
@@ -648,7 +653,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
-        let def_id = self.resolver.definitions().local_def_id(i.id);
+        let def_id = self.resolver.definitions().local_def_id(i.id).expect_local();
         hir::ForeignItem {
             hir_id: self.lower_node_id(i.id),
             ident: i.ident,
@@ -676,7 +681,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     hir::ForeignItemKind::Static(ty, m)
                 }
                 ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
-                ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"),
+                ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
             },
             vis: self.lower_visibility(&i.vis, None),
             span: i.span,
@@ -749,7 +754,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
-        let trait_item_def_id = self.resolver.definitions().local_def_id(i.id);
+        let trait_item_def_id = self.resolver.definitions().local_def_id(i.id).expect_local();
 
         let (generics, kind) = match i.kind {
             AssocItemKind::Const(_, ref ty, ref default) => {
@@ -761,13 +766,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) =
                     self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
-                (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
+                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
             }
             AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => {
                 let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
                 let (generics, sig) =
                     self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
-                (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
+                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
             }
             AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => {
                 let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
@@ -779,7 +784,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
                 (generics, kind)
             }
-            AssocItemKind::Macro(..) => bug!("macro item shouldn't exist at this point"),
+            AssocItemKind::MacCall(..) => bug!("macro item shouldn't exist at this point"),
         };
 
         hir::TraitItem {
@@ -801,7 +806,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             AssocItemKind::Fn(_, sig, _, default) => {
                 (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some())
             }
-            AssocItemKind::Macro(..) => unimplemented!(),
+            AssocItemKind::MacCall(..) => unimplemented!(),
         };
         let id = hir::TraitItemId { hir_id: self.lower_node_id(i.id) };
         let defaultness = hir::Defaultness::Default { has_value: has_default };
@@ -814,7 +819,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
-        let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
+        let impl_item_def_id = self.resolver.definitions().local_def_id(i.id).expect_local();
 
         let (generics, kind) = match &i.kind {
             AssocItemKind::Const(_, ty, expr) => {
@@ -838,7 +843,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     asyncness.opt_return_id(),
                 );
 
-                (generics, hir::ImplItemKind::Method(sig, body_id))
+                (generics, hir::ImplItemKind::Fn(sig, body_id))
             }
             AssocItemKind::TyAlias(_, generics, _, ty) => {
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
@@ -860,7 +865,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 };
                 (generics, kind)
             }
-            AssocItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"),
+            AssocItemKind::MacCall(..) => bug!("`TyMac` should have been expanded by now"),
         };
 
         hir::ImplItem {
@@ -895,7 +900,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 AssocItemKind::Fn(_, sig, ..) => {
                     hir::AssocItemKind::Method { has_self: sig.decl.has_self() }
                 }
-                AssocItemKind::Macro(..) => unimplemented!(),
+                AssocItemKind::MacCall(..) => unimplemented!(),
             },
         }
 
@@ -1211,7 +1216,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         generics: &Generics,
         sig: &FnSig,
-        fn_def_id: DefId,
+        fn_def_id: LocalDefId,
         impl_trait_return_allow: bool,
         is_async: Option<NodeId>,
     ) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
@@ -1223,7 +1228,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             |this, idty| {
                 this.lower_fn_decl(
                     &sig.decl,
-                    Some((fn_def_id, idty)),
+                    Some((fn_def_id.to_def_id(), idty)),
                     impl_trait_return_allow,
                     is_async,
                 )
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index dd9526ccee4..dcedcd51f50 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -37,7 +37,6 @@
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
 use rustc::hir::map::definitions::{DefKey, DefPathData, Definitions};
-use rustc::hir::map::Map;
 use rustc::{bug, span_bug};
 use rustc_ast::ast;
 use rustc_ast::ast::*;
@@ -54,7 +53,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{DefId, DefIdMap, DefIndex, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::intravisit;
 use rustc_hir::{ConstArg, GenericArg, ParamName};
 use rustc_index::vec::IndexVec;
@@ -153,7 +152,7 @@ struct LoweringContext<'a, 'hir: 'a> {
     /// against this list to see if it is already in-scope, or if a definition
     /// needs to be created for it.
     ///
-    /// We always store a `modern()` version of the param-name in this
+    /// We always store a `normalize_to_macros_2_0()` version of the param-name in this
     /// vector.
     in_scope_lifetimes: Vec<ParamName>,
 
@@ -161,7 +160,7 @@ struct LoweringContext<'a, 'hir: 'a> {
 
     type_def_lifetime_params: DefIdMap<usize>,
 
-    current_hir_id_owner: Vec<(DefIndex, u32)>,
+    current_hir_id_owner: Vec<(LocalDefId, u32)>,
     item_local_id_counters: NodeMap<u32>,
     node_id_to_hir_id: IndexVec<NodeId, hir::HirId>,
 
@@ -291,7 +290,7 @@ pub fn lower_crate<'a, 'hir>(
         anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
         type_def_lifetime_params: Default::default(),
         current_module: hir::CRATE_HIR_ID,
-        current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)],
+        current_hir_id_owner: vec![(LocalDefId { local_def_index: CRATE_DEF_INDEX }, 0)],
         item_local_id_counters: Default::default(),
         node_id_to_hir_id: IndexVec::new(),
         generator_kind: None,
@@ -408,7 +407,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
 
         impl MiscCollector<'_, '_, '_> {
-            fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: DefIndex) {
+            fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: LocalDefId) {
                 match tree.kind {
                     UseTreeKind::Simple(_, id1, id2) => {
                         for &id in &[id1, id2] {
@@ -464,7 +463,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     | ItemKind::Enum(_, ref generics)
                     | ItemKind::TyAlias(_, ref generics, ..)
                     | ItemKind::Trait(_, _, ref generics, ..) => {
-                        let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
+                        let def_id =
+                            self.lctx.resolver.definitions().local_def_id(item.id).expect_local();
                         let count = generics
                             .params
                             .iter()
@@ -473,7 +473,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 _ => false,
                             })
                             .count();
-                        self.lctx.type_def_lifetime_params.insert(def_id, count);
+                        self.lctx.type_def_lifetime_params.insert(def_id.to_def_id(), count);
                     }
                     ItemKind::Use(ref use_tree) => {
                         self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner);
@@ -535,9 +535,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id);
 
         hir::Crate {
-            module,
-            attrs,
-            span: c.span,
+            item: hir::CrateItem { module, attrs, span: c.span },
             exported_macros: self.arena.alloc_from_iter(self.exported_macros),
             non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
             items: self.items,
@@ -601,12 +599,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             .item_local_id_counters
             .insert(owner, HIR_ID_COUNTER_LOCKED)
             .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner));
-        let def_index = self.resolver.definitions().opt_def_index(owner).unwrap();
-        self.current_hir_id_owner.push((def_index, counter));
+        let def_id = self.resolver.definitions().local_def_id(owner).expect_local();
+        self.current_hir_id_owner.push((def_id, counter));
         let ret = f(self);
-        let (new_def_index, new_counter) = self.current_hir_id_owner.pop().unwrap();
+        let (new_def_id, new_counter) = self.current_hir_id_owner.pop().unwrap();
 
-        debug_assert!(def_index == new_def_index);
+        debug_assert!(def_id == new_def_id);
         debug_assert!(new_counter >= counter);
 
         let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap();
@@ -622,11 +620,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// properly. Calling the method twice with the same `NodeId` is fine though.
     fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
         self.lower_node_id_generic(ast_node_id, |this| {
-            let &mut (def_index, ref mut local_id_counter) =
+            let &mut (owner, ref mut local_id_counter) =
                 this.current_hir_id_owner.last_mut().unwrap();
             let local_id = *local_id_counter;
             *local_id_counter += 1;
-            hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) }
+            hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
         })
     }
 
@@ -644,12 +642,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             debug_assert!(local_id != HIR_ID_COUNTER_LOCKED);
 
             *local_id_counter += 1;
-            let def_index = this.resolver.definitions().opt_def_index(owner).expect(
+            let owner = this.resolver.definitions().opt_local_def_id(owner).expect(
                 "you forgot to call `create_def_with_parent` or are lowering node-IDs \
-                         that do not belong to the current owner",
+                 that do not belong to the current owner",
             );
 
-            hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) }
+            hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
         })
     }
 
@@ -727,7 +725,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// parameter while `f` is running (and restored afterwards).
     fn collect_in_band_defs<T>(
         &mut self,
-        parent_id: DefId,
+        parent_def_id: LocalDefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
         f: impl FnOnce(&mut Self) -> (Vec<hir::GenericParam<'hir>>, T),
     ) -> (Vec<hir::GenericParam<'hir>>, T) {
@@ -747,7 +745,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let params = lifetimes_to_define
             .into_iter()
-            .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_id.index))
+            .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id))
             .chain(in_band_ty_params.into_iter())
             .collect();
 
@@ -759,7 +757,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         span: Span,
         hir_name: ParamName,
-        parent_index: DefIndex,
+        parent_def_id: LocalDefId,
     ) -> hir::GenericParam<'hir> {
         let node_id = self.resolver.next_node_id();
 
@@ -774,7 +772,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         // Add a definition for the in-band lifetime def.
         self.resolver.definitions().create_def_with_parent(
-            parent_index,
+            parent_def_id,
             node_id,
             DefPathData::LifetimeNs(str_name),
             ExpnId::root(),
@@ -805,14 +803,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             return;
         }
 
-        if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.modern())) {
+        if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.normalize_to_macros_2_0())) {
             return;
         }
 
         let hir_name = ParamName::Plain(ident);
 
-        if self.lifetimes_to_define.iter().any(|(_, lt_name)| lt_name.modern() == hir_name.modern())
-        {
+        if self.lifetimes_to_define.iter().any(|(_, lt_name)| {
+            lt_name.normalize_to_macros_2_0() == hir_name.normalize_to_macros_2_0()
+        }) {
             return;
         }
 
@@ -840,7 +839,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> T {
         let old_len = self.in_scope_lifetimes.len();
         let lt_def_names = params.iter().filter_map(|param| match param.kind {
-            GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())),
+            GenericParamKind::Lifetime { .. } => {
+                Some(ParamName::Plain(param.ident.normalize_to_macros_2_0()))
+            }
             _ => None,
         });
         self.in_scope_lifetimes.extend(lt_def_names);
@@ -860,13 +861,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn add_in_band_defs<T>(
         &mut self,
         generics: &Generics,
-        parent_id: DefId,
+        parent_def_id: LocalDefId,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
         f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
     ) -> (hir::Generics<'hir>, T) {
         let (in_band_defs, (mut lowered_generics, res)) =
             self.with_in_scope_lifetime_defs(&generics.params, |this| {
-                this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
+                this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| {
                     let mut params = Vec::new();
                     // Note: it is necessary to lower generics *before* calling `f`.
                     // When lowering `async fn`, there's a final step when lowering
@@ -1048,9 +1049,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     // constructing the HIR for `impl bounds...` and then lowering that.
 
                     let impl_trait_node_id = self.resolver.next_node_id();
-                    let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
+                    let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
                     self.resolver.definitions().create_def_with_parent(
-                        parent_def_index,
+                        parent_def_id,
                         impl_trait_node_id,
                         DefPathData::ImplTrait,
                         ExpnId::root(),
@@ -1111,12 +1112,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                             // Construct a AnonConst where the expr is the "ty"'s path.
 
-                            let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
+                            let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
                             let node_id = self.resolver.next_node_id();
 
                             // Add a definition for the in-band const def.
                             self.resolver.definitions().create_def_with_parent(
-                                parent_def_index,
+                                parent_def_id,
                                 node_id,
                                 DefPathData::AnonConst,
                                 ExpnId::root(),
@@ -1278,8 +1279,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }
                     ImplTraitContext::Universal(in_band_ty_params) => {
                         // Add a definition for the in-band `Param`.
-                        let def_index =
-                            self.resolver.definitions().opt_def_index(def_node_id).unwrap();
+                        let def_id =
+                            self.resolver.definitions().local_def_id(def_node_id).expect_local();
 
                         let hir_bounds = self.lower_param_bounds(
                             bounds,
@@ -1304,7 +1305,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             None,
                             self.arena.alloc(hir::Path {
                                 span,
-                                res: Res::Def(DefKind::TyParam, DefId::local(def_index)),
+                                res: Res::Def(DefKind::TyParam, def_id.to_def_id()),
                                 segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
                             }),
                         ))
@@ -1334,7 +1335,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }
                 }
             }
-            TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"),
+            TyKind::MacCall(_) => bug!("`TyKind::MacCall` should have been expanded by now"),
             TyKind::CVarArgs => {
                 self.sess.delay_span_bug(
                     t.span,
@@ -1367,18 +1368,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // frequently opened issues show.
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
-        let opaque_ty_def_index =
-            self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap();
+        let opaque_ty_def_id =
+            self.resolver.definitions().local_def_id(opaque_ty_node_id).expect_local();
 
         self.allocate_hir_id_counter(opaque_ty_node_id);
 
         let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds);
 
-        let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
-            opaque_ty_node_id,
-            opaque_ty_def_index,
-            &hir_bounds,
-        );
+        let (lifetimes, lifetime_defs) =
+            self.lifetimes_from_impl_trait_bounds(opaque_ty_node_id, opaque_ty_def_id, &hir_bounds);
 
         debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes,);
 
@@ -1396,7 +1394,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 origin,
             };
 
-            trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index);
+            trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id);
             let opaque_ty_id =
                 lctx.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
 
@@ -1437,14 +1435,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lifetimes_from_impl_trait_bounds(
         &mut self,
         opaque_ty_id: NodeId,
-        parent_index: DefIndex,
+        parent_def_id: LocalDefId,
         bounds: hir::GenericBounds<'hir>,
     ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) {
         debug!(
             "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
-             parent_index={:?}, \
+             parent_def_id={:?}, \
              bounds={:#?})",
-            opaque_ty_id, parent_index, bounds,
+            opaque_ty_id, parent_def_id, bounds,
         );
 
         // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
@@ -1452,7 +1450,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
         struct ImplTraitLifetimeCollector<'r, 'a, 'hir> {
             context: &'r mut LoweringContext<'a, 'hir>,
-            parent: DefIndex,
+            parent: LocalDefId,
             opaque_ty_id: NodeId,
             collect_elided_lifetimes: bool,
             currently_bound_lifetimes: Vec<hir::LifetimeName>,
@@ -1462,9 +1460,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
 
         impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
-            type Map = Map<'v>;
+            type Map = intravisit::ErasedMap<'v>;
 
-            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
                 intravisit::NestedVisitorMap::None
             }
 
@@ -1590,7 +1588,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let mut lifetime_collector = ImplTraitLifetimeCollector {
             context: self,
-            parent: parent_index,
+            parent: parent_def_id,
             opaque_ty_id,
             collect_elided_lifetimes: true,
             currently_bound_lifetimes: Vec::new(),
@@ -1620,12 +1618,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 visitor.visit_ty(ty);
             }
         }
-        let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
+        let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
         let ty = l.ty.as_ref().map(|t| {
             self.lower_ty(
                 t,
                 if self.sess.features_untracked().impl_trait_in_bindings {
-                    ImplTraitContext::OpaqueTy(Some(parent_def_id), hir::OpaqueTyOrigin::Misc)
+                    ImplTraitContext::OpaqueTy(
+                        Some(parent_def_id.to_def_id()),
+                        hir::OpaqueTyOrigin::Misc,
+                    )
                 } else {
                     ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
                 },
@@ -1797,8 +1798,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
 
-        let opaque_ty_def_index =
-            self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap();
+        let opaque_ty_def_id =
+            self.resolver.definitions().local_def_id(opaque_ty_node_id).expect_local();
 
         self.allocate_hir_id_counter(opaque_ty_node_id);
 
@@ -1886,7 +1887,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
             let generic_params =
                 this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| {
-                    this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_index)
+                    this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id)
                 }));
 
             let opaque_ty_item = hir::OpaqueTy {
@@ -1900,7 +1901,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 origin: hir::OpaqueTyOrigin::AsyncFn,
             };
 
-            trace!("exist ty from async fn def index: {:#?}", opaque_ty_def_index);
+            trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
             let opaque_ty_id =
                 this.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
 
@@ -2282,7 +2283,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             StmtKind::Expr(ref e) => hir::StmtKind::Expr(self.lower_expr(e)),
             StmtKind::Semi(ref e) => hir::StmtKind::Semi(self.lower_expr(e)),
             StmtKind::Empty => return smallvec![],
-            StmtKind::Mac(..) => panic!("shouldn't exist here"),
+            StmtKind::MacCall(..) => panic!("shouldn't exist here"),
         };
         smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), kind, span: s.span }]
     }
diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs
index d6f4ba1529b..8ba6576f692 100644
--- a/src/librustc_ast_lowering/pat.rs
+++ b/src/librustc_ast_lowering/pat.rs
@@ -75,7 +75,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 self.ban_illegal_rest_pat(p.span)
             }
             PatKind::Paren(ref inner) => return self.lower_pat(inner),
-            PatKind::Mac(_) => panic!("Shouldn't exist here"),
+            PatKind::MacCall(_) => panic!("Shouldn't exist here"),
         };
 
         self.pat_with_node_id_of(p, node)
diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs
index 80d7e3d0d46..b5b0a3089ce 100644
--- a/src/librustc_ast_lowering/path.rs
+++ b/src/librustc_ast_lowering/path.rs
@@ -1,7 +1,6 @@
 use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode};
 use super::{GenericArgsCtor, ParenthesizedGenericArgs};
 
-use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
 use rustc::span_bug;
 use rustc_ast::ast::{self, *};
 use rustc_errors::{struct_span_err, Applicability};
@@ -9,6 +8,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
+use rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::Span;
 
@@ -75,7 +75,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             ParenthesizedGenericArgs::Ok
                         }
                         // `a::b::Trait(Args)::TraitItem`
-                        Res::Def(DefKind::Method, _)
+                        Res::Def(DefKind::AssocFn, _)
                         | Res::Def(DefKind::AssocConst, _)
                         | Res::Def(DefKind::AssocTy, _)
                             if i + 2 == proj_start =>
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index 69d5610e016..541c681840f 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -9,6 +9,7 @@
 use rustc_ast::ast::*;
 use rustc_ast::attr;
 use rustc_ast::expand::is_proc_macro_attr;
+use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::walk_list;
 use rustc_ast_pretty::pprust;
@@ -594,6 +595,54 @@ impl<'a> AstValidator<'a> {
             .span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind))
             .emit();
     }
+
+    fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
+        if !generics.params.is_empty() {
+            struct_span_err!(
+                self.session,
+                generics.span,
+                E0567,
+                "auto traits cannot have generic parameters"
+            )
+            .span_label(ident_span, "auto trait cannot have generic parameters")
+            .span_suggestion(
+                generics.span,
+                "remove the parameters",
+                String::new(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
+        }
+    }
+
+    fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
+        if let [first @ last] | [first, .., last] = &bounds[..] {
+            let span = first.span().to(last.span());
+            struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits")
+                .span_label(ident_span, "auto trait cannot have super traits")
+                .span_suggestion(
+                    span,
+                    "remove the super traits",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+        }
+    }
+
+    fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
+        if !trait_items.is_empty() {
+            let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
+            struct_span_err!(
+                self.session,
+                spans,
+                E0380,
+                "auto traits cannot have methods or associated items"
+            )
+            .span_label(ident_span, "auto trait cannot have items")
+            .emit();
+        }
+    }
 }
 
 fn validate_generic_param_order<'a>(
@@ -779,7 +828,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 defaultness: _,
                 constness: _,
                 generics: _,
-                of_trait: Some(_),
+                of_trait: Some(ref t),
                 ref self_ty,
                 items: _,
             } => {
@@ -794,13 +843,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                             .help("use `auto trait Trait {}` instead")
                             .emit();
                     }
-                    if let (Unsafe::Yes(span), ImplPolarity::Negative) = (unsafety, polarity) {
+                    if let (Unsafe::Yes(span), ImplPolarity::Negative(sp)) = (unsafety, polarity) {
                         struct_span_err!(
                             this.session,
-                            item.span,
+                            sp.to(t.path.span),
                             E0198,
                             "negative impls cannot be unsafe"
                         )
+                        .span_label(sp, "negative because of this")
                         .span_label(span, "unsafe because of this")
                         .emit();
                     }
@@ -816,38 +866,36 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 constness,
                 generics: _,
                 of_trait: None,
-                self_ty: _,
+                ref self_ty,
                 items: _,
             } => {
+                let error = |annotation_span, annotation| {
+                    let mut err = self.err_handler().struct_span_err(
+                        self_ty.span,
+                        &format!("inherent impls cannot be {}", annotation),
+                    );
+                    err.span_label(annotation_span, &format!("{} because of this", annotation));
+                    err.span_label(self_ty.span, "inherent impl for this type");
+                    err
+                };
+
                 self.invalid_visibility(
                     &item.vis,
                     Some("place qualifiers on individual impl items instead"),
                 );
                 if let Unsafe::Yes(span) = unsafety {
-                    struct_span_err!(
-                        self.session,
-                        item.span,
-                        E0197,
-                        "inherent impls cannot be unsafe"
-                    )
-                    .span_label(span, "unsafe because of this")
-                    .emit();
+                    error(span, "unsafe").code(error_code!(E0197)).emit();
                 }
-                if polarity == ImplPolarity::Negative {
-                    self.err_handler().span_err(item.span, "inherent impls cannot be negative");
+                if let ImplPolarity::Negative(span) = polarity {
+                    error(span, "negative").emit();
                 }
                 if let Defaultness::Default(def_span) = defaultness {
-                    let span = self.session.source_map().def_span(item.span);
-                    self.err_handler()
-                        .struct_span_err(span, "inherent impls cannot be `default`")
-                        .span_label(def_span, "`default` because of this")
+                    error(def_span, "`default`")
                         .note("only trait implementations may be annotated with `default`")
                         .emit();
                 }
                 if let Const::Yes(span) = constness {
-                    self.err_handler()
-                        .struct_span_err(item.span, "inherent impls cannot be `const`")
-                        .span_label(span, "`const` because of this")
+                    error(span, "`const`")
                         .note("only trait implementations may be annotated with `const`")
                         .emit();
                 }
@@ -882,33 +930,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
                 if is_auto == IsAuto::Yes {
                     // Auto traits cannot have generics, super traits nor contain items.
-                    if !generics.params.is_empty() {
-                        struct_span_err!(
-                            self.session,
-                            item.span,
-                            E0567,
-                            "auto traits cannot have generic parameters"
-                        )
-                        .emit();
-                    }
-                    if !bounds.is_empty() {
-                        struct_span_err!(
-                            self.session,
-                            item.span,
-                            E0568,
-                            "auto traits cannot have super traits"
-                        )
-                        .emit();
-                    }
-                    if !trait_items.is_empty() {
-                        struct_span_err!(
-                            self.session,
-                            item.span,
-                            E0380,
-                            "auto traits cannot have methods or associated items"
-                        )
-                        .emit();
-                    }
+                    self.deny_generic_params(generics, item.ident.span);
+                    self.deny_super_traits(bounds, item.ident.span);
+                    self.deny_items(trait_items, item.ident.span);
                 }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
 
@@ -976,7 +1000,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             ForeignItemKind::Static(_, _, body) => {
                 self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
             }
-            ForeignItemKind::Macro(..) => {}
+            ForeignItemKind::MacCall(..) => {}
         }
 
         visit::walk_foreign_item(self, fi)
@@ -1153,9 +1177,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         }) = fk.header()
         {
             self.err_handler()
-                .struct_span_err(span, "functions cannot be both `const` and `async`")
+                .struct_span_err(
+                    vec![*cspan, *aspan],
+                    "functions cannot be both `const` and `async`",
+                )
                 .span_label(*cspan, "`const` because of this")
                 .span_label(*aspan, "`async` because of this")
+                .span_label(span, "") // Point at the fn header.
                 .emit();
         }
 
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index a4ab54f8b4a..364c86bd99b 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -337,14 +337,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 }
             }
 
-            ast::ItemKind::Impl { polarity, defaultness, .. } => {
-                if polarity == ast::ImplPolarity::Negative {
+            ast::ItemKind::Impl { polarity, defaultness, ref of_trait, .. } => {
+                if let ast::ImplPolarity::Negative(span) = polarity {
                     gate_feature_post!(
                         &self,
                         optin_builtin_traits,
-                        i.span,
+                        span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(span)),
                         "negative trait bounds are not yet fully implemented; \
-                                        use marker types for now"
+                         use marker types for now"
                     );
                 }
 
@@ -366,7 +366,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, trait_alias, i.span, "trait aliases are experimental");
             }
 
-            ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
+            ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
                 let msg = "`macro` is experimental";
                 gate_feature_post!(&self, decl_macro, i.span, msg);
             }
@@ -399,7 +399,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             ast::ForeignItemKind::TyAlias(..) => {
                 gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
             }
-            ast::ForeignItemKind::Macro(..) => {}
+            ast::ForeignItemKind::MacCall(..) => {}
         }
 
         visit::walk_foreign_item(self, i)
@@ -542,15 +542,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     }
 
     fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
-        if let ast::Defaultness::Default(_) = i.kind.defaultness() {
-            gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
-        }
-
-        match i.kind {
+        let is_fn = match i.kind {
             ast::AssocItemKind::Fn(_, ref sig, _, _) => {
                 if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) {
                     gate_feature_post!(&self, const_fn, i.span, "const fn is unstable");
                 }
+                true
             }
             ast::AssocItemKind::TyAlias(_, ref generics, _, ref ty) => {
                 if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
@@ -565,8 +562,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     self.check_impl_trait(ty);
                 }
                 self.check_gat(generics, i.span);
+                false
             }
-            _ => {}
+            _ => false,
+        };
+        if let ast::Defaultness::Default(_) = i.kind.defaultness() {
+            // Limit `min_specialization` to only specializing functions.
+            gate_feature_fn!(
+                &self,
+                |x: &Features| x.specialization || (is_fn && x.min_specialization),
+                i.span,
+                sym::specialization,
+                "specialization is unstable"
+            );
         }
         visit::walk_assoc_item(self, i, ctxt)
     }
diff --git a/src/librustc_ast_passes/lib.rs b/src/librustc_ast_passes/lib.rs
index 520a7ac3e56..10081d36754 100644
--- a/src/librustc_ast_passes/lib.rs
+++ b/src/librustc_ast_passes/lib.rs
@@ -1,3 +1,4 @@
+#![feature(bindings_after_at)]
 //! The `rustc_ast_passes` crate contains passes which validate the AST in `syntax`
 //! parsed by `rustc_parse` and then lowered, after the passes in this crate,
 //! by `rustc_ast_lowering`.
diff --git a/src/librustc_ast_passes/node_count.rs b/src/librustc_ast_passes/node_count.rs
index 16bcec8360e..534d6c7b1ea 100644
--- a/src/librustc_ast_passes/node_count.rs
+++ b/src/librustc_ast_passes/node_count.rs
@@ -113,7 +113,7 @@ impl<'ast> Visitor<'ast> for NodeCounter {
         self.count += 1;
         walk_lifetime(self, lifetime)
     }
-    fn visit_mac(&mut self, _mac: &Mac) {
+    fn visit_mac(&mut self, _mac: &MacCall) {
         self.count += 1;
         walk_mac(self, _mac)
     }
diff --git a/src/librustc_ast_passes/show_span.rs b/src/librustc_ast_passes/show_span.rs
index 73a66ba566b..2366426d4dc 100644
--- a/src/librustc_ast_passes/show_span.rs
+++ b/src/librustc_ast_passes/show_span.rs
@@ -55,7 +55,7 @@ impl<'a> Visitor<'a> for ShowSpanVisitor<'a> {
         visit::walk_ty(self, t);
     }
 
-    fn visit_mac(&mut self, mac: &'a ast::Mac) {
+    fn visit_mac(&mut self, mac: &'a ast::MacCall) {
         visit::walk_mac(self, mac);
     }
 }
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index b11dda8af73..bb73e982a9c 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -148,12 +148,19 @@ pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
 
 // This makes comma-separated lists look slightly nicer,
 // and also addresses a specific regression described in issue #63896.
-fn tt_prepend_space(tt: &TokenTree) -> bool {
+fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
     match tt {
         TokenTree::Token(token) => match token.kind {
             token::Comma => false,
             _ => true,
         },
+        TokenTree::Delimited(_, DelimToken::Paren, _) => match prev {
+            TokenTree::Token(token) => match token.kind {
+                token::Ident(_, _) => false,
+                _ => true,
+            },
+            _ => true,
+        },
         _ => true,
     }
 }
@@ -650,11 +657,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     }
 
     fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) {
-        for (i, tt) in tts.into_trees().enumerate() {
-            if i != 0 && tt_prepend_space(&tt) {
+        let mut iter = tts.into_trees().peekable();
+        while let Some(tt) = iter.next() {
+            let show_space =
+                if let Some(next) = iter.peek() { tt_prepend_space(next, &tt) } else { false };
+            self.print_tt(tt, convert_dollar_crate);
+            if show_space {
                 self.space();
             }
-            self.print_tt(tt, convert_dollar_crate);
         }
     }
 
@@ -960,7 +970,7 @@ impl<'a> State<'a> {
             ast::TyKind::ImplicitSelf => {
                 self.s.word("Self");
             }
-            ast::TyKind::Mac(ref m) => {
+            ast::TyKind::MacCall(ref m) => {
                 self.print_mac(m);
             }
             ast::TyKind::CVarArgs => {
@@ -987,7 +997,7 @@ impl<'a> State<'a> {
             ast::ForeignItemKind::TyAlias(def, generics, bounds, ty) => {
                 self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
             }
-            ast::ForeignItemKind::Macro(m) => {
+            ast::ForeignItemKind::MacCall(m) => {
                 self.print_mac(m);
                 if m.args.need_semicolon() {
                     self.s.word(";");
@@ -1160,7 +1170,7 @@ impl<'a> State<'a> {
                     self.s.space();
                 }
 
-                if polarity == ast::ImplPolarity::Negative {
+                if let ast::ImplPolarity::Negative(_) = polarity {
                     self.s.word("!");
                 }
 
@@ -1231,14 +1241,14 @@ impl<'a> State<'a> {
                 self.print_where_clause(&generics.where_clause);
                 self.s.word(";");
             }
-            ast::ItemKind::Mac(ref mac) => {
+            ast::ItemKind::MacCall(ref mac) => {
                 self.print_mac(mac);
                 if mac.args.need_semicolon() {
                     self.s.word(";");
                 }
             }
             ast::ItemKind::MacroDef(ref macro_def) => {
-                let (kw, has_bang) = if macro_def.legacy {
+                let (kw, has_bang) = if macro_def.macro_rules {
                     ("macro_rules", true)
                 } else {
                     self.print_visibility(&item.vis);
@@ -1413,7 +1423,7 @@ impl<'a> State<'a> {
             ast::AssocItemKind::TyAlias(def, generics, bounds, ty) => {
                 self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
             }
-            ast::AssocItemKind::Macro(m) => {
+            ast::AssocItemKind::MacCall(m) => {
                 self.print_mac(m);
                 if m.args.need_semicolon() {
                     self.s.word(";");
@@ -1460,7 +1470,7 @@ impl<'a> State<'a> {
                 self.space_if_not_bol();
                 self.s.word(";");
             }
-            ast::StmtKind::Mac(ref mac) => {
+            ast::StmtKind::MacCall(ref mac) => {
                 let (ref mac, style, ref attrs) = **mac;
                 self.space_if_not_bol();
                 self.print_outer_attributes(attrs);
@@ -1570,7 +1580,7 @@ impl<'a> State<'a> {
         self.print_else(elseopt)
     }
 
-    crate fn print_mac(&mut self, m: &ast::Mac) {
+    crate fn print_mac(&mut self, m: &ast::MacCall) {
         self.print_mac_common(
             Some(MacHeader::Path(&m.path)),
             true,
@@ -2070,7 +2080,7 @@ impl<'a> State<'a> {
 
                 self.pclose();
             }
-            ast::ExprKind::Mac(ref m) => self.print_mac(m),
+            ast::ExprKind::MacCall(ref m) => self.print_mac(m),
             ast::ExprKind::Paren(ref e) => {
                 self.popen();
                 self.print_inner_attributes_inline(attrs);
@@ -2254,7 +2264,7 @@ impl<'a> State<'a> {
                 self.print_pat(inner);
                 self.pclose();
             }
-            PatKind::Mac(ref m) => self.print_mac(m),
+            PatKind::MacCall(ref m) => self.print_mac(m),
         }
         self.ann.post(self, AnnNode::Pat(pat))
     }
diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs
index 08eae24da9b..99083cca6cb 100644
--- a/src/librustc_attr/builtin.rs
+++ b/src/librustc_attr/builtin.rs
@@ -1024,7 +1024,7 @@ pub enum TransparencyError {
 
 pub fn find_transparency(
     attrs: &[Attribute],
-    is_legacy: bool,
+    macro_rules: bool,
 ) -> (Transparency, Option<TransparencyError>) {
     let mut transparency = None;
     let mut error = None;
@@ -1049,7 +1049,7 @@ pub fn find_transparency(
             }
         }
     }
-    let fallback = if is_legacy { Transparency::SemiTransparent } else { Transparency::Opaque };
+    let fallback = if macro_rules { Transparency::SemiTransparent } else { Transparency::Opaque };
     (transparency.map_or(fallback, |t| t.0), error)
 }
 
diff --git a/src/librustc_builtin_macros/assert.rs b/src/librustc_builtin_macros/assert.rs
index 09ff770e87b..3a3595b04d2 100644
--- a/src/librustc_builtin_macros/assert.rs
+++ b/src/librustc_builtin_macros/assert.rs
@@ -40,7 +40,7 @@ pub fn expand_assert<'cx>(
         ))
     });
     let args = P(MacArgs::Delimited(DelimSpan::from_single(sp), MacDelimiter::Parenthesis, tokens));
-    let panic_call = Mac {
+    let panic_call = MacCall {
         path: Path::from_ident(Ident::new(sym::panic, sp)),
         args,
         prior_type_ascription: None,
@@ -48,7 +48,7 @@ pub fn expand_assert<'cx>(
     let if_expr = cx.expr_if(
         sp,
         cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)),
-        cx.expr(sp, ExprKind::Mac(panic_call)),
+        cx.expr(sp, ExprKind::MacCall(panic_call)),
         None,
     );
     MacEager::expr(if_expr)
diff --git a/src/librustc_builtin_macros/cfg_accessible.rs b/src/librustc_builtin_macros/cfg_accessible.rs
new file mode 100644
index 00000000000..3607a4d0d15
--- /dev/null
+++ b/src/librustc_builtin_macros/cfg_accessible.rs
@@ -0,0 +1,54 @@
+//! Implementation of the `#[cfg_accessible(path)]` attribute macro.
+
+use rustc_ast::ast;
+use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
+use rustc_feature::AttributeTemplate;
+use rustc_parse::validate_attr;
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+
+crate struct Expander;
+
+fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
+    match mi.meta_item_list() {
+        None => {}
+        Some([]) => ecx.span_err(mi.span, "`cfg_accessible` path is not specified"),
+        Some([_, .., l]) => ecx.span_err(l.span(), "multiple `cfg_accessible` paths are specified"),
+        Some([nmi]) => match nmi.meta_item() {
+            None => ecx.span_err(nmi.span(), "`cfg_accessible` path cannot be a literal"),
+            Some(mi) => {
+                if !mi.is_word() {
+                    ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments");
+                }
+                return Some(&mi.path);
+            }
+        },
+    }
+    None
+}
+
+impl MultiItemModifier for Expander {
+    fn expand(
+        &self,
+        ecx: &mut ExtCtxt<'_>,
+        _span: Span,
+        meta_item: &ast::MetaItem,
+        item: Annotatable,
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
+        let template = AttributeTemplate { list: Some("path"), ..Default::default() };
+        let attr = &ecx.attribute(meta_item.clone());
+        validate_attr::check_builtin_attribute(ecx.parse_sess, attr, sym::cfg_accessible, template);
+
+        let path = match validate_input(ecx, meta_item) {
+            Some(path) => path,
+            None => return ExpandResult::Ready(Vec::new()),
+        };
+
+        let failure_msg = "cannot determine whether the path is accessible or not";
+        match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) {
+            Ok(true) => ExpandResult::Ready(vec![item]),
+            Ok(false) => ExpandResult::Ready(Vec::new()),
+            Err(_) => ExpandResult::Retry(item, failure_msg.into()),
+        }
+    }
+}
diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs
index e0c619fcbd3..84ed6e96aaf 100644
--- a/src/librustc_builtin_macros/deriving/generic/mod.rs
+++ b/src/librustc_builtin_macros/deriving/generic/mod.rs
@@ -360,7 +360,7 @@ fn find_type_parameters(
             visit::walk_ty(self, ty)
         }
 
-        fn visit_mac(&mut self, mac: &ast::Mac) {
+        fn visit_mac(&mut self, mac: &ast::MacCall) {
             self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros");
         }
     }
diff --git a/src/librustc_builtin_macros/deriving/mod.rs b/src/librustc_builtin_macros/deriving/mod.rs
index 5ba9d3800e1..b5ad67abf62 100644
--- a/src/librustc_builtin_macros/deriving/mod.rs
+++ b/src/librustc_builtin_macros/deriving/mod.rs
@@ -2,7 +2,7 @@
 
 use rustc_ast::ast::{self, ItemKind, MetaItem};
 use rustc_ast::ptr::P;
-use rustc_expand::base::{Annotatable, ExtCtxt, MultiItemModifier};
+use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
@@ -48,13 +48,13 @@ impl MultiItemModifier for BuiltinDerive {
         span: Span,
         meta_item: &MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable> {
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         // FIXME: Built-in derives often forget to give spans contexts,
         // so we are doing it here in a centralized way.
         let span = ecx.with_def_site_ctxt(span);
         let mut items = Vec::new();
         (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
-        items
+        ExpandResult::Ready(items)
     }
 }
 
diff --git a/src/librustc_builtin_macros/lib.rs b/src/librustc_builtin_macros/lib.rs
index 9a8b0a87cb7..26a59c6b1be 100644
--- a/src/librustc_builtin_macros/lib.rs
+++ b/src/librustc_builtin_macros/lib.rs
@@ -22,6 +22,7 @@ use rustc_span::symbol::sym;
 mod asm;
 mod assert;
 mod cfg;
+mod cfg_accessible;
 mod compile_error;
 mod concat;
 mod concat_idents;
@@ -85,6 +86,7 @@ pub fn register_builtin_macros(resolver: &mut dyn Resolver, edition: Edition) {
 
     register_attr! {
         bench: test::expand_bench,
+        cfg_accessible: cfg_accessible::Expander,
         global_allocator: global_allocator::expand,
         test: test::expand_test,
         test_case: test::expand_test_case,
diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs
index 79724662363..71622a3b7e6 100644
--- a/src/librustc_builtin_macros/proc_macro_harness.rs
+++ b/src/librustc_builtin_macros/proc_macro_harness.rs
@@ -59,7 +59,7 @@ pub fn inject(
     handler: &rustc_errors::Handler,
 ) -> ast::Crate {
     let ecfg = ExpansionConfig::default("proc_macro".to_string());
-    let mut cx = ExtCtxt::new(sess, ecfg, resolver);
+    let mut cx = ExtCtxt::new(sess, ecfg, resolver, None);
 
     let mut collect = CollectProcMacros {
         macros: Vec::new(),
@@ -341,7 +341,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
         self.in_root = prev_in_root;
     }
 
-    fn visit_mac(&mut self, mac: &'a ast::Mac) {
+    fn visit_mac(&mut self, mac: &'a ast::MacCall) {
         visit::walk_mac(self, mac)
     }
 }
diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs
index 5ad72a7443d..662bbe6a287 100644
--- a/src/librustc_builtin_macros/source_util.rs
+++ b/src/librustc_builtin_macros/source_util.rs
@@ -5,7 +5,7 @@ use rustc_ast::tokenstream::TokenStream;
 use rustc_ast_pretty::pprust;
 use rustc_expand::base::{self, *};
 use rustc_expand::panictry;
-use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership};
+use rustc_parse::{self, new_sub_parser_from_file, parser::Parser};
 use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
 use rustc_span::symbol::Symbol;
 use rustc_span::{self, Pos, Span};
@@ -108,8 +108,7 @@ pub fn expand_include<'cx>(
             return DummyResult::any(sp);
         }
     };
-    let directory_ownership = DirectoryOwnership::Owned { relative: None };
-    let p = new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);
+    let p = new_sub_parser_from_file(cx.parse_sess(), &file, None, sp);
 
     struct ExpandResult<'a> {
         p: Parser<'a>,
diff --git a/src/librustc_builtin_macros/standard_library_imports.rs b/src/librustc_builtin_macros/standard_library_imports.rs
index 30403f6dc41..f48fd6df9c9 100644
--- a/src/librustc_builtin_macros/standard_library_imports.rs
+++ b/src/librustc_builtin_macros/standard_library_imports.rs
@@ -39,7 +39,7 @@ pub fn inject(
     let call_site = DUMMY_SP.with_call_site_ctxt(expn_id);
 
     let ecfg = ExpansionConfig::default("std_lib_injection".to_string());
-    let cx = ExtCtxt::new(sess, ecfg, resolver);
+    let cx = ExtCtxt::new(sess, ecfg, resolver, None);
 
     // .rev() to preserve ordering above in combination with insert(0, ...)
     for &name in names.iter().rev() {
diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs
index bc194a3eec4..39009ca27f1 100644
--- a/src/librustc_builtin_macros/test.rs
+++ b/src/librustc_builtin_macros/test.rs
@@ -86,7 +86,7 @@ pub fn expand_test_or_bench(
             .raise();
     };
 
-    if let ast::ItemKind::Mac(_) = item.kind {
+    if let ast::ItemKind::MacCall(_) = item.kind {
         cx.parse_sess.span_diagnostic.span_warn(
             item.span,
             "`#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead.",
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index e7e1ad8eda7..b87767f4a41 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -138,7 +138,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
         smallvec![P(item)]
     }
 
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
         // Do nothing.
     }
 }
@@ -184,7 +184,7 @@ impl MutVisitor for EntryPointCleaner {
         smallvec![item]
     }
 
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
         // Do nothing.
     }
 }
@@ -202,7 +202,7 @@ fn generate_test_harness(
     let mut econfig = ExpansionConfig::default("test".to_string());
     econfig.features = Some(features);
 
-    let ext_cx = ExtCtxt::new(sess, econfig, resolver);
+    let ext_cx = ExtCtxt::new(sess, econfig, resolver, None);
 
     let expn_id = ext_cx.resolver.expansion_for_ast_pass(
         DUMMY_SP,
diff --git a/src/librustc_builtin_macros/util.rs b/src/librustc_builtin_macros/util.rs
index 8ef76a8657e..b486eadd1a8 100644
--- a/src/librustc_builtin_macros/util.rs
+++ b/src/librustc_builtin_macros/util.rs
@@ -6,7 +6,7 @@ use rustc_span::Symbol;
 
 pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
     // All the built-in macro attributes are "words" at the moment.
-    let template = AttributeTemplate::only_word();
+    let template = AttributeTemplate { word: true, ..Default::default() };
     let attr = ecx.attribute(meta_item.clone());
     validate_attr::check_builtin_attribute(ecx.parse_sess, &attr, name, template);
 }
diff --git a/src/librustc_codegen_llvm/README.md b/src/librustc_codegen_llvm/README.md
index dda2e5ac18f..97d8f76623e 100644
--- a/src/librustc_codegen_llvm/README.md
+++ b/src/librustc_codegen_llvm/README.md
@@ -2,6 +2,6 @@ The `codegen` crate contains the code to convert from MIR into LLVM IR,
 and then from LLVM IR into machine code. In general it contains code
 that runs towards the end of the compilation process.
 
-For more information about how codegen works, see the [rustc guide].
+For more information about how codegen works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/codegen.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/codegen.html
diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs
index 821377db0ee..4e7bc9fa0e2 100644
--- a/src/librustc_codegen_llvm/allocator.rs
+++ b/src/librustc_codegen_llvm/allocator.rs
@@ -1,5 +1,3 @@
-use std::ffi::CString;
-
 use crate::attributes;
 use libc::c_uint;
 use rustc::bug;
@@ -50,8 +48,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
             args.len() as c_uint,
             False,
         );
-        let name = CString::new(format!("__rust_{}", method.name)).unwrap();
-        let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr(), ty);
+        let name = format!("__rust_{}", method.name);
+        let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
 
         if tcx.sess.target.target.options.default_hidden_visibility {
             llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
@@ -60,8 +58,9 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
             attributes::emit_uwtable(llfn, true);
         }
 
-        let callee = CString::new(kind.fn_name(method.name)).unwrap();
-        let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr(), ty);
+        let callee = kind.fn_name(method.name);
+        let callee =
+            llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
         llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
 
         let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
@@ -73,14 +72,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
             .enumerate()
             .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
             .collect::<Vec<_>>();
-        let ret = llvm::LLVMRustBuildCall(
-            llbuilder,
-            callee,
-            args.as_ptr(),
-            args.len() as c_uint,
-            None,
-            "\0".as_ptr().cast(),
-        );
+        let ret =
+            llvm::LLVMRustBuildCall(llbuilder, callee, args.as_ptr(), args.len() as c_uint, None);
         llvm::LLVMSetTailCall(ret, True);
         if output.is_some() {
             llvm::LLVMBuildRet(llbuilder, ret);
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index 7975a70ab26..6edc3d5ecd4 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -12,7 +12,6 @@ use rustc_span::Span;
 
 use libc::{c_char, c_uint};
 use log::debug;
-use std::ffi::{CStr, CString};
 
 impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn codegen_inline_asm(
@@ -80,12 +79,11 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
             _ => self.type_struct(&output_types, false),
         };
 
-        let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
-        let constraint_cstr = CString::new(all_constraints).unwrap();
+        let asm = ia.asm.as_str();
         let r = inline_asm_call(
             self,
             &asm,
-            &constraint_cstr,
+            &all_constraints,
             &inputs,
             output_type,
             ia.volatile,
@@ -125,17 +123,17 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
 
 impl AsmMethods for CodegenCx<'ll, 'tcx> {
     fn codegen_global_asm(&self, ga: &hir::GlobalAsm) {
-        let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
+        let asm = ga.asm.as_str();
         unsafe {
-            llvm::LLVMRustAppendModuleInlineAsm(self.llmod, asm.as_ptr());
+            llvm::LLVMRustAppendModuleInlineAsm(self.llmod, asm.as_ptr().cast(), asm.len());
         }
     }
 }
 
 fn inline_asm_call(
     bx: &mut Builder<'a, 'll, 'tcx>,
-    asm: &CStr,
-    cons: &CStr,
+    asm: &str,
+    cons: &str,
     inputs: &[&'ll Value],
     output: &'ll llvm::Type,
     volatile: bool,
@@ -157,13 +155,15 @@ fn inline_asm_call(
     let fty = bx.cx.type_func(&argtys[..], output);
     unsafe {
         // Ask LLVM to verify that the constraints are well-formed.
-        let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr());
+        let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr().cast(), cons.len());
         debug!("constraint verification result: {:?}", constraints_ok);
         if constraints_ok {
             let v = llvm::LLVMRustInlineAsm(
                 fty,
-                asm.as_ptr(),
-                cons.as_ptr(),
+                asm.as_ptr().cast(),
+                asm.len(),
+                cons.as_ptr().cast(),
+                cons.len(),
                 volatile,
                 alignstack,
                 llvm::AsmDialect::from_generic(dia),
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index a9e4fdba030..072607fff85 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -3,8 +3,6 @@
 use std::ffi::CString;
 
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc::session::config::{OptLevel, Sanitizer};
-use rustc::session::Session;
 use rustc::ty::layout::HasTyCtxt;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -13,6 +11,8 @@ use rustc_data_structures::const_cstr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_session::config::{OptLevel, Sanitizer};
+use rustc_session::Session;
 use rustc_target::abi::call::Conv;
 use rustc_target::spec::PanicStrategy;
 
diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs
index 455b7086212..239ca57ba41 100644
--- a/src/librustc_codegen_llvm/back/archive.rs
+++ b/src/librustc_codegen_llvm/back/archive.rs
@@ -9,9 +9,9 @@ use std::str;
 
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind};
-use rustc::session::Session;
 use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
 use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME, RLIB_BYTECODE_EXTENSION};
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
 struct ArchiveConfig<'a> {
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 310cae978bf..1b64750f51f 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -9,7 +9,6 @@ use log::{debug, info};
 use rustc::bug;
 use rustc::dep_graph::WorkProduct;
 use rustc::middle::exported_symbols::SymbolExportLevel;
-use rustc::session::config::{self, Lto};
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
 use rustc_codegen_ssa::back::symbol_export;
 use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
@@ -19,6 +18,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{FatalError, Handler};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_session::cgu_reuse_tracker::CguReuse;
+use rustc_session::config::{self, Lto};
 
 use std::ffi::{CStr, CString};
 use std::fs::File;
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 0c243128104..2327b96e26c 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -15,8 +15,6 @@ use crate::LlvmCodegenBackend;
 use crate::ModuleLlvm;
 use log::debug;
 use rustc::bug;
-use rustc::session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, ModuleConfig};
 use rustc_codegen_ssa::traits::*;
@@ -25,6 +23,8 @@ use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_errors::{FatalError, Handler};
 use rustc_fs_util::{link_or_copy, path_to_c_string};
 use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
+use rustc_session::Session;
 
 use libc::{c_char, c_int, c_uint, c_void, size_t};
 use std::ffi::CString;
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index 04c084e459e..0d063d82c69 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -28,13 +28,13 @@ use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::exported_symbols;
 use rustc::mir::mono::{Linkage, Visibility};
-use rustc::session::config::DebugInfo;
 use rustc::ty::TyCtxt;
 use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
 use rustc_codegen_ssa::mono_item::MonoItemExt;
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_session::config::DebugInfo;
 use rustc_span::symbol::Symbol;
 
 use std::ffi::CString;
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 32604d5601d..b37d63fce65 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -7,7 +7,6 @@ use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 use libc::{c_char, c_uint};
 use log::debug;
-use rustc::session::config::{self, Sanitizer};
 use rustc::ty::layout::{self, Align, Size, TyLayout};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_codegen_ssa::base::to_immediate;
@@ -19,6 +18,7 @@ use rustc_codegen_ssa::MemFlags;
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::DefId;
+use rustc_session::config::{self, Sanitizer};
 use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
 use std::ffi::CStr;
@@ -1016,7 +1016,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 args.as_ptr() as *const &llvm::Value,
                 args.len() as c_uint,
                 bundle,
-                UNNAMED,
             )
         }
     }
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index df38eeec00f..609ddfc1d3a 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -259,11 +259,14 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 let base_addr = match alloc_kind {
                     Some(GlobalAlloc::Memory(alloc)) => {
                         let init = const_alloc_to_llvm(self, alloc);
-                        if alloc.mutability == Mutability::Mut {
-                            self.static_addr_of_mut(init, alloc.align, None)
-                        } else {
-                            self.static_addr_of(init, alloc.align, None)
+                        let value = match alloc.mutability {
+                            Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
+                            _ => self.static_addr_of(init, alloc.align, None),
+                        };
+                        if !self.sess().fewer_names() {
+                            llvm::set_value_name(value, format!("{:?}", ptr.alloc_id).as_bytes());
                         }
+                        value
                     }
                     Some(GlobalAlloc::Function(fn_instance)) => self.get_fn_addr(fn_instance),
                     Some(GlobalAlloc::Static(def_id)) => {
@@ -320,7 +323,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     }
 }
 
-pub fn val_ty(v: &'ll Value) -> &'ll Type {
+pub fn val_ty(v: &Value) -> &Type {
     unsafe { llvm::LLVMTypeOf(v) }
 }
 
@@ -342,6 +345,6 @@ fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
     ((hi as u128) << 64) | (lo as u128)
 }
 
-fn try_as_const_integral(v: &'ll Value) -> Option<&'ll ConstantInt> {
+fn try_as_const_integral(v: &Value) -> Option<&ConstantInt> {
     unsafe { llvm::LLVMIsAConstantInt(v) }
 }
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 3466363ac79..7b1526e9da1 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -1,37 +1,32 @@
-use crate::abi::FnAbi;
 use crate::attributes;
+use crate::callee::get_fn;
 use crate::debuginfo;
 use crate::llvm;
 use crate::llvm_util;
-use crate::value::Value;
-use rustc::dep_graph::DepGraphSafe;
-
 use crate::type_::Type;
-use rustc_codegen_ssa::traits::*;
+use crate::value::Value;
 
-use crate::callee::get_fn;
 use rustc::bug;
+use rustc::dep_graph::DepGraphSafe;
 use rustc::mir::mono::CodegenUnit;
-use rustc::session::config::{self, CFGuard, DebugInfo};
-use rustc::session::Session;
 use rustc::ty::layout::{
-    FnAbiExt, HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx,
+    HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx,
 };
 use rustc::ty::{self, Instance, Ty, TyCtxt};
 use rustc_codegen_ssa::base::wants_msvc_seh;
+use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::base_n;
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_hir::Unsafety;
-use rustc_target::spec::{HasTargetSpec, Target};
-
-use crate::abi::Abi;
+use rustc_session::config::{self, CFGuard, DebugInfo};
+use rustc_session::Session;
 use rustc_span::source_map::{Span, DUMMY_SP};
 use rustc_span::symbol::Symbol;
+use rustc_target::spec::{HasTargetSpec, Target};
+
 use std::cell::{Cell, RefCell};
 use std::ffi::CStr;
-use std::iter;
 use std::str;
 use std::sync::Arc;
 
@@ -87,7 +82,6 @@ pub struct CodegenCx<'ll, 'tcx> {
     pub dbg_cx: Option<debuginfo::CrateDebugContext<'ll, 'tcx>>,
 
     eh_personality: Cell<Option<&'ll Value>>,
-    eh_unwind_resume: Cell<Option<&'ll Value>>,
     pub rust_try_fn: Cell<Option<&'ll Value>>,
 
     intrinsics: RefCell<FxHashMap<&'static str, &'ll Value>>,
@@ -327,7 +321,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
             isize_ty,
             dbg_cx,
             eh_personality: Cell::new(None),
-            eh_unwind_resume: Cell::new(None),
             rust_try_fn: Cell::new(None),
             intrinsics: Default::default(),
             local_gen_sym_counter: Cell::new(0),
@@ -405,45 +398,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         llfn
     }
 
-    // Returns a Value of the "eh_unwind_resume" lang item if one is defined,
-    // otherwise declares it as an external function.
-    fn eh_unwind_resume(&self) -> &'ll Value {
-        let unwresume = &self.eh_unwind_resume;
-        if let Some(llfn) = unwresume.get() {
-            return llfn;
-        }
-
-        let tcx = self.tcx;
-        assert!(self.sess().target.target.options.custom_unwind_resume);
-        if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
-            let llfn = self.get_fn_addr(
-                ty::Instance::resolve(
-                    tcx,
-                    ty::ParamEnv::reveal_all(),
-                    def_id,
-                    tcx.intern_substs(&[]),
-                )
-                .unwrap(),
-            );
-            unwresume.set(Some(llfn));
-            return llfn;
-        }
-
-        let sig = ty::Binder::bind(tcx.mk_fn_sig(
-            iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
-            tcx.types.never,
-            false,
-            Unsafety::Unsafe,
-            Abi::C,
-        ));
-
-        let fn_abi = FnAbi::of_fn_ptr(self, sig, &[]);
-        let llfn = self.declare_fn("rust_eh_unwind_resume", &fn_abi);
-        attributes::apply_target_cpu_attr(self, llfn);
-        unwresume.set(Some(llfn));
-        llfn
-    }
-
     fn sess(&self) -> &Session {
         &self.tcx.sess
     }
diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
index cdb9657e1ff..09422f4ec37 100644
--- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
+++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
@@ -1,5 +1,5 @@
-use super::metadata::file_metadata;
-use super::utils::{span_start, DIB};
+use super::metadata::{file_metadata, UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
+use super::utils::DIB;
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
 
 use crate::common::CodegenCx;
@@ -7,10 +7,6 @@ use crate::llvm;
 use crate::llvm::debuginfo::{DIScope, DISubprogram};
 use rustc::mir::{Body, SourceScope};
 
-use libc::c_uint;
-
-use rustc_span::Pos;
-
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::Idx;
 
@@ -54,7 +50,7 @@ fn make_mir_scope(
         debug_context.scopes[parent]
     } else {
         // The root is the function itself.
-        let loc = span_start(cx, mir.span);
+        let loc = cx.lookup_debug_loc(mir.span.lo());
         debug_context.scopes[scope] = DebugScope {
             scope_metadata: Some(fn_metadata),
             file_start_pos: loc.file.start_pos,
@@ -70,7 +66,7 @@ fn make_mir_scope(
         return;
     }
 
-    let loc = span_start(cx, scope_data.span);
+    let loc = cx.lookup_debug_loc(scope_data.span.lo());
     let file_metadata = file_metadata(cx, &loc.file.name, debug_context.defining_crate);
 
     let scope_metadata = unsafe {
@@ -78,8 +74,8 @@ fn make_mir_scope(
             DIB(cx),
             parent_scope.scope_metadata.unwrap(),
             file_metadata,
-            loc.line as c_uint,
-            loc.col.to_usize() as c_uint,
+            loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
+            loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
         ))
     };
     debug_context.scopes[scope] = DebugScope {
diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs
index 753a4e18faf..e4cbffb6db3 100644
--- a/src/librustc_codegen_llvm/debuginfo/gdb.rs
+++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs
@@ -6,8 +6,8 @@ use crate::builder::Builder;
 use crate::common::CodegenCx;
 use crate::value::Value;
 use rustc::bug;
-use rustc::session::config::DebugInfo;
 use rustc_codegen_ssa::traits::*;
+use rustc_session::config::DebugInfo;
 
 use rustc_ast::attr;
 use rustc_span::symbol::sym;
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 46c4a511114..6a7ed4e1dc3 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -5,7 +5,7 @@ use self::RecursiveTypeDescription::*;
 use super::namespace::mangled_name_of_instance;
 use super::type_names::compute_debuginfo_type_name;
 use super::utils::{
-    create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, span_start, DIB,
+    create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB,
 };
 use super::CrateDebugContext;
 
@@ -24,7 +24,6 @@ use rustc::ich::NodeIdHashingMode;
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::mir::interpret::truncate;
 use rustc::mir::{self, Field, GeneratorLayout};
-use rustc::session::config::{self, DebugInfo};
 use rustc::ty::layout::{
     self, Align, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx,
 };
@@ -42,6 +41,7 @@ use rustc_fs_util::path_to_c_string;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_session::config::{self, DebugInfo};
 use rustc_span::symbol::{Interner, Symbol};
 use rustc_span::{self, FileName, Span};
 use rustc_target::abi::HasDataLayout;
@@ -2309,10 +2309,10 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
     let span = tcx.def_span(def_id);
 
     let (file_metadata, line_number) = if !span.is_dummy() {
-        let loc = span_start(cx, span);
-        (file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line as c_uint)
+        let loc = cx.lookup_debug_loc(span.lo());
+        (file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line)
     } else {
-        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
+        (unknown_file_metadata(cx), None)
     };
 
     let is_local_to_unit = is_node_local_to_unit(cx, def_id);
@@ -2339,7 +2339,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
             linkage_name.as_ptr().cast(),
             linkage_name.len(),
             file_metadata,
-            line_number,
+            line_number.unwrap_or(UNKNOWN_LINE_NUMBER),
             type_metadata,
             is_local_to_unit,
             global,
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 8deab1be3d3..85decff35b9 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -3,10 +3,10 @@ mod doc;
 
 use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
 
-use self::metadata::{file_metadata, type_metadata, TypeMap};
+use self::metadata::{file_metadata, type_metadata, TypeMap, UNKNOWN_LINE_NUMBER};
 use self::namespace::mangled_name_of_instance;
 use self::type_names::compute_debuginfo_type_name;
-use self::utils::{create_DIArray, is_node_local_to_unit, span_start, DIB};
+use self::utils::{create_DIArray, is_node_local_to_unit, DIB};
 
 use crate::llvm;
 use crate::llvm::debuginfo::{
@@ -20,12 +20,12 @@ use crate::builder::Builder;
 use crate::common::CodegenCx;
 use crate::value::Value;
 use rustc::mir;
-use rustc::session::config::{self, DebugInfo};
 use rustc::ty::{self, Instance, ParamEnv, Ty};
 use rustc_codegen_ssa::debuginfo::type_names;
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_index::vec::IndexVec;
+use rustc_session::config::{self, DebugInfo};
 
 use libc::c_uint;
 use log::debug;
@@ -248,7 +248,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
         let def_id = instance.def_id();
         let containing_scope = get_containing_scope(self, instance);
-        let loc = span_start(self, span);
+        let loc = self.lookup_debug_loc(span.lo());
         let file_metadata = file_metadata(self, &loc.file.name, def_id.krate);
 
         let function_type_metadata = unsafe {
@@ -304,9 +304,9 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 linkage_name.as_ptr().cast(),
                 linkage_name.len(),
                 file_metadata,
-                loc.line as c_uint,
+                loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
                 function_type_metadata,
-                scope_line as c_uint,
+                scope_line.unwrap_or(UNKNOWN_LINE_NUMBER),
                 flags,
                 spflags,
                 llfn,
@@ -530,7 +530,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         variable_kind: VariableKind,
         span: Span,
     ) -> &'ll DIVariable {
-        let loc = span_start(self, span);
+        let loc = self.lookup_debug_loc(span.lo());
         let file_metadata = file_metadata(self, &loc.file.name, dbg_context.defining_crate);
 
         let type_metadata = type_metadata(self, variable_type, span);
@@ -550,7 +550,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 name.as_ptr().cast(),
                 name.len(),
                 file_metadata,
-                loc.line as c_uint,
+                loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
                 type_metadata,
                 true,
                 DIFlags::FlagZero,
diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
index 1f871c7d207..66ae9d72c3e 100644
--- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs
+++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
@@ -1,32 +1,58 @@
-use super::metadata::UNKNOWN_COLUMN_NUMBER;
-use super::utils::{debug_context, span_start};
+use super::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
+use super::utils::debug_context;
 
 use crate::common::CodegenCx;
 use crate::llvm::debuginfo::DIScope;
 use crate::llvm::{self, Value};
 use rustc_codegen_ssa::traits::*;
 
-use libc::c_uint;
-use rustc_span::{Pos, Span};
+use rustc_data_structures::sync::Lrc;
+use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span};
+
+/// A source code location used to generate debug information.
+pub struct DebugLoc {
+    /// Information about the original source file.
+    pub file: Lrc<SourceFile>,
+    /// The (1-based) line number.
+    pub line: Option<u32>,
+    /// The (1-based) column number.
+    pub col: Option<u32>,
+}
 
 impl CodegenCx<'ll, '_> {
-    pub fn create_debug_loc(&self, scope: &'ll DIScope, span: Span) -> &'ll Value {
-        let loc = span_start(self, span);
+    /// Looks up debug source information about a `BytePos`.
+    pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
+        let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
+            Ok(SourceFileAndLine { sf: file, line }) => {
+                let line_pos = file.line_begin_pos(pos);
+
+                // Use 1-based indexing.
+                let line = (line + 1) as u32;
+                let col = (pos - line_pos).to_u32() + 1;
+
+                (file, Some(line), Some(col))
+            }
+            Err(file) => (file, None, None),
+        };
 
-        // For MSVC, set the column number to zero.
+        // For MSVC, omit the column number.
         // Otherwise, emit it. This mimics clang behaviour.
         // See discussion in https://github.com/rust-lang/rust/issues/42921
-        let col_used = if self.sess().target.target.options.is_like_msvc {
-            UNKNOWN_COLUMN_NUMBER
+        if self.sess().target.target.options.is_like_msvc {
+            DebugLoc { file, line, col: None }
         } else {
-            loc.col.to_usize() as c_uint
-        };
+            DebugLoc { file, line, col }
+        }
+    }
+
+    pub fn create_debug_loc(&self, scope: &'ll DIScope, span: Span) -> &'ll Value {
+        let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo());
 
         unsafe {
             llvm::LLVMRustDIBuilderCreateDebugLocation(
                 debug_context(self).llcontext,
-                loc.line as c_uint,
-                col_used,
+                line.unwrap_or(UNKNOWN_LINE_NUMBER),
+                col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
                 scope,
                 None,
             )
diff --git a/src/librustc_codegen_llvm/debuginfo/utils.rs b/src/librustc_codegen_llvm/debuginfo/utils.rs
index 4e17387e057..bef40decdf3 100644
--- a/src/librustc_codegen_llvm/debuginfo/utils.rs
+++ b/src/librustc_codegen_llvm/debuginfo/utils.rs
@@ -9,9 +9,6 @@ use rustc_hir::def_id::DefId;
 use crate::common::CodegenCx;
 use crate::llvm;
 use crate::llvm::debuginfo::{DIArray, DIBuilder, DIDescriptor, DIScope};
-use rustc_codegen_ssa::traits::*;
-
-use rustc_span::Span;
 
 pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool {
     // The is_local_to_unit flag indicates whether a function is local to the
@@ -32,11 +29,6 @@ pub fn create_DIArray(builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>
     };
 }
 
-/// Returns rustc_span::Loc corresponding to the beginning of the span
-pub fn span_start(cx: &CodegenCx<'_, '_>, span: Span) -> rustc_span::Loc {
-    cx.sess().source_map().lookup_char_pos(span.lo())
-}
-
 #[inline]
 pub fn debug_context(cx: &'a CodegenCx<'ll, 'tcx>) -> &'a CrateDebugContext<'ll, 'tcx> {
     cx.dbg_cx.as_ref().unwrap()
diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs
index 691f32dd85a..fab6321186b 100644
--- a/src/librustc_codegen_llvm/declare.rs
+++ b/src/librustc_codegen_llvm/declare.rs
@@ -21,7 +21,6 @@ use crate::value::Value;
 use log::debug;
 use rustc::ty::Ty;
 use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::small_c_str::SmallCStr;
 
 /// Declare a function.
 ///
@@ -34,8 +33,9 @@ fn declare_raw_fn(
     ty: &'ll Type,
 ) -> &'ll Value {
     debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
-    let namebuf = SmallCStr::new(name);
-    let llfn = unsafe { llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty) };
+    let llfn = unsafe {
+        llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_ptr().cast(), name.len(), ty)
+    };
 
     llvm::SetFunctionCallConv(llfn, callconv);
     // Function addresses in Rust are never significant, allowing functions to
@@ -83,8 +83,7 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
     fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
         debug!("get_declared_value(name={:?})", name);
-        let namebuf = SmallCStr::new(name);
-        unsafe { llvm::LLVMRustGetNamedValue(self.llmod, namebuf.as_ptr()) }
+        unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) }
     }
 
     fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 1ae9d2a6841..1ddfde526fa 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -195,26 +195,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                     .unwrap();
                 OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self)
             }
-            "init" => {
-                let ty = substs.type_at(0);
-                if !self.layout_of(ty).is_zst() {
-                    // Just zero out the stack slot.
-                    // If we store a zero constant, LLVM will drown in vreg allocation for large
-                    // data structures, and the generated code will be awful. (A telltale sign of
-                    // this is large quantities of `mov [byte ptr foo],0` in the generated code.)
-                    memset_intrinsic(
-                        self,
-                        false,
-                        ty,
-                        llresult,
-                        self.const_u8(0),
-                        self.const_usize(1),
-                    );
-                }
-                return;
-            }
-            // Effectively no-ops
-            "uninit" | "forget" => {
+            // Effectively no-op
+            "forget" => {
                 return;
             }
             "offset" => {
@@ -851,19 +833,21 @@ fn memset_intrinsic(
 
 fn try_intrinsic(
     bx: &mut Builder<'a, 'll, 'tcx>,
-    func: &'ll Value,
+    try_func: &'ll Value,
     data: &'ll Value,
-    local_ptr: &'ll Value,
+    catch_func: &'ll Value,
     dest: &'ll Value,
 ) {
     if bx.sess().no_landing_pads() {
-        bx.call(func, &[data], None);
-        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        bx.store(bx.const_null(bx.type_i8p()), dest, ptr_align);
+        bx.call(try_func, &[data], None);
+        // Return 0 unconditionally from the intrinsic call;
+        // we can never unwind.
+        let ret_align = bx.tcx().data_layout.i32_align.abi;
+        bx.store(bx.const_i32(0), dest, ret_align);
     } else if wants_msvc_seh(bx.sess()) {
-        codegen_msvc_try(bx, func, data, local_ptr, dest);
+        codegen_msvc_try(bx, try_func, data, catch_func, dest);
     } else {
-        codegen_gnu_try(bx, func, data, local_ptr, dest);
+        codegen_gnu_try(bx, try_func, data, catch_func, dest);
     }
 }
 
@@ -876,9 +860,9 @@ fn try_intrinsic(
 // as the old ones are still more optimized.
 fn codegen_msvc_try(
     bx: &mut Builder<'a, 'll, 'tcx>,
-    func: &'ll Value,
+    try_func: &'ll Value,
     data: &'ll Value,
-    local_ptr: &'ll Value,
+    catch_func: &'ll Value,
     dest: &'ll Value,
 ) {
     let llfn = get_rust_try_fn(bx, &mut |mut bx| {
@@ -890,15 +874,15 @@ fn codegen_msvc_try(
         let mut catchpad = bx.build_sibling_block("catchpad");
         let mut caught = bx.build_sibling_block("caught");
 
-        let func = llvm::get_param(bx.llfn(), 0);
+        let try_func = llvm::get_param(bx.llfn(), 0);
         let data = llvm::get_param(bx.llfn(), 1);
-        let local_ptr = llvm::get_param(bx.llfn(), 2);
+        let catch_func = llvm::get_param(bx.llfn(), 2);
 
         // We're generating an IR snippet that looks like:
         //
-        //   declare i32 @rust_try(%func, %data, %ptr) {
-        //      %slot = alloca [2 x i64]
-        //      invoke %func(%data) to label %normal unwind label %catchswitch
+        //   declare i32 @rust_try(%try_func, %data, %catch_func) {
+        //      %slot = alloca u8*
+        //      invoke %try_func(%data) to label %normal unwind label %catchswitch
         //
         //   normal:
         //      ret i32 0
@@ -908,8 +892,8 @@ fn codegen_msvc_try(
         //
         //   catchpad:
         //      %tok = catchpad within %cs [%type_descriptor, 0, %slot]
-        //      %ptr[0] = %slot[0]
-        //      %ptr[1] = %slot[1]
+        //      %ptr = load %slot
+        //      call %catch_func(%data, %ptr)
         //      catchret from %tok to label %caught
         //
         //   caught:
@@ -926,32 +910,57 @@ fn codegen_msvc_try(
         //          ~rust_panic();
         //
         //          uint64_t x[2];
-        //      }
+        //      };
         //
-        //      int bar(void (*foo)(void), uint64_t *ret) {
+        //      int __rust_try(
+        //          void (*try_func)(void*),
+        //          void *data,
+        //          void (*catch_func)(void*, void*) noexcept
+        //      ) {
         //          try {
-        //              foo();
+        //              try_func(data);
         //              return 0;
         //          } catch(rust_panic& a) {
-        //              ret[0] = a.x[0];
-        //              ret[1] = a.x[1];
-        //              a.x[0] = 0;
+        //              catch_func(data, &a);
         //              return 1;
         //          }
         //      }
         //
         // More information can be found in libstd's seh.rs implementation.
-        let i64_2 = bx.type_array(bx.type_i64(), 2);
-        let i64_2_ptr = bx.type_ptr_to(i64_2);
         let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        let slot = bx.alloca(i64_2_ptr, ptr_align);
-        bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
+        let slot = bx.alloca(bx.type_i8p(), ptr_align);
+        bx.invoke(try_func, &[data], normal.llbb(), catchswitch.llbb(), None);
 
         normal.ret(bx.const_i32(0));
 
         let cs = catchswitch.catch_switch(None, None, 1);
         catchswitch.add_handler(cs, catchpad.llbb());
 
+        // We can't use the TypeDescriptor defined in libpanic_unwind because it
+        // might be in another DLL and the SEH encoding only supports specifying
+        // a TypeDescriptor from the current module.
+        //
+        // However this isn't an issue since the MSVC runtime uses string
+        // comparison on the type name to match TypeDescriptors rather than
+        // pointer equality.
+        //
+        // So instead we generate a new TypeDescriptor in each module that uses
+        // `try` and let the linker merge duplicate definitions in the same
+        // module.
+        //
+        // When modifying, make sure that the type_name string exactly matches
+        // the one used in src/libpanic_unwind/seh.rs.
+        let type_info_vtable = bx.declare_global("??_7type_info@@6B@", bx.type_i8p());
+        let type_name = bx.const_bytes(b"rust_panic\0");
+        let type_info =
+            bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_i8p()), type_name], false);
+        let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info));
+        unsafe {
+            llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
+            llvm::SetUniqueComdat(bx.llmod, tydesc);
+            llvm::LLVMSetInitializer(tydesc, type_info);
+        }
+
         // The flag value of 8 indicates that we are catching the exception by
         // reference instead of by value. We can't use catch by value because
         // that requires copying the exception object, which we don't support
@@ -959,23 +968,9 @@ fn codegen_msvc_try(
         //
         // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
         let flags = bx.const_i32(8);
-        let tydesc = match bx.tcx().lang_items().eh_catch_typeinfo() {
-            Some(did) => bx.get_static(did),
-            None => bug!("eh_catch_typeinfo not defined, but needed for SEH unwinding"),
-        };
         let funclet = catchpad.catch_pad(cs, &[tydesc, flags, slot]);
-
-        let i64_align = bx.tcx().data_layout.i64_align.abi;
-        let payload_ptr = catchpad.load(slot, ptr_align);
-        let payload = catchpad.load(payload_ptr, i64_align);
-        let local_ptr = catchpad.bitcast(local_ptr, bx.type_ptr_to(i64_2));
-        catchpad.store(payload, local_ptr, i64_align);
-
-        // Clear the first word of the exception so avoid double-dropping it.
-        // This will be read by the destructor which is implicitly called at the
-        // end of the catch block by the runtime.
-        let payload_0_ptr = catchpad.inbounds_gep(payload_ptr, &[bx.const_i32(0), bx.const_i32(0)]);
-        catchpad.store(bx.const_u64(0), payload_0_ptr, i64_align);
+        let ptr = catchpad.load(slot, ptr_align);
+        catchpad.call(catch_func, &[data, ptr], Some(&funclet));
 
         catchpad.catch_ret(&funclet, caught.llbb());
 
@@ -984,7 +979,7 @@ fn codegen_msvc_try(
 
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
-    let ret = bx.call(llfn, &[func, data, local_ptr], None);
+    let ret = bx.call(llfn, &[try_func, data, catch_func], None);
     let i32_align = bx.tcx().data_layout.i32_align.abi;
     bx.store(ret, dest, i32_align);
 }
@@ -1002,38 +997,34 @@ fn codegen_msvc_try(
 // the right personality function.
 fn codegen_gnu_try(
     bx: &mut Builder<'a, 'll, 'tcx>,
-    func: &'ll Value,
+    try_func: &'ll Value,
     data: &'ll Value,
-    local_ptr: &'ll Value,
+    catch_func: &'ll Value,
     dest: &'ll Value,
 ) {
     let llfn = get_rust_try_fn(bx, &mut |mut bx| {
         // Codegens the shims described above:
         //
         //   bx:
-        //      invoke %func(%args...) normal %normal unwind %catch
+        //      invoke %try_func(%data) normal %normal unwind %catch
         //
         //   normal:
         //      ret 0
         //
         //   catch:
-        //      (ptr, _) = landingpad
-        //      store ptr, %local_ptr
+        //      (%ptr, _) = landingpad
+        //      call %catch_func(%data, %ptr)
         //      ret 1
-        //
-        // Note that the `local_ptr` data passed into the `try` intrinsic is
-        // expected to be `*mut *mut u8` for this to actually work, but that's
-        // managed by the standard library.
 
         bx.sideeffect();
 
         let mut then = bx.build_sibling_block("then");
         let mut catch = bx.build_sibling_block("catch");
 
-        let func = llvm::get_param(bx.llfn(), 0);
+        let try_func = llvm::get_param(bx.llfn(), 0);
         let data = llvm::get_param(bx.llfn(), 1);
-        let local_ptr = llvm::get_param(bx.llfn(), 2);
-        bx.invoke(func, &[data], then.llbb(), catch.llbb(), None);
+        let catch_func = llvm::get_param(bx.llfn(), 2);
+        bx.invoke(try_func, &[data], then.llbb(), catch.llbb(), None);
         then.ret(bx.const_i32(0));
 
         // Type indicator for the exception being thrown.
@@ -1053,15 +1044,13 @@ fn codegen_gnu_try(
         };
         catch.add_clause(vals, tydesc);
         let ptr = catch.extract_value(vals, 0);
-        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-        let bitcast = catch.bitcast(local_ptr, bx.type_ptr_to(bx.type_i8p()));
-        catch.store(ptr, bitcast, ptr_align);
+        catch.call(catch_func, &[data, ptr], None);
         catch.ret(bx.const_i32(1));
     });
 
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
-    let ret = bx.call(llfn, &[func, data, local_ptr], None);
+    let ret = bx.call(llfn, &[try_func, data, catch_func], None);
     let i32_align = bx.tcx().data_layout.i32_align.abi;
     bx.store(ret, dest, i32_align);
 }
@@ -1084,6 +1073,8 @@ fn gen_fn<'ll, 'tcx>(
     ));
     let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
     let llfn = cx.declare_fn(name, &fn_abi);
+    cx.set_frame_pointer_elimination(llfn);
+    cx.apply_target_cpu_attr(llfn);
     // FIXME(eddyb) find a nicer way to do this.
     unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
     let bx = Builder::new_block(cx, llfn, "entry-block");
@@ -1106,15 +1097,22 @@ fn get_rust_try_fn<'ll, 'tcx>(
     // Define the type up front for the signature of the rust_try function.
     let tcx = cx.tcx;
     let i8p = tcx.mk_mut_ptr(tcx.types.i8);
-    let fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
+    let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
         iter::once(i8p),
         tcx.mk_unit(),
         false,
         hir::Unsafety::Unsafe,
         Abi::Rust,
     )));
+    let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
+        [i8p, i8p].iter().cloned(),
+        tcx.mk_unit(),
+        false,
+        hir::Unsafety::Unsafe,
+        Abi::Rust,
+    )));
     let output = tcx.types.i32;
-    let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, codegen);
+    let rust_try = gen_fn(cx, "__rust_try", vec![try_fn_ty, i8p, catch_fn_ty], output, codegen);
     cx.rust_try_fn.set(Some(rust_try));
     rust_try
 }
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index f3265754574..fa730d289b1 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -15,31 +15,30 @@
 #![recursion_limit = "256"]
 
 use back::write::{create_informational_target_machine, create_target_machine};
-use rustc_span::symbol::Symbol;
 
 pub use llvm_util::target_features;
-use rustc::dep_graph::WorkProduct;
+use rustc::dep_graph::{DepGraph, WorkProduct};
+use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
+use rustc::ty::{self, TyCtxt};
+use rustc::util::common::ErrorReported;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
 use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
 use rustc_codegen_ssa::traits::*;
+use rustc_codegen_ssa::ModuleCodegen;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule};
+use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_errors::{FatalError, Handler};
+use rustc_serialize::json;
+use rustc_session::config::{self, OptLevel, OutputFilenames, PrintRequest};
+use rustc_session::Session;
+use rustc_span::symbol::Symbol;
+
 use std::any::Any;
 use std::ffi::CStr;
 use std::fs;
 use std::sync::Arc;
 
-use rustc::dep_graph::DepGraph;
-use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc::session::config::{self, OptLevel, OutputFilenames, PrintRequest};
-use rustc::session::Session;
-use rustc::ty::{self, TyCtxt};
-use rustc::util::common::ErrorReported;
-use rustc_codegen_ssa::ModuleCodegen;
-use rustc_codegen_utils::codegen_backend::CodegenBackend;
-use rustc_serialize::json;
-
 mod back {
     pub mod archive;
     pub mod bytecode;
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 31a0f528090..c17c06718f5 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -694,8 +694,8 @@ pub mod debuginfo {
     }
 
     impl DebugEmissionKind {
-        pub fn from_generic(kind: rustc::session::config::DebugInfo) -> Self {
-            use rustc::session::config::DebugInfo;
+        pub fn from_generic(kind: rustc_session::config::DebugInfo) -> Self {
+            use rustc_session::config::DebugInfo;
             match kind {
                 DebugInfo::None => DebugEmissionKind::NoDebug,
                 DebugInfo::Limited => DebugEmissionKind::LineTablesOnly,
@@ -732,7 +732,7 @@ extern "C" {
 
     /// See Module::setModuleInlineAsm.
     pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char);
-    pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char);
+    pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char, AsmLen: size_t);
 
     /// See llvm::LLVMTypeKind::getTypeID.
     pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;
@@ -879,13 +879,18 @@ extern "C" {
     pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
     pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
     pub fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
-    pub fn LLVMRustGetNamedValue(M: &Module, Name: *const c_char) -> Option<&Value>;
+    pub fn LLVMRustGetNamedValue(
+        M: &Module,
+        Name: *const c_char,
+        NameLen: size_t,
+    ) -> Option<&Value>;
     pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
 
     // Operations on functions
     pub fn LLVMRustGetOrInsertFunction(
         M: &'a Module,
         Name: *const c_char,
+        NameLen: size_t,
         FunctionTy: &'a Type,
     ) -> &'a Value;
     pub fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
@@ -1332,7 +1337,6 @@ extern "C" {
         Args: *const &'a Value,
         NumArgs: c_uint,
         Bundle: Option<&OperandBundleDef<'a>>,
-        Name: *const c_char,
     ) -> &'a Value;
     pub fn LLVMRustBuildMemCpy(
         B: &Builder<'a>,
@@ -1581,12 +1585,18 @@ extern "C" {
     pub fn LLVMRustInlineAsm(
         Ty: &Type,
         AsmString: *const c_char,
+        AsmStringLen: size_t,
         Constraints: *const c_char,
+        ConstraintsLen: size_t,
         SideEffects: Bool,
         AlignStack: Bool,
         Dialect: AsmDialect,
     ) -> &Value;
-    pub fn LLVMRustInlineAsmVerify(Ty: &Type, Constraints: *const c_char) -> bool;
+    pub fn LLVMRustInlineAsmVerify(
+        Ty: &Type,
+        Constraints: *const c_char,
+        ConstraintsLen: size_t,
+    ) -> bool;
 
     pub fn LLVMRustDebugMetadataVersion() -> u32;
     pub fn LLVMRustVersionMajor() -> u32;
diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs
index 96014cbee5d..a083e14979c 100644
--- a/src/librustc_codegen_llvm/llvm/mod.rs
+++ b/src/librustc_codegen_llvm/llvm/mod.rs
@@ -185,12 +185,12 @@ impl Drop for SectionIter<'a> {
     }
 }
 
-pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> {
+pub fn mk_section_iter(llof: &ffi::ObjectFile) -> SectionIter<'_> {
     unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
 }
 
 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
-pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
+pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
     unsafe {
         assert!(
             index < LLVMCountParams(llfn),
@@ -203,7 +203,7 @@ pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
 }
 
 /// Safe wrapper for `LLVMGetValueName2` into a byte slice
-pub fn get_value_name(value: &'a Value) -> &'a [u8] {
+pub fn get_value_name(value: &Value) -> &[u8] {
     unsafe {
         let mut len = 0;
         let data = LLVMGetValueName2(value, &mut len);
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 0081a75a4da..5e924c9af84 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -2,10 +2,10 @@ use crate::back::write::create_informational_target_machine;
 use crate::llvm;
 use libc::c_int;
 use rustc::bug;
-use rustc::session::config::PrintRequest;
-use rustc::session::Session;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_feature::UnstableFeatures;
+use rustc_session::config::PrintRequest;
+use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs
index aacaf130f9a..5bc1475df23 100644
--- a/src/librustc_codegen_llvm/type_.rs
+++ b/src/librustc_codegen_llvm/type_.rs
@@ -240,7 +240,7 @@ impl Type {
         unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) }
     }
 
-    pub fn i8p_llcx(llcx: &'ll llvm::Context) -> &'ll Type {
+    pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
         Type::i8_llcx(llcx).ptr_to()
     }
 
diff --git a/src/librustc_codegen_ssa/README.md b/src/librustc_codegen_ssa/README.md
index 2a3a4fcc5fc..90d991a3a4b 100644
--- a/src/librustc_codegen_ssa/README.md
+++ b/src/librustc_codegen_ssa/README.md
@@ -1,3 +1,3 @@
-Please read the rustc-guide chapter on [Backend Agnostic Codegen][bac].
+Please read the rustc-dev-guide chapter on [Backend Agnostic Codegen][bac].
 
-[bac]: https://rust-lang.github.io/rustc-guide/codegen/backend-agnostic.html
+[bac]: https://rustc-dev-guide.rust-lang.org/codegen/backend-agnostic.html
diff --git a/src/librustc_codegen_ssa/back/archive.rs b/src/librustc_codegen_ssa/back/archive.rs
index a357c350287..f83b4b2b0c0 100644
--- a/src/librustc_codegen_ssa/back/archive.rs
+++ b/src/librustc_codegen_ssa/back/archive.rs
@@ -1,4 +1,4 @@
-use rustc::session::Session;
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
 use std::io;
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 0dd2f029e8d..af413d3cdfe 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -1,15 +1,15 @@
 use rustc::middle::cstore::{EncodedMetadata, LibSource, NativeLibrary, NativeLibraryKind};
 use rustc::middle::dependency_format::Linkage;
-use rustc::session::config::{
+use rustc_data_structures::fx::FxHashSet;
+use rustc_fs_util::fix_windows_verbatim_for_gcc;
+use rustc_hir::def_id::CrateNum;
+use rustc_session::config::{
     self, CFGuard, DebugInfo, OutputFilenames, OutputType, PrintRequest, Sanitizer,
 };
-use rustc::session::search_paths::PathKind;
+use rustc_session::search_paths::PathKind;
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
-use rustc::session::{filesearch, Session};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_fs_util::fix_windows_verbatim_for_gcc;
-use rustc_hir::def_id::CrateNum;
+use rustc_session::{filesearch, Session};
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
 
@@ -490,6 +490,11 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
     info!("preparing {:?} to {:?}", crate_type, out_filename);
     let (linker, flavor) = linker_and_flavor(sess);
 
+    let any_dynamic_crate = crate_type == config::CrateType::Dylib
+        || codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| {
+            *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic)
+        });
+
     // The invocations of cc share some flags across platforms
     let (pname, mut cmd) = get_linker(sess, &linker, flavor);
 
@@ -497,7 +502,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
         cmd.args(args);
     }
     if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) {
-        if sess.crt_static() {
+        if sess.crt_static(Some(crate_type)) {
             cmd.args(args);
         }
     }
@@ -523,7 +528,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
         cmd.arg(get_file_path(sess, obj));
     }
 
-    if crate_type == config::CrateType::Executable && sess.crt_static() {
+    if crate_type == config::CrateType::Executable && sess.crt_static(Some(crate_type)) {
         for obj in &sess.target.target.options.pre_link_objects_exe_crt {
             cmd.arg(get_file_path(sess, obj));
         }
@@ -555,10 +560,19 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
     if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
         cmd.args(args);
     }
+    if any_dynamic_crate {
+        if let Some(args) = sess.target.target.options.late_link_args_dynamic.get(&flavor) {
+            cmd.args(args);
+        }
+    } else {
+        if let Some(args) = sess.target.target.options.late_link_args_static.get(&flavor) {
+            cmd.args(args);
+        }
+    }
     for obj in &sess.target.target.options.post_link_objects {
         cmd.arg(get_file_path(sess, obj));
     }
-    if sess.crt_static() {
+    if sess.crt_static(Some(crate_type)) {
         for obj in &sess.target.target.options.post_link_objects_crt {
             cmd.arg(get_file_path(sess, obj));
         }
@@ -1288,7 +1302,8 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
             let more_args = &sess.opts.cg.link_arg;
             let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
 
-            if is_pic(sess) && !sess.crt_static() && !args.any(|x| *x == "-static") {
+            if is_pic(sess) && !sess.crt_static(Some(crate_type)) && !args.any(|x| *x == "-static")
+            {
                 position_independent_executable = true;
             }
         }
@@ -1373,7 +1388,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
     if crate_type != config::CrateType::Executable {
         cmd.build_dylib(out_filename);
     }
-    if crate_type == config::CrateType::Executable && sess.crt_static() {
+    if crate_type == config::CrateType::Executable && sess.crt_static(Some(crate_type)) {
         cmd.build_static_executable();
     }
 
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 5aafb8a12d7..6b30ae8559d 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -2,7 +2,6 @@ use super::archive;
 use super::command::Command;
 use super::symbol_export;
 
-use rustc_data_structures::fx::FxHashMap;
 use std::ffi::{OsStr, OsString};
 use std::fs::{self, File};
 use std::io::prelude::*;
@@ -10,11 +9,12 @@ use std::io::{self, BufWriter};
 use std::path::{Path, PathBuf};
 
 use rustc::middle::dependency_format::Linkage;
-use rustc::session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel};
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_serialize::{json, Encoder};
+use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel};
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{LinkerFlavor, LldFlavor};
 
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 3fe256ce25b..8368d98884a 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -3,7 +3,6 @@ use std::sync::Arc;
 
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel};
-use rustc::session::config::{self, Sanitizer};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::Instance;
@@ -16,6 +15,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::Node;
 use rustc_index::vec::IndexVec;
+use rustc_session::config::{self, Sanitizer};
 
 pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
     crates_export_threshold(&tcx.sess.crate_types.borrow())
@@ -88,7 +88,7 @@ fn reachable_non_generics_provider(
                 // Only consider nodes that actually have exported symbols.
                 Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })
                 | Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. })
-                | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(..), .. }) => {
+                | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
                     let def_id = tcx.hir().local_def_id(hir_id);
                     let generics = tcx.generics_of(def_id);
                     if !generics.requires_monomorphization(tcx) &&
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 3afa4758253..303ee385658 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -14,10 +14,6 @@ use jobserver::{Acquired, Client};
 use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId};
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::exported_symbols::SymbolExportLevel;
-use rustc::session::config::{
-    self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath,
-};
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_ast::attr;
 use rustc_data_structures::fx::FxHashMap;
@@ -34,6 +30,10 @@ use rustc_incremental::{
     copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
 };
 use rustc_session::cgu_reuse_tracker::CguReuseTracker;
+use rustc_session::config::{
+    self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath,
+};
+use rustc_session::Session;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{sym, Symbol};
@@ -341,9 +341,9 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
 
     let crate_name = tcx.crate_name(LOCAL_CRATE);
     let crate_hash = tcx.crate_hash(LOCAL_CRATE);
-    let no_builtins = attr::contains_name(&tcx.hir().krate().attrs, sym::no_builtins);
+    let no_builtins = attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_builtins);
     let subsystem =
-        attr::first_attr_value_str_by_name(&tcx.hir().krate().attrs, sym::windows_subsystem);
+        attr::first_attr_value_str_by_name(&tcx.hir().krate().item.attrs, sym::windows_subsystem);
     let windows_subsystem = subsystem.map(|subsystem| {
         if subsystem != sym::windows && subsystem != sym::console {
             tcx.sess.fatal(&format!(
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index d6e1ab8909c..e57cae30b77 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -31,8 +31,6 @@ use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::middle::lang_items;
 use rustc::middle::lang_items::StartFnLangItem;
 use rustc::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
-use rustc::session::config::{self, EntryFnType, Lto};
-use rustc::session::Session;
 use rustc::ty::layout::{self, Align, HasTyCtxt, LayoutOf, TyLayout, VariantIdx};
 use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
 use rustc::ty::query::Providers;
@@ -46,6 +44,8 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_index::vec::Idx;
 use rustc_session::cgu_reuse_tracker::CguReuse;
+use rustc_session::config::{self, EntryFnType, Lto};
+use rustc_session::Session;
 use rustc_span::Span;
 
 use std::cmp;
diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs
index 28b61e0b36d..147b2399502 100644
--- a/src/librustc_codegen_ssa/common.rs
+++ b/src/librustc_codegen_ssa/common.rs
@@ -1,8 +1,8 @@
 #![allow(non_camel_case_types, non_snake_case)]
 
-use rustc::session::Session;
 use rustc::ty::{Ty, TyCtxt};
 use rustc_errors::struct_span_err;
+use rustc_session::Session;
 use rustc_span::Span;
 
 use crate::base;
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index a2bb39b9e40..d2afbdc23e1 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -21,12 +21,12 @@ use rustc::dep_graph::WorkProduct;
 use rustc::middle::cstore::{CrateSource, LibSource, NativeLibrary};
 use rustc::middle::dependency_format::Dependencies;
 use rustc::middle::lang_items::LangItem;
-use rustc::session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc::ty::query::Providers;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def_id::CrateNum;
+use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_span::symbol::Symbol;
 use std::path::{Path, PathBuf};
 
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index c8d352cd2dd..8433f793020 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -178,15 +178,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             let lp1 = bx.load_operand(lp1).immediate();
             slot.storage_dead(&mut bx);
 
-            if !bx.sess().target.target.options.custom_unwind_resume {
-                let mut lp = bx.const_undef(self.landing_pad_type());
-                lp = bx.insert_value(lp, lp0, 0);
-                lp = bx.insert_value(lp, lp1, 1);
-                bx.resume(lp);
-            } else {
-                bx.call(bx.eh_unwind_resume(), &[lp0], helper.funclet(self));
-                bx.unreachable();
-            }
+            let mut lp = bx.const_undef(self.landing_pad_type());
+            lp = bx.insert_value(lp, lp0, 0);
+            lp = bx.insert_value(lp, lp1, 1);
+            bx.resume(lp);
         }
     }
 
@@ -415,11 +410,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             AssertKind::BoundsCheck { ref len, ref index } => {
                 let len = self.codegen_operand(&mut bx, len).immediate();
                 let index = self.codegen_operand(&mut bx, index).immediate();
-                (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len])
+                // It's `fn panic_bounds_check(index: usize, len: usize)`,
+                // and `#[track_caller]` adds an implicit third argument.
+                (lang_items::PanicBoundsCheckFnLangItem, vec![index, len, location])
             }
             _ => {
                 let msg_str = Symbol::intern(msg.description());
                 let msg = bx.const_str(msg_str);
+                // It's `pub fn panic(expr: &str)`, with the wide reference being passed
+                // as two arguments, and `#[track_caller]` adds an implicit third argument.
                 (lang_items::PanicFnLangItem, vec![msg.0, msg.1, location])
             }
         };
@@ -445,38 +444,38 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
         cleanup: Option<mir::BasicBlock>,
     ) -> bool {
-        // Emit a panic or a no-op for `panic_if_uninhabited`.
+        // Emit a panic or a no-op for `assert_*` intrinsics.
         // These are intrinsics that compile to panics so that we can get a message
         // which mentions the offending type, even from a const context.
         #[derive(Debug, PartialEq)]
-        enum PanicIntrinsic {
-            IfUninhabited,
-            IfZeroInvalid,
-            IfAnyInvalid,
+        enum AssertIntrinsic {
+            Inhabited,
+            ZeroValid,
+            UninitValid,
         };
         let panic_intrinsic = intrinsic.and_then(|i| match i {
             // FIXME: Move to symbols instead of strings.
-            "panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited),
-            "panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid),
-            "panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid),
+            "assert_inhabited" => Some(AssertIntrinsic::Inhabited),
+            "assert_zero_valid" => Some(AssertIntrinsic::ZeroValid),
+            "assert_uninit_valid" => Some(AssertIntrinsic::UninitValid),
             _ => None,
         });
         if let Some(intrinsic) = panic_intrinsic {
-            use PanicIntrinsic::*;
+            use AssertIntrinsic::*;
             let ty = instance.unwrap().substs.type_at(0);
             let layout = bx.layout_of(ty);
             let do_panic = match intrinsic {
-                IfUninhabited => layout.abi.is_uninhabited(),
+                Inhabited => layout.abi.is_uninhabited(),
                 // We unwrap as the error type is `!`.
-                IfZeroInvalid => !layout.might_permit_raw_init(bx, /*zero:*/ true).unwrap(),
+                ZeroValid => !layout.might_permit_raw_init(bx, /*zero:*/ true).unwrap(),
                 // We unwrap as the error type is `!`.
-                IfAnyInvalid => !layout.might_permit_raw_init(bx, /*zero:*/ false).unwrap(),
+                UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false).unwrap(),
             };
             if do_panic {
                 let msg_str = if layout.abi.is_uninhabited() {
                     // Use this error even for the other intrinsics as it is more precise.
                     format!("attempted to instantiate uninhabited type `{}`", ty)
-                } else if intrinsic == IfZeroInvalid {
+                } else if intrinsic == ZeroValid {
                     format!("attempted to zero-initialize type `{}`, which is invalid", ty)
                 } else {
                     format!("attempted to leave type `{}` uninitialized, which is invalid", ty)
diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs
index 2dc1405f4e4..cbe5f511152 100644
--- a/src/librustc_codegen_ssa/mir/debuginfo.rs
+++ b/src/librustc_codegen_ssa/mir/debuginfo.rs
@@ -1,10 +1,10 @@
 use crate::traits::*;
 use rustc::mir;
-use rustc::session::config::DebugInfo;
 use rustc::ty;
 use rustc::ty::layout::{LayoutOf, Size};
 use rustc_hir::def_id::CrateNum;
 use rustc_index::vec::IndexVec;
+use rustc_session::config::DebugInfo;
 
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index 5535841156a..7acae300a2f 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -3,12 +3,12 @@ use super::CodegenObject;
 use crate::ModuleCodegen;
 
 use rustc::middle::cstore::EncodedMetadata;
-use rustc::session::{config, Session};
 use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout};
 use rustc::ty::Ty;
 use rustc::ty::TyCtxt;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_session::{config, Session};
 use rustc_span::symbol::Symbol;
 
 use std::sync::Arc;
diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs
index 691b94c2f9d..6863b474cb6 100644
--- a/src/librustc_codegen_ssa/traits/misc.rs
+++ b/src/librustc_codegen_ssa/traits/misc.rs
@@ -1,8 +1,8 @@
 use super::BackendTypes;
 use rustc::mir::mono::CodegenUnit;
-use rustc::session::Session;
 use rustc::ty::{self, Instance, Ty};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_session::Session;
 use std::cell::RefCell;
 use std::sync::Arc;
 
@@ -14,7 +14,6 @@ pub trait MiscMethods<'tcx>: BackendTypes {
     fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function;
     fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value;
     fn eh_personality(&self) -> Self::Value;
-    fn eh_unwind_resume(&self) -> Self::Value;
     fn sess(&self) -> &Session;
     fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>;
     fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml
index b5533a8307c..7ab59029bc8 100644
--- a/src/librustc_codegen_utils/Cargo.toml
+++ b/src/librustc_codegen_utils/Cargo.toml
@@ -21,3 +21,4 @@ rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_metadata = { path = "../librustc_metadata" }
+rustc_session = { path = "../librustc_session" }
diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs
index 96166e04c2e..561692e7066 100644
--- a/src/librustc_codegen_utils/codegen_backend.rs
+++ b/src/librustc_codegen_utils/codegen_backend.rs
@@ -10,11 +10,11 @@ use std::any::Any;
 
 use rustc::dep_graph::DepGraph;
 use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc::session::config::{OutputFilenames, PrintRequest};
-use rustc::session::Session;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc::util::common::ErrorReported;
+use rustc_session::config::{OutputFilenames, PrintRequest};
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
 pub use rustc_data_structures::sync::MetadataRef;
diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs
index 524fb0a59c2..1f53eec514b 100644
--- a/src/librustc_codegen_utils/link.rs
+++ b/src/librustc_codegen_utils/link.rs
@@ -1,6 +1,6 @@
-use rustc::session::config::{self, Input, OutputFilenames, OutputType};
-use rustc::session::Session;
 use rustc_ast::{ast, attr};
+use rustc_session::config::{self, Input, OutputFilenames, OutputType};
+use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use std::path::{Path, PathBuf};
@@ -167,7 +167,9 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: config::CrateType)
             if !sess.target.target.options.dynamic_linking {
                 return true;
             }
-            if sess.crt_static() && !sess.target.target.options.crt_static_allows_dylibs {
+            if sess.crt_static(Some(crate_type))
+                && !sess.target.target.options.crt_static_allows_dylibs
+            {
                 return true;
             }
         }
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index cfde09fad62..eb3fe49a5e9 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -89,12 +89,12 @@
 
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::mir::mono::{InstantiationMode, MonoItem};
-use rustc::session::config::SymbolManglingVersion;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Instance, TyCtxt};
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_hir::Node;
+use rustc_session::config::SymbolManglingVersion;
 
 use rustc_span::symbol::Symbol;
 
diff --git a/src/librustc_data_structures/box_region.rs b/src/librustc_data_structures/box_region.rs
index dbc54291f40..edeb4f83c7d 100644
--- a/src/librustc_data_structures/box_region.rs
+++ b/src/librustc_data_structures/box_region.rs
@@ -25,22 +25,6 @@ pub struct PinnedGenerator<I, A, R> {
 }
 
 impl<I, A, R> PinnedGenerator<I, A, R> {
-    #[cfg(bootstrap)]
-    pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
-        generator: T,
-    ) -> (I, Self) {
-        let mut result = PinnedGenerator { generator: Box::pin(generator) };
-
-        // Run it to the first yield to set it up
-        let init = match Pin::new(&mut result.generator).resume() {
-            GeneratorState::Yielded(YieldType::Initial(y)) => y,
-            _ => panic!(),
-        };
-
-        (init, result)
-    }
-
-    #[cfg(not(bootstrap))]
     pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
         generator: T,
     ) -> (I, Self) {
@@ -55,19 +39,6 @@ impl<I, A, R> PinnedGenerator<I, A, R> {
         (init, result)
     }
 
-    #[cfg(bootstrap)]
-    pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
-        BOX_REGION_ARG.with(|i| {
-            i.set(Action::Access(AccessAction(closure)));
-        });
-
-        // Call the generator, which in turn will call the closure in BOX_REGION_ARG
-        if let GeneratorState::Complete(_) = Pin::new(&mut self.generator).resume() {
-            panic!()
-        }
-    }
-
-    #[cfg(not(bootstrap))]
     pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
         BOX_REGION_ARG.with(|i| {
             i.set(Action::Access(AccessAction(closure)));
@@ -79,16 +50,6 @@ impl<I, A, R> PinnedGenerator<I, A, R> {
         }
     }
 
-    #[cfg(bootstrap)]
-    pub fn complete(&mut self) -> R {
-        // Tell the generator we want it to complete, consuming it and yielding a result
-        BOX_REGION_ARG.with(|i| i.set(Action::Complete));
-
-        let result = Pin::new(&mut self.generator).resume();
-        if let GeneratorState::Complete(r) = result { r } else { panic!() }
-    }
-
-    #[cfg(not(bootstrap))]
     pub fn complete(&mut self) -> R {
         // Tell the generator we want it to complete, consuming it and yielding a result
         BOX_REGION_ARG.with(|i| i.set(Action::Complete));
diff --git a/src/librustc_data_structures/frozen.rs b/src/librustc_data_structures/frozen.rs
new file mode 100644
index 00000000000..2daf5b04141
--- /dev/null
+++ b/src/librustc_data_structures/frozen.rs
@@ -0,0 +1,63 @@
+//! An immutable, owned value (except for interior mutability).
+//!
+//! The purpose of `Frozen` is to make a value immutable for the sake of defensive programming. For example,
+//! suppose we have the following:
+//!
+//! ```rust
+//! struct Bar { /* some data */ }
+//!
+//! struct Foo {
+//!     /// Some computed data that should never change after construction.
+//!     pub computed: Bar,
+//!
+//!     /* some other fields */
+//! }
+//!
+//! impl Bar {
+//!     /// Mutate the `Bar`.
+//!     pub fn mutate(&mut self) { }
+//! }
+//! ```
+//!
+//! Now suppose we want to pass around a mutable `Foo` instance but, we want to make sure that
+//! `computed` does not change accidentally (e.g. somebody might accidentally call
+//! `foo.computed.mutate()`). This is what `Frozen` is for. We can do the following:
+//!
+//! ```rust
+//! use rustc_data_structures::frozen::Frozen;
+//!
+//! struct Foo {
+//!     /// Some computed data that should never change after construction.
+//!     pub computed: Frozen<Bar>,
+//!
+//!     /* some other fields */
+//! }
+//! ```
+//!
+//! `Frozen` impls `Deref`, so we can ergonomically call methods on `Bar`, but it doesn't `impl
+//! DerefMut`.  Now calling `foo.compute.mutate()` will result in a compile-time error stating that
+//! `mutate` requires a mutable reference but we don't have one.
+//!
+//! # Caveats
+//!
+//! - `Frozen` doesn't try to defend against interior mutability (e.g. `Frozen<RefCell<Bar>>`).
+//! - `Frozen` doesn't pin it's contents (e.g. one could still do `foo.computed =
+//!    Frozen::freeze(new_bar)`).
+
+/// An owned immutable value.
+#[derive(Debug)]
+pub struct Frozen<T>(T);
+
+impl<T> Frozen<T> {
+    pub fn freeze(val: T) -> Self {
+        Frozen(val)
+    }
+}
+
+impl<T> std::ops::Deref for Frozen<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
diff --git a/src/librustc_data_structures/graph/scc/mod.rs b/src/librustc_data_structures/graph/scc/mod.rs
index 70fc2d7dad9..7ecf3e3cb8d 100644
--- a/src/librustc_data_structures/graph/scc/mod.rs
+++ b/src/librustc_data_structures/graph/scc/mod.rs
@@ -97,7 +97,7 @@ impl<N: Idx, S: Idx> GraphSuccessors<'graph> for Sccs<N, S> {
 }
 
 impl<N: Idx, S: Idx> WithSuccessors for Sccs<N, S> {
-    fn successors<'graph>(&'graph self, node: S) -> <Self as GraphSuccessors<'graph>>::Iter {
+    fn successors(&self, node: S) -> <Self as GraphSuccessors<'_>>::Iter {
         self.successors(node).iter().cloned()
     }
 }
diff --git a/src/librustc_data_structures/graph/vec_graph/mod.rs b/src/librustc_data_structures/graph/vec_graph/mod.rs
index 22c50afe6d0..064467174ca 100644
--- a/src/librustc_data_structures/graph/vec_graph/mod.rs
+++ b/src/librustc_data_structures/graph/vec_graph/mod.rs
@@ -101,7 +101,7 @@ impl<N: Idx> GraphSuccessors<'graph> for VecGraph<N> {
 }
 
 impl<N: Idx> WithSuccessors for VecGraph<N> {
-    fn successors<'graph>(&'graph self, node: N) -> <Self as GraphSuccessors<'graph>>::Iter {
+    fn successors(&self, node: N) -> <Self as GraphSuccessors<'_>>::Iter {
         self.successors(node).iter().cloned()
     }
 }
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 13792a0c890..f9f8ff5303e 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -94,6 +94,7 @@ pub mod profiling;
 pub mod vec_linked_list;
 pub mod work_queue;
 pub use atomic_ref::AtomicRef;
+pub mod frozen;
 
 pub struct OnDrop<F: Fn()>(pub F);
 
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 26f1741153c..3e644958231 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -33,6 +33,7 @@ rustc_interface = { path = "../librustc_interface" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
+rustc_session = { path = "../librustc_session" }
 
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
diff --git a/src/librustc_driver/README.md b/src/librustc_driver/README.md
index c4d73953e9b..37dc7f6ba5f 100644
--- a/src/librustc_driver/README.md
+++ b/src/librustc_driver/README.md
@@ -5,6 +5,6 @@ not contain any of the "main logic" of the compiler (though it does
 have some code related to pretty printing or other minor compiler
 options).
 
-For more information about how the driver works, see the [rustc guide].
+For more information about how the driver works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/rustc-driver.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustc-driver.html
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index e6c98ad27e8..34f0c182499 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -18,12 +18,7 @@ extern crate lazy_static;
 
 pub extern crate rustc_plugin_impl as plugin;
 
-use rustc::lint::{Lint, LintId};
 use rustc::middle::cstore::MetadataLoader;
-use rustc::session::config::nightly_options;
-use rustc::session::config::{ErrorOutputType, Input, OutputType, PrintRequest};
-use rustc::session::{config, DiagnosticOutput, Session};
-use rustc::session::{early_error, early_warn};
 use rustc::ty::TyCtxt;
 use rustc::util::common::ErrorReported;
 use rustc_codegen_ssa::CodegenResults;
@@ -43,6 +38,11 @@ use rustc_metadata::locator;
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
 use rustc_serialize::json::{self, ToJson};
+use rustc_session::config::nightly_options;
+use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest};
+use rustc_session::lint::{Lint, LintId};
+use rustc_session::{config, DiagnosticOutput, Session};
+use rustc_session::{early_error, early_warn};
 
 use std::borrow::Cow;
 use std::cmp::max;
@@ -652,7 +652,7 @@ impl RustcDefaultCalls {
         odir: &Option<PathBuf>,
         ofile: &Option<PathBuf>,
     ) -> Compilation {
-        use rustc::session::config::PrintRequest::*;
+        use rustc_session::config::PrintRequest::*;
         // PrintRequest::NativeStaticLibs is special - printed during linking
         // (empty iterator returns true)
         if sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) {
@@ -1124,12 +1124,7 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
         return None;
     }
 
-    let matches = if let Some(matches) = handle_options(&args) {
-        matches
-    } else {
-        return None;
-    };
-
+    let matches = handle_options(&args)?;
     let mut result = Vec::new();
     let mut excluded_cargo_defaults = false;
     for flag in ICE_REPORT_COMPILER_FLAGS {
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index ca129ac5984..1e5cc55a828 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -1,8 +1,6 @@
 //! The various pretty-printing routines.
 
 use rustc::hir::map as hir_map;
-use rustc::session::config::{Input, PpMode, PpSourceMode};
-use rustc::session::Session;
 use rustc::ty::{self, TyCtxt};
 use rustc::util::common::ErrorReported;
 use rustc_ast::ast;
@@ -11,6 +9,8 @@ use rustc_hir as hir;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::print as pprust_hir;
 use rustc_mir::util::{write_mir_graphviz, write_mir_pretty};
+use rustc_session::config::{Input, PpMode, PpSourceMode};
+use rustc_session::Session;
 use rustc_span::FileName;
 
 use std::cell::Cell;
@@ -96,7 +96,7 @@ trait PrinterSupport: pprust::PpAnn {
     ///
     /// (Rust does not yet support upcasting from a trait object to
     /// an object for one of its super-traits.)
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn;
+    fn pp_ann(&self) -> &dyn pprust::PpAnn;
 }
 
 trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
@@ -106,13 +106,13 @@ trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
 
     /// Provides a uniform interface for re-extracting a reference to an
     /// `hir_map::Map` from a value that now owns it.
-    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>>;
+    fn hir_map(&self) -> Option<hir_map::Map<'hir>>;
 
     /// Produces the pretty-print annotation object.
     ///
     /// (Rust does not yet support upcasting from a trait object to
     /// an object for one of its super-traits.)
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn;
+    fn pp_ann(&self) -> &dyn pprust_hir::PpAnn;
 
     /// Computes an user-readable representation of a path, if possible.
     fn node_path(&self, id: hir::HirId) -> Option<String> {
@@ -132,7 +132,7 @@ impl<'hir> PrinterSupport for NoAnn<'hir> {
         self.sess
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust::PpAnn {
         self
     }
 }
@@ -142,11 +142,11 @@ impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
         self.sess
     }
 
-    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
-        self.tcx.map(|tcx| *tcx.hir())
+    fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
+        self.tcx.map(|tcx| tcx.hir())
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
         self
     }
 }
@@ -155,7 +155,7 @@ impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
 impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
     fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
         if let Some(tcx) = self.tcx {
-            pprust_hir::PpAnn::nested(*tcx.hir(), state, nested)
+            pprust_hir::PpAnn::nested(&tcx.hir(), state, nested)
         }
     }
 }
@@ -170,7 +170,7 @@ impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
         self.sess
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust::PpAnn {
         self
     }
 }
@@ -216,11 +216,11 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
         self.sess
     }
 
-    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
-        self.tcx.map(|tcx| *tcx.hir())
+    fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
+        self.tcx.map(|tcx| tcx.hir())
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
         self
     }
 }
@@ -228,7 +228,7 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
 impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
     fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
         if let Some(ref tcx) = self.tcx {
-            pprust_hir::PpAnn::nested(*tcx.hir(), state, nested)
+            pprust_hir::PpAnn::nested(&tcx.hir(), state, nested)
         }
     }
     fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
@@ -315,11 +315,11 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
         &self.tcx.sess
     }
 
-    fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> {
-        Some(&self.tcx.hir())
+    fn hir_map(&self) -> Option<hir_map::Map<'tcx>> {
+        Some(self.tcx.hir())
     }
 
-    fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
+    fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
         self
     }
 
@@ -334,7 +334,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
         if let pprust_hir::Nested::Body(id) = nested {
             self.tables.set(self.tcx.body_tables(id));
         }
-        pprust_hir::PpAnn::nested(*self.tcx.hir(), state, nested);
+        pprust_hir::PpAnn::nested(&self.tcx.hir(), state, nested);
         self.tables.set(old_tables);
     }
     fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 11d1209923f..85339ab9aa1 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -349,8 +349,10 @@ E0623: include_str!("./error_codes/E0623.md"),
 E0624: include_str!("./error_codes/E0624.md"),
 E0626: include_str!("./error_codes/E0626.md"),
 E0627: include_str!("./error_codes/E0627.md"),
+E0628: include_str!("./error_codes/E0628.md"),
 E0631: include_str!("./error_codes/E0631.md"),
 E0633: include_str!("./error_codes/E0633.md"),
+E0634: include_str!("./error_codes/E0634.md"),
 E0635: include_str!("./error_codes/E0635.md"),
 E0636: include_str!("./error_codes/E0636.md"),
 E0637: include_str!("./error_codes/E0637.md"),
@@ -380,6 +382,7 @@ E0689: include_str!("./error_codes/E0689.md"),
 E0690: include_str!("./error_codes/E0690.md"),
 E0691: include_str!("./error_codes/E0691.md"),
 E0692: include_str!("./error_codes/E0692.md"),
+E0693: include_str!("./error_codes/E0693.md"),
 E0695: include_str!("./error_codes/E0695.md"),
 E0697: include_str!("./error_codes/E0697.md"),
 E0698: include_str!("./error_codes/E0698.md"),
@@ -411,6 +414,7 @@ E0735: include_str!("./error_codes/E0735.md"),
 E0736: include_str!("./error_codes/E0736.md"),
 E0737: include_str!("./error_codes/E0737.md"),
 E0738: include_str!("./error_codes/E0738.md"),
+E0739: include_str!("./error_codes/E0739.md"),
 E0740: include_str!("./error_codes/E0740.md"),
 E0741: include_str!("./error_codes/E0741.md"),
 E0742: include_str!("./error_codes/E0742.md"),
@@ -580,21 +584,18 @@ E0748: include_str!("./error_codes/E0748.md"),
 //  E0612, // merged into E0609
 //  E0613, // Removed (merged with E0609)
     E0625, // thread-local statics cannot be accessed at compile-time
-    E0628, // generators cannot have explicit parameters
     E0629, // missing 'feature' (rustc_const_unstable)
     // rustc_const_unstable attribute must be paired with stable/unstable
     // attribute
     E0630,
     E0632, // cannot provide explicit generic arguments when `impl Trait` is
            // used in argument position
-    E0634, // type has conflicting packed representaton hints
     E0640, // infer outlives requirements
 //  E0645, // trait aliases not finished
     E0657, // `impl Trait` can only capture lifetimes bound at the fn level
     E0667, // `impl Trait` in projections
     E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
     E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
-    E0693, // incorrect `repr(align)` attribute format
 //  E0694, // an unknown tool name found in scoped attributes
     E0696, // `continue` pointing to a labeled block
 //  E0702, // replaced with a generic attribute input check
@@ -610,5 +611,4 @@ E0748: include_str!("./error_codes/E0748.md"),
     E0722, // Malformed `#[optimize]` attribute
     E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
     E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
-    E0739, // invalid track_caller application/syntax
 }
diff --git a/src/librustc_error_codes/error_codes/E0117.md b/src/librustc_error_codes/error_codes/E0117.md
index 7fa211d4a27..0544667ccca 100644
--- a/src/librustc_error_codes/error_codes/E0117.md
+++ b/src/librustc_error_codes/error_codes/E0117.md
@@ -1,4 +1,4 @@
-The `Drop` trait was implemented on a non-struct type.
+Only traits defined in the current crate can be implemented for arbitrary types.
 
 Erroneous code example:
 
diff --git a/src/librustc_error_codes/error_codes/E0308.md b/src/librustc_error_codes/error_codes/E0308.md
index a907ca27297..7d87d54194e 100644
--- a/src/librustc_error_codes/error_codes/E0308.md
+++ b/src/librustc_error_codes/error_codes/E0308.md
@@ -1,10 +1,6 @@
-This error occurs when the compiler was unable to infer the concrete type of a
-variable. It can occur for several cases, the most common of which is a
-mismatch in the expected type that the compiler inferred for a variable's
-initializing expression, and the actual type explicitly assigned to the
-variable.
+Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = "I am not a number!";
@@ -15,3 +11,9 @@ let x: i32 = "I am not a number!";
 //      |
 //    type `i32` assigned to variable `x`
 ```
+
+This error occurs when the compiler was unable to infer the concrete type of a
+variable. It can occur for several cases, the most common of which is a
+mismatch in the expected type that the compiler inferred for a variable's
+initializing expression, and the actual type explicitly assigned to the
+variable.
diff --git a/src/librustc_error_codes/error_codes/E0412.md b/src/librustc_error_codes/error_codes/E0412.md
index 60a09610d86..d9ebc852bba 100644
--- a/src/librustc_error_codes/error_codes/E0412.md
+++ b/src/librustc_error_codes/error_codes/E0412.md
@@ -1,4 +1,4 @@
-The type name used is not in scope.
+A used type name is not in scope.
 
 Erroneous code examples:
 
diff --git a/src/librustc_error_codes/error_codes/E0422.md b/src/librustc_error_codes/error_codes/E0422.md
index a91ea6a9e22..828a52e7341 100644
--- a/src/librustc_error_codes/error_codes/E0422.md
+++ b/src/librustc_error_codes/error_codes/E0422.md
@@ -1,4 +1,5 @@
-You are trying to use an identifier that is either undefined or not a struct.
+An identifier that is neither defined nor a struct was used.
+
 Erroneous code example:
 
 ```compile_fail,E0422
diff --git a/src/librustc_error_codes/error_codes/E0423.md b/src/librustc_error_codes/error_codes/E0423.md
index 6a7c31f5e0d..a98ada17a46 100644
--- a/src/librustc_error_codes/error_codes/E0423.md
+++ b/src/librustc_error_codes/error_codes/E0423.md
@@ -1,8 +1,7 @@
 An identifier was used like a function name or a value was expected and the
 identifier exists but it belongs to a different namespace.
 
-For (an erroneous) example, here a `struct` variant name were used as a
-function:
+Erroneous code example:
 
 ```compile_fail,E0423
 struct Foo { a: bool };
diff --git a/src/librustc_error_codes/error_codes/E0434.md b/src/librustc_error_codes/error_codes/E0434.md
index e093f0796da..8fd60412baf 100644
--- a/src/librustc_error_codes/error_codes/E0434.md
+++ b/src/librustc_error_codes/error_codes/E0434.md
@@ -1,6 +1,4 @@
-This error indicates that a variable usage inside an inner function is invalid
-because the variable comes from a dynamic environment. Inner functions do not
-have access to their containing environment.
+A variable used inside an inner function comes from a dynamic environment.
 
 Erroneous code example:
 
@@ -14,8 +12,8 @@ fn foo() {
 }
 ```
 
-Functions do not capture local variables. To fix this error, you can replace the
-function with a closure:
+Inner functions do not have access to their containing environment. To fix this
+error, you can replace the function with a closure:
 
 ```
 fn foo() {
@@ -26,7 +24,7 @@ fn foo() {
 }
 ```
 
-or replace the captured variable with a constant or a static item:
+Or replace the captured variable with a constant or a static item:
 
 ```
 fn foo() {
diff --git a/src/librustc_error_codes/error_codes/E0628.md b/src/librustc_error_codes/error_codes/E0628.md
new file mode 100644
index 00000000000..40040c9a56a
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0628.md
@@ -0,0 +1,30 @@
+More than one parameter was used for a generator.
+
+Erroneous code example:
+
+```compile_fail,E0628
+#![feature(generators, generator_trait)]
+
+fn main() {
+    let generator = |a: i32, b: i32| {
+        // error: too many parameters for a generator
+        // Allowed only 0 or 1 parameter
+        yield a;
+    };
+}
+```
+
+At present, it is not permitted to pass more than one explicit
+parameter for a generator.This can be fixed by using
+at most 1 parameter for the generator. For example, we might resolve
+the previous example by passing only one parameter.
+
+```
+#![feature(generators, generator_trait)]
+
+fn main() {
+    let generator = |a: i32| {
+        yield a;
+    };
+}
+```
diff --git a/src/librustc_error_codes/error_codes/E0634.md b/src/librustc_error_codes/error_codes/E0634.md
new file mode 100644
index 00000000000..0c4ed2596e2
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0634.md
@@ -0,0 +1,20 @@
+A type has conflicting `packed` representation hints.
+
+Erroneous code examples:
+
+```compile_fail,E0634
+#[repr(packed, packed(2))] // error!
+struct Company(i32);
+
+#[repr(packed(2))] // error!
+#[repr(packed)]
+struct Company(i32);
+```
+
+You cannot use conflicting `packed` hints on a same type. If you want to pack a
+type to a given size, you should provide a size to packed:
+
+```
+#[repr(packed)] // ok!
+struct Company(i32);
+```
diff --git a/src/librustc_error_codes/error_codes/E0693.md b/src/librustc_error_codes/error_codes/E0693.md
new file mode 100644
index 00000000000..43e9d17979e
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0693.md
@@ -0,0 +1,19 @@
+`align` representation hint was incorrectly declared.
+
+Erroneous code examples:
+
+```compile_fail,E0693
+#[repr(align=8)] // error!
+struct Align8(i8);
+
+#[repr(align="8")] // error!
+struct Align8(i8);
+```
+
+This is a syntax error at the level of attribute declarations. The proper
+syntax for `align` representation hint is the following:
+
+```
+#[repr(align(8))] // ok!
+struct Align8(i8);
+```
diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md
new file mode 100644
index 00000000000..707751066ed
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0739.md
@@ -0,0 +1,13 @@
+`#[track_caller]` can not be applied on struct.
+
+Erroneous code example:
+
+```compile_fail,E0739
+#![feature(track_caller)]
+#[track_caller]
+struct Bar {
+    a: u8,
+}
+```
+
+[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 03f83e61636..26f1fa267f9 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -5,7 +5,7 @@
 //! There are various `Emitter` implementations that generate different output formats such as
 //! JSON and human readable output.
 //!
-//! The output types are defined in `librustc::session::config::ErrorOutputType`.
+//! The output types are defined in `rustc_session::config::ErrorOutputType`.
 
 use Destination::*;
 
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index f15e626c278..74c304c96b9 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -1,4 +1,5 @@
 use crate::expand::{self, AstFragment, Invocation};
+use crate::module::DirectoryOwnership;
 
 use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind};
 use rustc_ast::mut_visit::{self, MutVisitor};
@@ -10,7 +11,7 @@ use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS};
+use rustc_parse::{self, parser, MACRO_ARGUMENTS};
 use rustc_session::parse::ParseSess;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
@@ -258,8 +259,17 @@ impl Annotatable {
     }
 }
 
-// `meta_item` is the annotation, and `item` is the item being modified.
-// FIXME Decorators should follow the same pattern too.
+/// Result of an expansion that may need to be retried.
+/// Consider using this for non-`MultiItemModifier` expanders as well.
+pub enum ExpandResult<T, U> {
+    /// Expansion produced a result (possibly dummy).
+    Ready(T),
+    /// Expansion could not produce a result and needs to be retried.
+    /// The string is an explanation that will be printed if we are stuck in an infinite retry loop.
+    Retry(U, String),
+}
+
+// `meta_item` is the attribute, and `item` is the item being modified.
 pub trait MultiItemModifier {
     fn expand(
         &self,
@@ -267,13 +277,12 @@ pub trait MultiItemModifier {
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable>;
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable>;
 }
 
-impl<F, T> MultiItemModifier for F
+impl<F> MultiItemModifier for F
 where
-    F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> T,
-    T: Into<Vec<Annotatable>>,
+    F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> Vec<Annotatable>,
 {
     fn expand(
         &self,
@@ -281,14 +290,8 @@ where
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable> {
-        (*self)(ecx, span, meta_item, item).into()
-    }
-}
-
-impl Into<Vec<Annotatable>> for Annotatable {
-    fn into(self) -> Vec<Annotatable> {
-        vec![self]
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
+        ExpandResult::Ready(self(ecx, span, meta_item, item))
     }
 }
 
@@ -372,7 +375,7 @@ where
                 mut_visit::noop_visit_tt(tt, self)
             }
 
-            fn visit_mac(&mut self, mac: &mut ast::Mac) {
+            fn visit_mac(&mut self, mac: &mut ast::MacCall) {
                 mut_visit::noop_visit_mac(mac, self)
             }
         }
@@ -895,6 +898,7 @@ pub trait Resolver {
 
     fn has_derive_copy(&self, expn_id: ExpnId) -> bool;
     fn add_derive_copy(&mut self, expn_id: ExpnId);
+    fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
 }
 
 #[derive(Clone)]
@@ -922,6 +926,8 @@ pub struct ExtCtxt<'a> {
     pub resolver: &'a mut dyn Resolver,
     pub current_expansion: ExpansionData,
     pub expansions: FxHashMap<Span, Vec<String>>,
+    /// Called directly after having parsed an external `mod foo;` in expansion.
+    pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
 }
 
 impl<'a> ExtCtxt<'a> {
@@ -929,12 +935,14 @@ impl<'a> ExtCtxt<'a> {
         parse_sess: &'a ParseSess,
         ecfg: expand::ExpansionConfig<'a>,
         resolver: &'a mut dyn Resolver,
+        extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
     ) -> ExtCtxt<'a> {
         ExtCtxt {
             parse_sess,
             ecfg,
-            root_path: PathBuf::new(),
             resolver,
+            extern_mod_loaded,
+            root_path: PathBuf::new(),
             current_expansion: ExpansionData {
                 id: ExpnId::root(),
                 depth: 0,
diff --git a/src/librustc_parse/config.rs b/src/librustc_expand/config.rs
index f42091e7c29..72c09f35dfa 100644
--- a/src/librustc_parse/config.rs
+++ b/src/librustc_expand/config.rs
@@ -1,14 +1,5 @@
-//! Process the potential `cfg` attributes on a module.
-//! Also determine if the module should be included in this configuration.
-//!
-//! This module properly belongs in rustc_expand, but for now it's tied into
-//! parsing, so we leave it here to avoid complicated out-of-line dependencies.
-//!
-//! A principled solution to this wrong location would be to implement [#64197].
-//!
-//! [#64197]: https://github.com/rust-lang/rust/issues/64197
-
-use crate::{parse_in, validate_attr};
+//! Conditional compilation stripping.
+
 use rustc_ast::ast::{self, AttrItem, Attribute, MetaItem};
 use rustc_ast::attr::HasAttrs;
 use rustc_ast::mut_visit::*;
@@ -21,6 +12,7 @@ use rustc_feature::{Feature, Features, State as FeatureState};
 use rustc_feature::{
     ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
 };
+use rustc_parse::{parse_in, validate_attr};
 use rustc_session::parse::{feature_err, ParseSess};
 use rustc_span::edition::{Edition, ALL_EDITIONS};
 use rustc_span::symbol::{sym, Symbol};
@@ -519,7 +511,7 @@ impl<'a> MutVisitor for StripUnconfigured<'a> {
         noop_flat_map_assoc_item(configure!(self, item), self)
     }
 
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
         // Don't configure interpolated AST (cf. issue #34171).
         // Interpolated AST will get configured once the surrounding tokens are parsed.
     }
@@ -538,12 +530,3 @@ impl<'a> MutVisitor for StripUnconfigured<'a> {
 fn is_cfg(attr: &Attribute) -> bool {
     attr.check_name(sym::cfg)
 }
-
-/// Process the potential `cfg` attributes on a module.
-/// Also determine if the module should be included in this configuration.
-pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec<Attribute>) -> bool {
-    // Don't perform gated feature checking.
-    let mut strip_unconfigured = StripUnconfigured { sess, features: None };
-    strip_unconfigured.process_cfg_attrs(attrs);
-    !cfg_mods || strip_unconfigured.in_cfg(&attrs)
-}
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index effa89e8bfb..b6cc192cc33 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -1,7 +1,9 @@
 use crate::base::*;
 use crate::config::StripUnconfigured;
+use crate::configure;
 use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext};
 use crate::mbe::macro_rules::annotate_err_with_kind;
+use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership};
 use crate::placeholders::{placeholder, PlaceholderExpander};
 use crate::proc_macro::collect_derives;
 
@@ -17,10 +19,8 @@ use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
 use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::Features;
-use rustc_parse::configure;
 use rustc_parse::parser::Parser;
 use rustc_parse::validate_attr;
-use rustc_parse::DirectoryOwnership;
 use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::{feature_err, ParseSess};
@@ -271,7 +271,7 @@ pub struct Invocation {
 
 pub enum InvocationKind {
     Bang {
-        mac: ast::Mac,
+        mac: ast::MacCall,
         span: Span,
     },
     Attr {
@@ -408,7 +408,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         let mut undetermined_invocations = Vec::new();
         let (mut progress, mut force) = (false, !self.monotonic);
         loop {
-            let invoc = if let Some(invoc) = invocations.pop() {
+            let (invoc, res) = if let Some(invoc) = invocations.pop() {
                 invoc
             } else {
                 self.resolve_imports();
@@ -420,30 +420,51 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 continue;
             };
 
-            let eager_expansion_root =
-                if self.monotonic { invoc.expansion_data.id } else { orig_expansion_data.id };
-            let res = match self.cx.resolver.resolve_macro_invocation(
-                &invoc,
-                eager_expansion_root,
-                force,
-            ) {
-                Ok(res) => res,
-                Err(Indeterminate) => {
-                    undetermined_invocations.push(invoc);
-                    continue;
+            let res = match res {
+                Some(res) => res,
+                None => {
+                    let eager_expansion_root = if self.monotonic {
+                        invoc.expansion_data.id
+                    } else {
+                        orig_expansion_data.id
+                    };
+                    match self.cx.resolver.resolve_macro_invocation(
+                        &invoc,
+                        eager_expansion_root,
+                        force,
+                    ) {
+                        Ok(res) => res,
+                        Err(Indeterminate) => {
+                            // Cannot resolve, will retry this invocation later.
+                            undetermined_invocations.push((invoc, None));
+                            continue;
+                        }
+                    }
                 }
             };
 
-            progress = true;
             let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
             self.cx.current_expansion = invoc.expansion_data.clone();
 
             // FIXME(jseyfried): Refactor out the following logic
             let (expanded_fragment, new_invocations) = match res {
-                InvocationRes::Single(ext) => {
-                    let fragment = self.expand_invoc(invoc, &ext.kind);
-                    self.collect_invocations(fragment, &[])
-                }
+                InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) {
+                    ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]),
+                    ExpandResult::Retry(invoc, explanation) => {
+                        if force {
+                            // We are stuck, stop retrying and produce a dummy fragment.
+                            let span = invoc.span();
+                            self.cx.span_err(span, &explanation);
+                            let fragment = invoc.fragment_kind.dummy(span);
+                            self.collect_invocations(fragment, &[])
+                        } else {
+                            // Cannot expand, will retry this invocation later.
+                            undetermined_invocations
+                                .push((invoc, Some(InvocationRes::Single(ext))));
+                            continue;
+                        }
+                    }
+                },
                 InvocationRes::DeriveContainer(_exts) => {
                     // FIXME: Consider using the derive resolutions (`_exts`) immediately,
                     // instead of enqueuing the derives to be resolved again later.
@@ -463,14 +484,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     for path in derives {
                         let expn_id = ExpnId::fresh(None);
                         derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id));
-                        invocations.push(Invocation {
-                            kind: InvocationKind::Derive { path, item: item.clone() },
-                            fragment_kind: invoc.fragment_kind,
-                            expansion_data: ExpansionData {
-                                id: expn_id,
-                                ..invoc.expansion_data.clone()
+                        invocations.push((
+                            Invocation {
+                                kind: InvocationKind::Derive { path, item: item.clone() },
+                                fragment_kind: invoc.fragment_kind,
+                                expansion_data: ExpansionData {
+                                    id: expn_id,
+                                    ..invoc.expansion_data.clone()
+                                },
                             },
-                        });
+                            None,
+                        ));
                     }
                     let fragment =
                         invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item));
@@ -478,6 +502,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
             };
 
+            progress = true;
             if expanded_fragments.len() < depth {
                 expanded_fragments.push(Vec::new());
             }
@@ -535,7 +560,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         &mut self,
         mut fragment: AstFragment,
         extra_placeholders: &[NodeId],
-    ) -> (AstFragment, Vec<Invocation>) {
+    ) -> (AstFragment, Vec<(Invocation, Option<InvocationRes>)>) {
         // Resolve `$crate`s in the fragment for pretty-printing.
         self.cx.resolver.resolve_dollar_crates();
 
@@ -625,7 +650,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
     /// A macro's expansion does not fit in this fragment kind.
     /// For example, a non-type macro in a type position.
-    fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::Mac, span: Span) {
+    fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
         let msg = format!(
             "non-{kind} macro in {kind} position: {path}",
             kind = kind.name(),
@@ -635,13 +660,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         self.cx.trace_macros_diag();
     }
 
-    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment {
+    fn expand_invoc(
+        &mut self,
+        invoc: Invocation,
+        ext: &SyntaxExtensionKind,
+    ) -> ExpandResult<AstFragment, Invocation> {
         if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
             self.error_recursion_limit_reached();
         }
 
         let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
-        match invoc.kind {
+        ExpandResult::Ready(match invoc.kind {
             InvocationKind::Bang { mac, .. } => match ext {
                 SyntaxExtensionKind::Bang(expander) => {
                     self.gate_proc_macro_expansion_kind(span, fragment_kind);
@@ -663,7 +692,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
                 _ => unreachable!(),
             },
-            InvocationKind::Attr { attr, mut item, .. } => match ext {
+            InvocationKind::Attr { attr, mut item, derives, after_derive } => match ext {
                 SyntaxExtensionKind::Attr(expander) => {
                     self.gate_proc_macro_input(&item);
                     self.gate_proc_macro_attr_item(span, &item);
@@ -679,8 +708,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 SyntaxExtensionKind::LegacyAttr(expander) => {
                     match validate_attr::parse_meta(self.cx.parse_sess, &attr) {
                         Ok(meta) => {
-                            let item = expander.expand(self.cx, span, &meta, item);
-                            fragment_kind.expect_from_annotatables(item)
+                            let items = match expander.expand(self.cx, span, &meta, item) {
+                                ExpandResult::Ready(items) => items,
+                                ExpandResult::Retry(item, explanation) => {
+                                    // Reassemble the original invocation for retrying.
+                                    return ExpandResult::Retry(
+                                        Invocation {
+                                            kind: InvocationKind::Attr {
+                                                attr,
+                                                item,
+                                                derives,
+                                                after_derive,
+                                            },
+                                            ..invoc
+                                        },
+                                        explanation,
+                                    );
+                                }
+                            };
+                            fragment_kind.expect_from_annotatables(items)
                         }
                         Err(mut err) => {
                             err.emit();
@@ -702,19 +748,31 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 SyntaxExtensionKind::Derive(expander)
                 | SyntaxExtensionKind::LegacyDerive(expander) => {
                     if !item.derive_allowed() {
-                        return fragment_kind.dummy(span);
+                        return ExpandResult::Ready(fragment_kind.dummy(span));
                     }
                     if let SyntaxExtensionKind::Derive(..) = ext {
                         self.gate_proc_macro_input(&item);
                     }
                     let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
-                    let items = expander.expand(self.cx, span, &meta, item);
+                    let items = match expander.expand(self.cx, span, &meta, item) {
+                        ExpandResult::Ready(items) => items,
+                        ExpandResult::Retry(item, explanation) => {
+                            // Reassemble the original invocation for retrying.
+                            return ExpandResult::Retry(
+                                Invocation {
+                                    kind: InvocationKind::Derive { path: meta.path, item },
+                                    ..invoc
+                                },
+                                explanation,
+                            );
+                        }
+                    };
                     fragment_kind.expect_from_annotatables(items)
                 }
                 _ => unreachable!(),
             },
             InvocationKind::DeriveContainer { .. } => unreachable!(),
-        }
+        })
     }
 
     fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
@@ -768,7 +826,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 visit::walk_item(self, item);
             }
 
-            fn visit_mac(&mut self, _: &'ast ast::Mac) {}
+            fn visit_mac(&mut self, _: &'ast ast::MacCall) {}
         }
 
         if !self.cx.ecfg.proc_macro_hygiene() {
@@ -933,7 +991,7 @@ pub fn ensure_complete_parse<'a>(
 struct InvocationCollector<'a, 'b> {
     cx: &'a mut ExtCtxt<'b>,
     cfg: StripUnconfigured<'a>,
-    invocations: Vec<Invocation>,
+    invocations: Vec<(Invocation, Option<InvocationRes>)>,
     monotonic: bool,
 }
 
@@ -955,19 +1013,27 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         };
         let expn_id = ExpnId::fresh(expn_data);
         let vis = kind.placeholder_visibility();
-        self.invocations.push(Invocation {
-            kind,
-            fragment_kind,
-            expansion_data: ExpansionData {
-                id: expn_id,
-                depth: self.cx.current_expansion.depth + 1,
-                ..self.cx.current_expansion.clone()
+        self.invocations.push((
+            Invocation {
+                kind,
+                fragment_kind,
+                expansion_data: ExpansionData {
+                    id: expn_id,
+                    depth: self.cx.current_expansion.depth + 1,
+                    ..self.cx.current_expansion.clone()
+                },
             },
-        });
+            None,
+        ));
         placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
     }
 
-    fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
+    fn collect_bang(
+        &mut self,
+        mac: ast::MacCall,
+        span: Span,
+        kind: AstFragmentKind,
+    ) -> AstFragment {
         self.collect(kind, InvocationKind::Bang { mac, span })
     }
 
@@ -1110,7 +1176,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                     .into_inner();
             }
 
-            if let ast::ExprKind::Mac(mac) = expr.kind {
+            if let ast::ExprKind::MacCall(mac) = expr.kind {
                 self.check_attributes(&expr.attrs);
                 self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
             } else {
@@ -1257,7 +1323,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                     .map(|expr| expr.into_inner());
             }
 
-            if let ast::ExprKind::Mac(mac) = expr.kind {
+            if let ast::ExprKind::MacCall(mac) = expr.kind {
                 self.check_attributes(&expr.attrs);
                 self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr)
                     .make_opt_expr()
@@ -1274,12 +1340,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
     fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
         self.cfg.configure_pat(pat);
         match pat.kind {
-            PatKind::Mac(_) => {}
+            PatKind::MacCall(_) => {}
             _ => return noop_visit_pat(pat, self),
         }
 
         visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) {
-            PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(),
+            PatKind::MacCall(mac) => {
+                self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat()
+            }
             _ => unreachable!(),
         });
     }
@@ -1311,7 +1379,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
             }
         }
 
-        if let StmtKind::Mac(mac) = stmt.kind {
+        if let StmtKind::MacCall(mac) = stmt.kind {
             let (mac, style, attrs) = mac.into_inner();
             self.check_attributes(&attrs);
             let mut placeholder =
@@ -1359,59 +1427,83 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                 .make_items();
         }
 
+        let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck.
+        let ident = item.ident;
+        let span = item.span;
+
         match item.kind {
-            ast::ItemKind::Mac(..) => {
+            ast::ItemKind::MacCall(..) => {
+                item.attrs = attrs;
                 self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.kind {
-                    ItemKind::Mac(mac) => self
-                        .collect(
-                            AstFragmentKind::Items,
-                            InvocationKind::Bang { mac, span: item.span },
-                        )
+                    ItemKind::MacCall(mac) => self
+                        .collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span })
                         .make_items(),
                     _ => unreachable!(),
                 })
             }
-            ast::ItemKind::Mod(ast::Mod { inner, inline, .. })
-                if item.ident != Ident::invalid() =>
-            {
-                let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
+            ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => {
+                let sess = self.cx.parse_sess;
+                let orig_ownership = self.cx.current_expansion.directory_ownership;
                 let mut module = (*self.cx.current_expansion.module).clone();
-                module.mod_path.push(item.ident);
 
-                if inline {
-                    if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) {
-                        self.cx.current_expansion.directory_ownership =
-                            DirectoryOwnership::Owned { relative: None };
-                        module.directory.push(&*path.as_str());
-                    } else {
-                        module.directory.push(&*item.ident.as_str());
-                    }
+                let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
+                let dir = Directory { ownership: orig_ownership, path: module.directory };
+                let Directory { ownership, path } = if old_mod.inline {
+                    // Inline `mod foo { ... }`, but we still need to push directories.
+                    item.attrs = attrs;
+                    push_directory(ident, &item.attrs, dir)
                 } else {
-                    let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner);
-                    let mut path = match path {
-                        FileName::Real(path) => path,
-                        other => PathBuf::from(other.to_string()),
+                    // We have an outline `mod foo;` so we need to parse the file.
+                    let (new_mod, dir) =
+                        parse_external_mod(sess, ident, span, dir, &mut attrs, pushed);
+
+                    let krate = ast::Crate {
+                        span: new_mod.inner,
+                        module: new_mod,
+                        attrs,
+                        proc_macros: vec![],
                     };
-                    let directory_ownership = match path.file_name().unwrap().to_str() {
-                        Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
-                        Some(_) => DirectoryOwnership::Owned { relative: Some(item.ident) },
-                        None => DirectoryOwnership::UnownedViaMod,
+                    if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
+                        extern_mod_loaded(&krate);
+                    }
+
+                    *old_mod = krate.module;
+                    item.attrs = krate.attrs;
+                    // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
+                    item = match self.configure(item) {
+                        Some(node) => node,
+                        None => {
+                            if *pushed {
+                                sess.included_mod_stack.borrow_mut().pop();
+                            }
+                            return Default::default();
+                        }
                     };
-                    path.pop();
-                    module.directory = path;
-                    self.cx.current_expansion.directory_ownership = directory_ownership;
-                }
+                    dir
+                };
 
+                // Set the module info before we flat map.
+                self.cx.current_expansion.directory_ownership = ownership;
+                module.directory = path;
+                module.mod_path.push(ident);
                 let orig_module =
                     mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
+
                 let result = noop_flat_map_item(item, self);
+
+                // Restore the module info.
                 self.cx.current_expansion.module = orig_module;
-                self.cx.current_expansion.directory_ownership = orig_directory_ownership;
+                self.cx.current_expansion.directory_ownership = orig_ownership;
+                if *pushed {
+                    sess.included_mod_stack.borrow_mut().pop();
+                }
                 result
             }
-
-            _ => noop_flat_map_item(item, self),
+            _ => {
+                item.attrs = attrs;
+                noop_flat_map_item(item, self)
+            }
         }
     }
 
@@ -1432,10 +1524,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
 
         match item.kind {
-            ast::AssocItemKind::Macro(..) => {
+            ast::AssocItemKind::MacCall(..) => {
                 self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.kind {
-                    ast::AssocItemKind::Macro(mac) => self
+                    ast::AssocItemKind::MacCall(mac) => self
                         .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
                         .make_trait_items(),
                     _ => unreachable!(),
@@ -1462,10 +1554,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
 
         match item.kind {
-            ast::AssocItemKind::Macro(..) => {
+            ast::AssocItemKind::MacCall(..) => {
                 self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.kind {
-                    ast::AssocItemKind::Macro(mac) => self
+                    ast::AssocItemKind::MacCall(mac) => self
                         .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
                         .make_impl_items(),
                     _ => unreachable!(),
@@ -1477,12 +1569,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
 
     fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
         match ty.kind {
-            ast::TyKind::Mac(_) => {}
+            ast::TyKind::MacCall(_) => {}
             _ => return noop_visit_ty(ty, self),
         };
 
         visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) {
-            ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(),
+            ast::TyKind::MacCall(mac) => {
+                self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty()
+            }
             _ => unreachable!(),
         });
     }
@@ -1511,10 +1605,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
 
         match foreign_item.kind {
-            ast::ForeignItemKind::Macro(..) => {
+            ast::ForeignItemKind::MacCall(..) => {
                 self.check_attributes(&foreign_item.attrs);
                 foreign_item.and_then(|item| match item.kind {
-                    ast::ForeignItemKind::Macro(mac) => self
+                    ast::ForeignItemKind::MacCall(mac) => self
                         .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
                         .make_foreign_items(),
                     _ => unreachable!(),
diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs
index f119c956ced..0320a275e5d 100644
--- a/src/librustc_expand/lib.rs
+++ b/src/librustc_expand/lib.rs
@@ -1,9 +1,11 @@
+#![feature(bool_to_option)]
 #![feature(cow_is_borrowed)]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
+#![feature(try_blocks)]
 
 extern crate proc_macro as pm;
 
@@ -33,8 +35,10 @@ pub use mbe::macro_rules::compile_declarative_macro;
 crate use rustc_span::hygiene;
 pub mod base;
 pub mod build;
+#[macro_use]
+pub mod config;
 pub mod expand;
-pub use rustc_parse::config;
+pub mod module;
 pub mod proc_macro;
 
 crate mod mbe;
diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs
index 6eb834beac6..582c26162ed 100644
--- a/src/librustc_expand/mbe/macro_check.rs
+++ b/src/librustc_expand/mbe/macro_check.rs
@@ -112,7 +112,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::kw;
-use rustc_span::{symbol::Ident, MultiSpan, Span};
+use rustc_span::{symbol::MacroRulesNormalizedIdent, MultiSpan, Span};
 
 use smallvec::SmallVec;
 
@@ -179,7 +179,7 @@ struct BinderInfo {
 }
 
 /// An environment of meta-variables to their binder information.
-type Binders = FxHashMap<Ident, BinderInfo>;
+type Binders = FxHashMap<MacroRulesNormalizedIdent, BinderInfo>;
 
 /// The state at which we entered a macro definition in the RHS of another macro definition.
 struct MacroState<'a> {
@@ -245,6 +245,7 @@ fn check_binders(
             if macros.is_empty() {
                 sess.span_diagnostic.span_bug(span, "unexpected MetaVar in lhs");
             }
+            let name = MacroRulesNormalizedIdent::new(name);
             // There are 3 possibilities:
             if let Some(prev_info) = binders.get(&name) {
                 // 1. The meta-variable is already bound in the current LHS: This is an error.
@@ -264,6 +265,7 @@ fn check_binders(
             if !macros.is_empty() {
                 sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in nested lhs");
             }
+            let name = MacroRulesNormalizedIdent::new(name);
             if let Some(prev_info) = get_binder_info(macros, binders, name) {
                 // Duplicate binders at the top-level macro definition are errors. The lint is only
                 // for nested macro definitions.
@@ -300,7 +302,7 @@ fn check_binders(
 fn get_binder_info<'a>(
     mut macros: &'a Stack<'a, MacroState<'a>>,
     binders: &'a Binders,
-    name: Ident,
+    name: MacroRulesNormalizedIdent,
 ) -> Option<&'a BinderInfo> {
     binders.get(&name).or_else(|| macros.find_map(|state| state.binders.get(&name)))
 }
@@ -331,6 +333,7 @@ fn check_occurrences(
             sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in rhs")
         }
         TokenTree::MetaVar(span, name) => {
+            let name = MacroRulesNormalizedIdent::new(name);
             check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name);
         }
         TokenTree::Delimited(_, ref del) => {
@@ -419,10 +422,10 @@ fn check_nested_occurrences(
             | (NestedMacroState::MacroName, &TokenTree::Delimited(_, ref del))
                 if del.delim == DelimToken::Brace =>
             {
-                let legacy = state == NestedMacroState::MacroRulesNotName;
+                let macro_rules = state == NestedMacroState::MacroRulesNotName;
                 state = NestedMacroState::Empty;
                 let rest =
-                    check_nested_macro(sess, node_id, legacy, &del.tts, &nested_macros, valid);
+                    check_nested_macro(sess, node_id, macro_rules, &del.tts, &nested_macros, valid);
                 // If we did not check the whole macro definition, then check the rest as if outside
                 // the macro definition.
                 check_nested_occurrences(
@@ -493,21 +496,21 @@ fn check_nested_occurrences(
 /// Arguments:
 /// - `sess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
-/// - `legacy` specifies whether the macro is legacy
+/// - `macro_rules` specifies whether the macro is `macro_rules`
 /// - `tts` is checked as a list of (LHS) => {RHS}
 /// - `macros` is the stack of outer macros
 /// - `valid` is set in case of errors
 fn check_nested_macro(
     sess: &ParseSess,
     node_id: NodeId,
-    legacy: bool,
+    macro_rules: bool,
     tts: &[TokenTree],
     macros: &Stack<'_, MacroState<'_>>,
     valid: &mut bool,
 ) -> usize {
     let n = tts.len();
     let mut i = 0;
-    let separator = if legacy { TokenKind::Semi } else { TokenKind::Comma };
+    let separator = if macro_rules { TokenKind::Semi } else { TokenKind::Comma };
     loop {
         // We expect 3 token trees: `(LHS) => {RHS}`. The separator is checked after.
         if i + 2 >= n
@@ -522,7 +525,7 @@ fn check_nested_macro(
         let mut binders = Binders::default();
         check_binders(sess, node_id, lhs, macros, &mut binders, &Stack::Empty, valid);
         check_occurrences(sess, node_id, rhs, macros, &binders, &Stack::Empty, valid);
-        // Since the last semicolon is optional for legacy macros and decl_macro are not terminated,
+        // Since the last semicolon is optional for `macro_rules` macros and decl_macro are not terminated,
         // we increment our checked position by how many token trees we already checked (the 3
         // above) before checking for the separator.
         i += 3;
@@ -552,7 +555,7 @@ fn check_ops_is_prefix(
     binders: &Binders,
     ops: &Stack<'_, KleeneToken>,
     span: Span,
-    name: Ident,
+    name: MacroRulesNormalizedIdent,
 ) {
     let macros = macros.push(MacroState { binders, ops: ops.into() });
     // Accumulates the stacks the operators of each state until (and including when) the
@@ -598,7 +601,7 @@ fn ops_is_prefix(
     sess: &ParseSess,
     node_id: NodeId,
     span: Span,
-    name: Ident,
+    name: MacroRulesNormalizedIdent,
     binder_ops: &[KleeneToken],
     occurrence_ops: &[KleeneToken],
 ) {
diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs
index 6d4d7f5b4f3..3b9158f4445 100644
--- a/src/librustc_expand/mbe/macro_parser.rs
+++ b/src/librustc_expand/mbe/macro_parser.rs
@@ -76,13 +76,13 @@ use TokenTreeOrTokenTreeSlice::*;
 
 use crate::mbe::{self, TokenTree};
 
-use rustc_ast::ast::{Ident, Name};
+use rustc_ast::ast::Name;
 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_session::parse::ParseSess;
-use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol};
 
 use rustc_errors::{FatalError, PResult};
 use rustc_span::Span;
@@ -273,9 +273,10 @@ crate enum ParseResult<T> {
     Error(rustc_span::Span, String),
 }
 
-/// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es.
-/// This represents the mapping of metavars to the token trees they bind to.
-crate type NamedParseResult = ParseResult<FxHashMap<Ident, NamedMatch>>;
+/// A `ParseResult` where the `Success` variant contains a mapping of
+/// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping
+/// of metavars to the token trees they bind to.
+crate type NamedParseResult = ParseResult<FxHashMap<MacroRulesNormalizedIdent, NamedMatch>>;
 
 /// Count how many metavars are named in the given matcher `ms`.
 pub(super) fn count_names(ms: &[TokenTree]) -> usize {
@@ -368,7 +369,7 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
         sess: &ParseSess,
         m: &TokenTree,
         res: &mut I,
-        ret_val: &mut FxHashMap<Ident, NamedMatch>,
+        ret_val: &mut FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
     ) -> Result<(), (rustc_span::Span, String)> {
         match *m {
             TokenTree::Sequence(_, ref seq) => {
@@ -386,7 +387,9 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
                     return Err((span, "missing fragment specifier".to_string()));
                 }
             }
-            TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val.entry(bind_name) {
+            TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val
+                .entry(MacroRulesNormalizedIdent::new(bind_name))
+            {
                 Vacant(spot) => {
                     spot.insert(res.next().unwrap());
                 }
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index 3040a9aefbb..3de2169f114 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -1,4 +1,4 @@
-use crate::base::{DummyResult, ExpansionData, ExtCtxt, MacResult, TTMacroExpander};
+use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
 use crate::base::{SyntaxExtension, SyntaxExtensionKind};
 use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind};
 use crate::mbe;
@@ -18,11 +18,10 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder, FatalError};
 use rustc_feature::Features;
 use rustc_parse::parser::Parser;
-use rustc_parse::Directory;
 use rustc_session::parse::ParseSess;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::Transparency;
-use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::symbol::{kw, sym, MacroRulesNormalizedIdent, Symbol};
 use rustc_span::Span;
 
 use log::debug;
@@ -182,6 +181,8 @@ fn generic_extension<'cx>(
     lhses: &[mbe::TokenTree],
     rhses: &[mbe::TokenTree],
 ) -> Box<dyn MacResult + 'cx> {
+    let sess = cx.parse_sess;
+
     if cx.trace_macros() {
         let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone()));
         trace_macros_note(&mut cx.expansions, sp, msg);
@@ -209,7 +210,7 @@ fn generic_extension<'cx>(
     // hacky, but speeds up the `html5ever` benchmark significantly. (Issue
     // 68836 suggests a more comprehensive but more complex change to deal with
     // this situation.)
-    let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
+    let parser = parser_from_cx(sess, arg.clone());
 
     for (i, lhs) in lhses.iter().enumerate() {
         // try each arm's matchers
@@ -222,14 +223,13 @@ fn generic_extension<'cx>(
         // This is used so that if a matcher is not `Success(..)`ful,
         // then the spans which became gated when parsing the unsuccessful matcher
         // are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
-        let mut gated_spans_snapshot =
-            mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut());
+        let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut());
 
         match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) {
             Success(named_matches) => {
                 // The matcher was `Success(..)`ful.
                 // Merge the gated spans from parsing the matcher with the pre-existing ones.
-                cx.parse_sess.gated_spans.merge(gated_spans_snapshot);
+                sess.gated_spans.merge(gated_spans_snapshot);
 
                 let rhs = match rhses[i] {
                     // ignore delimiters
@@ -258,11 +258,7 @@ fn generic_extension<'cx>(
                     trace_macros_note(&mut cx.expansions, sp, msg);
                 }
 
-                let directory = Directory {
-                    path: cx.current_expansion.module.directory.clone(),
-                    ownership: cx.current_expansion.directory_ownership,
-                };
-                let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None);
+                let mut p = Parser::new(sess, tts, false, None);
                 p.root_module_name =
                     cx.current_expansion.module.mod_path.last().map(|id| id.to_string());
                 p.last_type_ascription = cx.current_expansion.prior_type_ascription;
@@ -289,7 +285,7 @@ fn generic_extension<'cx>(
 
         // The matcher was not `Success(..)`ful.
         // Restore to the state before snapshotting and maybe try again.
-        mem::swap(&mut gated_spans_snapshot, &mut cx.parse_sess.gated_spans.spans.borrow_mut());
+        mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut());
     }
     drop(parser);
 
@@ -309,8 +305,7 @@ fn generic_extension<'cx>(
                 mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
                 _ => continue,
             };
-            let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
-            match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) {
+            match parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt) {
                 Success(_) => {
                     if comma_span.is_dummy() {
                         err.note("you might be missing a comma");
@@ -350,8 +345,8 @@ pub fn compile_declarative_macro(
     let tt_spec = ast::Ident::new(sym::tt, def.span);
 
     // Parse the macro_rules! invocation
-    let (is_legacy, body) = match &def.kind {
-        ast::ItemKind::MacroDef(macro_def) => (macro_def.legacy, macro_def.body.inner_tokens()),
+    let (macro_rules, body) = match &def.kind {
+        ast::ItemKind::MacroDef(def) => (def.macro_rules, def.body.inner_tokens()),
         _ => unreachable!(),
     };
 
@@ -370,7 +365,7 @@ pub fn compile_declarative_macro(
                     mbe::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec),
                 ],
                 separator: Some(Token::new(
-                    if is_legacy { token::Semi } else { token::Comma },
+                    if macro_rules { token::Semi } else { token::Comma },
                     def.span,
                 )),
                 kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, def.span),
@@ -382,7 +377,7 @@ pub fn compile_declarative_macro(
             DelimSpan::dummy(),
             Lrc::new(mbe::SequenceRepetition {
                 tts: vec![mbe::TokenTree::token(
-                    if is_legacy { token::Semi } else { token::Comma },
+                    if macro_rules { token::Semi } else { token::Comma },
                     def.span,
                 )],
                 separator: None,
@@ -392,7 +387,7 @@ pub fn compile_declarative_macro(
         ),
     ];
 
-    let parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS);
+    let parser = Parser::new(sess, body, true, rustc_parse::MACRO_ARGUMENTS);
     let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) {
         Success(m) => m,
         Failure(token, msg) => {
@@ -411,7 +406,7 @@ pub fn compile_declarative_macro(
     let mut valid = true;
 
     // Extract the arguments:
-    let lhses = match argument_map[&lhs_nm] {
+    let lhses = match argument_map[&MacroRulesNormalizedIdent::new(lhs_nm)] {
         MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
@@ -428,7 +423,7 @@ pub fn compile_declarative_macro(
         _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"),
     };
 
-    let rhses = match argument_map[&rhs_nm] {
+    let rhses = match argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] {
         MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
@@ -456,7 +451,7 @@ pub fn compile_declarative_macro(
     // that is not lint-checked and trigger the "failed to process buffered lint here" bug.
     valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses);
 
-    let (transparency, transparency_error) = attr::find_transparency(&def.attrs, is_legacy);
+    let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
     match transparency_error {
         Some(TransparencyError::UnknownTransparency(value, span)) => {
             diag.span_err(span, &format!("unknown macro transparency: `{}`", value))
@@ -1209,16 +1204,8 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
     }
 }
 
-fn parser_from_cx<'cx>(
-    current_expansion: &'cx ExpansionData,
-    sess: &'cx ParseSess,
-    tts: TokenStream,
-) -> Parser<'cx> {
-    let directory = Directory {
-        path: current_expansion.module.directory.clone(),
-        ownership: current_expansion.directory_ownership,
-    };
-    Parser::new(sess, tts, Some(directory), true, true, rustc_parse::MACRO_ARGUMENTS)
+fn parser_from_cx(sess: &ParseSess, tts: TokenStream) -> Parser<'_> {
+    Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS)
 }
 
 /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For
diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs
index d12dedf9e0c..1b1093c9529 100644
--- a/src/librustc_expand/mbe/transcribe.rs
+++ b/src/librustc_expand/mbe/transcribe.rs
@@ -2,7 +2,7 @@ use crate::base::ExtCtxt;
 use crate::mbe;
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch};
 
-use rustc_ast::ast::{Ident, Mac};
+use rustc_ast::ast::MacCall;
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::token::{self, NtTT, Token};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
@@ -10,6 +10,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::pluralize;
 use rustc_span::hygiene::{ExpnId, Transparency};
+use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::Span;
 
 use smallvec::{smallvec, SmallVec};
@@ -23,7 +24,7 @@ impl MutVisitor for Marker {
         *span = span.apply_mark(self.0, self.1)
     }
 
-    fn visit_mac(&mut self, mac: &mut Mac) {
+    fn visit_mac(&mut self, mac: &mut MacCall) {
         mut_visit::noop_visit_mac(mac, self)
     }
 }
@@ -81,7 +82,7 @@ impl Iterator for Frame {
 /// Along the way, we do some additional error checking.
 pub(super) fn transcribe(
     cx: &ExtCtxt<'_>,
-    interp: &FxHashMap<Ident, NamedMatch>,
+    interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
     src: Vec<mbe::TokenTree>,
     transparency: Transparency,
 ) -> TokenStream {
@@ -223,9 +224,10 @@ pub(super) fn transcribe(
             }
 
             // Replace the meta-var with the matched token tree from the invocation.
-            mbe::TokenTree::MetaVar(mut sp, mut ident) => {
+            mbe::TokenTree::MetaVar(mut sp, mut orignal_ident) => {
                 // Find the matched nonterminal from the macro invocation, and use it to replace
                 // the meta-var.
+                let ident = MacroRulesNormalizedIdent::new(orignal_ident);
                 if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
                     if let MatchedNonterminal(ref nt) = cur_matched {
                         // FIXME #2887: why do we apply a mark when matching a token tree meta-var
@@ -249,9 +251,9 @@ pub(super) fn transcribe(
                     // If we aren't able to match the meta-var, we push it back into the result but
                     // with modified syntax context. (I believe this supports nested macros).
                     marker.visit_span(&mut sp);
-                    marker.visit_ident(&mut ident);
+                    marker.visit_ident(&mut orignal_ident);
                     result.push(TokenTree::token(token::Dollar, sp).into());
-                    result.push(TokenTree::Token(Token::from_ast_ident(ident)).into());
+                    result.push(TokenTree::Token(Token::from_ast_ident(orignal_ident)).into());
                 }
             }
 
@@ -287,8 +289,8 @@ pub(super) fn transcribe(
 /// into the right place in nested matchers. If we attempt to descend too far, the macro writer has
 /// made a mistake, and we return `None`.
 fn lookup_cur_matched<'a>(
-    ident: Ident,
-    interpolations: &'a FxHashMap<Ident, NamedMatch>,
+    ident: MacroRulesNormalizedIdent,
+    interpolations: &'a FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
     repeats: &[(usize, usize)],
 ) -> Option<&'a NamedMatch> {
     interpolations.get(&ident).map(|matched| {
@@ -316,7 +318,7 @@ enum LockstepIterSize {
 
     /// A `MetaVar` with an actual `MatchedSeq`. The length of the match and the name of the
     /// meta-var are returned.
-    Constraint(usize, Ident),
+    Constraint(usize, MacroRulesNormalizedIdent),
 
     /// Two `Constraint`s on the same sequence had different lengths. This is an error.
     Contradiction(String),
@@ -360,7 +362,7 @@ impl LockstepIterSize {
 /// multiple nested matcher sequences.
 fn lockstep_iter_size(
     tree: &mbe::TokenTree,
-    interpolations: &FxHashMap<Ident, NamedMatch>,
+    interpolations: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
     repeats: &[(usize, usize)],
 ) -> LockstepIterSize {
     use mbe::TokenTree;
@@ -376,6 +378,7 @@ fn lockstep_iter_size(
             })
         }
         TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => {
+            let name = MacroRulesNormalizedIdent::new(name);
             match lookup_cur_matched(name, interpolations, repeats) {
                 Some(matched) => match matched {
                     MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
diff --git a/src/librustc_expand/module.rs b/src/librustc_expand/module.rs
new file mode 100644
index 00000000000..2d5e4d4e889
--- /dev/null
+++ b/src/librustc_expand/module.rs
@@ -0,0 +1,306 @@
+use rustc_ast::ast::{self, Attribute, Ident, Mod};
+use rustc_ast::{attr, token};
+use rustc_errors::{struct_span_err, PResult};
+use rustc_parse::new_sub_parser_from_file;
+use rustc_session::parse::ParseSess;
+use rustc_span::source_map::{FileName, Span};
+use rustc_span::symbol::sym;
+
+use std::path::{self, Path, PathBuf};
+
+#[derive(Clone)]
+pub struct Directory {
+    pub path: PathBuf,
+    pub ownership: DirectoryOwnership,
+}
+
+#[derive(Copy, Clone)]
+pub enum DirectoryOwnership {
+    Owned {
+        // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`.
+        relative: Option<ast::Ident>,
+    },
+    UnownedViaBlock,
+    UnownedViaMod,
+}
+
+/// Information about the path to a module.
+// Public for rustfmt usage.
+pub struct ModulePath<'a> {
+    name: String,
+    path_exists: bool,
+    pub result: PResult<'a, ModulePathSuccess>,
+}
+
+// Public for rustfmt usage.
+pub struct ModulePathSuccess {
+    pub path: PathBuf,
+    pub ownership: DirectoryOwnership,
+}
+
+crate fn parse_external_mod(
+    sess: &ParseSess,
+    id: ast::Ident,
+    span: Span, // The span to blame on errors.
+    Directory { mut ownership, path }: Directory,
+    attrs: &mut Vec<Attribute>,
+    pop_mod_stack: &mut bool,
+) -> (Mod, Directory) {
+    // We bail on the first error, but that error does not cause a fatal error... (1)
+    let result: PResult<'_, _> = try {
+        // Extract the file path and the new ownership.
+        let mp = submod_path(sess, id, span, &attrs, ownership, &path)?;
+        ownership = mp.ownership;
+
+        // Ensure file paths are acyclic.
+        let mut included_mod_stack = sess.included_mod_stack.borrow_mut();
+        error_on_circular_module(sess, span, &mp.path, &included_mod_stack)?;
+        included_mod_stack.push(mp.path.clone());
+        *pop_mod_stack = true; // We have pushed, so notify caller.
+        drop(included_mod_stack);
+
+        // Actually parse the external file as amodule.
+        let mut p0 = new_sub_parser_from_file(sess, &mp.path, Some(id.to_string()), span);
+        let mut module = p0.parse_mod(&token::Eof)?;
+        module.0.inline = false;
+        module
+    };
+    // (1) ...instead, we return a dummy module.
+    let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_default();
+    attrs.append(&mut new_attrs);
+
+    // Extract the directory path for submodules of `module`.
+    let path = sess.source_map().span_to_unmapped_path(module.inner);
+    let mut path = match path {
+        FileName::Real(path) => path,
+        other => PathBuf::from(other.to_string()),
+    };
+    path.pop();
+
+    (module, Directory { ownership, path })
+}
+
+fn error_on_circular_module<'a>(
+    sess: &'a ParseSess,
+    span: Span,
+    path: &Path,
+    included_mod_stack: &[PathBuf],
+) -> PResult<'a, ()> {
+    if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
+        let mut err = String::from("circular modules: ");
+        for p in &included_mod_stack[i..] {
+            err.push_str(&p.to_string_lossy());
+            err.push_str(" -> ");
+        }
+        err.push_str(&path.to_string_lossy());
+        return Err(sess.span_diagnostic.struct_span_err(span, &err[..]));
+    }
+    Ok(())
+}
+
+crate fn push_directory(
+    id: Ident,
+    attrs: &[Attribute],
+    Directory { mut ownership, mut path }: Directory,
+) -> Directory {
+    if let Some(filename) = attr::first_attr_value_str_by_name(attrs, sym::path) {
+        path.push(&*filename.as_str());
+        ownership = DirectoryOwnership::Owned { relative: None };
+    } else {
+        // We have to push on the current module name in the case of relative
+        // paths in order to ensure that any additional module paths from inline
+        // `mod x { ... }` come after the relative extension.
+        //
+        // For example, a `mod z { ... }` inside `x/y.rs` should set the current
+        // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
+        if let DirectoryOwnership::Owned { relative } = &mut ownership {
+            if let Some(ident) = relative.take() {
+                // Remove the relative offset.
+                path.push(&*ident.as_str());
+            }
+        }
+        path.push(&*id.as_str());
+    }
+    Directory { ownership, path }
+}
+
+fn submod_path<'a>(
+    sess: &'a ParseSess,
+    id: ast::Ident,
+    span: Span,
+    attrs: &[Attribute],
+    ownership: DirectoryOwnership,
+    dir_path: &Path,
+) -> PResult<'a, ModulePathSuccess> {
+    if let Some(path) = submod_path_from_attr(attrs, dir_path) {
+        let ownership = match path.file_name().and_then(|s| s.to_str()) {
+            // All `#[path]` files are treated as though they are a `mod.rs` file.
+            // This means that `mod foo;` declarations inside `#[path]`-included
+            // files are siblings,
+            //
+            // Note that this will produce weirdness when a file named `foo.rs` is
+            // `#[path]` included and contains a `mod foo;` declaration.
+            // If you encounter this, it's your own darn fault :P
+            Some(_) => DirectoryOwnership::Owned { relative: None },
+            _ => DirectoryOwnership::UnownedViaMod,
+        };
+        return Ok(ModulePathSuccess { ownership, path });
+    }
+
+    let relative = match ownership {
+        DirectoryOwnership::Owned { relative } => relative,
+        DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None,
+    };
+    let ModulePath { path_exists, name, result } =
+        default_submod_path(sess, id, span, relative, dir_path);
+    match ownership {
+        DirectoryOwnership::Owned { .. } => Ok(result?),
+        DirectoryOwnership::UnownedViaBlock => {
+            let _ = result.map_err(|mut err| err.cancel());
+            error_decl_mod_in_block(sess, span, path_exists, &name)
+        }
+        DirectoryOwnership::UnownedViaMod => {
+            let _ = result.map_err(|mut err| err.cancel());
+            error_cannot_declare_mod_here(sess, span, path_exists, &name)
+        }
+    }
+}
+
+fn error_decl_mod_in_block<'a, T>(
+    sess: &'a ParseSess,
+    span: Span,
+    path_exists: bool,
+    name: &str,
+) -> PResult<'a, T> {
+    let msg = "Cannot declare a non-inline module inside a block unless it has a path attribute";
+    let mut err = sess.span_diagnostic.struct_span_err(span, msg);
+    if path_exists {
+        let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", name);
+        err.span_note(span, &msg);
+    }
+    Err(err)
+}
+
+fn error_cannot_declare_mod_here<'a, T>(
+    sess: &'a ParseSess,
+    span: Span,
+    path_exists: bool,
+    name: &str,
+) -> PResult<'a, T> {
+    let mut err =
+        sess.span_diagnostic.struct_span_err(span, "cannot declare a new module at this location");
+    if !span.is_dummy() {
+        if let FileName::Real(src_path) = sess.source_map().span_to_filename(span) {
+            if let Some(stem) = src_path.file_stem() {
+                let mut dest_path = src_path.clone();
+                dest_path.set_file_name(stem);
+                dest_path.push("mod.rs");
+                err.span_note(
+                    span,
+                    &format!(
+                        "maybe move this module `{}` to its own directory via `{}`",
+                        src_path.display(),
+                        dest_path.display()
+                    ),
+                );
+            }
+        }
+    }
+    if path_exists {
+        err.span_note(
+            span,
+            &format!("... or maybe `use` the module `{}` instead of possibly redeclaring it", name),
+        );
+    }
+    Err(err)
+}
+
+/// Derive a submodule path from the first found `#[path = "path_string"]`.
+/// The provided `dir_path` is joined with the `path_string`.
+// Public for rustfmt usage.
+pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
+    // Extract path string from first `#[path = "path_string"]` attribute.
+    let path_string = attr::first_attr_value_str_by_name(attrs, sym::path)?;
+    let path_string = path_string.as_str();
+
+    // On windows, the base path might have the form
+    // `\\?\foo\bar` in which case it does not tolerate
+    // mixed `/` and `\` separators, so canonicalize
+    // `/` to `\`.
+    #[cfg(windows)]
+    let path_string = path_string.replace("/", "\\");
+
+    Some(dir_path.join(&*path_string))
+}
+
+/// Returns a path to a module.
+// Public for rustfmt usage.
+pub fn default_submod_path<'a>(
+    sess: &'a ParseSess,
+    id: ast::Ident,
+    span: Span,
+    relative: Option<ast::Ident>,
+    dir_path: &Path,
+) -> ModulePath<'a> {
+    // If we're in a foo.rs file instead of a mod.rs file,
+    // we need to look for submodules in
+    // `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than
+    // `./<id>.rs` and `./<id>/mod.rs`.
+    let relative_prefix_string;
+    let relative_prefix = if let Some(ident) = relative {
+        relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR);
+        &relative_prefix_string
+    } else {
+        ""
+    };
+
+    let mod_name = id.name.to_string();
+    let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
+    let secondary_path_str =
+        format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR);
+    let default_path = dir_path.join(&default_path_str);
+    let secondary_path = dir_path.join(&secondary_path_str);
+    let default_exists = sess.source_map().file_exists(&default_path);
+    let secondary_exists = sess.source_map().file_exists(&secondary_path);
+
+    let result = match (default_exists, secondary_exists) {
+        (true, false) => Ok(ModulePathSuccess {
+            path: default_path,
+            ownership: DirectoryOwnership::Owned { relative: Some(id) },
+        }),
+        (false, true) => Ok(ModulePathSuccess {
+            path: secondary_path,
+            ownership: DirectoryOwnership::Owned { relative: None },
+        }),
+        (false, false) => {
+            let mut err = struct_span_err!(
+                sess.span_diagnostic,
+                span,
+                E0583,
+                "file not found for module `{}`",
+                mod_name,
+            );
+            err.help(&format!(
+                "to create the module `{}`, create file \"{}\"",
+                mod_name,
+                default_path.display(),
+            ));
+            Err(err)
+        }
+        (true, true) => {
+            let mut err = struct_span_err!(
+                sess.span_diagnostic,
+                span,
+                E0584,
+                "file for module `{}` found at both {} and {}",
+                mod_name,
+                default_path_str,
+                secondary_path_str,
+            );
+            err.help("delete or rename one of them to remove the ambiguity");
+            Err(err)
+        }
+    };
+
+    ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result }
+}
diff --git a/src/librustc_expand/mut_visit/tests.rs b/src/librustc_expand/mut_visit/tests.rs
index 4c947d8fa2b..70fb8975d4d 100644
--- a/src/librustc_expand/mut_visit/tests.rs
+++ b/src/librustc_expand/mut_visit/tests.rs
@@ -17,7 +17,7 @@ impl MutVisitor for ToZzIdentMutVisitor {
     fn visit_ident(&mut self, ident: &mut ast::Ident) {
         *ident = Ident::from_str("zz");
     }
-    fn visit_mac(&mut self, mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, mac: &mut ast::MacCall) {
         mut_visit::noop_visit_mac(mac, self)
     }
 }
diff --git a/src/librustc_expand/parse/tests.rs b/src/librustc_expand/parse/tests.rs
index 55e815bd4a4..4add896258f 100644
--- a/src/librustc_expand/parse/tests.rs
+++ b/src/librustc_expand/parse/tests.rs
@@ -281,7 +281,7 @@ fn ttdelim_span() {
         .unwrap();
 
         let tts: Vec<_> = match expr.kind {
-            ast::ExprKind::Mac(ref mac) => mac.args.inner_tokens().trees().collect(),
+            ast::ExprKind::MacCall(ref mac) => mac.args.inner_tokens().trees().collect(),
             _ => panic!("not a macro"),
         };
 
diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs
index cd4f0a61d42..e1781f8636e 100644
--- a/src/librustc_expand/placeholders.rs
+++ b/src/librustc_expand/placeholders.rs
@@ -15,8 +15,8 @@ pub fn placeholder(
     id: ast::NodeId,
     vis: Option<ast::Visibility>,
 ) -> AstFragment {
-    fn mac_placeholder() -> ast::Mac {
-        ast::Mac {
+    fn mac_placeholder() -> ast::MacCall {
+        ast::MacCall {
             path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
             args: P(ast::MacArgs::Empty),
             prior_type_ascription: None,
@@ -32,11 +32,11 @@ pub fn placeholder(
             id,
             span,
             attrs: ast::AttrVec::new(),
-            kind: ast::ExprKind::Mac(mac_placeholder()),
+            kind: ast::ExprKind::MacCall(mac_placeholder()),
         })
     };
-    let ty = || P(ast::Ty { id, kind: ast::TyKind::Mac(mac_placeholder()), span });
-    let pat = || P(ast::Pat { id, kind: ast::PatKind::Mac(mac_placeholder()), span });
+    let ty = || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span });
+    let pat = || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span });
 
     match kind {
         AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
@@ -47,7 +47,7 @@ pub fn placeholder(
             ident,
             vis,
             attrs,
-            kind: ast::ItemKind::Mac(mac_placeholder()),
+            kind: ast::ItemKind::MacCall(mac_placeholder()),
             tokens: None,
         })]),
         AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
@@ -56,7 +56,7 @@ pub fn placeholder(
             ident,
             vis,
             attrs,
-            kind: ast::AssocItemKind::Macro(mac_placeholder()),
+            kind: ast::AssocItemKind::MacCall(mac_placeholder()),
             tokens: None,
         })]),
         AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
@@ -65,7 +65,7 @@ pub fn placeholder(
             ident,
             vis,
             attrs,
-            kind: ast::AssocItemKind::Macro(mac_placeholder()),
+            kind: ast::AssocItemKind::MacCall(mac_placeholder()),
             tokens: None,
         })]),
         AstFragmentKind::ForeignItems => {
@@ -75,19 +75,21 @@ pub fn placeholder(
                 ident,
                 vis,
                 attrs,
-                kind: ast::ForeignItemKind::Macro(mac_placeholder()),
+                kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
                 tokens: None,
             })])
         }
-        AstFragmentKind::Pat => {
-            AstFragment::Pat(P(ast::Pat { id, span, kind: ast::PatKind::Mac(mac_placeholder()) }))
-        }
+        AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
+            id,
+            span,
+            kind: ast::PatKind::MacCall(mac_placeholder()),
+        })),
         AstFragmentKind::Ty => {
-            AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::Mac(mac_placeholder()) }))
+            AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::MacCall(mac_placeholder()) }))
         }
         AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
             let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::AttrVec::new()));
-            ast::Stmt { id, span, kind: ast::StmtKind::Mac(mac) }
+            ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) }
         }]),
         AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
             attrs: Default::default(),
@@ -239,7 +241,7 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
 
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         match item.kind {
-            ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
+            ast::ItemKind::MacCall(_) => return self.remove(item.id).make_items(),
             ast::ItemKind::MacroDef(_) => return smallvec![item],
             _ => {}
         }
@@ -249,14 +251,14 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
 
     fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         match item.kind {
-            ast::AssocItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
+            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_trait_items(),
             _ => noop_flat_map_assoc_item(item, self),
         }
     }
 
     fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         match item.kind {
-            ast::AssocItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
+            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_impl_items(),
             _ => noop_flat_map_assoc_item(item, self),
         }
     }
@@ -266,28 +268,28 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
         item: P<ast::ForeignItem>,
     ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
         match item.kind {
-            ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(),
+            ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(),
             _ => noop_flat_map_foreign_item(item, self),
         }
     }
 
     fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
         match expr.kind {
-            ast::ExprKind::Mac(_) => *expr = self.remove(expr.id).make_expr(),
+            ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(),
             _ => noop_visit_expr(expr, self),
         }
     }
 
     fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
         match expr.kind {
-            ast::ExprKind::Mac(_) => self.remove(expr.id).make_opt_expr(),
+            ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
             _ => noop_filter_map_expr(expr, self),
         }
     }
 
     fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
         let (style, mut stmts) = match stmt.kind {
-            ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
+            ast::StmtKind::MacCall(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
             _ => return noop_flat_map_stmt(stmt, self),
         };
 
@@ -302,14 +304,14 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
 
     fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
         match pat.kind {
-            ast::PatKind::Mac(_) => *pat = self.remove(pat.id).make_pat(),
+            ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(),
             _ => noop_visit_pat(pat, self),
         }
     }
 
     fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
         match ty.kind {
-            ast::TyKind::Mac(_) => *ty = self.remove(ty.id).make_ty(),
+            ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(),
             _ => noop_visit_ty(ty, self),
         }
     }
@@ -328,12 +330,12 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
     fn visit_mod(&mut self, module: &mut ast::Mod) {
         noop_visit_mod(module, self);
         module.items.retain(|item| match item.kind {
-            ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions
+            ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions
             _ => true,
         });
     }
 
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
         // Do nothing.
     }
 }
diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs
index 84a546345bb..cb9afa4cd4f 100644
--- a/src/librustc_expand/proc_macro.rs
+++ b/src/librustc_expand/proc_macro.rs
@@ -79,7 +79,7 @@ impl MultiItemModifier for ProcMacroDerive {
         span: Span,
         _meta_item: &ast::MetaItem,
         item: Annotatable,
-    ) -> Vec<Annotatable> {
+    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         let item = match item {
             Annotatable::Arm(..)
             | Annotatable::Field(..)
@@ -99,7 +99,7 @@ impl MultiItemModifier for ProcMacroDerive {
                     "proc-macro derives may only be \
                                     applied to a struct, enum, or union",
                 );
-                return Vec::new();
+                return ExpandResult::Ready(Vec::new());
             }
         };
         match item.kind {
@@ -110,7 +110,7 @@ impl MultiItemModifier for ProcMacroDerive {
                     "proc-macro derives may only be \
                                     applied to a struct, enum, or union",
                 );
-                return Vec::new();
+                return ExpandResult::Ready(Vec::new());
             }
         }
 
@@ -158,7 +158,7 @@ impl MultiItemModifier for ProcMacroDerive {
             FatalError.raise();
         }
 
-        items
+        ExpandResult::Ready(items)
     }
 }
 
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 3a0fc6f8da1..9f1fee8fc09 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -301,6 +301,11 @@ declare_features! (
     /// Allows specialization of implementations (RFC 1210).
     (active, specialization, "1.7.0", Some(31844), None),
 
+    /// A minimal, sound subset of specialization intended to be used by the
+    /// standard library until the soundness issues with specialization
+    /// are fixed.
+    (active, min_specialization, "1.7.0", Some(31844), None),
+
     /// Allows using `#[naked]` on functions.
     (active, naked_functions, "1.9.0", Some(32408), None),
 
diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs
index e9a5364c658..eaebdd9fb95 100644
--- a/src/librustc_feature/builtin_attrs.rs
+++ b/src/librustc_feature/builtin_attrs.rs
@@ -85,19 +85,13 @@ impl AttributeGate {
 
 /// A template that the attribute input must match.
 /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
 pub struct AttributeTemplate {
     pub word: bool,
     pub list: Option<&'static str>,
     pub name_value_str: Option<&'static str>,
 }
 
-impl AttributeTemplate {
-    pub fn only_word() -> Self {
-        Self { word: true, list: None, name_value_str: None }
-    }
-}
-
 /// A convenience macro for constructing attribute templates.
 /// E.g., `template!(Word, List: "description")` means that the attribute
 /// supports forms `#[attr]` and `#[attr(description)]`.
@@ -530,6 +524,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         rustc_test_marker, Normal, template!(Word),
         "the `#[rustc_test_marker]` attribute is used internally to track tests",
     ),
+    rustc_attr!(
+        rustc_unsafe_specialization_marker, Normal, template!(Word),
+        "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations"
+    ),
+    rustc_attr!(
+        rustc_specialization_trait, Normal, template!(Word),
+        "the `#[rustc_specialization_trait]` attribute is used to check specializations"
+    ),
 
     // ==========================================================================
     // Internal attributes, Testing:
diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs
index 595543eaf53..696aa5c6f7d 100644
--- a/src/librustc_hir/def.rs
+++ b/src/librustc_hir/def.rs
@@ -72,7 +72,7 @@ pub enum DefKind {
     Static,
     /// Refers to the struct or enum variant's constructor.
     Ctor(CtorOf, CtorKind),
-    Method,
+    AssocFn,
     AssocConst,
 
     // Macro namespace
@@ -107,7 +107,7 @@ impl DefKind {
             DefKind::Union => "union",
             DefKind::Trait => "trait",
             DefKind::ForeignTy => "foreign type",
-            DefKind::Method => "method",
+            DefKind::AssocFn => "associated function",
             DefKind::Const => "constant",
             DefKind::AssocConst => "associated constant",
             DefKind::TyParam => "type parameter",
@@ -122,6 +122,7 @@ impl DefKind {
             DefKind::AssocTy
             | DefKind::AssocConst
             | DefKind::AssocOpaqueTy
+            | DefKind::AssocFn
             | DefKind::Enum
             | DefKind::OpaqueTy => "an",
             DefKind::Macro(macro_kind) => macro_kind.article(),
@@ -150,7 +151,7 @@ impl DefKind {
             | DefKind::ConstParam
             | DefKind::Static
             | DefKind::Ctor(..)
-            | DefKind::Method
+            | DefKind::AssocFn
             | DefKind::AssocConst => ns == Namespace::ValueNS,
 
             DefKind::Macro(..) => ns == Namespace::MacroNS,
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index f948e22e84b..0ef35b184e1 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -13,7 +13,6 @@ use rustc_ast::ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyl
 pub use rustc_ast::ast::{BorrowKind, ImplPolarity, IsAuto};
 pub use rustc_ast::ast::{CaptureBy, Movability, Mutability};
 use rustc_ast::node_id::NodeMap;
-use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::parser::ExprPrecedence;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
@@ -80,9 +79,9 @@ impl ParamName {
         }
     }
 
-    pub fn modern(&self) -> ParamName {
+    pub fn normalize_to_macros_2_0(&self) -> ParamName {
         match *self {
-            ParamName::Plain(ident) => ParamName::Plain(ident.modern()),
+            ParamName::Plain(ident) => ParamName::Plain(ident.normalize_to_macros_2_0()),
             param_name => param_name,
         }
     }
@@ -152,9 +151,11 @@ impl LifetimeName {
         self == &LifetimeName::Static
     }
 
-    pub fn modern(&self) -> LifetimeName {
+    pub fn normalize_to_macros_2_0(&self) -> LifetimeName {
         match *self {
-            LifetimeName::Param(param_name) => LifetimeName::Param(param_name.modern()),
+            LifetimeName::Param(param_name) => {
+                LifetimeName::Param(param_name.normalize_to_macros_2_0())
+            }
             lifetime_name => lifetime_name,
         }
     }
@@ -597,7 +598,7 @@ pub struct WhereEqPredicate<'hir> {
     pub rhs_ty: &'hir Ty<'hir>,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub struct ModuleItems {
     // Use BTreeSets here so items are in the same order as in the
     // list of all items in Crate
@@ -606,17 +607,23 @@ pub struct ModuleItems {
     pub impl_items: BTreeSet<ImplItemId>,
 }
 
+/// A type representing only the top-level module.
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+pub struct CrateItem<'hir> {
+    pub module: Mod<'hir>,
+    pub attrs: &'hir [Attribute],
+    pub span: Span,
+}
+
 /// The top-level data structure that stores the entire contents of
 /// the crate currently being compiled.
 ///
-/// For more details, see the [rustc guide].
+/// For more details, see the [rustc dev guide].
 ///
-/// [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
+/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 #[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct Crate<'hir> {
-    pub module: Mod<'hir>,
-    pub attrs: &'hir [Attribute],
-    pub span: Span,
+    pub item: CrateItem<'hir>,
     pub exported_macros: &'hir [MacroDef<'hir>],
     // Attributes from non-exported macros, kept only for collecting the library feature list.
     pub non_exported_macro_attrs: &'hir [Attribute],
@@ -722,13 +729,12 @@ impl Crate<'_> {
 /// Not parsed directly, but created on macro import or `macro_rules!` expansion.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub struct MacroDef<'hir> {
-    pub name: Name,
+    pub ident: Ident,
     pub vis: Visibility<'hir>,
     pub attrs: &'hir [Attribute],
     pub hir_id: HirId,
     pub span: Span,
-    pub body: TokenStream,
-    pub legacy: bool,
+    pub ast: ast::MacroDef,
 }
 
 /// A block of statements `{ .. }`, which may have a label (in this case the
@@ -1850,7 +1856,7 @@ pub struct TraitItem<'hir> {
 
 /// Represents a trait method's body (or just argument names).
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
-pub enum TraitMethod<'hir> {
+pub enum TraitFn<'hir> {
     /// No default body in the trait, just a signature.
     Required(&'hir [Ident]),
 
@@ -1863,8 +1869,8 @@ pub enum TraitMethod<'hir> {
 pub enum TraitItemKind<'hir> {
     /// An associated constant with an optional value (otherwise `impl`s must contain a value).
     Const(&'hir Ty<'hir>, Option<BodyId>),
-    /// A method with an optional body.
-    Method(FnSig<'hir>, TraitMethod<'hir>),
+    /// An associated function with an optional body.
+    Fn(FnSig<'hir>, TraitFn<'hir>),
     /// An associated type with (possibly empty) bounds and optional concrete
     /// type.
     Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
@@ -1897,8 +1903,8 @@ pub enum ImplItemKind<'hir> {
     /// An associated constant of the given type, set to the constant result
     /// of the expression.
     Const(&'hir Ty<'hir>, BodyId),
-    /// A method implementation with the given signature and body.
-    Method(FnSig<'hir>, BodyId),
+    /// An associated function implementation with the given signature and body.
+    Fn(FnSig<'hir>, BodyId),
     /// An associated type.
     TyAlias(&'hir Ty<'hir>),
     /// An associated `type = impl Trait`.
@@ -1909,7 +1915,7 @@ impl ImplItemKind<'_> {
     pub fn namespace(&self) -> Namespace {
         match self {
             ImplItemKind::OpaqueTy(..) | ImplItemKind::TyAlias(..) => Namespace::TypeNS,
-            ImplItemKind::Const(..) | ImplItemKind::Method(..) => Namespace::ValueNS,
+            ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS,
         }
     }
 }
@@ -2653,7 +2659,7 @@ pub type TraitMap<ID = HirId> = NodeMap<Vec<TraitCandidate<ID>>>;
 // imported.
 pub type GlobMap = NodeMap<FxHashSet<Name>>;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub enum Node<'hir> {
     Param(&'hir Param<'hir>),
     Item(&'hir Item<'hir>),
@@ -2683,7 +2689,7 @@ pub enum Node<'hir> {
     GenericParam(&'hir GenericParam<'hir>),
     Visibility(&'hir Visibility<'hir>),
 
-    Crate,
+    Crate(&'hir CrateItem<'hir>),
 }
 
 impl Node<'_> {
@@ -2699,8 +2705,8 @@ impl Node<'_> {
 
     pub fn fn_decl(&self) -> Option<&FnDecl<'_>> {
         match self {
-            Node::TraitItem(TraitItem { kind: TraitItemKind::Method(fn_sig, _), .. })
-            | Node::ImplItem(ImplItem { kind: ImplItemKind::Method(fn_sig, _), .. })
+            Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
+            | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
             | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
             Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
                 Some(fn_decl)
diff --git a/src/librustc_hir/hir_id.rs b/src/librustc_hir/hir_id.rs
index 6d2ec445763..1c7987e965f 100644
--- a/src/librustc_hir/hir_id.rs
+++ b/src/librustc_hir/hir_id.rs
@@ -1,9 +1,8 @@
-use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
-use rustc_serialize::{self, Decodable, Decoder, Encodable, Encoder};
+use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
 use std::fmt;
 
 /// Uniquely identifies a node in the HIR of the current crate. It is
-/// composed of the `owner`, which is the `DefIndex` of the directly enclosing
+/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
 /// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
 /// and the `local_id` which is unique within the given owner.
 ///
@@ -12,41 +11,12 @@ use std::fmt;
 /// the `local_id` part of the `HirId` changing, which is a very useful property in
 /// incremental compilation where we have to persist things through changes to
 /// the code base.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
 pub struct HirId {
-    pub owner: DefIndex,
+    pub owner: LocalDefId,
     pub local_id: ItemLocalId,
 }
 
-impl HirId {
-    pub fn owner_def_id(self) -> DefId {
-        DefId::local(self.owner)
-    }
-
-    pub fn owner_local_def_id(self) -> LocalDefId {
-        LocalDefId::from_def_id(DefId::local(self.owner))
-    }
-}
-
-impl rustc_serialize::UseSpecializedEncodable for HirId {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        let HirId { owner, local_id } = *self;
-
-        owner.encode(s)?;
-        local_id.encode(s)?;
-        Ok(())
-    }
-}
-
-impl rustc_serialize::UseSpecializedDecodable for HirId {
-    fn default_decode<D: Decoder>(d: &mut D) -> Result<HirId, D::Error> {
-        let owner = DefIndex::decode(d)?;
-        let local_id = ItemLocalId::decode(d)?;
-
-        Ok(HirId { owner, local_id })
-    }
-}
-
 impl fmt::Display for HirId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self)
@@ -70,9 +40,12 @@ rustc_index::newtype_index! {
 rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId);
 
 /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`.
-pub const CRATE_HIR_ID: HirId =
-    HirId { owner: CRATE_DEF_INDEX, local_id: ItemLocalId::from_u32_const(0) };
+pub const CRATE_HIR_ID: HirId = HirId {
+    owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
+    local_id: ItemLocalId::from_u32(0),
+};
 
-pub const DUMMY_HIR_ID: HirId = HirId { owner: CRATE_DEF_INDEX, local_id: DUMMY_ITEM_LOCAL_ID };
+pub const DUMMY_HIR_ID: HirId =
+    HirId { owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, local_id: DUMMY_ITEM_LOCAL_ID };
 
 pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX;
diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs
index 45257b04d79..316b31f0698 100644
--- a/src/librustc_hir/intravisit.rs
+++ b/src/librustc_hir/intravisit.rs
@@ -127,6 +127,25 @@ pub trait Map<'hir> {
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
 }
 
+/// An erased version of `Map<'hir>`, using dynamic dispatch.
+/// NOTE: This type is effectively only usable with `NestedVisitorMap::None`.
+pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>);
+
+impl<'hir> Map<'hir> for ErasedMap<'hir> {
+    fn body(&self, id: BodyId) -> &'hir Body<'hir> {
+        self.0.body(id)
+    }
+    fn item(&self, id: HirId) -> &'hir Item<'hir> {
+        self.0.item(id)
+    }
+    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
+        self.0.trait_item(id)
+    }
+    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
+        self.0.impl_item(id)
+    }
+}
+
 /// Specifies what nested things a visitor wants to visit. The most
 /// common choice is `OnlyBodies`, which will cause the visitor to
 /// visit fn bodies for fns that it encounters, but skip over nested
@@ -134,7 +153,7 @@ pub trait Map<'hir> {
 ///
 /// See the comments on `ItemLikeVisitor` for more details on the overall
 /// visit strategy.
-pub enum NestedVisitorMap<'this, M> {
+pub enum NestedVisitorMap<M> {
     /// Do not visit any nested things. When you add a new
     /// "non-nested" thing, you will want to audit such uses to see if
     /// they remain valid.
@@ -151,20 +170,20 @@ pub enum NestedVisitorMap<'this, M> {
     /// to use `visit_all_item_likes()` as an outer loop,
     /// and to have the visitor that visits the contents of each item
     /// using this setting.
-    OnlyBodies(&'this M),
+    OnlyBodies(M),
 
     /// Visits all nested things, including item-likes.
     ///
     /// **This is an unusual choice.** It is used when you want to
     /// process everything within their lexical context. Typically you
     /// kick off the visit by doing `walk_krate()`.
-    All(&'this M),
+    All(M),
 }
 
-impl<'this, M> NestedVisitorMap<'this, M> {
+impl<M> NestedVisitorMap<M> {
     /// Returns the map to use for an "intra item-like" thing (if any).
     /// E.g., function body.
-    fn intra(self) -> Option<&'this M> {
+    fn intra(self) -> Option<M> {
         match self {
             NestedVisitorMap::None => None,
             NestedVisitorMap::OnlyBodies(map) => Some(map),
@@ -174,7 +193,7 @@ impl<'this, M> NestedVisitorMap<'this, M> {
 
     /// Returns the map to use for an "item-like" thing (if any).
     /// E.g., item, impl-item.
-    fn inter(self) -> Option<&'this M> {
+    fn inter(self) -> Option<M> {
         match self {
             NestedVisitorMap::None => None,
             NestedVisitorMap::OnlyBodies(_) => None,
@@ -221,7 +240,7 @@ pub trait Visitor<'v>: Sized {
     /// `panic!()`. This way, if a new `visit_nested_XXX` variant is
     /// added in the future, we will see the panic in your code and
     /// fix it appropriately.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map>;
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map>;
 
     /// Invoked when a nested item is encountered. By default does
     /// nothing unless you override `nested_visit_map` to return other than
@@ -284,7 +303,7 @@ pub trait Visitor<'v>: Sized {
     /// If you use this, you probably don't want to process the
     /// contents of nested item-like things, since the outer loop will
     /// visit them as well.
-    fn as_deep_visitor<'s>(&'s mut self) -> DeepVisitor<'s, Self> {
+    fn as_deep_visitor(&mut self) -> DeepVisitor<'_, Self> {
         DeepVisitor::new(self)
     }
 
@@ -438,14 +457,14 @@ pub trait Visitor<'v>: Sized {
 
 /// Walks the contents of a crate. See also `Crate::visit_all_items`.
 pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
-    visitor.visit_mod(&krate.module, krate.span, CRATE_HIR_ID);
-    walk_list!(visitor, visit_attribute, krate.attrs);
+    visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID);
+    walk_list!(visitor, visit_attribute, krate.item.attrs);
     walk_list!(visitor, visit_macro_def, krate.exported_macros);
 }
 
 pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) {
     visitor.visit_id(macro_def.hir_id);
-    visitor.visit_name(macro_def.span, macro_def.name);
+    visitor.visit_ident(macro_def.ident);
     walk_list!(visitor, visit_attribute, macro_def.attrs);
 }
 
@@ -911,14 +930,14 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_nested_body, default);
         }
-        TraitItemKind::Method(ref sig, TraitMethod::Required(param_names)) => {
+        TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
             visitor.visit_id(trait_item.hir_id);
             visitor.visit_fn_decl(&sig.decl);
             for &param_name in param_names {
                 visitor.visit_ident(param_name);
             }
         }
-        TraitItemKind::Method(ref sig, TraitMethod::Provided(body_id)) => {
+        TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
             visitor.visit_fn(
                 FnKind::Method(trait_item.ident, sig, None, &trait_item.attrs),
                 &sig.decl,
@@ -968,7 +987,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
             visitor.visit_ty(ty);
             visitor.visit_nested_body(body);
         }
-        ImplItemKind::Method(ref sig, body_id) => {
+        ImplItemKind::Fn(ref sig, body_id) => {
             visitor.visit_fn(
                 FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), &impl_item.attrs),
                 &sig.decl,
diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs
index fc91b68e3ea..89457009a8b 100644
--- a/src/librustc_hir/lang_items.rs
+++ b/src/librustc_hir/lang_items.rs
@@ -240,7 +240,6 @@ language_item_table! {
     StartFnLangItem,             "start",              start_fn,                Target::Fn;
 
     EhPersonalityLangItem,       "eh_personality",     eh_personality,          Target::Fn;
-    EhUnwindResumeLangItem,      "eh_unwind_resume",   eh_unwind_resume,        Target::Fn;
     EhCatchTypeinfoLangItem,     "eh_catch_typeinfo",  eh_catch_typeinfo,       Target::Static;
 
     OwnedBoxLangItem,            "owned_box",          owned_box,               Target::Struct;
diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs
index d958dfc681b..fa5c72b060d 100644
--- a/src/librustc_hir/lib.rs
+++ b/src/librustc_hir/lib.rs
@@ -1,9 +1,11 @@
-//! HIR datatypes. See the [rustc guide] for more info.
+//! HIR datatypes. See the [rustc dev guide] for more info.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 
 #![feature(crate_visibility_modifier)]
+#![feature(const_if_match)]
 #![feature(const_fn)] // For the unsizing cast on `&[]`
+#![feature(const_panic)]
 #![feature(in_band_lifetimes)]
 #![feature(specialization)]
 #![recursion_limit = "256"]
diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs
index 8cbbef959ce..4e9618b7676 100644
--- a/src/librustc_hir/print.rs
+++ b/src/librustc_hir/print.rs
@@ -102,7 +102,7 @@ impl<'a> State<'a> {
             Node::Ctor(..) => panic!("cannot print isolated Ctor"),
             Node::Local(a) => self.print_local_decl(&a),
             Node::MacroDef(_) => panic!("cannot print MacroDef"),
-            Node::Crate => panic!("cannot print Crate"),
+            Node::Crate(..) => panic!("cannot print Crate"),
         }
     }
 }
@@ -151,7 +151,7 @@ pub fn print_crate<'a>(
     // When printing the AST, we sometimes need to inject `#[no_std]` here.
     // Since you can't compile the HIR, it's not necessary.
 
-    s.print_mod(&krate.module, &krate.attrs);
+    s.print_mod(&krate.item.module, &krate.item.attrs);
     s.print_remaining_comments();
     s.s.eof()
 }
@@ -652,7 +652,7 @@ impl<'a> State<'a> {
                     self.word_nbsp("const");
                 }
 
-                if let hir::ImplPolarity::Negative = polarity {
+                if let hir::ImplPolarity::Negative(_) = polarity {
                     self.s.word("!");
                 }
 
@@ -886,13 +886,13 @@ impl<'a> State<'a> {
                     Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
                 self.print_associated_const(ti.ident, &ty, default, &vis);
             }
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => {
                 let vis =
                     Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
                 self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None);
                 self.s.word(";");
             }
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                 let vis =
                     Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
                 self.head("");
@@ -925,7 +925,7 @@ impl<'a> State<'a> {
             hir::ImplItemKind::Const(ref ty, expr) => {
                 self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis);
             }
-            hir::ImplItemKind::Method(ref sig, body) => {
+            hir::ImplItemKind::Fn(ref sig, body) => {
                 self.head("");
                 self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body));
                 self.nbsp();
diff --git a/src/librustc_hir/stable_hash_impls.rs b/src/librustc_hir/stable_hash_impls.rs
index 3938a0369b9..996b3108969 100644
--- a/src/librustc_hir/stable_hash_impls.rs
+++ b/src/librustc_hir/stable_hash_impls.rs
@@ -1,7 +1,11 @@
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 
-use crate::hir::{BodyId, Expr, ImplItemId, ItemId, Mod, TraitItemId, Ty, VisibilityKind};
-use crate::hir_id::HirId;
+use crate::hir::{
+    BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty,
+    VisibilityKind,
+};
+use crate::hir_id::{HirId, ItemLocalId};
+use rustc_span::def_id::{DefPathHash, LocalDefId};
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
 /// This is a hack to allow using the `HashStable_Generic` derive macro
@@ -16,6 +20,36 @@ pub trait HashStableContext:
     fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher);
     fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher);
     fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher);
+    fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F);
+    fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash;
+}
+
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        let def_path_hash = hcx.local_def_path_hash(self.owner);
+        (def_path_hash, self.local_id)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        self.hir_id.to_stable_hash_key(hcx)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        self.hir_id.to_stable_hash_key(hcx)
+    }
 }
 
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for HirId {
@@ -78,3 +112,56 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for VisibilityKind<'_>
         hcx.hash_hir_visibility_kind(self, hasher)
     }
 }
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItem<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            generics.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItem<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let ImplItem {
+            hir_id: _,
+            ident,
+            ref vis,
+            defaultness,
+            ref attrs,
+            ref generics,
+            ref kind,
+            span,
+        } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            vis.hash_stable(hcx, hasher);
+            defaultness.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            generics.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            vis.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
diff --git a/src/librustc_hir/target.rs b/src/librustc_hir/target.rs
index 501976fc3cb..3a4485a1b17 100644
--- a/src/librustc_hir/target.rs
+++ b/src/librustc_hir/target.rs
@@ -105,10 +105,10 @@ impl Target {
     pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
         match trait_item.kind {
             TraitItemKind::Const(..) => Target::AssocConst,
-            TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
+            TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
                 Target::Method(MethodKind::Trait { body: false })
             }
-            TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
+            TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => {
                 Target::Method(MethodKind::Trait { body: true })
             }
             TraitItemKind::Type(..) => Target::AssocTy,
diff --git a/src/librustc_hir/weak_lang_items.rs b/src/librustc_hir/weak_lang_items.rs
index 405a31d5a69..c0560eb8d45 100644
--- a/src/librustc_hir/weak_lang_items.rs
+++ b/src/librustc_hir/weak_lang_items.rs
@@ -43,6 +43,5 @@ impl LanguageItems {
 weak_lang_items! {
     panic_impl,         PanicImplLangItem,          rust_begin_unwind;
     eh_personality,     EhPersonalityLangItem,      rust_eh_personality;
-    eh_unwind_resume,   EhUnwindResumeLangItem,     rust_eh_unwind_resume;
     oom,                OomLangItem,                rust_oom;
 }
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index c82ed0c2c49..a7dccaf974b 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -68,7 +68,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
         let (if_this_changed, then_this_would_need) = {
             let mut visitor =
                 IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] };
-            visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().attrs);
+            visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().item.attrs);
             tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
             (visitor.if_this_changed, visitor.then_this_would_need)
         };
@@ -120,7 +120,7 @@ impl IfThisChanged<'tcx> {
             if attr.check_name(sym::rustc_if_this_changed) {
                 let dep_node_interned = self.argument(attr);
                 let dep_node = match dep_node_interned {
-                    None => def_path_hash.to_dep_node(DepKind::Hir),
+                    None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner),
                     Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) {
                         Ok(n) => n,
                         Err(()) => {
@@ -162,8 +162,8 @@ impl IfThisChanged<'tcx> {
 impl Visitor<'tcx> for IfThisChanged<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index 261540abcad..54d7e0ece50 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -44,7 +44,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) {
 
         let ams = AssertModuleSource { tcx, available_cgus };
 
-        for attr in tcx.hir().krate().attrs {
+        for attr in tcx.hir().krate().item.attrs {
             ams.check_attr(attr);
         }
     })
diff --git a/src/librustc_incremental/persist/README.md b/src/librustc_incremental/persist/README.md
index 8131d2840b4..b01fe219e1e 100644
--- a/src/librustc_incremental/persist/README.md
+++ b/src/librustc_incremental/persist/README.md
@@ -1,3 +1,3 @@
-For info on how the incremental compilation works, see the [rustc guide].
+For info on how the incremental compilation works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/query.html
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index e212dc81070..df5fd110db9 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -53,9 +53,9 @@ const BASE_FN: &[&str] = &[
 
 /// DepNodes for Hir, which is pretty much everything
 const BASE_HIR: &[&str] = &[
-    // Hir and HirBody should be computed for all nodes
-    label_strs::Hir,
-    label_strs::HirBody,
+    // hir_owner and hir_owner_items should be computed for all nodes
+    label_strs::hir_owner,
+    label_strs::hir_owner_items,
 ];
 
 /// `impl` implementation of struct/trait
@@ -328,12 +328,12 @@ impl DirtyCleanVisitor<'tcx> {
                 }
             }
             HirNode::TraitItem(item) => match item.kind {
-                TraitItemKind::Method(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT),
+                TraitItemKind::Fn(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT),
                 TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_IN_TRAIT),
                 TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT),
             },
             HirNode::ImplItem(item) => match item.kind {
-                ImplItemKind::Method(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL),
+                ImplItemKind::Fn(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL),
                 ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
                 ImplItemKind::TyAlias(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
                 ImplItemKind::OpaqueTy(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
@@ -548,8 +548,8 @@ impl FindAllAttrs<'tcx> {
 impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
-        intravisit::NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_attribute(&mut self, attr: &'tcx Attribute) {
diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs
index 5c72b049d97..048a81b81ba 100644
--- a/src/librustc_incremental/persist/file_format.rs
+++ b/src/librustc_incremental/persist/file_format.rs
@@ -14,8 +14,8 @@ use std::fs;
 use std::io::{self, Read};
 use std::path::Path;
 
-use rustc::session::config::nightly_options;
 use rustc_serialize::opaque::Encoder;
+use rustc_session::config::nightly_options;
 
 /// The first few bytes of files generated by incremental compilation.
 const FILE_MAGIC: &[u8] = b"RSIC";
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index 8548ad392d2..4926f726f35 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -103,11 +103,11 @@
 //! unsupported file system and emit a warning in that case. This is not yet
 //! implemented.
 
-use rustc::session::{CrateDisambiguator, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::{base_n, flock};
 use rustc_fs_util::{link_or_copy, LinkOrCopy};
+use rustc_session::{CrateDisambiguator, Session};
 
 use std::fs as std_fs;
 use std::io;
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 6c57f79e1a7..8a11586250d 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -1,12 +1,12 @@
 //! Code to save/load the dep-graph from files.
 
 use rustc::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
-use rustc::session::Session;
 use rustc::ty::query::OnDiskCache;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_serialize::opaque::Decoder;
 use rustc_serialize::Decodable as RustcDecodable;
+use rustc_session::Session;
 use std::path::Path;
 
 use super::data::*;
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 87f39dedd02..b465a11c99c 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -1,10 +1,10 @@
 use rustc::dep_graph::{DepGraph, DepKind, WorkProduct, WorkProductId};
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::join;
 use rustc_serialize::opaque::Encoder;
 use rustc_serialize::Encodable as RustcEncodable;
+use rustc_session::Session;
 use std::fs;
 use std::path::PathBuf;
 
diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs
index b1861acec04..aa3588b284b 100644
--- a/src/librustc_incremental/persist/work_product.rs
+++ b/src/librustc_incremental/persist/work_product.rs
@@ -2,8 +2,8 @@
 
 use crate::persist::fs::*;
 use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId};
-use rustc::session::Session;
 use rustc_fs_util::link_or_copy;
+use rustc_session::Session;
 use std::fs as std_fs;
 use std::path::PathBuf;
 
diff --git a/src/librustc_index/lib.rs b/src/librustc_index/lib.rs
index 86dd1a29d0c..e8aa1a209e9 100644
--- a/src/librustc_index/lib.rs
+++ b/src/librustc_index/lib.rs
@@ -1,4 +1,7 @@
 #![feature(allow_internal_unstable)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(unboxed_closures)]
 #![feature(test)]
 #![feature(fn_traits)]
diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs
index 7020939fa20..d8c67f6210c 100644
--- a/src/librustc_index/vec.rs
+++ b/src/librustc_index/vec.rs
@@ -120,10 +120,10 @@ macro_rules! newtype_index {
         impl $type {
             $v const MAX_AS_U32: u32 = $max;
 
-            $v const MAX: Self = Self::from_u32_const($max);
+            $v const MAX: Self = Self::from_u32($max);
 
             #[inline]
-            $v fn from_usize(value: usize) -> Self {
+            $v const fn from_usize(value: usize) -> Self {
                 assert!(value <= ($max as usize));
                 unsafe {
                     Self::from_u32_unchecked(value as u32)
@@ -131,31 +131,13 @@ macro_rules! newtype_index {
             }
 
             #[inline]
-            $v fn from_u32(value: u32) -> Self {
+            $v const fn from_u32(value: u32) -> Self {
                 assert!(value <= $max);
                 unsafe {
                     Self::from_u32_unchecked(value)
                 }
             }
 
-            /// Hacky variant of `from_u32` for use in constants.
-            /// This version checks the "max" constraint by using an
-            /// invalid array dereference.
-            #[inline]
-            $v const fn from_u32_const(value: u32) -> Self {
-                // This will fail at const eval time unless `value <=
-                // max` is true (in which case we get the index 0).
-                // It will also fail at runtime, of course, but in a
-                // kind of wacky way.
-                let _ = ["out of range value used"][
-                    !(value <= $max) as usize
-                ];
-
-                unsafe {
-                    Self { private: value }
-                }
-            }
-
             #[inline]
             $v const unsafe fn from_u32_unchecked(value: u32) -> Self {
                 Self { private: value }
@@ -163,19 +145,19 @@ macro_rules! newtype_index {
 
             /// Extracts the value of this index as an integer.
             #[inline]
-            $v fn index(self) -> usize {
+            $v const fn index(self) -> usize {
                 self.as_usize()
             }
 
             /// Extracts the value of this index as a `u32`.
             #[inline]
-            $v fn as_u32(self) -> u32 {
+            $v const fn as_u32(self) -> u32 {
                 self.private
             }
 
             /// Extracts the value of this index as a `usize`.
             #[inline]
-            $v fn as_usize(self) -> usize {
+            $v const fn as_usize(self) -> usize {
                 self.as_u32() as usize
             }
         }
@@ -500,7 +482,7 @@ macro_rules! newtype_index {
                    const $name:ident = $constant:expr,
                    $($tokens:tt)*) => (
         $(#[doc = $doc])*
-        $v const $name: $type = $type::from_u32_const($constant);
+        $v const $name: $type = $type::from_u32($constant);
         $crate::newtype_index!(
             @derives      [$($derives,)*]
             @attrs        [$(#[$attrs])*]
diff --git a/src/librustc_infer/Cargo.toml b/src/librustc_infer/Cargo.toml
index de99214901d..9ecd056430c 100644
--- a/src/librustc_infer/Cargo.toml
+++ b/src/librustc_infer/Cargo.toml
@@ -10,14 +10,11 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
-rustc_attr = { path = "../librustc_attr" }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_index = { path = "../librustc_index" }
 rustc_macros = { path = "../librustc_macros" }
diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs
index 4d3f25290e1..964e378f7ab 100644
--- a/src/librustc_infer/infer/canonical/canonicalizer.rs
+++ b/src/librustc_infer/infer/canonical/canonicalizer.rs
@@ -1,9 +1,9 @@
 //! This module contains the "canonicalizer" itself.
 //!
 //! For an overview of what canonicalization is and how it fits into
-//! rustc, check out the [chapter in the rustc guide][c].
+//! rustc, check out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::canonical::{
     Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Canonicalized,
@@ -33,9 +33,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// with a mapping M that maps `'?0` to `'static`.
     ///
     /// To get a good understanding of what is happening here, check
-    /// out the [chapter in the rustc guide][c].
+    /// out the [chapter in the rustc dev guide][c].
     ///
-    /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query
+    /// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#canonicalizing-the-query
     pub fn canonicalize_query<V>(
         &self,
         value: &V,
@@ -77,9 +77,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// reference to `'static` alone.
     ///
     /// To get a good understanding of what is happening here, check
-    /// out the [chapter in the rustc guide][c].
+    /// out the [chapter in the rustc dev guide][c].
     ///
-    /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result
+    /// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#canonicalizing-the-query-result
     pub fn canonicalize_response<V>(&self, value: &V) -> Canonicalized<'tcx, V>
     where
         V: TypeFoldable<'tcx>,
diff --git a/src/librustc_infer/infer/canonical/mod.rs b/src/librustc_infer/infer/canonical/mod.rs
index ba019a8cf03..0e9593e8ea6 100644
--- a/src/librustc_infer/infer/canonical/mod.rs
+++ b/src/librustc_infer/infer/canonical/mod.rs
@@ -17,9 +17,9 @@
 //! `instantiate_query_result` method.
 //!
 //! For a more detailed look at what is happening here, check
-//! out the [chapter in the rustc guide][c].
+//! out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
 use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs
index 966bd997877..9322df48235 100644
--- a/src/librustc_infer/infer/canonical/query_response.rs
+++ b/src/librustc_infer/infer/canonical/query_response.rs
@@ -3,9 +3,9 @@
 //! encode them therein.
 //!
 //! For an overview of what canonicaliation is and how it fits into
-//! rustc, check out the [chapter in the rustc guide][c].
+//! rustc, check out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::canonical::substitute::{substitute_value, CanonicalExt};
 use crate::infer::canonical::{
@@ -14,7 +14,7 @@ use crate::infer::canonical::{
 };
 use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
-use crate::infer::{InferCtxt, InferCtxtBuilder, InferOk, InferResult, NLLRegionVariableOrigin};
+use crate::infer::{InferCtxt, InferOk, InferResult, NLLRegionVariableOrigin};
 use crate::traits::query::{Fallible, NoSolution};
 use crate::traits::{DomainGoal, TraitEngine};
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
@@ -26,52 +26,8 @@ use rustc::ty::{self, BoundVar, Ty, TyCtxt};
 use rustc_data_structures::captures::Captures;
 use rustc_index::vec::Idx;
 use rustc_index::vec::IndexVec;
-use rustc_span::DUMMY_SP;
 use std::fmt::Debug;
 
-impl<'tcx> InferCtxtBuilder<'tcx> {
-    /// The "main method" for a canonicalized trait query. Given the
-    /// canonical key `canonical_key`, this method will create a new
-    /// inference context, instantiate the key, and run your operation
-    /// `op`. The operation should yield up a result (of type `R`) as
-    /// well as a set of trait obligations that must be fully
-    /// satisfied. These obligations will be processed and the
-    /// canonical result created.
-    ///
-    /// Returns `NoSolution` in the event of any error.
-    ///
-    /// (It might be mildly nicer to implement this on `TyCtxt`, and
-    /// not `InferCtxtBuilder`, but that is a bit tricky right now.
-    /// In part because we would need a `for<'tcx>` sort of
-    /// bound for the closure and in part because it is convenient to
-    /// have `'tcx` be free on this function so that we can talk about
-    /// `K: TypeFoldable<'tcx>`.)
-    pub fn enter_canonical_trait_query<K, R>(
-        &mut self,
-        canonical_key: &Canonical<'tcx, K>,
-        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
-    where
-        K: TypeFoldable<'tcx>,
-        R: Debug + TypeFoldable<'tcx>,
-        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable,
-    {
-        self.enter_with_canonical(
-            DUMMY_SP,
-            canonical_key,
-            |ref infcx, key, canonical_inference_vars| {
-                let mut fulfill_cx = TraitEngine::new(infcx.tcx);
-                let value = operation(infcx, &mut *fulfill_cx, key)?;
-                infcx.make_canonicalized_query_response(
-                    canonical_inference_vars,
-                    value,
-                    &mut *fulfill_cx,
-                )
-            },
-        )
-    }
-}
-
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// This method is meant to be invoked as the final step of a canonical query
     /// implementation. It is given:
@@ -196,9 +152,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// the query before applying this function.)
     ///
     /// To get a good understanding of what is happening here, check
-    /// out the [chapter in the rustc guide][c].
+    /// out the [chapter in the rustc dev guide][c].
     ///
-    /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#processing-the-canonicalized-query-result
+    /// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#processing-the-canonicalized-query-result
     pub fn instantiate_query_response_and_region_obligations<R>(
         &self,
         cause: &ObligationCause<'tcx>,
diff --git a/src/librustc_infer/infer/canonical/substitute.rs b/src/librustc_infer/infer/canonical/substitute.rs
index 99ddedfe881..afef32c1ffe 100644
--- a/src/librustc_infer/infer/canonical/substitute.rs
+++ b/src/librustc_infer/infer/canonical/substitute.rs
@@ -2,9 +2,9 @@
 //! `Canonical<'tcx, T>`.
 //!
 //! For an overview of what canonicalization is and how it fits into
-//! rustc, check out the [chapter in the rustc guide][c].
+//! rustc, check out the [chapter in the rustc dev guide][c].
 //!
-//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 
 use crate::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc::ty::fold::TypeFoldable;
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index 40b493de9f4..ebbfcb28db2 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -49,8 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError;
 use super::region_constraints::GenericKind;
 use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
 
-use crate::infer::opaque_types;
-use crate::infer::{self, SuppressRegionErrors};
+use crate::infer;
 use crate::traits::error_reporting::report_object_safety_error;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
@@ -269,14 +268,14 @@ fn item_scope_tag(item: &hir::Item<'_>) -> &'static str {
 
 fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str {
     match item.kind {
-        hir::TraitItemKind::Method(..) => "method body",
+        hir::TraitItemKind::Fn(..) => "method body",
         hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item",
     }
 }
 
 fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str {
     match item.kind {
-        hir::ImplItemKind::Method(..) => "method body",
+        hir::ImplItemKind::Fn(..) => "method body",
         hir::ImplItemKind::Const(..)
         | hir::ImplItemKind::OpaqueTy(..)
         | hir::ImplItemKind::TyAlias(..) => "associated item",
@@ -288,22 +287,93 @@ fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option
     (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))
 }
 
+pub fn unexpected_hidden_region_diagnostic(
+    tcx: TyCtxt<'tcx>,
+    region_scope_tree: Option<&region::ScopeTree>,
+    span: Span,
+    hidden_ty: Ty<'tcx>,
+    hidden_region: ty::Region<'tcx>,
+) -> DiagnosticBuilder<'tcx> {
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0700,
+        "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
+    );
+
+    // Explain the region we are capturing.
+    if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region {
+        // Assuming regionck succeeded (*), we ought to always be
+        // capturing *some* region from the fn header, and hence it
+        // ought to be free. So under normal circumstances, we will go
+        // down this path which gives a decent human readable
+        // explanation.
+        //
+        // (*) if not, the `tainted_by_errors` flag would be set to
+        // true in any case, so we wouldn't be here at all.
+        note_and_explain_free_region(
+            tcx,
+            &mut err,
+            &format!("hidden type `{}` captures ", hidden_ty),
+            hidden_region,
+            "",
+        );
+    } else {
+        // Ugh. This is a painful case: the hidden region is not one
+        // that we can easily summarize or explain. This can happen
+        // in a case like
+        // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
+        //
+        // ```
+        // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
+        //   if condition() { a } else { b }
+        // }
+        // ```
+        //
+        // Here the captured lifetime is the intersection of `'a` and
+        // `'b`, which we can't quite express.
+
+        if let Some(region_scope_tree) = region_scope_tree {
+            // If the `region_scope_tree` is available, this is being
+            // invoked from the "region inferencer error". We can at
+            // least report a really cryptic error for now.
+            note_and_explain_region(
+                tcx,
+                region_scope_tree,
+                &mut err,
+                &format!("hidden type `{}` captures ", hidden_ty),
+                hidden_region,
+                "",
+            );
+        } else {
+            // If the `region_scope_tree` is *unavailable*, this is
+            // being invoked by the code that comes *after* region
+            // inferencing. This is a bug, as the region inferencer
+            // ought to have noticed the failed constraint and invoked
+            // error reporting, which in turn should have prevented us
+            // from getting trying to infer the hidden type
+            // completely.
+            tcx.sess.delay_span_bug(
+                span,
+                &format!(
+                    "hidden type captures unexpected lifetime `{:?}` \
+                     but no region inference failure",
+                    hidden_region,
+                ),
+            );
+        }
+    }
+
+    err
+}
+
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn report_region_errors(
         &self,
         region_scope_tree: &region::ScopeTree,
         errors: &Vec<RegionResolutionError<'tcx>>,
-        suppress: SuppressRegionErrors,
     ) {
-        debug!(
-            "report_region_errors(): {} errors to start, suppress = {:?}",
-            errors.len(),
-            suppress
-        );
-
-        if suppress.suppressed() {
-            return;
-        }
+        debug!("report_region_errors(): {} errors to start", errors.len());
 
         // try to pre-process the errors, which will group some of them
         // together into a `ProcessedErrors` group:
@@ -410,7 +480,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         span,
                     } => {
                         let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
-                        opaque_types::unexpected_hidden_region_diagnostic(
+                        unexpected_hidden_region_diagnostic(
                             self.tcx,
                             Some(region_scope_tree),
                             span,
@@ -2077,7 +2147,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
 /// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks
 /// extra information about each type, but we only care about the category.
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
-crate enum TyCategory {
+pub enum TyCategory {
     Closure,
     Opaque,
     Generator,
diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs
index 285f0c9cf51..0eda4555e25 100644
--- a/src/librustc_infer/infer/error_reporting/need_type_info.rs
+++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs
@@ -16,7 +16,7 @@ use std::borrow::Cow;
 struct FindLocalByTypeVisitor<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
     target_ty: Ty<'tcx>,
-    hir_map: &'a Map<'tcx>,
+    hir_map: Map<'tcx>,
     found_local_pattern: Option<&'tcx Pat<'tcx>>,
     found_arg_pattern: Option<&'tcx Pat<'tcx>>,
     found_ty: Option<Ty<'tcx>>,
@@ -25,7 +25,7 @@ struct FindLocalByTypeVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
-    fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: &'a Map<'tcx>) -> Self {
+    fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: Map<'tcx>) -> Self {
         Self {
             infcx,
             target_ty,
@@ -69,8 +69,8 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
 impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.hir_map)
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.hir_map)
     }
 
     fn visit_local(&mut self, local: &'tcx Local<'tcx>) {
@@ -223,7 +223,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let ty = self.resolve_vars_if_possible(&ty);
         let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
 
-        let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir());
+        let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, self.tcx.hir());
         let ty_to_string = |ty: Ty<'tcx>| -> String {
             let mut s = String::new();
             let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
@@ -468,7 +468,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             &segment.args,
         ) {
             let borrow = tables.borrow();
-            if let Some((DefKind::Method, did)) = borrow.type_dependent_def(e.hir_id) {
+            if let Some((DefKind::AssocFn, did)) = borrow.type_dependent_def(e.hir_id) {
                 let generics = self.tcx.generics_of(did);
                 if !generics.params.is_empty() {
                     err.span_suggestion(
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs
index 1a09729ef64..50b324c7227 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -3,6 +3,8 @@
 
 use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
+use crate::infer::lexical_region_resolve::RegionResolutionError;
+use crate::infer::SubregionOrigin;
 use rustc::util::common::ErrorReported;
 
 use rustc_errors::struct_span_err;
@@ -47,6 +49,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
         let (span, sub, sup) = self.regions()?;
 
+        if let Some(RegionResolutionError::ConcreteFailure(
+            SubregionOrigin::ReferenceOutlivesReferent(..),
+            ..,
+        )) = self.error
+        {
+            // This error doesn't make much sense in this case.
+            return None;
+        }
+
         // Determine whether the sub and sup consist of both anonymous (elided) regions.
         let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
 
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs
index 2ae7f4cc04f..15acf632b2c 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -33,11 +33,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 let fndecl = match self.tcx().hir().get(hir_id) {
                     Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. })
                     | Node::TraitItem(&hir::TraitItem {
-                        kind: hir::TraitItemKind::Method(ref m, ..),
+                        kind: hir::TraitItemKind::Fn(ref m, ..),
                         ..
                     })
                     | Node::ImplItem(&hir::ImplItem {
-                        kind: hir::ImplItemKind::Method(ref m, ..),
+                        kind: hir::ImplItemKind::Fn(ref m, ..),
                         ..
                     }) => &m.decl,
                     _ => return None,
@@ -93,8 +93,8 @@ struct FindNestedTypeVisitor<'tcx> {
 impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
@@ -212,8 +212,8 @@ struct TyPathVisitor<'tcx> {
 impl Visitor<'tcx> for TyPathVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'tcx>> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Map<'tcx>> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
index d8c314a0d2f..2357ee689d5 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
@@ -17,12 +17,7 @@ mod util;
 
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool {
-        if let Some(tables) = self.in_progress_tables {
-            let tables = tables.borrow();
-            NiceRegionError::new(self, error.clone(), Some(&tables)).try_report().is_some()
-        } else {
-            NiceRegionError::new(self, error.clone(), None).try_report().is_some()
-        }
+        NiceRegionError::new(self, error.clone()).try_report().is_some()
     }
 }
 
@@ -30,16 +25,11 @@ pub struct NiceRegionError<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     error: Option<RegionResolutionError<'tcx>>,
     regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>,
-    tables: Option<&'cx ty::TypeckTables<'tcx>>,
 }
 
 impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
-    pub fn new(
-        infcx: &'cx InferCtxt<'cx, 'tcx>,
-        error: RegionResolutionError<'tcx>,
-        tables: Option<&'cx ty::TypeckTables<'tcx>>,
-    ) -> Self {
-        Self { infcx, error: Some(error), regions: None, tables }
+    pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self {
+        Self { infcx, error: Some(error), regions: None }
     }
 
     pub fn new_from_span(
@@ -47,9 +37,8 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
         span: Span,
         sub: ty::Region<'tcx>,
         sup: ty::Region<'tcx>,
-        tables: Option<&'cx ty::TypeckTables<'tcx>>,
     ) -> Self {
-        Self { infcx, error: None, regions: Some((span, sub, sup)), tables }
+        Self { infcx, error: None, regions: Some((span, sub, sup)) }
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs
index cab632935fd..de72c276595 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs
@@ -51,52 +51,44 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         };
 
         let hir = &self.tcx().hir();
-        if let Some(hir_id) = hir.as_local_hir_id(id) {
-            if let Some(body_id) = hir.maybe_body_owned_by(hir_id) {
-                let body = hir.body(body_id);
-                let owner_id = hir.body_owner(body_id);
-                let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
-                if let Some(tables) = self.tables {
-                    body.params
-                        .iter()
-                        .enumerate()
-                        .filter_map(|(index, param)| {
-                            // May return None; sometimes the tables are not yet populated.
-                            let ty_hir_id = fn_decl.inputs[index].hir_id;
-                            let param_ty_span = hir.span(ty_hir_id);
-                            let ty = tables.node_type_opt(param.hir_id)?;
-                            let mut found_anon_region = false;
-                            let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| {
-                                if *r == *anon_region {
-                                    found_anon_region = true;
-                                    replace_region
-                                } else {
-                                    r
-                                }
-                            });
-                            if found_anon_region {
-                                let is_first = index == 0;
-                                Some(AnonymousParamInfo {
-                                    param,
-                                    param_ty: new_param_ty,
-                                    param_ty_span,
-                                    bound_region,
-                                    is_first,
-                                })
-                            } else {
-                                None
-                            }
-                        })
-                        .next()
+        let hir_id = hir.as_local_hir_id(id)?;
+        let body_id = hir.maybe_body_owned_by(hir_id)?;
+        let body = hir.body(body_id);
+        let owner_id = hir.body_owner(body_id);
+        let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
+        let poly_fn_sig = self.tcx().fn_sig(id);
+        let fn_sig = self.tcx().liberate_late_bound_regions(id, &poly_fn_sig);
+        body.params
+            .iter()
+            .enumerate()
+            .filter_map(|(index, param)| {
+                // May return None; sometimes the tables are not yet populated.
+                let ty = fn_sig.inputs()[index];
+                let mut found_anon_region = false;
+                let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| {
+                    if *r == *anon_region {
+                        found_anon_region = true;
+                        replace_region
+                    } else {
+                        r
+                    }
+                });
+                if found_anon_region {
+                    let ty_hir_id = fn_decl.inputs[index].hir_id;
+                    let param_ty_span = hir.span(ty_hir_id);
+                    let is_first = index == 0;
+                    Some(AnonymousParamInfo {
+                        param,
+                        param_ty: new_param_ty,
+                        param_ty_span,
+                        bound_region,
+                        is_first,
+                    })
                 } else {
                     None
                 }
-            } else {
-                None
-            }
-        } else {
-            None
-        }
+            })
+            .next()
     }
 
     // Here, we check for the case where the anonymous region
diff --git a/src/librustc_infer/infer/higher_ranked/README.md b/src/librustc_infer/infer/higher_ranked/README.md
index e7afaa5beb0..533d0ef7e6c 100644
--- a/src/librustc_infer/infer/higher_ranked/README.md
+++ b/src/librustc_infer/infer/higher_ranked/README.md
@@ -1,8 +1,8 @@
 To learn more about how Higher-ranked trait bounds work in the _old_ trait
-solver, see [this chapter][oldhrtb] of the rustc-guide.
+solver, see [this chapter][oldhrtb] of the rustc-dev-guide.
 
 To learn more about how they work in the _new_ trait solver, see [this
 chapter][newhrtb].
 
-[oldhrtb]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html
-[newhrtb]: https://rust-lang.github.io/rustc-guide/borrow_check/region_inference.html#placeholders-and-universes
+[oldhrtb]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
+[newhrtb]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference.html#placeholders-and-universes
diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs
index 33781188a95..105b987f85e 100644
--- a/src/librustc_infer/infer/higher_ranked/mod.rs
+++ b/src/librustc_infer/infer/higher_ranked/mod.rs
@@ -71,9 +71,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// needed (but is also permitted).
     ///
     /// For more information about how placeholders and HRTBs work, see
-    /// the [rustc guide].
+    /// the [rustc dev guide].
     ///
-    /// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html
+    /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
     pub fn replace_bound_vars_with_placeholders<T>(
         &self,
         binder: &ty::Binder<T>,
diff --git a/src/librustc_infer/infer/lexical_region_resolve/README.md b/src/librustc_infer/infer/lexical_region_resolve/README.md
index c26b5625a90..e0b2c0bffee 100644
--- a/src/librustc_infer/infer/lexical_region_resolve/README.md
+++ b/src/librustc_infer/infer/lexical_region_resolve/README.md
@@ -2,6 +2,6 @@
 Lexical Region Resolution was removed in https://github.com/rust-lang/rust/pull/64790.
 
 Rust now uses Non-lexical lifetimes. For more info, please see the [borrowck
-chapter][bc] in the rustc-guide.
+chapter][bc] in the rustc-dev-guide.
 
-[bc]: https://rust-lang.github.io/rustc-guide/borrow_check/region_inference.html
+[bc]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference.html
diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs
index b7278ecd5e4..3af10e850d5 100644
--- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs
@@ -7,6 +7,7 @@ use crate::infer::region_constraints::RegionConstraintData;
 use crate::infer::region_constraints::VarInfos;
 use crate::infer::region_constraints::VerifyBound;
 use crate::infer::RegionVariableOrigin;
+use crate::infer::RegionckMode;
 use crate::infer::SubregionOrigin;
 use rustc::middle::free_region::RegionRelations;
 use rustc::ty::fold::TypeFoldable;
@@ -33,12 +34,29 @@ pub fn resolve<'tcx>(
     region_rels: &RegionRelations<'_, 'tcx>,
     var_infos: VarInfos,
     data: RegionConstraintData<'tcx>,
+    mode: RegionckMode,
 ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
     debug!("RegionConstraintData: resolve_regions()");
     let mut errors = vec![];
     let mut resolver = LexicalResolver { region_rels, var_infos, data };
-    let values = resolver.infer_variable_values(&mut errors);
-    (values, errors)
+    match mode {
+        RegionckMode::Solve => {
+            let values = resolver.infer_variable_values(&mut errors);
+            (values, errors)
+        }
+        RegionckMode::Erase { suppress_errors: false } => {
+            // Do real inference to get errors, then erase the results.
+            let mut values = resolver.infer_variable_values(&mut errors);
+            let re_erased = region_rels.tcx.lifetimes.re_erased;
+
+            values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased));
+            (values, errors)
+        }
+        RegionckMode::Erase { suppress_errors: true } => {
+            // Skip region inference entirely.
+            (resolver.erased_data(region_rels.tcx), Vec::new())
+        }
+    }
 }
 
 /// Contains the result of lexical region resolution. Offers methods
@@ -163,6 +181,19 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
     }
 
+    /// An erased version of the lexical region resolutions. Used when we're
+    /// erasing regions and suppressing errors: in item bodies with
+    /// `-Zborrowck=mir`.
+    fn erased_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
+        LexicalRegionResolutions {
+            error_region: tcx.lifetimes.re_static,
+            values: IndexVec::from_elem_n(
+                VarValue::Value(tcx.lifetimes.re_erased),
+                self.num_vars(),
+            ),
+        }
+    }
+
     fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) {
         debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context);
         for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() {
diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs
index 938a0e7ab39..391fce946bf 100644
--- a/src/librustc_infer/infer/mod.rs
+++ b/src/librustc_infer/infer/mod.rs
@@ -5,7 +5,6 @@ pub use self::LateBoundRegionConversionTime::*;
 pub use self::RegionVariableOrigin::*;
 pub use self::SubregionOrigin::*;
 pub use self::ValuePairs::*;
-pub use rustc::ty::IntVarValue;
 
 use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
 
@@ -13,18 +12,17 @@ use rustc::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
 use rustc::middle::free_region::RegionRelations;
-use rustc::middle::lang_items;
 use rustc::middle::region;
 use rustc::mir;
 use rustc::mir::interpret::ConstEvalResult;
-use rustc::session::config::BorrowckMode;
+use rustc::traits::select;
 use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use rustc::ty::fold::{TypeFoldable, TypeFolder};
 use rustc::ty::relate::RelateResult;
 use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
+pub use rustc::ty::IntVarValue;
 use rustc::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
 use rustc::ty::{ConstVid, FloatVid, IntVid, TyVid};
-
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
@@ -32,8 +30,10 @@ use rustc_data_structures::unify as ut;
 use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_session::config::BorrowckMode;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
+
 use std::cell::{Cell, Ref, RefCell};
 use std::collections::BTreeMap;
 use std::fmt;
@@ -58,7 +58,6 @@ pub mod lattice;
 mod lexical_region_resolve;
 mod lub;
 pub mod nll_relate;
-pub mod opaque_types;
 pub mod outlives;
 pub mod region_constraints;
 pub mod resolve;
@@ -80,31 +79,50 @@ pub type Bound<T> = Option<T>;
 pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
 pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"
 
-/// A flag that is used to suppress region errors. This is normally
-/// false, but sometimes -- when we are doing region checks that the
-/// NLL borrow checker will also do -- it might be set to true.
-#[derive(Copy, Clone, Default, Debug)]
-pub struct SuppressRegionErrors {
-    suppressed: bool,
+/// How we should handle region solving.
+///
+/// This is used so that the region values inferred by HIR region solving are
+/// not exposed, and so that we can avoid doing work in HIR typeck that MIR
+/// typeck will also do.
+#[derive(Copy, Clone, Debug)]
+pub enum RegionckMode {
+    /// The default mode: report region errors, don't erase regions.
+    Solve,
+    /// Erase the results of region after solving.
+    Erase {
+        /// A flag that is used to suppress region errors, when we are doing
+        /// region checks that the NLL borrow checker will also do -- it might
+        /// be set to true.
+        suppress_errors: bool,
+    },
+}
+
+impl Default for RegionckMode {
+    fn default() -> Self {
+        RegionckMode::Solve
+    }
 }
 
-impl SuppressRegionErrors {
+impl RegionckMode {
     pub fn suppressed(self) -> bool {
-        self.suppressed
+        match self {
+            Self::Solve => false,
+            Self::Erase { suppress_errors } => suppress_errors,
+        }
     }
 
     /// Indicates that the MIR borrowck will repeat these region
     /// checks, so we should ignore errors if NLL is (unconditionally)
     /// enabled.
-    pub fn when_nll_is_enabled(tcx: TyCtxt<'_>) -> Self {
+    pub fn for_item_body(tcx: TyCtxt<'_>) -> Self {
         // FIXME(Centril): Once we actually remove `::Migrate` also make
         // this always `true` and then proceed to eliminate the dead code.
         match tcx.borrowck_mode() {
             // If we're on Migrate mode, report AST region errors
-            BorrowckMode::Migrate => SuppressRegionErrors { suppressed: false },
+            BorrowckMode::Migrate => RegionckMode::Erase { suppress_errors: false },
 
             // If we're on MIR, don't report AST region errors as they should be reported by NLL
-            BorrowckMode::Mir => SuppressRegionErrors { suppressed: true },
+            BorrowckMode::Mir => RegionckMode::Erase { suppress_errors: true },
         }
     }
 }
@@ -215,10 +233,10 @@ pub struct InferCtxt<'a, 'tcx> {
 
     /// Caches the results of trait selection. This cache is used
     /// for things that have to do with the parameters in scope.
-    pub selection_cache: traits::SelectionCache<'tcx>,
+    pub selection_cache: select::SelectionCache<'tcx>,
 
     /// Caches the results of trait evaluation.
-    pub evaluation_cache: traits::EvaluationCache<'tcx>,
+    pub evaluation_cache: select::EvaluationCache<'tcx>,
 
     /// the set of predicates on which errors have been reported, to
     /// avoid reporting the same error twice.
@@ -1208,20 +1226,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         region_context: DefId,
         region_map: &region::ScopeTree,
         outlives_env: &OutlivesEnvironment<'tcx>,
-        suppress: SuppressRegionErrors,
+        mode: RegionckMode,
     ) {
         assert!(
             self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(),
             "region_obligations not empty: {:#?}",
             self.inner.borrow().region_obligations
         );
-
-        let region_rels = &RegionRelations::new(
-            self.tcx,
-            region_context,
-            region_map,
-            outlives_env.free_region_map(),
-        );
         let (var_infos, data) = self
             .inner
             .borrow_mut()
@@ -1229,8 +1240,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             .take()
             .expect("regions already resolved")
             .into_infos_and_data();
+
+        let region_rels = &RegionRelations::new(
+            self.tcx,
+            region_context,
+            region_map,
+            outlives_env.free_region_map(),
+        );
+
         let (lexical_region_resolutions, errors) =
-            lexical_region_resolve::resolve(region_rels, var_infos, data);
+            lexical_region_resolve::resolve(region_rels, var_infos, data, mode);
 
         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
         assert!(old_value.is_none());
@@ -1241,7 +1260,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             // this infcx was in use.  This is totally hokey but
             // otherwise we have a hard time separating legit region
             // errors from silly ones.
-            self.report_region_errors(region_map, &errors, suppress);
+            self.report_region_errors(region_map, &errors);
         }
     }
 
@@ -1474,27 +1493,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             .verify_generic_bound(origin, kind, a, bound);
     }
 
-    pub fn type_is_copy_modulo_regions(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        ty: Ty<'tcx>,
-        span: Span,
-    ) -> bool {
-        let ty = self.resolve_vars_if_possible(&ty);
-
-        if !(param_env, ty).has_local_value() {
-            return ty.is_copy_modulo_regions(self.tcx, param_env, span);
-        }
-
-        let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
-
-        // This can get called from typeck (by euv), and `moves_by_default`
-        // rightly refuses to work with inference variables, but
-        // moves_by_default has a cache, which we want to use in other
-        // cases.
-        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
-    }
-
     /// Obtains the latest type of the given closure; this may be a
     /// closure in the current function, in which case its
     /// `ClosureKind` may not yet be known.
@@ -1518,30 +1516,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         closure_sig_ty.fn_sig(self.tcx)
     }
 
-    /// Normalizes associated types in `value`, potentially returning
-    /// new obligations that must further be processed.
-    pub fn partially_normalize_associated_types_in<T>(
-        &self,
-        span: Span,
-        body_id: hir::HirId,
-        param_env: ty::ParamEnv<'tcx>,
-        value: &T,
-    ) -> InferOk<'tcx, T>
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        debug!("partially_normalize_associated_types_in(value={:?})", value);
-        let mut selcx = traits::SelectionContext::new(self);
-        let cause = ObligationCause::misc(span, body_id);
-        let traits::Normalized { value, obligations } =
-            traits::normalize(&mut selcx, param_env, cause, value);
-        debug!(
-            "partially_normalize_associated_types_in: result={:?} predicates={:?}",
-            value, obligations
-        );
-        InferOk { value, obligations }
-    }
-
     /// Clears the selection, evaluation, and projection caches. This is useful when
     /// repeatedly attempting to select an `Obligation` while changing only
     /// its `ParamEnv`, since `FulfillmentContext` doesn't use probing.
diff --git a/src/librustc_infer/infer/outlives/env.rs b/src/librustc_infer/infer/outlives/env.rs
index aac6c7640ca..6c1e86bf408 100644
--- a/src/librustc_infer/infer/outlives/env.rs
+++ b/src/librustc_infer/infer/outlives/env.rs
@@ -1,10 +1,11 @@
 use crate::infer::{GenericKind, InferCtxt};
-use crate::traits::query::outlives_bounds::{self, OutlivesBound};
+use crate::traits::query::OutlivesBound;
+use rustc::ty;
 use rustc::ty::free_region_map::FreeRegionMap;
-use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
-use rustc_span::Span;
+
+use super::explicit_outlives_bounds;
 
 /// The `OutlivesEnvironment` collects information about what outlives
 /// what in a given type-checking setting. For example, if we have a
@@ -76,7 +77,7 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
             region_bound_pairs_accum: vec![],
         };
 
-        env.add_outlives_bounds(None, outlives_bounds::explicit_outlives_bounds(param_env));
+        env.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
 
         env
     }
@@ -142,39 +143,6 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
         self.region_bound_pairs_accum.truncate(len);
     }
 
-    /// This method adds "implied bounds" into the outlives environment.
-    /// Implied bounds are outlives relationships that we can deduce
-    /// on the basis that certain types must be well-formed -- these are
-    /// either the types that appear in the function signature or else
-    /// the input types to an impl. For example, if you have a function
-    /// like
-    ///
-    /// ```
-    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
-    /// ```
-    ///
-    /// we can assume in the caller's body that `'b: 'a` and that `T:
-    /// 'b` (and hence, transitively, that `T: 'a`). This method would
-    /// add those assumptions into the outlives-environment.
-    ///
-    /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
-    pub fn add_implied_bounds(
-        &mut self,
-        infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: &[Ty<'tcx>],
-        body_id: hir::HirId,
-        span: Span,
-    ) {
-        debug!("add_implied_bounds()");
-
-        for &ty in fn_sig_tys {
-            let ty = infcx.resolve_vars_if_possible(&ty);
-            debug!("add_implied_bounds: ty = {}", ty);
-            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
-            self.add_outlives_bounds(Some(infcx), implied_bounds)
-        }
-    }
-
     /// Save the current set of region-bound pairs under the given `body_id`.
     pub fn save_implied_bounds(&mut self, body_id: hir::HirId) {
         let old =
@@ -188,8 +156,11 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
     /// contain inference variables, it must be supplied, in which
     /// case we will register "givens" on the inference context. (See
     /// `RegionConstraintData`.)
-    fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I)
-    where
+    pub fn add_outlives_bounds<I>(
+        &mut self,
+        infcx: Option<&InferCtxt<'a, 'tcx>>,
+        outlives_bounds: I,
+    ) where
         I: IntoIterator<Item = OutlivesBound<'tcx>>,
     {
         // Record relationships such as `T:'x` that don't go into the
diff --git a/src/librustc_infer/infer/outlives/mod.rs b/src/librustc_infer/infer/outlives/mod.rs
index 6fc72470c9f..75cf742de31 100644
--- a/src/librustc_infer/infer/outlives/mod.rs
+++ b/src/librustc_infer/infer/outlives/mod.rs
@@ -3,3 +3,25 @@
 pub mod env;
 pub mod obligations;
 pub mod verify;
+
+use rustc::traits::query::OutlivesBound;
+use rustc::ty;
+
+pub fn explicit_outlives_bounds<'tcx>(
+    param_env: ty::ParamEnv<'tcx>,
+) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
+    debug!("explicit_outlives_bounds()");
+    param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate {
+        ty::Predicate::Projection(..)
+        | ty::Predicate::Trait(..)
+        | ty::Predicate::Subtype(..)
+        | ty::Predicate::WellFormed(..)
+        | ty::Predicate::ObjectSafe(..)
+        | ty::Predicate::ClosureKind(..)
+        | ty::Predicate::TypeOutlives(..)
+        | ty::Predicate::ConstEvaluatable(..) => None,
+        ty::Predicate::RegionOutlives(ref data) => data
+            .no_bound_vars()
+            .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
+    })
+}
diff --git a/src/librustc_infer/infer/region_constraints/README.md b/src/librustc_infer/infer/region_constraints/README.md
index d789fb0de10..0231dd06677 100644
--- a/src/librustc_infer/infer/region_constraints/README.md
+++ b/src/librustc_infer/infer/region_constraints/README.md
@@ -1,3 +1,3 @@
-For info on how the current borrowck works, see the [rustc guide].
+For info on how the current borrowck works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs
index 6c66ef47f33..cb8ae8c592b 100644
--- a/src/librustc_infer/lib.rs
+++ b/src/librustc_infer/lib.rs
@@ -1,13 +1,12 @@
-//! This crates defines the trait resolution method and the type inference engine.
+//! This crates defines the type inference engine.
 //!
-//! - **Traits.** Trait resolution is implemented in the `traits` module.
 //! - **Type inference.** The type inference code can be found in the `infer` module;
 //!   this code handles low-level equality and subtyping operations. The
 //!   type check pass in the compiler is found in the `librustc_typeck` crate.
 //!
-//! For more information about how rustc works, see the [rustc guide].
+//! For more information about how rustc works, see the [rustc dev guide].
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
 //!
 //! # Note
 //!
@@ -17,12 +16,11 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(drain_filter)]
 #![feature(never_type)]
 #![feature(range_is_empty)]
 #![feature(in_band_lifetimes)]
 #![feature(crate_visibility_modifier)]
-#![recursion_limit = "512"]
+#![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/src/librustc_infer/traits/engine.rs b/src/librustc_infer/traits/engine.rs
index e23810dd161..9ad722342a1 100644
--- a/src/librustc_infer/traits/engine.rs
+++ b/src/librustc_infer/traits/engine.rs
@@ -1,9 +1,9 @@
 use crate::infer::InferCtxt;
 use crate::traits::Obligation;
-use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc::ty::{self, ToPredicate, Ty, WithConstness};
 use rustc_hir::def_id::DefId;
 
-use super::{FulfillmentContext, FulfillmentError};
+use super::FulfillmentError;
 use super::{ObligationCause, PredicateObligation};
 
 pub trait TraitEngine<'tcx>: 'tcx {
@@ -76,9 +76,3 @@ impl<T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
         }
     }
 }
-
-impl dyn TraitEngine<'tcx> {
-    pub fn new(_tcx: TyCtxt<'tcx>) -> Box<Self> {
-        Box::new(FulfillmentContext::new())
-    }
-}
diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs
index 10143ae015f..8943ce4e6c5 100644
--- a/src/librustc_infer/traits/error_reporting/mod.rs
+++ b/src/librustc_infer/traits/error_reporting/mod.rs
@@ -1,452 +1,16 @@
-pub mod on_unimplemented;
-pub mod suggestions;
+use super::ObjectSafetyViolation;
 
-use super::{
-    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
-    MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause,
-    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
-    OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
-    TraitNotObjectSafe,
-};
-
-use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc::mir::interpret::ErrorHandled;
-use rustc::session::DiagnosticMessageId;
-use rustc::ty::error::ExpectedFound;
-use rustc::ty::fast_reject;
-use rustc::ty::fold::TypeFolder;
-use rustc::ty::SubtypePredicate;
-use rustc::ty::{
-    self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
-};
+use crate::infer::InferCtxt;
+use rustc::ty::TyCtxt;
 use rustc_ast::ast;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
-use rustc_span::source_map::SourceMap;
-use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use rustc_hir::def_id::DefId;
+use rustc_span::Span;
 use std::fmt;
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn report_fulfillment_errors(
-        &self,
-        errors: &[FulfillmentError<'tcx>],
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        #[derive(Debug)]
-        struct ErrorDescriptor<'tcx> {
-            predicate: ty::Predicate<'tcx>,
-            index: Option<usize>, // None if this is an old error
-        }
-
-        let mut error_map: FxHashMap<_, Vec<_>> = self
-            .reported_trait_errors
-            .borrow()
-            .iter()
-            .map(|(&span, predicates)| {
-                (
-                    span,
-                    predicates
-                        .iter()
-                        .map(|&predicate| ErrorDescriptor { predicate, index: None })
-                        .collect(),
-                )
-            })
-            .collect();
-
-        for (index, error) in errors.iter().enumerate() {
-            // We want to ignore desugarings here: spans are equivalent even
-            // if one is the result of a desugaring and the other is not.
-            let mut span = error.obligation.cause.span;
-            let expn_data = span.ctxt().outer_expn_data();
-            if let ExpnKind::Desugaring(_) = expn_data.kind {
-                span = expn_data.call_site;
-            }
-
-            error_map.entry(span).or_default().push(ErrorDescriptor {
-                predicate: error.obligation.predicate,
-                index: Some(index),
-            });
-
-            self.reported_trait_errors
-                .borrow_mut()
-                .entry(span)
-                .or_default()
-                .push(error.obligation.predicate.clone());
-        }
-
-        // We do this in 2 passes because we want to display errors in order, though
-        // maybe it *is* better to sort errors by span or something.
-        let mut is_suppressed = vec![false; errors.len()];
-        for (_, error_set) in error_map.iter() {
-            // We want to suppress "duplicate" errors with the same span.
-            for error in error_set {
-                if let Some(index) = error.index {
-                    // Suppress errors that are either:
-                    // 1) strictly implied by another error.
-                    // 2) implied by an error with a smaller index.
-                    for error2 in error_set {
-                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
-                            // Avoid errors being suppressed by already-suppressed
-                            // errors, to prevent all errors from being suppressed
-                            // at once.
-                            continue;
-                        }
-
-                        if self.error_implies(&error2.predicate, &error.predicate)
-                            && !(error2.index >= error.index
-                                && self.error_implies(&error.predicate, &error2.predicate))
-                        {
-                            info!("skipping {:?} (implied by {:?})", error, error2);
-                            is_suppressed[index] = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        for (error, suppressed) in errors.iter().zip(is_suppressed) {
-            if !suppressed {
-                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
-            }
-        }
-    }
-
-    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
-    // `error` occurring implies that `cond` occurs.
-    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
-        if cond == error {
-            return true;
-        }
-
-        let (cond, error) = match (cond, error) {
-            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
-            _ => {
-                // FIXME: make this work in other cases too.
-                return false;
-            }
-        };
-
-        for implication in super::elaborate_predicates(self.tcx, vec![*cond]) {
-            if let ty::Predicate::Trait(implication, _) = implication {
-                let error = error.to_poly_trait_ref();
-                let implication = implication.to_poly_trait_ref();
-                // FIXME: I'm just not taking associated types at all here.
-                // Eventually I'll need to implement param-env-aware
-                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
-                let param_env = ty::ParamEnv::empty();
-                if self.can_sub(param_env, error, implication).is_ok() {
-                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
-
-    fn report_fulfillment_error(
-        &self,
-        error: &FulfillmentError<'tcx>,
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        debug!("report_fulfillment_error({:?})", error);
-        match error.code {
-            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
-                self.report_selection_error(
-                    &error.obligation,
-                    selection_error,
-                    fallback_has_occurred,
-                    error.points_at_arg_span,
-                );
-            }
-            FulfillmentErrorCode::CodeProjectionError(ref e) => {
-                self.report_projection_error(&error.obligation, e);
-            }
-            FulfillmentErrorCode::CodeAmbiguity => {
-                self.maybe_report_ambiguity(&error.obligation, body_id);
-            }
-            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
-                self.report_mismatched_types(
-                    &error.obligation.cause,
-                    expected_found.expected,
-                    expected_found.found,
-                    err.clone(),
-                )
-                .emit();
-            }
-        }
-    }
-
-    fn report_projection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &MismatchedProjectionTypes<'tcx>,
-    ) {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-
-        if predicate.references_error() {
-            return;
-        }
-
-        self.probe(|_| {
-            let err_buf;
-            let mut err = &error.err;
-            let mut values = None;
-
-            // try to find the mismatched types to report the error with.
-            //
-            // this can fail if the problem was higher-ranked, in which
-            // cause I have no idea for a good error message.
-            if let ty::Predicate::Projection(ref data) = predicate {
-                let mut selcx = SelectionContext::new(self);
-                let (data, _) = self.replace_bound_vars_with_fresh_vars(
-                    obligation.cause.span,
-                    infer::LateBoundRegionConversionTime::HigherRankedType,
-                    data,
-                );
-                let mut obligations = vec![];
-                let normalized_ty = super::normalize_projection_type(
-                    &mut selcx,
-                    obligation.param_env,
-                    data.projection_ty,
-                    obligation.cause.clone(),
-                    0,
-                    &mut obligations,
-                );
-
-                debug!(
-                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
-                    obligation.cause, obligation.param_env
-                );
-
-                debug!(
-                    "report_projection_error normalized_ty={:?} data.ty={:?}",
-                    normalized_ty, data.ty
-                );
-
-                let is_normalized_ty_expected = match &obligation.cause.code {
-                    ObligationCauseCode::ItemObligation(_)
-                    | ObligationCauseCode::BindingObligation(_, _)
-                    | ObligationCauseCode::ObjectCastObligation(_) => false,
-                    _ => true,
-                };
-
-                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
-                    is_normalized_ty_expected,
-                    normalized_ty,
-                    data.ty,
-                ) {
-                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
-                        is_normalized_ty_expected,
-                        normalized_ty,
-                        data.ty,
-                    )));
-
-                    err_buf = error;
-                    err = &err_buf;
-                }
-            }
-
-            let msg = format!("type mismatch resolving `{}`", predicate);
-            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
-            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-            if fresh {
-                let mut diag = struct_span_err!(
-                    self.tcx.sess,
-                    obligation.cause.span,
-                    E0271,
-                    "type mismatch resolving `{}`",
-                    predicate
-                );
-                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
-                self.note_obligation_cause(&mut diag, obligation);
-                diag.emit();
-            }
-        });
-    }
-
-    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        /// returns the fuzzy category of a given type, or None
-        /// if the type can be equated to any type.
-        fn type_category(t: Ty<'_>) -> Option<u32> {
-            match t.kind {
-                ty::Bool => Some(0),
-                ty::Char => Some(1),
-                ty::Str => Some(2),
-                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
-                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
-                ty::Ref(..) | ty::RawPtr(..) => Some(5),
-                ty::Array(..) | ty::Slice(..) => Some(6),
-                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
-                ty::Dynamic(..) => Some(8),
-                ty::Closure(..) => Some(9),
-                ty::Tuple(..) => Some(10),
-                ty::Projection(..) => Some(11),
-                ty::Param(..) => Some(12),
-                ty::Opaque(..) => Some(13),
-                ty::Never => Some(14),
-                ty::Adt(adt, ..) => match adt.adt_kind() {
-                    AdtKind::Struct => Some(15),
-                    AdtKind::Union => Some(16),
-                    AdtKind::Enum => Some(17),
-                },
-                ty::Generator(..) => Some(18),
-                ty::Foreign(..) => Some(19),
-                ty::GeneratorWitness(..) => Some(20),
-                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
-                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-            }
-        }
-
-        match (type_category(a), type_category(b)) {
-            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
-                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
-                _ => cat_a == cat_b,
-            },
-            // infer and error can be equated to all types
-            _ => true,
-        }
-    }
-
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
-        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
-            hir::GeneratorKind::Gen => "a generator",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
-        })
-    }
-
-    fn find_similar_impl_candidates(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Vec<ty::TraitRef<'tcx>> {
-        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
-        let all_impls = self.tcx.all_impls(trait_ref.def_id());
-
-        match simp {
-            Some(simp) => all_impls
-                .iter()
-                .filter_map(|&def_id| {
-                    let imp = self.tcx.impl_trait_ref(def_id).unwrap();
-                    let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
-                    if let Some(imp_simp) = imp_simp {
-                        if simp != imp_simp {
-                            return None;
-                        }
-                    }
-
-                    Some(imp)
-                })
-                .collect(),
-            None => {
-                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
-            }
-        }
-    }
-
-    fn report_similar_impl_candidates(
-        &self,
-        impl_candidates: Vec<ty::TraitRef<'tcx>>,
-        err: &mut DiagnosticBuilder<'_>,
-    ) {
-        if impl_candidates.is_empty() {
-            return;
-        }
-
-        let len = impl_candidates.len();
-        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
-
-        let normalize = |candidate| {
-            self.tcx.infer_ctxt().enter(|ref infcx| {
-                let normalized = infcx
-                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
-                    .normalize(candidate)
-                    .ok();
-                match normalized {
-                    Some(normalized) => format!("\n  {:?}", normalized.value),
-                    None => format!("\n  {:?}", candidate),
-                }
-            })
-        };
-
-        // Sort impl candidates so that ordering is consistent for UI tests.
-        let mut normalized_impl_candidates =
-            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
-
-        // Sort before taking the `..end` range,
-        // because the ordering of `impl_candidates` may not be deterministic:
-        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
-        normalized_impl_candidates.sort();
-
-        err.help(&format!(
-            "the following implementations were found:{}{}",
-            normalized_impl_candidates[..end].join(""),
-            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
-        ));
-    }
-
-    /// Reports that an overflow has occurred and halts compilation. We
-    /// halt compilation unconditionally because it is important that
-    /// overflows never be masked -- they basically represent computations
-    /// whose result could not be truly determined and thus we can't say
-    /// if the program type checks or not -- and they are unusual
-    /// occurrences in any case.
-    pub fn report_overflow_error<T>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        suggest_increasing_limit: bool,
-    ) -> !
-    where
-        T: fmt::Display + TypeFoldable<'tcx>,
-    {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            obligation.cause.span,
-            E0275,
-            "overflow evaluating the requirement `{}`",
-            predicate
-        );
-
-        if suggest_increasing_limit {
-            self.suggest_new_overflow_limit(&mut err);
-        }
-
-        self.note_obligation_cause_code(
-            &mut err,
-            &obligation.predicate,
-            &obligation.cause.code,
-            &mut vec![],
-        );
-
-        err.emit();
-        self.tcx.sess.abort_if_errors();
-        bug!();
-    }
-
-    /// Reports that a cycle was detected which led to overflow and halts
-    /// compilation. This is equivalent to `report_overflow_error` except
-    /// that we can give a more helpful error message (and, in particular,
-    /// we do not suggest increasing the overflow limit, which is not
-    /// going to help).
-    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
-        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
-        assert!(!cycle.is_empty());
-
-        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
-
-        self.report_overflow_error(&cycle[0], false);
-    }
-
     pub fn report_extra_impl_obligation(
         &self,
         error_span: Span,
@@ -469,550 +33,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         err
     }
-
-    /// Gets the parent trait chain start
-    fn get_parent_trait_ref(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-    ) -> Option<(String, Option<Span>)> {
-        match code {
-            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                match self.get_parent_trait_ref(&data.parent_code) {
-                    Some(t) => Some(t),
-                    None => {
-                        let ty = parent_trait_ref.skip_binder().self_ty();
-                        let span =
-                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
-                        Some((ty.to_string(), span))
-                    }
-                }
-            }
-            _ => None,
-        }
-    }
-
-    pub fn report_selection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &SelectionError<'tcx>,
-        fallback_has_occurred: bool,
-        points_at_arg: bool,
-    ) {
-        let tcx = self.tcx;
-        let span = obligation.cause.span;
-
-        let mut err = match *error {
-            SelectionError::Unimplemented => {
-                if let ObligationCauseCode::CompareImplMethodObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                }
-                | ObligationCauseCode::CompareImplTypeObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                } = obligation.cause.code
-                {
-                    self.report_extra_impl_obligation(
-                        span,
-                        item_name,
-                        impl_item_def_id,
-                        trait_item_def_id,
-                        &format!("`{}`", obligation.predicate),
-                    )
-                    .emit();
-                    return;
-                }
-                match obligation.predicate {
-                    ty::Predicate::Trait(ref trait_predicate, _) => {
-                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
-
-                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
-                            return;
-                        }
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
-                        let (post_message, pre_message, type_def) = self
-                            .get_parent_trait_ref(&obligation.cause.code)
-                            .map(|(t, s)| {
-                                (
-                                    format!(" in `{}`", t),
-                                    format!("within `{}`, ", t),
-                                    s.map(|s| (format!("within this `{}`", t), s)),
-                                )
-                            })
-                            .unwrap_or_default();
-
-                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
-                            self.on_unimplemented_note(trait_ref, obligation);
-                        let have_alt_message = message.is_some() || label.is_some();
-                        let is_try = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_to_snippet(span)
-                            .map(|s| &s == "?")
-                            .unwrap_or(false);
-                        let is_from = format!("{}", trait_ref.print_only_trait_path())
-                            .starts_with("std::convert::From<");
-                        let (message, note) = if is_try && is_from {
-                            (
-                                Some(format!(
-                                    "`?` couldn't convert the error to `{}`",
-                                    trait_ref.self_ty(),
-                                )),
-                                Some(
-                                    "the question mark operation (`?`) implicitly performs a \
-                                     conversion on the error value using the `From` trait"
-                                        .to_owned(),
-                                ),
-                            )
-                        } else {
-                            (message, note)
-                        };
-
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0277,
-                            "{}",
-                            message.unwrap_or_else(|| format!(
-                                "the trait bound `{}` is not satisfied{}",
-                                trait_ref.without_const().to_predicate(),
-                                post_message,
-                            ))
-                        );
-
-                        let explanation =
-                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
-                                "consider using `()`, or a `Result`".to_owned()
-                            } else {
-                                format!(
-                                    "{}the trait `{}` is not implemented for `{}`",
-                                    pre_message,
-                                    trait_ref.print_only_trait_path(),
-                                    trait_ref.self_ty(),
-                                )
-                            };
-
-                        if self.suggest_add_reference_to_arg(
-                            &obligation,
-                            &mut err,
-                            &trait_ref,
-                            points_at_arg,
-                            have_alt_message,
-                        ) {
-                            self.note_obligation_cause(&mut err, obligation);
-                            err.emit();
-                            return;
-                        }
-                        if let Some(ref s) = label {
-                            // If it has a custom `#[rustc_on_unimplemented]`
-                            // error message, let's display it as the label!
-                            err.span_label(span, s.as_str());
-                            err.help(&explanation);
-                        } else {
-                            err.span_label(span, explanation);
-                        }
-                        if let Some((msg, span)) = type_def {
-                            err.span_label(span, &msg);
-                        }
-                        if let Some(ref s) = note {
-                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
-                            err.note(s.as_str());
-                        }
-                        if let Some(ref s) = enclosing_scope {
-                            let enclosing_scope_span = tcx.def_span(
-                                tcx.hir()
-                                    .opt_local_def_id(obligation.cause.body_id)
-                                    .unwrap_or_else(|| {
-                                        tcx.hir().body_owner_def_id(hir::BodyId {
-                                            hir_id: obligation.cause.body_id,
-                                        })
-                                    }),
-                            );
-
-                            err.span_label(enclosing_scope_span, s.as_str());
-                        }
-
-                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
-                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
-                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
-                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
-                        self.note_version_mismatch(&mut err, &trait_ref);
-                        if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
-                            err.emit();
-                            return;
-                        }
-
-                        // Try to report a help message
-                        if !trait_ref.has_infer_types_or_consts()
-                            && self.predicate_can_apply(obligation.param_env, trait_ref)
-                        {
-                            // If a where-clause may be useful, remind the
-                            // user that they can add it.
-                            //
-                            // don't display an on-unimplemented note, as
-                            // these notes will often be of the form
-                            //     "the type `T` can't be frobnicated"
-                            // which is somewhat confusing.
-                            self.suggest_restricting_param_bound(
-                                &mut err,
-                                &trait_ref,
-                                obligation.cause.body_id,
-                            );
-                        } else {
-                            if !have_alt_message {
-                                // Can't show anything else useful, try to find similar impls.
-                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
-                                self.report_similar_impl_candidates(impl_candidates, &mut err);
-                            }
-                            self.suggest_change_mut(
-                                &obligation,
-                                &mut err,
-                                &trait_ref,
-                                points_at_arg,
-                            );
-                        }
-
-                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
-                        // implemented, and fallback has occurred, then it could be due to a
-                        // variable that used to fallback to `()` now falling back to `!`. Issue a
-                        // note informing about the change in behaviour.
-                        if trait_predicate.skip_binder().self_ty().is_never()
-                            && fallback_has_occurred
-                        {
-                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
-                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
-                                    self.tcx.mk_unit(),
-                                    &trait_pred.trait_ref.substs[1..],
-                                );
-                                trait_pred
-                            });
-                            let unit_obligation = Obligation {
-                                predicate: ty::Predicate::Trait(
-                                    predicate,
-                                    hir::Constness::NotConst,
-                                ),
-                                ..obligation.clone()
-                            };
-                            if self.predicate_may_hold(&unit_obligation) {
-                                err.note(
-                                    "the trait is implemented for `()`. \
-                                     Possibly this error has been caused by changes to \
-                                     Rust's type-inference algorithm (see issue #48950 \
-                                     <https://github.com/rust-lang/rust/issues/48950> \
-                                     for more information). Consider whether you meant to use \
-                                     the type `()` here instead.",
-                                );
-                            }
-                        }
-
-                        err
-                    }
-
-                    ty::Predicate::Subtype(ref predicate) => {
-                        // Errors for Subtype predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
-                        // not selection error.
-                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
-                    }
-
-                    ty::Predicate::RegionOutlives(ref predicate) => {
-                        let predicate = self.resolve_vars_if_possible(predicate);
-                        let err = self
-                            .region_outlives_predicate(&obligation.cause, &predicate)
-                            .err()
-                            .unwrap();
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0279,
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate,
-                            err,
-                        )
-                    }
-
-                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
-                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0280,
-                            "the requirement `{}` is not satisfied",
-                            predicate
-                        )
-                    }
-
-                    ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = self.tcx.object_safety_violations(trait_def_id);
-                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
-                    }
-
-                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
-                        let closure_span = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
-                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            closure_span,
-                            E0525,
-                            "expected a closure that implements the `{}` trait, \
-                             but this closure only implements `{}`",
-                            kind,
-                            found_kind
-                        );
-
-                        err.span_label(
-                            closure_span,
-                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
-                        );
-                        err.span_label(
-                            obligation.cause.span,
-                            format!("the requirement to implement `{}` derives from here", kind),
-                        );
-
-                        // Additional context information explaining why the closure only implements
-                        // a particular trait.
-                        if let Some(tables) = self.in_progress_tables {
-                            let tables = tables.borrow();
-                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
-                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnOnce` because it moves the \
-                                         variable `{}` out of its environment",
-                                            name
-                                        ),
-                                    );
-                                }
-                                (ty::ClosureKind::FnMut, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnMut` because it mutates the \
-                                         variable `{}` here",
-                                            name
-                                        ),
-                                    );
-                                }
-                                _ => {}
-                            }
-                        }
-
-                        err.emit();
-                        return;
-                    }
-
-                    ty::Predicate::WellFormed(ty) => {
-                        // WF predicates cannot themselves make
-                        // errors. They can only block due to
-                        // ambiguity; otherwise, they always
-                        // degenerate into other obligations
-                        // (which may fail).
-                        span_bug!(span, "WF predicate not satisfied for {:?}", ty);
-                    }
-
-                    ty::Predicate::ConstEvaluatable(..) => {
-                        // Errors for `ConstEvaluatable` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
-                        span_bug!(
-                            span,
-                            "const-evaluatable requirement gave wrong error: `{:?}`",
-                            obligation
-                        )
-                    }
-                }
-            }
-
-            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
-                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
-                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
-
-                if expected_trait_ref.self_ty().references_error() {
-                    return;
-                }
-
-                let found_trait_ty = found_trait_ref.self_ty();
-
-                let found_did = match found_trait_ty.kind {
-                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
-                    ty::Adt(def, _) => Some(def.did),
-                    _ => None,
-                };
-
-                let found_span = found_did
-                    .and_then(|did| self.tcx.hir().span_if_local(did))
-                    .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
-
-                if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
-                    // We check closures twice, with obligations flowing in different directions,
-                    // but we want to complain about them only once.
-                    return;
-                }
-
-                self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
-
-                let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
-                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
-                    _ => vec![ArgKind::empty()],
-                };
-
-                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
-                let expected = match expected_ty.kind {
-                    ty::Tuple(ref tys) => tys
-                        .iter()
-                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
-                        .collect(),
-                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
-                };
-
-                if found.len() == expected.len() {
-                    self.report_closure_arg_mismatch(
-                        span,
-                        found_span,
-                        found_trait_ref,
-                        expected_trait_ref,
-                    )
-                } else {
-                    let (closure_span, found) = found_did
-                        .and_then(|did| self.tcx.hir().get_if_local(did))
-                        .map(|node| {
-                            let (found_span, found) = self.get_fn_like_arguments(node);
-                            (Some(found_span), found)
-                        })
-                        .unwrap_or((found_span, found));
-
-                    self.report_arg_count_mismatch(
-                        span,
-                        closure_span,
-                        expected,
-                        found,
-                        found_trait_ty.is_closure(),
-                    )
-                }
-            }
-
-            TraitNotObjectSafe(did) => {
-                let violations = self.tcx.object_safety_violations(did);
-                report_object_safety_error(self.tcx, span, did, violations)
-            }
-
-            ConstEvalFailure(ErrorHandled::TooGeneric) => {
-                // In this instance, we have a const expression containing an unevaluated
-                // generic parameter. We have no idea whether this expression is valid or
-                // not (e.g. it might result in an error), but we don't want to just assume
-                // that it's okay, because that might result in post-monomorphisation time
-                // errors. The onus is really on the caller to provide values that it can
-                // prove are well-formed.
-                let mut err = self
-                    .tcx
-                    .sess
-                    .struct_span_err(span, "constant expression depends on a generic parameter");
-                // FIXME(const_generics): we should suggest to the user how they can resolve this
-                // issue. However, this is currently not actually possible
-                // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
-                err.note("this may fail depending on what value the parameter takes");
-                err
-            }
-
-            // Already reported in the query.
-            ConstEvalFailure(ErrorHandled::Reported) => {
-                self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
-                return;
-            }
-
-            Overflow => {
-                bug!("overflow should be handled before the `report_selection_error` path");
-            }
-        };
-
-        self.note_obligation_cause(&mut err, obligation);
-        self.point_at_returns_when_relevant(&mut err, &obligation);
-
-        err.emit();
-    }
-
-    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
-    /// with the same path as `trait_ref`, a help message about
-    /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) {
-        let get_trait_impl = |trait_def_id| {
-            let mut trait_impl = None;
-            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
-                if trait_impl.is_none() {
-                    trait_impl = Some(impl_def_id);
-                }
-            });
-            trait_impl
-        };
-        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
-        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
-        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
-            .iter()
-            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
-            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
-            .collect();
-        for trait_with_same_path in traits_with_same_path {
-            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
-                let impl_span = self.tcx.def_span(impl_def_id);
-                err.span_help(impl_span, "trait impl with same name found");
-                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
-                let crate_msg = format!(
-                    "perhaps two different versions of crate `{}` are being used?",
-                    trait_crate
-                );
-                err.note(&crate_msg);
-            }
-        }
-    }
-
-    fn mk_obligation_for_def_id(
-        &self,
-        def_id: DefId,
-        output_ty: Ty<'tcx>,
-        cause: ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> PredicateObligation<'tcx> {
-        let new_trait_ref =
-            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
-        Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
-    }
-}
-
-pub fn recursive_type_with_infinite_size_error(
-    tcx: TyCtxt<'tcx>,
-    type_def_id: DefId,
-) -> DiagnosticBuilder<'tcx> {
-    assert!(type_def_id.is_local());
-    let span = tcx.hir().span_if_local(type_def_id).unwrap();
-    let span = tcx.sess.source_map().def_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0072,
-        "recursive type `{}` has infinite size",
-        tcx.def_path_str(type_def_id)
-    );
-    err.span_label(span, "recursive type has infinite size");
-    err.help(&format!(
-        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
-                           at some point to make `{}` representable",
-        tcx.def_path_str(type_def_id)
-    ));
-    err
 }
 
 pub fn report_object_safety_error(
@@ -1084,560 +104,3 @@ pub fn report_object_safety_error(
 
     err
 }
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    fn maybe_report_ambiguity(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        body_id: Option<hir::BodyId>,
-    ) {
-        // Unable to successfully determine, probably means
-        // insufficient type information, but could mean
-        // ambiguous impls. The latter *ought* to be a
-        // coherence violation, so we don't report it here.
-
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let span = obligation.cause.span;
-
-        debug!(
-            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
-            predicate, obligation, body_id, obligation.cause.code,
-        );
-
-        // Ambiguity errors are often caused as fallout from earlier
-        // errors. So just ignore them if this infcx is tainted.
-        if self.is_tainted_by_errors() {
-            return;
-        }
-
-        let mut err = match predicate {
-            ty::Predicate::Trait(ref data, _) => {
-                let trait_ref = data.to_poly_trait_ref();
-                let self_ty = trait_ref.self_ty();
-                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
-
-                if predicate.references_error() {
-                    return;
-                }
-                // Typically, this ambiguity should only happen if
-                // there are unresolved type inference variables
-                // (otherwise it would suggest a coherence
-                // failure). But given #21974 that is not necessarily
-                // the case -- we can have multiple where clauses that
-                // are only distinguished by a region, which results
-                // in an ambiguity even when all types are fully
-                // known, since we don't dispatch based on region
-                // relationships.
-
-                // This is kind of a hack: it frequently happens that some earlier
-                // error prevents types from being fully inferred, and then we get
-                // a bunch of uninteresting errors saying something like "<generic
-                // #0> doesn't implement Sized".  It may even be true that we
-                // could just skip over all checks where the self-ty is an
-                // inference variable, but I was afraid that there might be an
-                // inference variable created, registered as an obligation, and
-                // then never forced by writeback, and hence by skipping here we'd
-                // be ignoring the fact that we don't KNOW the type works
-                // out. Though even that would probably be harmless, given that
-                // we're only talking about builtin traits, which are known to be
-                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
-                // avoid inundating the user with unnecessary errors, but we now
-                // check upstream for type errors and don't add the obligations to
-                // begin with in those cases.
-                if self
-                    .tcx
-                    .lang_items()
-                    .sized_trait()
-                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
-                {
-                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
-                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let (
-                    Ok(ref snippet),
-                    ObligationCauseCode::BindingObligation(ref def_id, _),
-                ) =
-                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
-                {
-                    let generics = self.tcx.generics_of(*def_id);
-                    if !generics.params.is_empty() && !snippet.ends_with('>') {
-                        // FIXME: To avoid spurious suggestions in functions where type arguments
-                        // where already supplied, we check the snippet to make sure it doesn't
-                        // end with a turbofish. Ideally we would have access to a `PathSegment`
-                        // instead. Otherwise we would produce the following output:
-                        //
-                        // error[E0283]: type annotations needed
-                        //   --> $DIR/issue-54954.rs:3:24
-                        //    |
-                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
-                        //    |                        |
-                        //    |                        cannot infer type
-                        //    |                        help: consider specifying the type argument
-                        //    |                        in the function call:
-                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
-                        // ...
-                        // LL |     const fn const_val<T: Sized>() -> usize {
-                        //    |              --------- - required by this bound in `Tt::const_val`
-                        //    |
-                        //    = note: cannot resolve `_: Tt`
-
-                        err.span_suggestion(
-                            span,
-                            &format!(
-                                "consider specifying the type argument{} in the function call",
-                                if generics.params.len() > 1 { "s" } else { "" },
-                            ),
-                            format!(
-                                "{}::<{}>",
-                                snippet,
-                                generics
-                                    .params
-                                    .iter()
-                                    .map(|p| p.name.to_string())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            ),
-                            Applicability::HasPlaceholders,
-                        );
-                    }
-                }
-                err
-            }
-
-            ty::Predicate::WellFormed(ty) => {
-                // Same hacky approach as above to avoid deluging user
-                // with error messages.
-                if ty.references_error() || self.tcx.sess.has_errors() {
-                    return;
-                }
-                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
-            }
-
-            ty::Predicate::Subtype(ref data) => {
-                if data.references_error() || self.tcx.sess.has_errors() {
-                    // no need to overload user in such cases
-                    return;
-                }
-                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
-                // both must be type variables, or the other would've been instantiated
-                assert!(a.is_ty_var() && b.is_ty_var());
-                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
-            }
-            ty::Predicate::Projection(ref data) => {
-                let trait_ref = data.to_poly_trait_ref(self.tcx);
-                let self_ty = trait_ref.self_ty();
-                if predicate.references_error() {
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                err
-            }
-
-            _ => {
-                if self.tcx.sess.has_errors() {
-                    return;
-                }
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0284,
-                    "type annotations needed: cannot resolve `{}`",
-                    predicate,
-                );
-                err.span_label(span, &format!("cannot resolve `{}`", predicate));
-                err
-            }
-        };
-        self.note_obligation_cause(&mut err, obligation);
-        err.emit();
-    }
-
-    /// Returns `true` if the trait predicate may apply for *some* assignment
-    /// to the type parameters.
-    fn predicate_can_apply(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitRef<'tcx>,
-    ) -> bool {
-        struct ParamToVarFolder<'a, 'tcx> {
-            infcx: &'a InferCtxt<'a, 'tcx>,
-            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
-        }
-
-        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
-            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
-                self.infcx.tcx
-            }
-
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
-                    let infcx = self.infcx;
-                    self.var_map.entry(ty).or_insert_with(|| {
-                        infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
-                            span: DUMMY_SP,
-                        })
-                    })
-                } else {
-                    ty.super_fold_with(self)
-                }
-            }
-        }
-
-        self.probe(|_| {
-            let mut selcx = SelectionContext::new(self);
-
-            let cleaned_pred =
-                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
-
-            let cleaned_pred = super::project::normalize(
-                &mut selcx,
-                param_env,
-                ObligationCause::dummy(),
-                &cleaned_pred,
-            )
-            .value;
-
-            let obligation = Obligation::new(
-                ObligationCause::dummy(),
-                param_env,
-                cleaned_pred.without_const().to_predicate(),
-            );
-
-            self.predicate_may_hold(&obligation)
-        })
-    }
-
-    fn note_obligation_cause(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        // First, attempt to add note to this error with an async-await-specific
-        // message, and fall back to regular note otherwise.
-        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
-            self.note_obligation_cause_code(
-                err,
-                &obligation.predicate,
-                &obligation.cause.code,
-                &mut vec![],
-            );
-            self.suggest_unsized_bound_if_applicable(err, obligation);
-        }
-    }
-
-    fn suggest_unsized_bound_if_applicable(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        if let (
-            ty::Predicate::Trait(pred, _),
-            ObligationCauseCode::BindingObligation(item_def_id, span),
-        ) = (&obligation.predicate, &obligation.cause.code)
-        {
-            if let (Some(generics), true) = (
-                self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()),
-                Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
-            ) {
-                for param in generics.params {
-                    if param.span == *span
-                        && !param.bounds.iter().any(|bound| {
-                            bound.trait_def_id() == self.tcx.lang_items().sized_trait()
-                        })
-                    {
-                        let (span, separator) = match param.bounds {
-                            [] => (span.shrink_to_hi(), ":"),
-                            [.., bound] => (bound.span().shrink_to_hi(), " + "),
-                        };
-                        err.span_suggestion(
-                            span,
-                            "consider relaxing the implicit `Sized` restriction",
-                            format!("{} ?Sized", separator),
-                            Applicability::MachineApplicable,
-                        );
-                        return;
-                    }
-                }
-            }
-        }
-    }
-
-    fn is_recursive_obligation(
-        &self,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-        cause_code: &ObligationCauseCode<'tcx>,
-    ) -> bool {
-        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
-            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-
-            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
-                return true;
-            }
-        }
-        false
-    }
-}
-
-/// Summarizes information
-#[derive(Clone)]
-pub enum ArgKind {
-    /// An argument of non-tuple type. Parameters are (name, ty)
-    Arg(String, String),
-
-    /// An argument of tuple type. For a "found" argument, the span is
-    /// the locationo in the source of the pattern. For a "expected"
-    /// argument, it will be None. The vector is a list of (name, ty)
-    /// strings for the components of the tuple.
-    Tuple(Option<Span>, Vec<(String, String)>),
-}
-
-impl ArgKind {
-    fn empty() -> ArgKind {
-        ArgKind::Arg("_".to_owned(), "_".to_owned())
-    }
-
-    /// Creates an `ArgKind` from the expected type of an
-    /// argument. It has no name (`_`) and an optional source span.
-    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
-        match t.kind {
-            ty::Tuple(ref tys) => ArgKind::Tuple(
-                span,
-                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
-            ),
-            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
-        }
-    }
-}
-
-/// Suggest restricting a type param with a new bound.
-pub fn suggest_constraining_type_param(
-    tcx: TyCtxt<'_>,
-    generics: &hir::Generics<'_>,
-    err: &mut DiagnosticBuilder<'_>,
-    param_name: &str,
-    constraint: &str,
-    source_map: &SourceMap,
-    span: Span,
-    def_id: Option<DefId>,
-) -> bool {
-    const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound with";
-    const MSG_RESTRICT_TYPE: &str = "consider restricting this type parameter with";
-    const MSG_RESTRICT_TYPE_FURTHER: &str = "consider further restricting this type parameter with";
-
-    let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
-
-    let param = if let Some(param) = param {
-        param
-    } else {
-        return false;
-    };
-
-    if def_id == tcx.lang_items().sized_trait() {
-        // Type parameters are already `Sized` by default.
-        err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint));
-        return true;
-    }
-
-    if param_name.starts_with("impl ") {
-        // If there's an `impl Trait` used in argument position, suggest
-        // restricting it:
-        //
-        //   fn foo(t: impl Foo) { ... }
-        //             --------
-        //             |
-        //             help: consider further restricting this bound with `+ Bar`
-        //
-        // Suggestion for tools in this case is:
-        //
-        //   fn foo(t: impl Foo) { ... }
-        //             --------
-        //             |
-        //             replace with: `impl Foo + Bar`
-
-        err.span_help(param.span, &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint));
-
-        err.tool_only_span_suggestion(
-            param.span,
-            MSG_RESTRICT_BOUND_FURTHER,
-            format!("{} + {}", param_name, constraint),
-            Applicability::MachineApplicable,
-        );
-
-        return true;
-    }
-
-    if generics.where_clause.predicates.is_empty() {
-        if let Some(bounds_span) = param.bounds_span() {
-            // If user has provided some bounds, suggest restricting them:
-            //
-            //   fn foo<T: Foo>(t: T) { ... }
-            //             ---
-            //             |
-            //             help: consider further restricting this bound with `+ Bar`
-            //
-            // Suggestion for tools in this case is:
-            //
-            //   fn foo<T: Foo>(t: T) { ... }
-            //          --
-            //          |
-            //          replace with: `T: Bar +`
-
-            err.span_help(
-                bounds_span,
-                &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
-            );
-
-            let span_hi = param.span.with_hi(span.hi());
-            let span_with_colon = source_map.span_through_char(span_hi, ':');
-
-            if span_hi != param.span && span_with_colon != span_hi {
-                err.tool_only_span_suggestion(
-                    span_with_colon,
-                    MSG_RESTRICT_BOUND_FURTHER,
-                    format!("{}: {} + ", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            }
-        } else {
-            // If user hasn't provided any bounds, suggest adding a new one:
-            //
-            //   fn foo<T>(t: T) { ... }
-            //          - help: consider restricting this type parameter with `T: Foo`
-
-            err.span_help(
-                param.span,
-                &format!("{} `{}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
-            );
-
-            err.tool_only_span_suggestion(
-                param.span,
-                MSG_RESTRICT_TYPE,
-                format!("{}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        }
-
-        true
-    } else {
-        // This part is a bit tricky, because using the `where` clause user can
-        // provide zero, one or many bounds for the same type parameter, so we
-        // have following cases to consider:
-        //
-        // 1) When the type parameter has been provided zero bounds
-        //
-        //    Message:
-        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
-        //             - help: consider restricting this type parameter with `where X: Bar`
-        //
-        //    Suggestion:
-        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
-        //                                           - insert: `, X: Bar`
-        //
-        //
-        // 2) When the type parameter has been provided one bound
-        //
-        //    Message:
-        //      fn foo<T>(t: T) where T: Foo { ... }
-        //                            ^^^^^^
-        //                            |
-        //                            help: consider further restricting this bound with `+ Bar`
-        //
-        //    Suggestion:
-        //      fn foo<T>(t: T) where T: Foo { ... }
-        //                            ^^
-        //                            |
-        //                            replace with: `T: Bar +`
-        //
-        //
-        // 3) When the type parameter has been provided many bounds
-        //
-        //    Message:
-        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
-        //             - help: consider further restricting this type parameter with `where T: Zar`
-        //
-        //    Suggestion:
-        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
-        //                                          - insert: `, T: Zar`
-
-        let mut param_spans = Vec::new();
-
-        for predicate in generics.where_clause.predicates {
-            if let WherePredicate::BoundPredicate(WhereBoundPredicate {
-                span, bounded_ty, ..
-            }) = predicate
-            {
-                if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
-                    if let Some(segment) = path.segments.first() {
-                        if segment.ident.to_string() == param_name {
-                            param_spans.push(span);
-                        }
-                    }
-                }
-            }
-        }
-
-        let where_clause_span =
-            generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi();
-
-        match &param_spans[..] {
-            &[] => {
-                err.span_help(
-                    param.span,
-                    &format!("{} `where {}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
-                );
-
-                err.tool_only_span_suggestion(
-                    where_clause_span,
-                    MSG_RESTRICT_TYPE,
-                    format!(", {}: {}", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            &[&param_span] => {
-                err.span_help(
-                    param_span,
-                    &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
-                );
-
-                let span_hi = param_span.with_hi(span.hi());
-                let span_with_colon = source_map.span_through_char(span_hi, ':');
-
-                if span_hi != param_span && span_with_colon != span_hi {
-                    err.tool_only_span_suggestion(
-                        span_with_colon,
-                        MSG_RESTRICT_BOUND_FURTHER,
-                        format!("{}: {} +", param_name, constraint),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-
-            _ => {
-                err.span_help(
-                    param.span,
-                    &format!(
-                        "{} `where {}: {}`",
-                        MSG_RESTRICT_TYPE_FURTHER, param_name, constraint,
-                    ),
-                );
-
-                err.tool_only_span_suggestion(
-                    where_clause_span,
-                    MSG_RESTRICT_BOUND_FURTHER,
-                    format!(", {}: {}", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            }
-        }
-
-        true
-    }
-}
diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs
index 800f8e91a78..1c0785497be 100644
--- a/src/librustc_infer/traits/mod.rs
+++ b/src/librustc_infer/traits/mod.rs
@@ -2,114 +2,32 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
 
-#[allow(dead_code)]
-pub mod auto_trait;
-pub mod codegen;
-mod coherence;
 mod engine;
 pub mod error_reporting;
-mod fulfill;
-pub mod misc;
-mod object_safety;
-mod on_unimplemented;
 mod project;
-pub mod query;
-mod select;
-mod specialize;
 mod structural_impls;
-mod structural_match;
 mod util;
-pub mod wf;
 
-use crate::infer::outlives::env::OutlivesEnvironment;
-use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt};
-use rustc::middle::region;
 use rustc::ty::error::{ExpectedFound, TypeError};
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{InternalSubsts, SubstsRef};
-use rustc::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness};
-use rustc::util::common::ErrorReported;
+use rustc::ty::{self, Ty};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_span::{Span, DUMMY_SP};
-
-use std::fmt::Debug;
+use rustc_span::Span;
 
 pub use self::FulfillmentErrorCode::*;
 pub use self::ObligationCauseCode::*;
 pub use self::SelectionError::*;
 pub use self::Vtable::*;
 
-pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
-pub use self::coherence::{OrphanCheckErr, OverlapResult};
 pub use self::engine::{TraitEngine, TraitEngineExt};
-pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
-pub use self::object_safety::astconv_object_safety_violations;
-pub use self::object_safety::is_vtable_safe_method;
-pub use self::object_safety::MethodViolationCode;
-pub use self::object_safety::ObjectSafetyViolation;
-pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
 pub use self::project::MismatchedProjectionTypes;
 pub use self::project::{
-    normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type,
-};
-pub use self::project::{Normalized, ProjectionCache, ProjectionCacheSnapshot, Reveal};
-pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
-pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
-pub use self::specialize::find_associated_item;
-pub use self::specialize::specialization_graph::FutureCompatOverlapError;
-pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
-pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
-pub use self::structural_match::search_for_structural_match_violation;
-pub use self::structural_match::type_marked_structural;
-pub use self::structural_match::NonStructuralMatchTy;
-pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
-pub use self::util::{expand_trait_aliases, TraitAliasExpander};
-pub use self::util::{
-    get_vtable_index_of_object_method, impl_is_default, impl_item_is_final,
-    predicate_for_trait_def, upcast_choices,
-};
-pub use self::util::{
-    supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
+    Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
+    ProjectionCacheSnapshot, Reveal,
 };
+crate use self::util::elaborate_predicates;
 
 pub use rustc::traits::*;
 
-/// Whether to skip the leak check, as part of a future compatibility warning step.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum SkipLeakCheck {
-    Yes,
-    No,
-}
-
-impl SkipLeakCheck {
-    fn is_yes(self) -> bool {
-        self == SkipLeakCheck::Yes
-    }
-}
-
-/// The "default" for skip-leak-check corresponds to the current
-/// behavior (do not skip the leak check) -- not the behavior we are
-/// transitioning into.
-impl Default for SkipLeakCheck {
-    fn default() -> Self {
-        SkipLeakCheck::No
-    }
-}
-
-/// The mode that trait queries run in.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum TraitQueryMode {
-    // Standard/un-canonicalized queries get accurate
-    // spans etc. passed in and hence can do reasonable
-    // error reporting on their own.
-    Standard,
-    // Canonicalized queries get dummy spans and hence
-    // must generally propagate errors to
-    // pre-canonicalization callsites.
-    Canonical,
-}
-
 /// An `Obligation` represents some trait reference (e.g., `int: Eq`) for
 /// which the vtable must be found. The process of finding a vtable is
 /// called "resolving" the `Obligation`. This process consists of
@@ -165,418 +83,6 @@ pub enum FulfillmentErrorCode<'tcx> {
     CodeAmbiguity,
 }
 
-/// Creates predicate obligations from the generic bounds.
-pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
-) -> PredicateObligations<'tcx> {
-    util::predicates_for_generics(cause, 0, param_env, generic_bounds)
-}
-
-/// Determines whether the type `ty` is known to meet `bound` and
-/// returns true if so. Returns false if `ty` either does not meet
-/// `bound` or is not known to meet bound (note that this is
-/// conservative towards *no impl*, which is the opposite of the
-/// `evaluate` methods).
-pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-    def_id: DefId,
-    span: Span,
-) -> bool {
-    debug!(
-        "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})",
-        ty,
-        infcx.tcx.def_path_str(def_id)
-    );
-
-    let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
-    let obligation = Obligation {
-        param_env,
-        cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
-        recursion_depth: 0,
-        predicate: trait_ref.without_const().to_predicate(),
-    };
-
-    let result = infcx.predicate_must_hold_modulo_regions(&obligation);
-    debug!(
-        "type_known_to_meet_ty={:?} bound={} => {:?}",
-        ty,
-        infcx.tcx.def_path_str(def_id),
-        result
-    );
-
-    if result && ty.has_infer_types_or_consts() {
-        // Because of inference "guessing", selection can sometimes claim
-        // to succeed while the success requires a guess. To ensure
-        // this function's result remains infallible, we must confirm
-        // that guess. While imperfect, I believe this is sound.
-
-        // The handling of regions in this area of the code is terrible,
-        // see issue #29149. We should be able to improve on this with
-        // NLL.
-        let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
-
-        // We can use a dummy node-id here because we won't pay any mind
-        // to region obligations that arise (there shouldn't really be any
-        // anyhow).
-        let cause = ObligationCause::misc(span, hir::DUMMY_HIR_ID);
-
-        fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause);
-
-        // Note: we only assume something is `Copy` if we can
-        // *definitively* show that it implements `Copy`. Otherwise,
-        // assume it is move; linear is always ok.
-        match fulfill_cx.select_all_or_error(infcx) {
-            Ok(()) => {
-                debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
-                    ty,
-                    infcx.tcx.def_path_str(def_id)
-                );
-                true
-            }
-            Err(e) => {
-                debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
-                    ty,
-                    infcx.tcx.def_path_str(def_id),
-                    e
-                );
-                false
-            }
-        }
-    } else {
-        result
-    }
-}
-
-fn do_normalize_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    region_context: DefId,
-    cause: ObligationCause<'tcx>,
-    elaborated_env: ty::ParamEnv<'tcx>,
-    predicates: Vec<ty::Predicate<'tcx>>,
-) -> Result<Vec<ty::Predicate<'tcx>>, ErrorReported> {
-    debug!(
-        "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})",
-        predicates, region_context, cause,
-    );
-    let span = cause.span;
-    tcx.infer_ctxt().enter(|infcx| {
-        // FIXME. We should really... do something with these region
-        // obligations. But this call just continues the older
-        // behavior (i.e., doesn't cause any new bugs), and it would
-        // take some further refactoring to actually solve them. In
-        // particular, we would have to handle implied bounds
-        // properly, and that code is currently largely confined to
-        // regionck (though I made some efforts to extract it
-        // out). -nmatsakis
-        //
-        // @arielby: In any case, these obligations are checked
-        // by wfcheck anyway, so I'm not sure we have to check
-        // them here too, and we will remove this function when
-        // we move over to lazy normalization *anyway*.
-        let fulfill_cx = FulfillmentContext::new_ignoring_regions();
-        let predicates =
-            match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, &predicates) {
-                Ok(predicates) => predicates,
-                Err(errors) => {
-                    infcx.report_fulfillment_errors(&errors, None, false);
-                    return Err(ErrorReported);
-                }
-            };
-
-        debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
-
-        let region_scope_tree = region::ScopeTree::default();
-
-        // We can use the `elaborated_env` here; the region code only
-        // cares about declarations like `'a: 'b`.
-        let outlives_env = OutlivesEnvironment::new(elaborated_env);
-
-        infcx.resolve_regions_and_report_errors(
-            region_context,
-            &region_scope_tree,
-            &outlives_env,
-            SuppressRegionErrors::default(),
-        );
-
-        let predicates = match infcx.fully_resolve(&predicates) {
-            Ok(predicates) => predicates,
-            Err(fixup_err) => {
-                // If we encounter a fixup error, it means that some type
-                // variable wound up unconstrained. I actually don't know
-                // if this can happen, and I certainly don't expect it to
-                // happen often, but if it did happen it probably
-                // represents a legitimate failure due to some kind of
-                // unconstrained variable, and it seems better not to ICE,
-                // all things considered.
-                tcx.sess.span_err(span, &fixup_err.to_string());
-                return Err(ErrorReported);
-            }
-        };
-        if predicates.has_local_value() {
-            // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
-            Err(ErrorReported)
-        } else {
-            Ok(predicates)
-        }
-    })
-}
-
-// FIXME: this is gonna need to be removed ...
-/// Normalizes the parameter environment, reporting errors if they occur.
-pub fn normalize_param_env_or_error<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    region_context: DefId,
-    unnormalized_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-) -> ty::ParamEnv<'tcx> {
-    // I'm not wild about reporting errors here; I'd prefer to
-    // have the errors get reported at a defined place (e.g.,
-    // during typeck). Instead I have all parameter
-    // environments, in effect, going through this function
-    // and hence potentially reporting errors. This ensures of
-    // course that we never forget to normalize (the
-    // alternative seemed like it would involve a lot of
-    // manual invocations of this fn -- and then we'd have to
-    // deal with the errors at each of those sites).
-    //
-    // In any case, in practice, typeck constructs all the
-    // parameter environments once for every fn as it goes,
-    // and errors will get reported then; so after typeck we
-    // can be sure that no errors should occur.
-
-    debug!(
-        "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})",
-        region_context, unnormalized_env, cause
-    );
-
-    let mut predicates: Vec<_> =
-        util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()).collect();
-
-    debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
-
-    let elaborated_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        unnormalized_env.reveal,
-        unnormalized_env.def_id,
-    );
-
-    // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
-    // normalization expects its param-env to be already normalized, which means we have
-    // a circularity.
-    //
-    // The way we handle this is by normalizing the param-env inside an unnormalized version
-    // of the param-env, which means that if the param-env contains unnormalized projections,
-    // we'll have some normalization failures. This is unfortunate.
-    //
-    // Lazy normalization would basically handle this by treating just the
-    // normalizing-a-trait-ref-requires-itself cycles as evaluation failures.
-    //
-    // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated
-    // types, so to make the situation less bad, we normalize all the predicates *but*
-    // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and
-    // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment.
-    //
-    // This works fairly well because trait matching  does not actually care about param-env
-    // TypeOutlives predicates - these are normally used by regionck.
-    let outlives_predicates: Vec<_> = predicates
-        .drain_filter(|predicate| match predicate {
-            ty::Predicate::TypeOutlives(..) => true,
-            _ => false,
-        })
-        .collect();
-
-    debug!(
-        "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
-        predicates, outlives_predicates
-    );
-    let non_outlives_predicates = match do_normalize_predicates(
-        tcx,
-        region_context,
-        cause.clone(),
-        elaborated_env,
-        predicates,
-    ) {
-        Ok(predicates) => predicates,
-        // An unnormalized env is better than nothing.
-        Err(ErrorReported) => {
-            debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
-            return elaborated_env;
-        }
-    };
-
-    debug!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates);
-
-    // Not sure whether it is better to include the unnormalized TypeOutlives predicates
-    // here. I believe they should not matter, because we are ignoring TypeOutlives param-env
-    // predicates here anyway. Keeping them here anyway because it seems safer.
-    let outlives_env: Vec<_> =
-        non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
-    let outlives_env =
-        ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal, None);
-    let outlives_predicates = match do_normalize_predicates(
-        tcx,
-        region_context,
-        cause,
-        outlives_env,
-        outlives_predicates,
-    ) {
-        Ok(predicates) => predicates,
-        // An unnormalized env is better than nothing.
-        Err(ErrorReported) => {
-            debug!("normalize_param_env_or_error: errored resolving outlives predicates");
-            return elaborated_env;
-        }
-    };
-    debug!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates);
-
-    let mut predicates = non_outlives_predicates;
-    predicates.extend(outlives_predicates);
-    debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
-    ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        unnormalized_env.reveal,
-        unnormalized_env.def_id,
-    )
-}
-
-pub fn fully_normalize<'a, 'tcx, T>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    mut fulfill_cx: FulfillmentContext<'tcx>,
-    cause: ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    value: &T,
-) -> Result<T, Vec<FulfillmentError<'tcx>>>
-where
-    T: TypeFoldable<'tcx>,
-{
-    debug!("fully_normalize_with_fulfillcx(value={:?})", value);
-    let selcx = &mut SelectionContext::new(infcx);
-    let Normalized { value: normalized_value, obligations } =
-        project::normalize(selcx, param_env, cause, value);
-    debug!(
-        "fully_normalize: normalized_value={:?} obligations={:?}",
-        normalized_value, obligations
-    );
-    for obligation in obligations {
-        fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
-    }
-
-    debug!("fully_normalize: select_all_or_error start");
-    fulfill_cx.select_all_or_error(infcx)?;
-    debug!("fully_normalize: select_all_or_error complete");
-    let resolved_value = infcx.resolve_vars_if_possible(&normalized_value);
-    debug!("fully_normalize: resolved_value={:?}", resolved_value);
-    Ok(resolved_value)
-}
-
-/// Normalizes the predicates and checks whether they hold in an empty
-/// environment. If this returns false, then either normalize
-/// encountered an error or one of the predicates did not hold. Used
-/// when creating vtables to check for unsatisfiable methods.
-pub fn normalize_and_test_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    predicates: Vec<ty::Predicate<'tcx>>,
-) -> bool {
-    debug!("normalize_and_test_predicates(predicates={:?})", predicates);
-
-    let result = tcx.infer_ctxt().enter(|infcx| {
-        let param_env = ty::ParamEnv::reveal_all();
-        let mut selcx = SelectionContext::new(&infcx);
-        let mut fulfill_cx = FulfillmentContext::new();
-        let cause = ObligationCause::dummy();
-        let Normalized { value: predicates, obligations } =
-            normalize(&mut selcx, param_env, cause.clone(), &predicates);
-        for obligation in obligations {
-            fulfill_cx.register_predicate_obligation(&infcx, obligation);
-        }
-        for predicate in predicates {
-            let obligation = Obligation::new(cause.clone(), param_env, predicate);
-            fulfill_cx.register_predicate_obligation(&infcx, obligation);
-        }
-
-        fulfill_cx.select_all_or_error(&infcx).is_ok()
-    });
-    debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", predicates, result);
-    result
-}
-
-fn substitute_normalize_and_test_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: (DefId, SubstsRef<'tcx>),
-) -> bool {
-    debug!("substitute_normalize_and_test_predicates(key={:?})", key);
-
-    let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
-    let result = normalize_and_test_predicates(tcx, predicates);
-
-    debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result);
-    result
-}
-
-/// Given a trait `trait_ref`, iterates the vtable entries
-/// that come from `trait_ref`, including its supertraits.
-#[inline] // FIXME(#35870): avoid closures being unexported due to `impl Trait`.
-fn vtable_methods<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
-    debug!("vtable_methods({:?})", trait_ref);
-
-    tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
-        let trait_methods = tcx
-            .associated_items(trait_ref.def_id())
-            .in_definition_order()
-            .filter(|item| item.kind == ty::AssocKind::Method);
-
-        // Now list each method's DefId and InternalSubsts (for within its trait).
-        // If the method can never be called from this object, produce None.
-        trait_methods.map(move |trait_method| {
-            debug!("vtable_methods: trait_method={:?}", trait_method);
-            let def_id = trait_method.def_id;
-
-            // Some methods cannot be called on an object; skip those.
-            if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
-                debug!("vtable_methods: not vtable safe");
-                return None;
-            }
-
-            // The method may have some early-bound lifetimes; add regions for those.
-            let substs = trait_ref.map_bound(|trait_ref| {
-                InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
-                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                        trait_ref.substs[param.index as usize]
-                    }
-                })
-            });
-
-            // The trait type may have higher-ranked lifetimes in it;
-            // erase them if they appear, so that we get the type
-            // at some particular call site.
-            let substs =
-                tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &substs);
-
-            // It's possible that the method relies on where-clauses that
-            // do not hold for this particular set of type parameters.
-            // Note that this method could then never be called, so we
-            // do not want to try and codegen it, in that case (see #23435).
-            let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
-            if !normalize_and_test_predicates(tcx, predicates.predicates) {
-                debug!("vtable_methods: predicates do not hold");
-                return None;
-            }
-
-            Some((def_id, substs))
-        })
-    }))
-}
-
 impl<'tcx, O> Obligation<'tcx, O> {
     pub fn new(
         cause: ObligationCause<'tcx>,
@@ -586,7 +92,7 @@ impl<'tcx, O> Obligation<'tcx, O> {
         Obligation { cause, param_env, recursion_depth: 0, predicate }
     }
 
-    fn with_depth(
+    pub fn with_depth(
         cause: ObligationCause<'tcx>,
         recursion_depth: usize,
         param_env: ty::ParamEnv<'tcx>,
@@ -615,7 +121,7 @@ impl<'tcx, O> Obligation<'tcx, O> {
 }
 
 impl<'tcx> FulfillmentError<'tcx> {
-    fn new(
+    pub fn new(
         obligation: PredicateObligation<'tcx>,
         code: FulfillmentErrorCode<'tcx>,
     ) -> FulfillmentError<'tcx> {
@@ -624,19 +130,7 @@ impl<'tcx> FulfillmentError<'tcx> {
 }
 
 impl<'tcx> TraitObligation<'tcx> {
-    fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
+    pub fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
         self.predicate.map_bound(|p| p.self_ty())
     }
 }
-
-pub fn provide(providers: &mut ty::query::Providers<'_>) {
-    object_safety::provide(providers);
-    *providers = ty::query::Providers {
-        specialization_graph_of: specialize::specialization_graph_provider,
-        specializes: specialize::specializes,
-        codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
-        vtable_methods,
-        substitute_normalize_and_test_predicates,
-        ..*providers
-    };
-}
diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs
index 78483cf6577..183e4be1890 100644
--- a/src/librustc_infer/traits/project.rs
+++ b/src/librustc_infer/traits/project.rs
@@ -1,398 +1,18 @@
 //! Code for projecting associated types out of trait references.
 
-use super::elaborate_predicates;
-use super::specialization_graph;
-use super::translate_substs;
-use super::util;
-use super::Obligation;
-use super::ObligationCause;
 use super::PredicateObligation;
-use super::Selection;
-use super::SelectionContext;
-use super::SelectionError;
-use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableImplData};
 
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use rustc::ty::fold::{TypeFoldable, TypeFolder};
-use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
-use rustc_ast::ast::Ident;
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::{self, Ty};
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::sym;
-use rustc_span::DUMMY_SP;
 
 pub use rustc::traits::Reveal;
 
-pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
-
-pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
-
-pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
-
-/// When attempting to resolve `<T as TraitRef>::Name` ...
-#[derive(Debug)]
-pub enum ProjectionTyError<'tcx> {
-    /// ...we found multiple sources of information and couldn't resolve the ambiguity.
-    TooManyCandidates,
-
-    /// ...an error occurred matching `T : TraitRef`
-    TraitSelectionError(SelectionError<'tcx>),
-}
-
 #[derive(Clone)]
 pub struct MismatchedProjectionTypes<'tcx> {
     pub err: ty::error::TypeError<'tcx>,
 }
 
-#[derive(PartialEq, Eq, Debug)]
-enum ProjectionTyCandidate<'tcx> {
-    // from a where-clause in the env or object type
-    ParamEnv(ty::PolyProjectionPredicate<'tcx>),
-
-    // from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
-    TraitDef(ty::PolyProjectionPredicate<'tcx>),
-
-    // from a "impl" (or a "pseudo-impl" returned by select)
-    Select(Selection<'tcx>),
-}
-
-enum ProjectionTyCandidateSet<'tcx> {
-    None,
-    Single(ProjectionTyCandidate<'tcx>),
-    Ambiguous,
-    Error(SelectionError<'tcx>),
-}
-
-impl<'tcx> ProjectionTyCandidateSet<'tcx> {
-    fn mark_ambiguous(&mut self) {
-        *self = ProjectionTyCandidateSet::Ambiguous;
-    }
-
-    fn mark_error(&mut self, err: SelectionError<'tcx>) {
-        *self = ProjectionTyCandidateSet::Error(err);
-    }
-
-    // Returns true if the push was successful, or false if the candidate
-    // was discarded -- this could be because of ambiguity, or because
-    // a higher-priority candidate is already there.
-    fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
-        use self::ProjectionTyCandidate::*;
-        use self::ProjectionTyCandidateSet::*;
-
-        // This wacky variable is just used to try and
-        // make code readable and avoid confusing paths.
-        // It is assigned a "value" of `()` only on those
-        // paths in which we wish to convert `*self` to
-        // ambiguous (and return false, because the candidate
-        // was not used). On other paths, it is not assigned,
-        // and hence if those paths *could* reach the code that
-        // comes after the match, this fn would not compile.
-        let convert_to_ambiguous;
-
-        match self {
-            None => {
-                *self = Single(candidate);
-                return true;
-            }
-
-            Single(current) => {
-                // Duplicates can happen inside ParamEnv. In the case, we
-                // perform a lazy deduplication.
-                if current == &candidate {
-                    return false;
-                }
-
-                // Prefer where-clauses. As in select, if there are multiple
-                // candidates, we prefer where-clause candidates over impls.  This
-                // may seem a bit surprising, since impls are the source of
-                // "truth" in some sense, but in fact some of the impls that SEEM
-                // applicable are not, because of nested obligations. Where
-                // clauses are the safer choice. See the comment on
-                // `select::SelectionCandidate` and #21974 for more details.
-                match (current, candidate) {
-                    (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
-                    (ParamEnv(..), _) => return false,
-                    (_, ParamEnv(..)) => unreachable!(),
-                    (_, _) => convert_to_ambiguous = (),
-                }
-            }
-
-            Ambiguous | Error(..) => {
-                return false;
-            }
-        }
-
-        // We only ever get here when we moved from a single candidate
-        // to ambiguous.
-        let () = convert_to_ambiguous;
-        *self = Ambiguous;
-        false
-    }
-}
-
-/// Evaluates constraints of the form:
-///
-///     for<...> <T as Trait>::U == V
-///
-/// If successful, this may result in additional obligations. Also returns
-/// the projection cache key used to track these additional obligations.
-pub fn poly_project_and_unify_type<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &PolyProjectionObligation<'tcx>,
-) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
-    debug!("poly_project_and_unify_type(obligation={:?})", obligation);
-
-    let infcx = selcx.infcx();
-    infcx.commit_if_ok(|snapshot| {
-        let (placeholder_predicate, placeholder_map) =
-            infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
-
-        let placeholder_obligation = obligation.with(placeholder_predicate);
-        let result = project_and_unify_type(selcx, &placeholder_obligation)?;
-        infcx
-            .leak_check(false, &placeholder_map, snapshot)
-            .map_err(|err| MismatchedProjectionTypes { err })?;
-        Ok(result)
-    })
-}
-
-/// Evaluates constraints of the form:
-///
-///     <T as Trait>::U == V
-///
-/// If successful, this may result in additional obligations.
-fn project_and_unify_type<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionObligation<'tcx>,
-) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
-    debug!("project_and_unify_type(obligation={:?})", obligation);
-
-    let mut obligations = vec![];
-    let normalized_ty = match opt_normalize_projection_type(
-        selcx,
-        obligation.param_env,
-        obligation.predicate.projection_ty,
-        obligation.cause.clone(),
-        obligation.recursion_depth,
-        &mut obligations,
-    ) {
-        Some(n) => n,
-        None => return Ok(None),
-    };
-
-    debug!(
-        "project_and_unify_type: normalized_ty={:?} obligations={:?}",
-        normalized_ty, obligations
-    );
-
-    let infcx = selcx.infcx();
-    match infcx
-        .at(&obligation.cause, obligation.param_env)
-        .eq(normalized_ty, obligation.predicate.ty)
-    {
-        Ok(InferOk { obligations: inferred_obligations, value: () }) => {
-            obligations.extend(inferred_obligations);
-            Ok(Some(obligations))
-        }
-        Err(err) => {
-            debug!("project_and_unify_type: equating types encountered error {:?}", err);
-            Err(MismatchedProjectionTypes { err })
-        }
-    }
-}
-
-/// Normalizes any associated type projections in `value`, replacing
-/// them with a fully resolved type where possible. The return value
-/// combines the normalized result and any additional obligations that
-/// were incurred as result.
-pub fn normalize<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    value: &T,
-) -> Normalized<'tcx, T>
-where
-    T: TypeFoldable<'tcx>,
-{
-    let mut obligations = Vec::new();
-    let value = normalize_to(selcx, param_env, cause, value, &mut obligations);
-    Normalized { value, obligations }
-}
-
-pub fn normalize_to<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    value: &T,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> T
-where
-    T: TypeFoldable<'tcx>,
-{
-    normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations)
-}
-
-/// As `normalize`, but with a custom depth.
-pub fn normalize_with_depth<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    value: &T,
-) -> Normalized<'tcx, T>
-where
-    T: TypeFoldable<'tcx>,
-{
-    let mut obligations = Vec::new();
-    let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations);
-    Normalized { value, obligations }
-}
-
-pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    value: &T,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> T
-where
-    T: TypeFoldable<'tcx>,
-{
-    debug!("normalize_with_depth(depth={}, value={:?})", depth, value);
-    let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
-    let result = normalizer.fold(value);
-    debug!(
-        "normalize_with_depth: depth={} result={:?} with {} obligations",
-        depth,
-        result,
-        normalizer.obligations.len()
-    );
-    debug!("normalize_with_depth: depth={} obligations={:?}", depth, normalizer.obligations);
-    result
-}
-
-struct AssocTypeNormalizer<'a, 'b, 'tcx> {
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    obligations: &'a mut Vec<PredicateObligation<'tcx>>,
-    depth: usize,
-}
-
-impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
-    fn new(
-        selcx: &'a mut SelectionContext<'b, 'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        cause: ObligationCause<'tcx>,
-        depth: usize,
-        obligations: &'a mut Vec<PredicateObligation<'tcx>>,
-    ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
-        AssocTypeNormalizer { selcx, param_env, cause, obligations, depth }
-    }
-
-    fn fold<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
-        let value = self.selcx.infcx().resolve_vars_if_possible(value);
-
-        if !value.has_projections() { value } else { value.fold_with(self) }
-    }
-}
-
-impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
-    fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
-        self.selcx.tcx()
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_projections() {
-            return ty;
-        }
-        // We don't want to normalize associated types that occur inside of region
-        // binders, because they may contain bound regions, and we can't cope with that.
-        //
-        // Example:
-        //
-        //     for<'a> fn(<T as Foo<&'a>>::A)
-        //
-        // Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
-        // normalize it when we instantiate those bound regions (which
-        // should occur eventually).
-
-        let ty = ty.super_fold_with(self);
-        match ty.kind {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
-                // (*)
-                // Only normalize `impl Trait` after type-checking, usually in codegen.
-                match self.param_env.reveal {
-                    Reveal::UserFacing => ty,
-
-                    Reveal::All => {
-                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
-                        if self.depth >= recursion_limit {
-                            let obligation = Obligation::with_depth(
-                                self.cause.clone(),
-                                recursion_limit,
-                                self.param_env,
-                                ty,
-                            );
-                            self.selcx.infcx().report_overflow_error(&obligation, true);
-                        }
-
-                        let generic_ty = self.tcx().type_of(def_id);
-                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
-                        self.depth += 1;
-                        let folded_ty = self.fold_ty(concrete_ty);
-                        self.depth -= 1;
-                        folded_ty
-                    }
-                }
-            }
-
-            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
-                // (*)
-
-                // (*) This is kind of hacky -- we need to be able to
-                // handle normalization within binders because
-                // otherwise we wind up a need to normalize when doing
-                // trait matching (since you can have a trait
-                // obligation like `for<'a> T::B : Fn(&'a int)`), but
-                // we can't normalize with bound regions in scope. So
-                // far now we just ignore binders but only normalize
-                // if all bound regions are gone (and then we still
-                // have to renormalize whenever we instantiate a
-                // binder). It would be better to normalize in a
-                // binding-aware fashion.
-
-                let normalized_ty = normalize_projection_type(
-                    self.selcx,
-                    self.param_env,
-                    *data,
-                    self.cause.clone(),
-                    self.depth,
-                    &mut self.obligations,
-                );
-                debug!(
-                    "AssocTypeNormalizer: depth={} normalized {:?} to {:?}, \
-                     now with {} obligations",
-                    self.depth,
-                    ty,
-                    normalized_ty,
-                    self.obligations.len()
-                );
-                normalized_ty
-            }
-
-            _ => ty,
-        }
-    }
-
-    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        constant.eval(self.selcx.tcx(), self.param_env)
-    }
-}
-
 #[derive(Clone, TypeFoldable)]
 pub struct Normalized<'tcx, T> {
     pub value: T,
@@ -403,1100 +23,7 @@ pub type NormalizedTy<'tcx> = Normalized<'tcx, Ty<'tcx>>;
 
 impl<'tcx, T> Normalized<'tcx, T> {
     pub fn with<U>(self, value: U) -> Normalized<'tcx, U> {
-        Normalized { value, obligations: self.obligations }
-    }
-}
-
-/// The guts of `normalize`: normalize a specific projection like `<T
-/// as Trait>::Item`. The result is always a type (and possibly
-/// additional obligations). If ambiguity arises, which implies that
-/// there are unresolved type variables in the projection, we will
-/// substitute a fresh type variable `$X` and generate a new
-/// obligation `<T as Trait>::Item == $X` for later.
-pub fn normalize_projection_type<'a, 'b, 'tcx>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> Ty<'tcx> {
-    opt_normalize_projection_type(
-        selcx,
-        param_env,
-        projection_ty,
-        cause.clone(),
-        depth,
-        obligations,
-    )
-    .unwrap_or_else(move || {
-        // if we bottom out in ambiguity, create a type variable
-        // and a deferred predicate to resolve this when more type
-        // information is available.
-
-        let tcx = selcx.infcx().tcx;
-        let def_id = projection_ty.item_def_id;
-        let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::NormalizeProjectionType,
-            span: tcx.def_span(def_id),
-        });
-        let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
-        let obligation =
-            Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate());
-        obligations.push(obligation);
-        ty_var
-    })
-}
-
-/// The guts of `normalize`: normalize a specific projection like `<T
-/// as Trait>::Item`. The result is always a type (and possibly
-/// additional obligations). Returns `None` in the case of ambiguity,
-/// which indicates that there are unbound type variables.
-///
-/// This function used to return `Option<NormalizedTy<'tcx>>`, which contains a
-/// `Ty<'tcx>` and an obligations vector. But that obligation vector was very
-/// often immediately appended to another obligations vector. So now this
-/// function takes an obligations vector and appends to it directly, which is
-/// slightly uglier but avoids the need for an extra short-lived allocation.
-fn opt_normalize_projection_type<'a, 'b, 'tcx>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> Option<Ty<'tcx>> {
-    let infcx = selcx.infcx();
-
-    let projection_ty = infcx.resolve_vars_if_possible(&projection_ty);
-    let cache_key = ProjectionCacheKey { ty: projection_ty };
-
-    debug!(
-        "opt_normalize_projection_type(\
-         projection_ty={:?}, \
-         depth={})",
-        projection_ty, depth
-    );
-
-    // FIXME(#20304) For now, I am caching here, which is good, but it
-    // means we don't capture the type variables that are created in
-    // the case of ambiguity. Which means we may create a large stream
-    // of such variables. OTOH, if we move the caching up a level, we
-    // would not benefit from caching when proving `T: Trait<U=Foo>`
-    // bounds. It might be the case that we want two distinct caches,
-    // or else another kind of cache entry.
-
-    let cache_result = infcx.inner.borrow_mut().projection_cache.try_start(cache_key);
-    match cache_result {
-        Ok(()) => {}
-        Err(ProjectionCacheEntry::Ambiguous) => {
-            // If we found ambiguity the last time, that means we will continue
-            // to do so until some type in the key changes (and we know it
-            // hasn't, because we just fully resolved it).
-            debug!(
-                "opt_normalize_projection_type: \
-                 found cache entry: ambiguous"
-            );
-            return None;
-        }
-        Err(ProjectionCacheEntry::InProgress) => {
-            // If while normalized A::B, we are asked to normalize
-            // A::B, just return A::B itself. This is a conservative
-            // answer, in the sense that A::B *is* clearly equivalent
-            // to A::B, though there may be a better value we can
-            // find.
-
-            // Under lazy normalization, this can arise when
-            // bootstrapping.  That is, imagine an environment with a
-            // where-clause like `A::B == u32`. Now, if we are asked
-            // to normalize `A::B`, we will want to check the
-            // where-clauses in scope. So we will try to unify `A::B`
-            // with `A::B`, which can trigger a recursive
-            // normalization. In that case, I think we will want this code:
-            //
-            // ```
-            // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id,
-            //                                    projection_ty.substs;
-            // return Some(NormalizedTy { value: v, obligations: vec![] });
-            // ```
-
-            debug!(
-                "opt_normalize_projection_type: \
-                 found cache entry: in-progress"
-            );
-
-            // But for now, let's classify this as an overflow:
-            let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
-            let obligation =
-                Obligation::with_depth(cause, recursion_limit, param_env, projection_ty);
-            selcx.infcx().report_overflow_error(&obligation, false);
-        }
-        Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
-            // This is the hottest path in this function.
-            //
-            // If we find the value in the cache, then return it along
-            // with the obligations that went along with it. Note
-            // that, when using a fulfillment context, these
-            // obligations could in principle be ignored: they have
-            // already been registered when the cache entry was
-            // created (and hence the new ones will quickly be
-            // discarded as duplicated). But when doing trait
-            // evaluation this is not the case, and dropping the trait
-            // evaluations can causes ICEs (e.g., #43132).
-            debug!(
-                "opt_normalize_projection_type: \
-                 found normalized ty `{:?}`",
-                ty
-            );
-
-            // Once we have inferred everything we need to know, we
-            // can ignore the `obligations` from that point on.
-            if infcx.unresolved_type_vars(&ty.value).is_none() {
-                infcx.inner.borrow_mut().projection_cache.complete_normalized(cache_key, &ty);
-            // No need to extend `obligations`.
-            } else {
-                obligations.extend(ty.obligations);
-            }
-
-            obligations.push(get_paranoid_cache_value_obligation(
-                infcx,
-                param_env,
-                projection_ty,
-                cause,
-                depth,
-            ));
-            return Some(ty.value);
-        }
-        Err(ProjectionCacheEntry::Error) => {
-            debug!(
-                "opt_normalize_projection_type: \
-                 found error"
-            );
-            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
-            obligations.extend(result.obligations);
-            return Some(result.value);
-        }
-    }
-
-    let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
-    match project_type(selcx, &obligation) {
-        Ok(ProjectedTy::Progress(Progress {
-            ty: projected_ty,
-            obligations: mut projected_obligations,
-        })) => {
-            // if projection succeeded, then what we get out of this
-            // is also non-normalized (consider: it was derived from
-            // an impl, where-clause etc) and hence we must
-            // re-normalize it
-
-            debug!(
-                "opt_normalize_projection_type: \
-                 projected_ty={:?} \
-                 depth={} \
-                 projected_obligations={:?}",
-                projected_ty, depth, projected_obligations
-            );
-
-            let result = if projected_ty.has_projections() {
-                let mut normalizer = AssocTypeNormalizer::new(
-                    selcx,
-                    param_env,
-                    cause,
-                    depth + 1,
-                    &mut projected_obligations,
-                );
-                let normalized_ty = normalizer.fold(&projected_ty);
-
-                debug!(
-                    "opt_normalize_projection_type: \
-                     normalized_ty={:?} depth={}",
-                    normalized_ty, depth
-                );
-
-                Normalized { value: normalized_ty, obligations: projected_obligations }
-            } else {
-                Normalized { value: projected_ty, obligations: projected_obligations }
-            };
-
-            let cache_value = prune_cache_value_obligations(infcx, &result);
-            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, cache_value);
-            obligations.extend(result.obligations);
-            Some(result.value)
-        }
-        Ok(ProjectedTy::NoProgress(projected_ty)) => {
-            debug!(
-                "opt_normalize_projection_type: \
-                 projected_ty={:?} no progress",
-                projected_ty
-            );
-            let result = Normalized { value: projected_ty, obligations: vec![] };
-            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, result.clone());
-            // No need to extend `obligations`.
-            Some(result.value)
-        }
-        Err(ProjectionTyError::TooManyCandidates) => {
-            debug!(
-                "opt_normalize_projection_type: \
-                 too many candidates"
-            );
-            infcx.inner.borrow_mut().projection_cache.ambiguous(cache_key);
-            None
-        }
-        Err(ProjectionTyError::TraitSelectionError(_)) => {
-            debug!("opt_normalize_projection_type: ERROR");
-            // if we got an error processing the `T as Trait` part,
-            // just return `ty::err` but add the obligation `T :
-            // Trait`, which when processed will cause the error to be
-            // reported later
-
-            infcx.inner.borrow_mut().projection_cache.error(cache_key);
-            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
-            obligations.extend(result.obligations);
-            Some(result.value)
-        }
-    }
-}
-
-/// If there are unresolved type variables, then we need to include
-/// any subobligations that bind them, at least until those type
-/// variables are fully resolved.
-fn prune_cache_value_obligations<'a, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    result: &NormalizedTy<'tcx>,
-) -> NormalizedTy<'tcx> {
-    if infcx.unresolved_type_vars(&result.value).is_none() {
-        return NormalizedTy { value: result.value, obligations: vec![] };
-    }
-
-    let mut obligations: Vec<_> = result
-        .obligations
-        .iter()
-        .filter(|obligation| match obligation.predicate {
-            // We found a `T: Foo<X = U>` predicate, let's check
-            // if `U` references any unresolved type
-            // variables. In principle, we only care if this
-            // projection can help resolve any of the type
-            // variables found in `result.value` -- but we just
-            // check for any type variables here, for fear of
-            // indirect obligations (e.g., we project to `?0`,
-            // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
-            // ?0>`).
-            ty::Predicate::Projection(ref data) => infcx.unresolved_type_vars(&data.ty()).is_some(),
-
-            // We are only interested in `T: Foo<X = U>` predicates, whre
-            // `U` references one of `unresolved_type_vars`. =)
-            _ => false,
-        })
-        .cloned()
-        .collect();
-
-    obligations.shrink_to_fit();
-
-    NormalizedTy { value: result.value, obligations }
-}
-
-/// Whenever we give back a cache result for a projection like `<T as
-/// Trait>::Item ==> X`, we *always* include the obligation to prove
-/// that `T: Trait` (we may also include some other obligations). This
-/// may or may not be necessary -- in principle, all the obligations
-/// that must be proven to show that `T: Trait` were also returned
-/// when the cache was first populated. But there are some vague concerns,
-/// and so we take the precautionary measure of including `T: Trait` in
-/// the result:
-///
-/// Concern #1. The current setup is fragile. Perhaps someone could
-/// have failed to prove the concerns from when the cache was
-/// populated, but also not have used a snapshot, in which case the
-/// cache could remain populated even though `T: Trait` has not been
-/// shown. In this case, the "other code" is at fault -- when you
-/// project something, you are supposed to either have a snapshot or
-/// else prove all the resulting obligations -- but it's still easy to
-/// get wrong.
-///
-/// Concern #2. Even within the snapshot, if those original
-/// obligations are not yet proven, then we are able to do projections
-/// that may yet turn out to be wrong. This *may* lead to some sort
-/// of trouble, though we don't have a concrete example of how that
-/// can occur yet. But it seems risky at best.
-fn get_paranoid_cache_value_obligation<'a, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-) -> PredicateObligation<'tcx> {
-    let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
-    Obligation {
-        cause,
-        recursion_depth: depth,
-        param_env,
-        predicate: trait_ref.without_const().to_predicate(),
-    }
-}
-
-/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
-/// hold. In various error cases, we cannot generate a valid
-/// normalized projection. Therefore, we create an inference variable
-/// return an associated obligation that, when fulfilled, will lead to
-/// an error.
-///
-/// Note that we used to return `Error` here, but that was quite
-/// dubious -- the premise was that an error would *eventually* be
-/// reported, when the obligation was processed. But in general once
-/// you see a `Error` you are supposed to be able to assume that an
-/// error *has been* reported, so that you can take whatever heuristic
-/// paths you want to take. To make things worse, it was possible for
-/// cycles to arise, where you basically had a setup like `<MyType<$0>
-/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
-/// Trait>::Foo> to `[type error]` would lead to an obligation of
-/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
-/// an error for this obligation, but we legitimately should not,
-/// because it contains `[type error]`. Yuck! (See issue #29857 for
-/// one case where this arose.)
-fn normalize_to_error<'a, 'tcx>(
-    selcx: &mut SelectionContext<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-) -> NormalizedTy<'tcx> {
-    let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref();
-    let trait_obligation = Obligation {
-        cause,
-        recursion_depth: depth,
-        param_env,
-        predicate: trait_ref.without_const().to_predicate(),
-    };
-    let tcx = selcx.infcx().tcx;
-    let def_id = projection_ty.item_def_id;
-    let new_value = selcx.infcx().next_ty_var(TypeVariableOrigin {
-        kind: TypeVariableOriginKind::NormalizeProjectionType,
-        span: tcx.def_span(def_id),
-    });
-    Normalized { value: new_value, obligations: vec![trait_obligation] }
-}
-
-enum ProjectedTy<'tcx> {
-    Progress(Progress<'tcx>),
-    NoProgress(Ty<'tcx>),
-}
-
-struct Progress<'tcx> {
-    ty: Ty<'tcx>,
-    obligations: Vec<PredicateObligation<'tcx>>,
-}
-
-impl<'tcx> Progress<'tcx> {
-    fn error(tcx: TyCtxt<'tcx>) -> Self {
-        Progress { ty: tcx.types.err, obligations: vec![] }
-    }
-
-    fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
-        debug!(
-            "with_addl_obligations: self.obligations.len={} obligations.len={}",
-            self.obligations.len(),
-            obligations.len()
-        );
-
-        debug!(
-            "with_addl_obligations: self.obligations={:?} obligations={:?}",
-            self.obligations, obligations
-        );
-
-        self.obligations.append(&mut obligations);
-        self
-    }
-}
-
-/// Computes the result of a projection type (if we can).
-///
-/// IMPORTANT:
-/// - `obligation` must be fully normalized
-fn project_type<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
-    debug!("project(obligation={:?})", obligation);
-
-    let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
-    if obligation.recursion_depth >= recursion_limit {
-        debug!("project: overflow!");
-        return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
-    }
-
-    let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
-
-    debug!("project: obligation_trait_ref={:?}", obligation_trait_ref);
-
-    if obligation_trait_ref.references_error() {
-        return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx())));
-    }
-
-    let mut candidates = ProjectionTyCandidateSet::None;
-
-    // Make sure that the following procedures are kept in order. ParamEnv
-    // needs to be first because it has highest priority, and Select checks
-    // the return value of push_candidate which assumes it's ran at last.
-    assemble_candidates_from_param_env(selcx, obligation, &obligation_trait_ref, &mut candidates);
-
-    assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
-
-    assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
-
-    match candidates {
-        ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress(
-            confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate),
-        )),
-        ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
-            selcx
-                .tcx()
-                .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs),
-        )),
-        // Error occurred while trying to processing impls.
-        ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)),
-        // Inherent ambiguity that prevents us from even enumerating the
-        // candidates.
-        ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates),
-    }
-}
-
-/// The first thing we have to do is scan through the parameter
-/// environment to see whether there are any projection predicates
-/// there that can answer this question.
-fn assemble_candidates_from_param_env<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-) {
-    debug!("assemble_candidates_from_param_env(..)");
-    assemble_candidates_from_predicates(
-        selcx,
-        obligation,
-        obligation_trait_ref,
-        candidate_set,
-        ProjectionTyCandidate::ParamEnv,
-        obligation.param_env.caller_bounds.iter().cloned(),
-    );
-}
-
-/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
-/// that the definition of `Foo` has some clues:
-///
-/// ```
-/// trait Foo {
-///     type FooT : Bar<BarT=i32>
-/// }
-/// ```
-///
-/// Here, for example, we could conclude that the result is `i32`.
-fn assemble_candidates_from_trait_def<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-) {
-    debug!("assemble_candidates_from_trait_def(..)");
-
-    let tcx = selcx.tcx();
-    // Check whether the self-type is itself a projection.
-    let (def_id, substs) = match obligation_trait_ref.self_ty().kind {
-        ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs),
-        ty::Opaque(def_id, substs) => (def_id, substs),
-        ty::Infer(ty::TyVar(_)) => {
-            // If the self-type is an inference variable, then it MAY wind up
-            // being a projected type, so induce an ambiguity.
-            candidate_set.mark_ambiguous();
-            return;
-        }
-        _ => return,
-    };
-
-    // If so, extract what we know from the trait and try to come up with a good answer.
-    let trait_predicates = tcx.predicates_of(def_id);
-    let bounds = trait_predicates.instantiate(tcx, substs);
-    let bounds = elaborate_predicates(tcx, bounds.predicates);
-    assemble_candidates_from_predicates(
-        selcx,
-        obligation,
-        obligation_trait_ref,
-        candidate_set,
-        ProjectionTyCandidate::TraitDef,
-        bounds,
-    )
-}
-
-fn assemble_candidates_from_predicates<'cx, 'tcx, I>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-    ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
-    env_predicates: I,
-) where
-    I: IntoIterator<Item = ty::Predicate<'tcx>>,
-{
-    debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
-    let infcx = selcx.infcx();
-    for predicate in env_predicates {
-        debug!("assemble_candidates_from_predicates: predicate={:?}", predicate);
-        if let ty::Predicate::Projection(data) = predicate {
-            let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
-
-            let is_match = same_def_id
-                && infcx.probe(|_| {
-                    let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx);
-                    let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-                    infcx
-                        .at(&obligation.cause, obligation.param_env)
-                        .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                        .map(|InferOk { obligations: _, value: () }| {
-                            // FIXME(#32730) -- do we need to take obligations
-                            // into account in any way? At the moment, no.
-                        })
-                        .is_ok()
-                });
-
-            debug!(
-                "assemble_candidates_from_predicates: candidate={:?} \
-                 is_match={} same_def_id={}",
-                data, is_match, same_def_id
-            );
-
-            if is_match {
-                candidate_set.push_candidate(ctor(data));
-            }
-        }
-    }
-}
-
-fn assemble_candidates_from_impls<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-) {
-    // If we are resolving `<T as TraitRef<...>>::Item == Type`,
-    // start out by selecting the predicate `T as TraitRef<...>`:
-    let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-    let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
-    let _ = selcx.infcx().commit_if_ok(|_| {
-        let vtable = match selcx.select(&trait_obligation) {
-            Ok(Some(vtable)) => vtable,
-            Ok(None) => {
-                candidate_set.mark_ambiguous();
-                return Err(());
-            }
-            Err(e) => {
-                debug!("assemble_candidates_from_impls: selection error {:?}", e);
-                candidate_set.mark_error(e);
-                return Err(());
-            }
-        };
-
-        let eligible = match &vtable {
-            super::VtableClosure(_)
-            | super::VtableGenerator(_)
-            | super::VtableFnPointer(_)
-            | super::VtableObject(_)
-            | super::VtableTraitAlias(_) => {
-                debug!("assemble_candidates_from_impls: vtable={:?}", vtable);
-                true
-            }
-            super::VtableImpl(impl_data) => {
-                // We have to be careful when projecting out of an
-                // impl because of specialization. If we are not in
-                // codegen (i.e., projection mode is not "any"), and the
-                // impl's type is declared as default, then we disable
-                // projection (even if the trait ref is fully
-                // monomorphic). In the case where trait ref is not
-                // fully monomorphic (i.e., includes type parameters),
-                // this is because those type parameters may
-                // ultimately be bound to types from other crates that
-                // may have specialized impls we can't see. In the
-                // case where the trait ref IS fully monomorphic, this
-                // is a policy decision that we made in the RFC in
-                // order to preserve flexibility for the crate that
-                // defined the specializable impl to specialize later
-                // for existing types.
-                //
-                // In either case, we handle this by not adding a
-                // candidate for an impl if it contains a `default`
-                // type.
-                //
-                // NOTE: This should be kept in sync with the similar code in
-                // `rustc::ty::instance::resolve_associated_item()`.
-                let node_item =
-                    assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id);
-
-                let is_default = if node_item.node.is_from_trait() {
-                    // If true, the impl inherited a `type Foo = Bar`
-                    // given in the trait, which is implicitly default.
-                    // Otherwise, the impl did not specify `type` and
-                    // neither did the trait:
-                    //
-                    // ```rust
-                    // trait Foo { type T; }
-                    // impl Foo for Bar { }
-                    // ```
-                    //
-                    // This is an error, but it will be
-                    // reported in `check_impl_items_against_trait`.
-                    // We accept it here but will flag it as
-                    // an error when we confirm the candidate
-                    // (which will ultimately lead to `normalize_to_error`
-                    // being invoked).
-                    false
-                } else {
-                    // If we're looking at a trait *impl*, the item is
-                    // specializable if the impl or the item are marked
-                    // `default`.
-                    node_item.item.defaultness.is_default()
-                        || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
-                };
-
-                match is_default {
-                    // Non-specializable items are always projectable
-                    false => true,
-
-                    // Only reveal a specializable default if we're past type-checking
-                    // and the obligation is monomorphic, otherwise passes such as
-                    // transmute checking and polymorphic MIR optimizations could
-                    // get a result which isn't correct for all monomorphizations.
-                    true if obligation.param_env.reveal == Reveal::All => {
-                        // NOTE(eddyb) inference variables can resolve to parameters, so
-                        // assume `poly_trait_ref` isn't monomorphic, if it contains any.
-                        let poly_trait_ref =
-                            selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
-                        !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
-                    }
-
-                    true => {
-                        debug!(
-                            "assemble_candidates_from_impls: not eligible due to default: \
-                             assoc_ty={} predicate={}",
-                            selcx.tcx().def_path_str(node_item.item.def_id),
-                            obligation.predicate,
-                        );
-                        false
-                    }
-                }
-            }
-            super::VtableParam(..) => {
-                // This case tell us nothing about the value of an
-                // associated type. Consider:
-                //
-                // ```
-                // trait SomeTrait { type Foo; }
-                // fn foo<T:SomeTrait>(...) { }
-                // ```
-                //
-                // If the user writes `<T as SomeTrait>::Foo`, then the `T
-                // : SomeTrait` binding does not help us decide what the
-                // type `Foo` is (at least, not more specifically than
-                // what we already knew).
-                //
-                // But wait, you say! What about an example like this:
-                //
-                // ```
-                // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
-                // ```
-                //
-                // Doesn't the `T : Sometrait<Foo=usize>` predicate help
-                // resolve `T::Foo`? And of course it does, but in fact
-                // that single predicate is desugared into two predicates
-                // in the compiler: a trait predicate (`T : SomeTrait`) and a
-                // projection. And the projection where clause is handled
-                // in `assemble_candidates_from_param_env`.
-                false
-            }
-            super::VtableAutoImpl(..) | super::VtableBuiltin(..) => {
-                // These traits have no associated types.
-                span_bug!(
-                    obligation.cause.span,
-                    "Cannot project an associated type from `{:?}`",
-                    vtable
-                );
-            }
-        };
-
-        if eligible {
-            if candidate_set.push_candidate(ProjectionTyCandidate::Select(vtable)) {
-                Ok(())
-            } else {
-                Err(())
-            }
-        } else {
-            Err(())
-        }
-    });
-}
-
-fn confirm_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate: ProjectionTyCandidate<'tcx>,
-) -> Progress<'tcx> {
-    debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
-
-    match candidate {
-        ProjectionTyCandidate::ParamEnv(poly_projection)
-        | ProjectionTyCandidate::TraitDef(poly_projection) => {
-            confirm_param_env_candidate(selcx, obligation, poly_projection)
-        }
-
-        ProjectionTyCandidate::Select(vtable) => {
-            confirm_select_candidate(selcx, obligation, obligation_trait_ref, vtable)
-        }
-    }
-}
-
-fn confirm_select_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    vtable: Selection<'tcx>,
-) -> Progress<'tcx> {
-    match vtable {
-        super::VtableImpl(data) => confirm_impl_candidate(selcx, obligation, data),
-        super::VtableGenerator(data) => confirm_generator_candidate(selcx, obligation, data),
-        super::VtableClosure(data) => confirm_closure_candidate(selcx, obligation, data),
-        super::VtableFnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
-        super::VtableObject(_) => confirm_object_candidate(selcx, obligation, obligation_trait_ref),
-        super::VtableAutoImpl(..)
-        | super::VtableParam(..)
-        | super::VtableBuiltin(..)
-        | super::VtableTraitAlias(..) =>
-        // we don't create Select candidates with this kind of resolution
-        {
-            span_bug!(
-                obligation.cause.span,
-                "Cannot project an associated type from `{:?}`",
-                vtable
-            )
-        }
-    }
-}
-
-fn confirm_object_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-) -> Progress<'tcx> {
-    let self_ty = obligation_trait_ref.self_ty();
-    let object_ty = selcx.infcx().shallow_resolve(self_ty);
-    debug!("confirm_object_candidate(object_ty={:?})", object_ty);
-    let data = match object_ty.kind {
-        ty::Dynamic(ref data, ..) => data,
-        _ => span_bug!(
-            obligation.cause.span,
-            "confirm_object_candidate called with non-object: {:?}",
-            object_ty
-        ),
-    };
-    let env_predicates = data
-        .projection_bounds()
-        .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate())
-        .collect();
-    let env_predicate = {
-        let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
-
-        // select only those projections that are actually projecting an
-        // item with the correct name
-        let env_predicates = env_predicates.filter_map(|p| match p {
-            ty::Predicate::Projection(data) => {
-                if data.projection_def_id() == obligation.predicate.item_def_id {
-                    Some(data)
-                } else {
-                    None
-                }
-            }
-            _ => None,
-        });
-
-        // select those with a relevant trait-ref
-        let mut env_predicates = env_predicates.filter(|data| {
-            let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
-            let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-            selcx.infcx().probe(|_| {
-                selcx
-                    .infcx()
-                    .at(&obligation.cause, obligation.param_env)
-                    .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                    .is_ok()
-            })
-        });
-
-        // select the first matching one; there really ought to be one or
-        // else the object type is not WF, since an object type should
-        // include all of its projections explicitly
-        match env_predicates.next() {
-            Some(env_predicate) => env_predicate,
-            None => {
-                debug!(
-                    "confirm_object_candidate: no env-predicate \
-                     found in object type `{:?}`; ill-formed",
-                    object_ty
-                );
-                return Progress::error(selcx.tcx());
-            }
-        }
-    };
-
-    confirm_param_env_candidate(selcx, obligation, env_predicate)
-}
-
-fn confirm_generator_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx());
-    let Normalized { value: gen_sig, obligations } = normalize_with_depth(
-        selcx,
-        obligation.param_env,
-        obligation.cause.clone(),
-        obligation.recursion_depth + 1,
-        &gen_sig,
-    );
-
-    debug!(
-        "confirm_generator_candidate: obligation={:?},gen_sig={:?},obligations={:?}",
-        obligation, gen_sig, obligations
-    );
-
-    let tcx = selcx.tcx();
-
-    let gen_def_id = tcx.lang_items().gen_trait().unwrap();
-
-    let predicate = super::util::generator_trait_ref_and_outputs(
-        tcx,
-        gen_def_id,
-        obligation.predicate.self_ty(),
-        gen_sig,
-    )
-    .map_bound(|(trait_ref, yield_ty, return_ty)| {
-        let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name;
-        let ty = if name == sym::Return {
-            return_ty
-        } else if name == sym::Yield {
-            yield_ty
-        } else {
-            bug!()
-        };
-
-        ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                substs: trait_ref.substs,
-                item_def_id: obligation.predicate.item_def_id,
-            },
-            ty,
-        }
-    });
-
-    confirm_param_env_candidate(selcx, obligation, predicate)
-        .with_addl_obligations(vtable.nested)
-        .with_addl_obligations(obligations)
-}
-
-fn confirm_fn_pointer_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
-    let sig = fn_type.fn_sig(selcx.tcx());
-    let Normalized { value: sig, obligations } = normalize_with_depth(
-        selcx,
-        obligation.param_env,
-        obligation.cause.clone(),
-        obligation.recursion_depth + 1,
-        &sig,
-    );
-
-    confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
-        .with_addl_obligations(fn_pointer_vtable.nested)
-        .with_addl_obligations(obligations)
-}
-
-fn confirm_closure_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let tcx = selcx.tcx();
-    let infcx = selcx.infcx();
-    let closure_sig_ty = vtable.substs.as_closure().sig_ty(vtable.closure_def_id, tcx);
-    let closure_sig = infcx.shallow_resolve(closure_sig_ty).fn_sig(tcx);
-    let Normalized { value: closure_sig, obligations } = normalize_with_depth(
-        selcx,
-        obligation.param_env,
-        obligation.cause.clone(),
-        obligation.recursion_depth + 1,
-        &closure_sig,
-    );
-
-    debug!(
-        "confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}",
-        obligation, closure_sig, obligations
-    );
-
-    confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
-        .with_addl_obligations(vtable.nested)
-        .with_addl_obligations(obligations)
-}
-
-fn confirm_callable_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    fn_sig: ty::PolyFnSig<'tcx>,
-    flag: util::TupleArgumentsFlag,
-) -> Progress<'tcx> {
-    let tcx = selcx.tcx();
-
-    debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig);
-
-    // the `Output` associated type is declared on `FnOnce`
-    let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap();
-
-    let predicate = super::util::closure_trait_ref_and_return_type(
-        tcx,
-        fn_once_def_id,
-        obligation.predicate.self_ty(),
-        fn_sig,
-        flag,
-    )
-    .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
-        projection_ty: ty::ProjectionTy::from_ref_and_name(
-            tcx,
-            trait_ref,
-            Ident::with_dummy_span(rustc_hir::FN_OUTPUT_NAME),
-        ),
-        ty: ret_type,
-    });
-
-    confirm_param_env_candidate(selcx, obligation, predicate)
-}
-
-fn confirm_param_env_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
-) -> Progress<'tcx> {
-    let infcx = selcx.infcx();
-    let cause = &obligation.cause;
-    let param_env = obligation.param_env;
-
-    let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars(
-        cause.span,
-        LateBoundRegionConversionTime::HigherRankedType,
-        &poly_cache_entry,
-    );
-
-    let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx);
-    let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx);
-    match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) {
-        Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations },
-        Err(e) => {
-            let msg = format!(
-                "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
-                obligation, poly_cache_entry, e,
-            );
-            debug!("confirm_param_env_candidate: {}", msg);
-            infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg);
-            Progress { ty: infcx.tcx.types.err, obligations: vec![] }
-        }
-    }
-}
-
-fn confirm_impl_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let tcx = selcx.tcx();
-
-    let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
-    let assoc_item_id = obligation.predicate.item_def_id;
-    let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
-
-    let param_env = obligation.param_env;
-    let assoc_ty = assoc_ty_def(selcx, impl_def_id, assoc_item_id);
-
-    if !assoc_ty.item.defaultness.has_value() {
-        // This means that the impl is missing a definition for the
-        // associated type. This error will be reported by the type
-        // checker method `check_impl_items_against_trait`, so here we
-        // just return Error.
-        debug!(
-            "confirm_impl_candidate: no associated type {:?} for {:?}",
-            assoc_ty.item.ident, obligation.predicate
-        );
-        return Progress { ty: tcx.types.err, obligations: nested };
-    }
-    let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
-    let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
-    let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
-        let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
-        tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
-    } else {
-        tcx.type_of(assoc_ty.item.def_id)
-    };
-    if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
-        tcx.sess
-            .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts");
-        Progress { ty: tcx.types.err, obligations: nested }
-    } else {
-        Progress { ty: ty.subst(tcx, substs), obligations: nested }
-    }
-}
-
-/// Locate the definition of an associated type in the specialization hierarchy,
-/// starting from the given impl.
-///
-/// Based on the "projection mode", this lookup may in fact only examine the
-/// topmost impl. See the comments for `Reveal` for more details.
-fn assoc_ty_def(
-    selcx: &SelectionContext<'_, '_>,
-    impl_def_id: DefId,
-    assoc_ty_def_id: DefId,
-) -> specialization_graph::NodeItem<ty::AssocItem> {
-    let tcx = selcx.tcx();
-    let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
-    let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
-    let trait_def = tcx.trait_def(trait_def_id);
-
-    // This function may be called while we are still building the
-    // specialization graph that is queried below (via TraidDef::ancestors()),
-    // so, in order to avoid unnecessary infinite recursion, we manually look
-    // for the associated item at the given impl.
-    // If there is no such item in that impl, this function will fail with a
-    // cycle error if the specialization graph is currently being built.
-    let impl_node = specialization_graph::Node::Impl(impl_def_id);
-    for item in impl_node.items(tcx) {
-        if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
-            && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
-        {
-            return specialization_graph::NodeItem {
-                node: specialization_graph::Node::Impl(impl_def_id),
-                item: *item,
-            };
-        }
-    }
-
-    if let Some(assoc_item) =
-        trait_def.ancestors(tcx, impl_def_id).leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type)
-    {
-        assoc_item
-    } else {
-        // This is saying that neither the trait nor
-        // the impl contain a definition for this
-        // associated type.  Normally this situation
-        // could only arise through a compiler bug --
-        // if the user wrote a bad item name, it
-        // should have failed in astconv.
-        bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id))
+        Normalized { value: value, obligations: self.obligations }
     }
 }
 
@@ -1541,26 +68,14 @@ pub struct ProjectionCacheKey<'tcx> {
     ty: ty::ProjectionTy<'tcx>,
 }
 
-impl<'cx, 'tcx> ProjectionCacheKey<'tcx> {
-    pub fn from_poly_projection_predicate(
-        selcx: &mut SelectionContext<'cx, 'tcx>,
-        predicate: &ty::PolyProjectionPredicate<'tcx>,
-    ) -> Option<Self> {
-        let infcx = selcx.infcx();
-        // We don't do cross-snapshot caching of obligations with escaping regions,
-        // so there's no cache key to use
-        predicate.no_bound_vars().map(|predicate| ProjectionCacheKey {
-            // We don't attempt to match up with a specific type-variable state
-            // from a specific call to `opt_normalize_projection_type` - if
-            // there's no precise match, the original cache entry is "stranded"
-            // anyway.
-            ty: infcx.resolve_vars_if_possible(&predicate.projection_ty),
-        })
+impl ProjectionCacheKey<'tcx> {
+    pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self {
+        Self { ty }
     }
 }
 
 #[derive(Clone, Debug)]
-enum ProjectionCacheEntry<'tcx> {
+pub enum ProjectionCacheEntry<'tcx> {
     InProgress,
     Ambiguous,
     Error,
@@ -1596,7 +111,7 @@ impl<'tcx> ProjectionCache<'tcx> {
     /// Try to start normalize `key`; returns an error if
     /// normalization already occurred (this error corresponds to a
     /// cache hit, so it's actually a good thing).
-    fn try_start(
+    pub fn try_start(
         &mut self,
         key: ProjectionCacheKey<'tcx>,
     ) -> Result<(), ProjectionCacheEntry<'tcx>> {
@@ -1609,7 +124,7 @@ impl<'tcx> ProjectionCache<'tcx> {
     }
 
     /// Indicates that `key` was normalized to `value`.
-    fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'tcx>) {
+    pub fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'tcx>) {
         debug!(
             "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
             key, value
@@ -1662,14 +177,14 @@ impl<'tcx> ProjectionCache<'tcx> {
     /// ambiguity. No point in trying it again then until we gain more
     /// type information (in which case, the "fully resolved" key will
     /// be different).
-    fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
+    pub fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
         let fresh = self.map.insert(key, ProjectionCacheEntry::Ambiguous);
         assert!(!fresh, "never started projecting `{:?}`", key);
     }
 
     /// Indicates that trying to normalize `key` resulted in
     /// error.
-    fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
+    pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
         let fresh = self.map.insert(key, ProjectionCacheEntry::Error);
         assert!(!fresh, "never started projecting `{:?}`", key);
     }
diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs
index cd4595e76cc..a7c02671115 100644
--- a/src/librustc_infer/traits/util.rs
+++ b/src/librustc_infer/traits/util.rs
@@ -1,16 +1,8 @@
-use rustc_errors::DiagnosticBuilder;
-use rustc_span::Span;
 use smallvec::smallvec;
-use smallvec::SmallVec;
 
 use rustc::ty::outlives::Component;
-use rustc::ty::subst::{GenericArg, Subst, SubstsRef};
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc::ty::{self, ToPolyTraitRef, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-
-use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
 
 fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
     match *pred {
@@ -55,7 +47,7 @@ struct PredicateSet<'tcx> {
 
 impl PredicateSet<'tcx> {
     fn new(tcx: TyCtxt<'tcx>) -> Self {
-        Self { tcx, set: Default::default() }
+        Self { tcx: tcx, set: Default::default() }
     }
 
     fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
@@ -96,21 +88,6 @@ pub struct Elaborator<'tcx> {
     visited: PredicateSet<'tcx>,
 }
 
-pub fn elaborate_trait_ref<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> Elaborator<'tcx> {
-    elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
-}
-
-pub fn elaborate_trait_refs<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
-) -> Elaborator<'tcx> {
-    let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
-    elaborate_predicates(tcx, predicates)
-}
-
 pub fn elaborate_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     mut predicates: Vec<ty::Predicate<'tcx>>,
@@ -121,10 +98,6 @@ pub fn elaborate_predicates<'tcx>(
 }
 
 impl Elaborator<'tcx> {
-    pub fn filter_to_traits(self) -> FilterToTraits<Self> {
-        FilterToTraits::new(self)
-    }
-
     fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
         let tcx = self.visited.tcx;
         match *predicate {
@@ -250,426 +223,3 @@ impl Iterator for Elaborator<'tcx> {
         }
     }
 }
-
-///////////////////////////////////////////////////////////////////////////
-// Supertrait iterator
-///////////////////////////////////////////////////////////////////////////
-
-pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
-
-pub fn supertraits<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> Supertraits<'tcx> {
-    elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
-}
-
-pub fn transitive_bounds<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
-) -> Supertraits<'tcx> {
-    elaborate_trait_refs(tcx, bounds).filter_to_traits()
-}
-
-///////////////////////////////////////////////////////////////////////////
-// `TraitAliasExpander` iterator
-///////////////////////////////////////////////////////////////////////////
-
-/// "Trait alias expansion" is the process of expanding a sequence of trait
-/// references into another sequence by transitively following all trait
-/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias
-/// `trait Foo = Bar + Sync;`, and another trait alias
-/// `trait Bar = Read + Write`, then the bounds would expand to
-/// `Read + Write + Sync + Send`.
-/// Expansion is done via a DFS (depth-first search), and the `visited` field
-/// is used to avoid cycles.
-pub struct TraitAliasExpander<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    stack: Vec<TraitAliasExpansionInfo<'tcx>>,
-}
-
-/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
-#[derive(Debug, Clone)]
-pub struct TraitAliasExpansionInfo<'tcx> {
-    pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>,
-}
-
-impl<'tcx> TraitAliasExpansionInfo<'tcx> {
-    fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
-        Self { path: smallvec![(trait_ref, span)] }
-    }
-
-    /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
-    /// trait aliases.
-    pub fn label_with_exp_info(
-        &self,
-        diag: &mut DiagnosticBuilder<'_>,
-        top_label: &str,
-        use_desc: &str,
-    ) {
-        diag.span_label(self.top().1, top_label);
-        if self.path.len() > 1 {
-            for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
-                diag.span_label(*sp, format!("referenced here ({})", use_desc));
-            }
-        }
-        diag.span_label(
-            self.bottom().1,
-            format!("trait alias used in trait object type ({})", use_desc),
-        );
-    }
-
-    pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> {
-        &self.top().0
-    }
-
-    pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
-        self.path.last().unwrap()
-    }
-
-    pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
-        self.path.first().unwrap()
-    }
-
-    fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
-        let mut path = self.path.clone();
-        path.push((trait_ref, span));
-
-        Self { path }
-    }
-}
-
-pub fn expand_trait_aliases<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_refs: impl IntoIterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
-) -> TraitAliasExpander<'tcx> {
-    let items: Vec<_> = trait_refs
-        .into_iter()
-        .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span))
-        .collect();
-    TraitAliasExpander { tcx, stack: items }
-}
-
-impl<'tcx> TraitAliasExpander<'tcx> {
-    /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item`
-    /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`.
-    /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
-    /// trait alias.
-    /// The return value indicates whether `item` should be yielded to the user.
-    fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
-        let tcx = self.tcx;
-        let trait_ref = item.trait_ref();
-        let pred = trait_ref.without_const().to_predicate();
-
-        debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
-
-        // Don't recurse if this bound is not a trait alias.
-        let is_alias = tcx.is_trait_alias(trait_ref.def_id());
-        if !is_alias {
-            return true;
-        }
-
-        // Don't recurse if this trait alias is already on the stack for the DFS search.
-        let anon_pred = anonymize_predicate(tcx, &pred);
-        if item.path.iter().rev().skip(1).any(|(tr, _)| {
-            anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred
-        }) {
-            return false;
-        }
-
-        // Get components of trait alias.
-        let predicates = tcx.super_predicates_of(trait_ref.def_id());
-
-        let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
-            pred.subst_supertrait(tcx, &trait_ref)
-                .to_opt_poly_trait_ref()
-                .map(|trait_ref| item.clone_and_push(trait_ref, *span))
-        });
-        debug!("expand_trait_aliases: items={:?}", items.clone());
-
-        self.stack.extend(items);
-
-        false
-    }
-}
-
-impl<'tcx> Iterator for TraitAliasExpander<'tcx> {
-    type Item = TraitAliasExpansionInfo<'tcx>;
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.stack.len(), None)
-    }
-
-    fn next(&mut self) -> Option<TraitAliasExpansionInfo<'tcx>> {
-        while let Some(item) = self.stack.pop() {
-            if self.expand(&item) {
-                return Some(item);
-            }
-        }
-        None
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Iterator over def-IDs of supertraits
-///////////////////////////////////////////////////////////////////////////
-
-pub struct SupertraitDefIds<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    stack: Vec<DefId>,
-    visited: FxHashSet<DefId>,
-}
-
-pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> {
-    SupertraitDefIds {
-        tcx,
-        stack: vec![trait_def_id],
-        visited: Some(trait_def_id).into_iter().collect(),
-    }
-}
-
-impl Iterator for SupertraitDefIds<'tcx> {
-    type Item = DefId;
-
-    fn next(&mut self) -> Option<DefId> {
-        let def_id = self.stack.pop()?;
-        let predicates = self.tcx.super_predicates_of(def_id);
-        let visited = &mut self.visited;
-        self.stack.extend(
-            predicates
-                .predicates
-                .iter()
-                .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref())
-                .map(|trait_ref| trait_ref.def_id())
-                .filter(|&super_def_id| visited.insert(super_def_id)),
-        );
-        Some(def_id)
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Other
-///////////////////////////////////////////////////////////////////////////
-
-/// A filter around an iterator of predicates that makes it yield up
-/// just trait references.
-pub struct FilterToTraits<I> {
-    base_iterator: I,
-}
-
-impl<I> FilterToTraits<I> {
-    fn new(base: I) -> FilterToTraits<I> {
-        FilterToTraits { base_iterator: base }
-    }
-}
-
-impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
-    type Item = ty::PolyTraitRef<'tcx>;
-
-    fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
-        while let Some(pred) = self.base_iterator.next() {
-            if let ty::Predicate::Trait(data, _) = pred {
-                return Some(data.to_poly_trait_ref());
-            }
-        }
-        None
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.base_iterator.size_hint();
-        (0, upper)
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Other
-///////////////////////////////////////////////////////////////////////////
-
-/// Instantiate all bound parameters of the impl with the given substs,
-/// returning the resulting trait ref and all obligations that arise.
-/// The obligations are closed under normalization.
-pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
-    selcx: &mut SelectionContext<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    impl_def_id: DefId,
-    impl_substs: SubstsRef<'tcx>,
-) -> (ty::TraitRef<'tcx>, Vec<PredicateObligation<'tcx>>) {
-    let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
-    let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs);
-    let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
-        super::normalize(selcx, param_env, ObligationCause::dummy(), &impl_trait_ref);
-
-    let predicates = selcx.tcx().predicates_of(impl_def_id);
-    let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
-    let Normalized { value: predicates, obligations: normalization_obligations2 } =
-        super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates);
-    let impl_obligations =
-        predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates);
-
-    let impl_obligations: Vec<_> = impl_obligations
-        .into_iter()
-        .chain(normalization_obligations1)
-        .chain(normalization_obligations2)
-        .collect();
-
-    (impl_trait_ref, impl_obligations)
-}
-
-/// See [`super::obligations_for_generics`].
-pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
-    recursion_depth: usize,
-    param_env: ty::ParamEnv<'tcx>,
-    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
-) -> Vec<PredicateObligation<'tcx>> {
-    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
-
-    generic_bounds
-        .predicates
-        .iter()
-        .map(|&predicate| Obligation {
-            cause: cause.clone(),
-            recursion_depth,
-            param_env,
-            predicate,
-        })
-        .collect()
-}
-
-pub fn predicate_for_trait_ref<'tcx>(
-    cause: ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-    recursion_depth: usize,
-) -> PredicateObligation<'tcx> {
-    Obligation {
-        cause,
-        param_env,
-        recursion_depth,
-        predicate: trait_ref.without_const().to_predicate(),
-    }
-}
-
-pub fn predicate_for_trait_def(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    trait_def_id: DefId,
-    recursion_depth: usize,
-    self_ty: Ty<'tcx>,
-    params: &[GenericArg<'tcx>],
-) -> PredicateObligation<'tcx> {
-    let trait_ref =
-        ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) };
-    predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
-}
-
-/// Casts a trait reference into a reference to one of its super
-/// traits; returns `None` if `target_trait_def_id` is not a
-/// supertrait.
-pub fn upcast_choices(
-    tcx: TyCtxt<'tcx>,
-    source_trait_ref: ty::PolyTraitRef<'tcx>,
-    target_trait_def_id: DefId,
-) -> Vec<ty::PolyTraitRef<'tcx>> {
-    if source_trait_ref.def_id() == target_trait_def_id {
-        return vec![source_trait_ref]; // Shortcut the most common case.
-    }
-
-    supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
-}
-
-/// Given a trait `trait_ref`, returns the number of vtable entries
-/// that come from `trait_ref`, excluding its supertraits. Used in
-/// computing the vtable base for an upcast trait of a trait object.
-pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
-    let mut entries = 0;
-    // Count number of methods and add them to the total offset.
-    // Skip over associated types and constants.
-    for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
-        if trait_item.kind == ty::AssocKind::Method {
-            entries += 1;
-        }
-    }
-    entries
-}
-
-/// Given an upcast trait object described by `object`, returns the
-/// index of the method `method_def_id` (which should be part of
-/// `object.upcast_trait_ref`) within the vtable for `object`.
-pub fn get_vtable_index_of_object_method<N>(
-    tcx: TyCtxt<'tcx>,
-    object: &super::VtableObjectData<'tcx, N>,
-    method_def_id: DefId,
-) -> usize {
-    // Count number of methods preceding the one we are selecting and
-    // add them to the total offset.
-    // Skip over associated types and constants.
-    let mut entries = object.vtable_base;
-    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
-        if trait_item.def_id == method_def_id {
-            // The item with the ID we were given really ought to be a method.
-            assert_eq!(trait_item.kind, ty::AssocKind::Method);
-            return entries;
-        }
-        if trait_item.kind == ty::AssocKind::Method {
-            entries += 1;
-        }
-    }
-
-    bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
-}
-
-pub fn closure_trait_ref_and_return_type(
-    tcx: TyCtxt<'tcx>,
-    fn_trait_def_id: DefId,
-    self_ty: Ty<'tcx>,
-    sig: ty::PolyFnSig<'tcx>,
-    tuple_arguments: TupleArgumentsFlag,
-) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> {
-    let arguments_tuple = match tuple_arguments {
-        TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
-        TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
-    };
-    let trait_ref = ty::TraitRef {
-        def_id: fn_trait_def_id,
-        substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
-    };
-    ty::Binder::bind((trait_ref, sig.skip_binder().output()))
-}
-
-pub fn generator_trait_ref_and_outputs(
-    tcx: TyCtxt<'tcx>,
-    fn_trait_def_id: DefId,
-    self_ty: Ty<'tcx>,
-    sig: ty::PolyGenSig<'tcx>,
-) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
-    let trait_ref = ty::TraitRef {
-        def_id: fn_trait_def_id,
-        substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]),
-    };
-    ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
-}
-
-pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool {
-    match tcx.hir().as_local_hir_id(node_item_def_id) {
-        Some(hir_id) => {
-            let item = tcx.hir().expect_item(hir_id);
-            if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
-                defaultness.is_default()
-            } else {
-                false
-            }
-        }
-        None => tcx.impl_defaultness(node_item_def_id).is_default(),
-    }
-}
-
-pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
-    assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id())
-}
-
-pub enum TupleArgumentsFlag {
-    Yes,
-    No,
-}
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index b29480a8810..e84181f1d75 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -42,6 +42,7 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_plugin_impl = { path = "../librustc_plugin_impl" }
 rustc_privacy = { path = "../librustc_privacy" }
 rustc_resolve = { path = "../librustc_resolve" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
 rustc_ty = { path = "../librustc_ty" }
 tempfile = "3.0.5"
 once_cell = "1"
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index e15217dfa67..c5ebcf0696f 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -1,10 +1,6 @@
 pub use crate::passes::BoxedResolver;
 use crate::util;
 
-use rustc::lint;
-use rustc::session::config::{self, ErrorOutputType, Input, OutputFilenames};
-use rustc::session::early_error;
-use rustc::session::{DiagnosticOutput, Session};
 use rustc::ty;
 use rustc::util::common::ErrorReported;
 use rustc_ast::ast::{self, MetaItemKind};
@@ -16,7 +12,11 @@ use rustc_data_structures::OnDrop;
 use rustc_errors::registry::Registry;
 use rustc_lint::LintStore;
 use rustc_parse::new_parser_from_source_str;
+use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames};
+use rustc_session::early_error;
+use rustc_session::lint;
 use rustc_session::parse::{CrateConfig, ParseSess};
+use rustc_session::{DiagnosticOutput, Session};
 use rustc_span::edition;
 use rustc_span::source_map::{FileLoader, FileName, SourceMap};
 use std::path::PathBuf;
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 29e9ea1833f..ee323b204b7 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -5,14 +5,9 @@ use crate::util;
 use log::{info, log_enabled, warn};
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
-use rustc::hir::map;
-use rustc::lint;
+use rustc::hir::map::Definitions;
 use rustc::middle;
 use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn};
-use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType};
-use rustc::session::config::{PpMode, PpSourceMode};
-use rustc::session::search_paths::PathKind;
-use rustc::session::Session;
 use rustc::ty::steal::Steal;
 use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
 use rustc::util::common::ErrorReported;
@@ -27,7 +22,6 @@ use rustc_errors::PResult;
 use rustc_expand::base::ExtCtxt;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_hir::Crate;
-use rustc_infer::traits;
 use rustc_lint::LintStore;
 use rustc_mir as mir;
 use rustc_mir_build as mir_build;
@@ -35,8 +29,14 @@ use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
 use rustc_passes::{self, hir_stats, layout_test};
 use rustc_plugin_impl as plugin;
 use rustc_resolve::{Resolver, ResolverArenas};
+use rustc_session::config::{self, CrateType, Input, OutputFilenames, OutputType};
+use rustc_session::config::{PpMode, PpSourceMode};
+use rustc_session::lint;
+use rustc_session::search_paths::PathKind;
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_span::FileName;
+use rustc_trait_selection::traits;
 use rustc_typeck as typeck;
 
 use rustc_serialize::json;
@@ -210,14 +210,7 @@ pub fn register_plugins<'a>(
     Ok((krate, Lrc::new(lint_store)))
 }
 
-fn configure_and_expand_inner<'a>(
-    sess: &'a Session,
-    lint_store: &'a LintStore,
-    mut krate: ast::Crate,
-    crate_name: &str,
-    resolver_arenas: &'a ResolverArenas<'a>,
-    metadata_loader: &'a MetadataLoaderDyn,
-) -> Result<(ast::Crate, Resolver<'a>)> {
+fn pre_expansion_lint(sess: &Session, lint_store: &LintStore, krate: &ast::Crate) {
     sess.time("pre_AST_expansion_lint_checks", || {
         rustc_lint::check_ast_crate(
             sess,
@@ -228,6 +221,17 @@ fn configure_and_expand_inner<'a>(
             rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
         );
     });
+}
+
+fn configure_and_expand_inner<'a>(
+    sess: &'a Session,
+    lint_store: &'a LintStore,
+    mut krate: ast::Crate,
+    crate_name: &str,
+    resolver_arenas: &'a ResolverArenas<'a>,
+    metadata_loader: &'a MetadataLoaderDyn,
+) -> Result<(ast::Crate, Resolver<'a>)> {
+    pre_expansion_lint(sess, lint_store, &krate);
 
     let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas);
     rustc_builtin_macros::register_builtin_macros(&mut resolver, sess.edition());
@@ -291,7 +295,8 @@ fn configure_and_expand_inner<'a>(
             ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string())
         };
 
-        let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver);
+        let extern_mod_loaded = |k: &ast::Crate| pre_expansion_lint(sess, lint_store, k);
+        let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver, Some(&extern_mod_loaded));
 
         // Expand macros now!
         let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
@@ -713,10 +718,7 @@ pub fn create_global_ctxt<'tcx>(
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
 ) -> QueryContext<'tcx> {
     let sess = &compiler.session();
-    let defs = mem::take(&mut resolver_outputs.definitions);
-
-    // Construct the HIR map.
-    let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, krate, dep_graph, defs);
+    let defs: &'tcx Definitions = arena.alloc(mem::take(&mut resolver_outputs.definitions));
 
     let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
 
@@ -742,7 +744,9 @@ pub fn create_global_ctxt<'tcx>(
                 extern_providers,
                 arena,
                 resolver_outputs,
-                hir_map,
+                krate,
+                defs,
+                dep_graph,
                 query_result_on_disk_cache,
                 &crate_name,
                 &outputs,
@@ -763,6 +767,8 @@ pub fn create_global_ctxt<'tcx>(
 fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
     assert_eq!(cnum, LOCAL_CRATE);
 
+    rustc::hir::map::check_crate(tcx);
+
     let sess = tcx.sess;
     let mut entry_point = None;
 
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index 426d97cc09b..3514829dca7 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -3,8 +3,6 @@ use crate::passes::{self, BoxedResolver, QueryContext};
 
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
-use rustc::session::config::{OutputFilenames, OutputType};
-use rustc::session::Session;
 use rustc::ty::steal::Steal;
 use rustc::ty::{GlobalCtxt, ResolverOutputs};
 use rustc::util::common::ErrorReported;
@@ -15,6 +13,8 @@ use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::Crate;
 use rustc_incremental::DepGraphFuture;
 use rustc_lint::LintStore;
+use rustc_session::config::{OutputFilenames, OutputType};
+use rustc_session::Session;
 use std::any::Any;
 use std::cell::{Ref, RefCell, RefMut};
 use std::mem;
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index 1b80cf4e3db..db5ada92914 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -2,16 +2,16 @@ extern crate getopts;
 
 use crate::interface::parse_cfgspecs;
 
-use rustc::lint::Level;
 use rustc::middle::cstore;
-use rustc::session::config::{build_configuration, build_session_options, to_crate_config};
-use rustc::session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
-use rustc::session::config::{ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
-use rustc::session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion};
-use rustc::session::search_paths::SearchPath;
-use rustc::session::{build_session, Session};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
+use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
+use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
+use rustc_session::config::{ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
+use rustc_session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion};
+use rustc_session::lint::Level;
+use rustc_session::search_paths::SearchPath;
+use rustc_session::{build_session, Session};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_span::symbol::sym;
 use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel};
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 7866ddbd4cc..5c4de9e7155 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -1,5 +1,4 @@
 use log::info;
-use rustc::lint;
 use rustc::ty;
 use rustc_ast::ast::{AttrVec, BlockCheckMode};
 use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
@@ -18,7 +17,7 @@ use rustc_metadata::dynamic_lib::DynamicLibrary;
 use rustc_resolve::{self, Resolver};
 use rustc_session as session;
 use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
-use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::parse::CrateConfig;
 use rustc_session::CrateDisambiguator;
 use rustc_session::{config, early_error, filesearch, DiagnosticOutput, Session};
@@ -49,7 +48,7 @@ pub fn add_configuration(
 
     cfg.extend(codegen_backend.target_features(sess).into_iter().map(|feat| (tf, Some(feat))));
 
-    if sess.crt_static_feature() {
+    if sess.crt_static_feature(None) {
         cfg.insert((tf, Some(Symbol::intern("crt-static"))));
     }
 }
@@ -780,7 +779,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
 
     // in general the pretty printer processes unexpanded code, so
     // we override the default `visit_mac` method which panics.
-    fn visit_mac(&mut self, mac: &mut ast::Mac) {
+    fn visit_mac(&mut self, mac: &mut ast::MacCall) {
         noop_visit_mac(mac, self)
     }
 }
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index 6470d25fe0a..9785af5eab2 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -24,3 +24,4 @@ rustc_feature = { path = "../librustc_feature" }
 rustc_index = { path = "../librustc_index" }
 rustc_session = { path = "../librustc_session" }
 rustc_infer = { path = "../librustc_infer" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index e1680015bea..408031028b1 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -22,7 +22,6 @@
 //! `late_lint_methods!` invocation in `lib.rs`.
 
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc::hir::map::Map;
 use rustc::lint::LintDiagnosticBuilder;
 use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt};
 use rustc_ast::ast::{self, Expr};
@@ -39,12 +38,12 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{GenericParamKind, PatKind};
 use rustc_hir::{HirIdSet, Node};
-use rustc_infer::traits::misc::can_type_implement_copy;
 use rustc_session::lint::FutureIncompatibleInfo;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, Span};
+use rustc_trait_selection::traits::misc::can_type_implement_copy;
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
@@ -399,7 +398,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
     }
 
     fn check_crate(&mut self, cx: &LateContext<'_, '_>, krate: &hir::Crate<'_>) {
-        self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate");
+        self.check_missing_docs_attrs(cx, None, &krate.item.attrs, krate.item.span, "crate");
 
         for macro_def in krate.exported_macros {
             let has_doc = macro_def.attrs.iter().any(|a| has_doc(a));
@@ -465,7 +464,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
 
         let desc = match trait_item.kind {
             hir::TraitItemKind::Const(..) => "an associated constant",
-            hir::TraitItemKind::Method(..) => "a trait method",
+            hir::TraitItemKind::Fn(..) => "a trait method",
             hir::TraitItemKind::Type(..) => "an associated type",
         };
 
@@ -486,7 +485,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
 
         let desc = match impl_item.kind {
             hir::ImplItemKind::Const(..) => "an associated constant",
-            hir::ImplItemKind::Method(..) => "a method",
+            hir::ImplItemKind::Fn(..) => "a method",
             hir::ImplItemKind::TyAlias(_) => "an associated type",
             hir::ImplItemKind::OpaqueTy(_) => "an associated `impl Trait` type",
         };
@@ -778,7 +777,7 @@ impl EarlyLintPass for UnusedDocComment {
             ast::StmtKind::Empty
             | ast::StmtKind::Semi(_)
             | ast::StmtKind::Expr(_)
-            | ast::StmtKind::Mac(_) => return,
+            | ast::StmtKind::MacCall(_) => return,
         };
 
         warn_if_doc(cx, stmt.span, kind, stmt.kind.attrs());
@@ -1071,9 +1070,9 @@ impl TypeAliasBounds {
             err: &'a mut DiagnosticBuilder<'db>,
         }
         impl<'a, 'db, 'v> Visitor<'v> for WalkAssocTypes<'a, 'db> {
-            type Map = Map<'v>;
+            type Map = intravisit::ErasedMap<'v>;
 
-            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
                 intravisit::NestedVisitorMap::None
             }
 
@@ -1478,7 +1477,7 @@ impl EarlyLintPass for KeywordIdents {
     fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef, _id: ast::NodeId) {
         self.check_tokens(cx, mac_def.body.inner_tokens());
     }
-    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
+    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) {
         self.check_tokens(cx, mac.args.inner_tokens());
     }
     fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs
index ff6e9e000b0..34da29c9747 100644
--- a/src/librustc_lint/early.rs
+++ b/src/librustc_lint/early.rs
@@ -18,7 +18,7 @@ use crate::context::{EarlyContext, LintContext, LintStore};
 use crate::passes::{EarlyLintPass, EarlyLintPassObject};
 use rustc_ast::ast;
 use rustc_ast::visit as ast_visit;
-use rustc_session::lint::{LintBuffer, LintPass};
+use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
 use rustc_session::Session;
 use rustc_span::Span;
 
@@ -37,13 +37,7 @@ struct EarlyContextAndPass<'a, T: EarlyLintPass> {
 impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
     fn check_id(&mut self, id: ast::NodeId) {
         for early_lint in self.context.buffered.take(id) {
-            let rustc_session::lint::BufferedEarlyLint {
-                span,
-                msg,
-                node_id: _,
-                lint_id,
-                diagnostic,
-            } = early_lint;
+            let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint;
             self.context.lookup_with_diagnostics(
                 lint_id.lint,
                 Some(span),
@@ -249,7 +243,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         self.check_id(id);
     }
 
-    fn visit_mac(&mut self, mac: &'a ast::Mac) {
+    fn visit_mac(&mut self, mac: &'a ast::MacCall) {
         // FIXME(#54110): So, this setup isn't really right. I think
         // that (a) the librustc_ast visitor ought to be doing this as
         // part of `walk_mac`, and (b) we should be calling
@@ -326,11 +320,9 @@ pub fn check_ast_crate<T: EarlyLintPass>(
     lint_buffer: Option<LintBuffer>,
     builtin_lints: T,
 ) {
-    let mut passes: Vec<_> = if pre_expansion {
-        lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect()
-    } else {
-        lint_store.early_passes.iter().map(|p| (p)()).collect()
-    };
+    let passes =
+        if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes };
+    let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect();
     let mut buffered = lint_buffer.unwrap_or_default();
 
     if !sess.opts.debugging_opts.no_interleave_lints {
diff --git a/src/librustc_lint/internal.rs b/src/librustc_lint/internal.rs
index db109aef6eb..d8c685f2b22 100644
--- a/src/librustc_lint/internal.rs
+++ b/src/librustc_lint/internal.rs
@@ -140,7 +140,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind {
                 }
             }
             TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => {
-                if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) {
+                if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
                     if cx.tcx.impl_trait_ref(impl_did).is_some() {
                         return;
                     }
diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs
index ee03232a0ce..d2cc5510603 100644
--- a/src/librustc_lint/late.rs
+++ b/src/librustc_lint/late.rs
@@ -33,7 +33,7 @@ use std::slice;
 
 /// Extract the `LintStore` from the query context.
 /// This function exists because we've erased `LintStore` as `dyn Any` in the context.
-crate fn unerased_lint_store<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx LintStore {
+crate fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore {
     let store: &dyn Any = &*tcx.lint_store;
     store.downcast_ref().unwrap()
 }
@@ -99,8 +99,8 @@ impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx>
     /// Because lints are scoped lexically, we want to walk nested
     /// items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, Self::Map> {
-        hir_visit::NestedVisitorMap::All(&self.context.tcx.hir())
+    fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
+        hir_visit::NestedVisitorMap::All(self.context.tcx.hir())
     }
 
     fn visit_nested_body(&mut self, body: hir::BodyId) {
@@ -419,7 +419,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc
     let mut cx = LateContextAndPass { context, pass };
 
     // Visit the whole crate.
-    cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.attrs, |cx| {
+    cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.item.attrs, |cx| {
         // since the root module isn't visited as an item (because it isn't an
         // item), warn for it here.
         lint_callback!(cx, check_crate, krate);
diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs
index e0db2ae64ff..2062f9499ae 100644
--- a/src/librustc_lint/levels.rs
+++ b/src/librustc_lint/levels.rs
@@ -29,7 +29,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
     let mut builder = LintLevelMapBuilder { levels, tcx, store };
     let krate = tcx.hir().krate();
 
-    let push = builder.levels.push(&krate.attrs, &store);
+    let push = builder.levels.push(&krate.item.attrs, &store);
     builder.levels.register_id(hir::CRATE_HIR_ID);
     for macro_def in krate.exported_macros {
         builder.levels.register_id(macro_def.hir_id);
@@ -438,8 +438,8 @@ impl LintLevelMapBuilder<'_, '_> {
 impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
-        intravisit::NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index b0560dc9fdf..afab55358d9 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -343,7 +343,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::TraitItem<'_>) {
-        if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(pnames)) = item.kind {
+        if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind {
             self.check_snake_case(cx, "trait method", &item.ident);
             for param_name in pnames {
                 self.check_snake_case(cx, "variable", param_name);
diff --git a/src/librustc_lint/passes.rs b/src/librustc_lint/passes.rs
index 813be2a032f..ace15471445 100644
--- a/src/librustc_lint/passes.rs
+++ b/src/librustc_lint/passes.rs
@@ -198,7 +198,7 @@ macro_rules! early_lint_methods {
             fn check_path(a: &ast::Path, b: ast::NodeId);
             fn check_attribute(a: &ast::Attribute);
             fn check_mac_def(a: &ast::MacroDef, b: ast::NodeId);
-            fn check_mac(a: &ast::Mac);
+            fn check_mac(a: &ast::MacCall);
 
             /// Called when entering a syntax node that can have lint attributes such
             /// as `#[allow(...)]`. Called with *all* the attributes of that node.
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 86d93612e99..4949c93d45e 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -165,7 +165,7 @@ fn report_bin_hex_error(
         let mut err = lint.build(&format!("literal out of range for {}", t));
         err.note(&format!(
             "the literal `{}` (decimal `{}`) does not fit into \
-                    an `{}` and will become `{}{}`",
+             the type `{}` and will become `{}{}`",
             repr_str, val, t, actually, t
         ));
         if let Some(sugg_ty) = get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative)
@@ -242,7 +242,7 @@ fn lint_int_literal<'a, 'tcx>(
     v: u128,
 ) {
     let int_type = t.normalize(cx.sess().target.ptr_width);
-    let (_, max) = int_ty_range(int_type);
+    let (min, max) = int_ty_range(int_type);
     let max = max as u128;
     let negative = type_limits.negated_expr_id == e.hir_id;
 
@@ -267,7 +267,19 @@ fn lint_int_literal<'a, 'tcx>(
         }
 
         cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
-            lint.build(&format!("literal out of range for `{}`", t.name_str())).emit()
+            lint.build(&format!("literal out of range for `{}`", t.name_str()))
+                .note(&format!(
+                    "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
+                    cx.sess()
+                        .source_map()
+                        .span_to_snippet(lit.span)
+                        .ok()
+                        .expect("must get snippet from literal"),
+                    t.name_str(),
+                    min,
+                    max,
+                ))
+                .emit();
         });
     }
 }
@@ -320,7 +332,19 @@ fn lint_uint_literal<'a, 'tcx>(
             return;
         }
         cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
-            lint.build(&format!("literal out of range for `{}`", t.name_str())).emit()
+            lint.build(&format!("literal out of range for `{}`", t.name_str()))
+                .note(&format!(
+                    "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
+                    cx.sess()
+                        .source_map()
+                        .span_to_snippet(lit.span)
+                        .ok()
+                        .expect("must get snippet from literal"),
+                    t.name_str(),
+                    min,
+                    max,
+                ))
+                .emit()
         });
     }
 }
@@ -352,7 +376,17 @@ fn lint_literal<'a, 'tcx>(
             };
             if is_infinite == Ok(true) {
                 cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
-                    lint.build(&format!("literal out of range for `{}`", t.name_str())).emit()
+                    lint.build(&format!("literal out of range for `{}`", t.name_str()))
+                        .note(&format!(
+                            "the literal `{}` does not fit into the type `{}` and will be converted to `std::{}::INFINITY`",
+                            cx.sess()
+                                .source_map()
+                                .span_to_snippet(lit.span)
+                                .expect("must get snippet from literal"),
+                            t.name_str(),
+                            t.name_str(),
+                        ))
+                        .emit();
                 });
             }
         }
@@ -998,10 +1032,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
             let ty = cx.tcx.erase_regions(&t);
             let layout = match cx.layout_of(ty) {
                 Ok(layout) => layout,
-                Err(ty::layout::LayoutError::Unknown(_)) => return,
-                Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => {
-                    bug!("failed to get layout for `{}`: {}", t, err);
-                }
+                Err(ty::layout::LayoutError::Unknown(_))
+                | Err(ty::layout::LayoutError::SizeOverflow(_)) => return,
             };
             let (variants, tag) = match layout.variants {
                 layout::Variants::Multiple {
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 02f04b23459..229740615f7 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -54,7 +54,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
                 match callee.kind {
                     hir::ExprKind::Path(ref qpath) => {
                         match cx.tables.qpath_res(qpath, callee.hir_id) {
-                            Res::Def(DefKind::Fn, def_id) | Res::Def(DefKind::Method, def_id) => {
+                            Res::Def(DefKind::Fn, def_id) | Res::Def(DefKind::AssocFn, def_id) => {
                                 Some(def_id)
                             }
                             // `Res::Local` if it was a closure, for which we
@@ -124,7 +124,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
             descr_post: &str,
             plural_len: usize,
         ) -> bool {
-            if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(cx.tcx.parent_module(expr.hir_id), ty)
+            if ty.is_unit()
+                || cx.tcx.is_ty_uninhabited_from(
+                    cx.tcx.parent_module(expr.hir_id).to_def_id(),
+                    ty,
+                    cx.param_env,
+                )
             {
                 return true;
             }
@@ -538,7 +543,7 @@ impl EarlyLintPass for UnusedParens {
             // Do not lint on `(..)` as that will result in the other arms being useless.
             Paren(_)
             // The other cases do not contain sub-patterns.
-            | Wild | Rest | Lit(..) | Mac(..) | Range(..) | Ident(.., None) | Path(..) => return,
+            | Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => return,
             // These are list-like patterns; parens can always be removed.
             TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
                 self.check_unused_parens_pat(cx, p, false, false);
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index a8e308c5c9e..088cba83ef9 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -26,6 +26,7 @@ stable_deref_trait = "1.0.0"
 rustc_ast = { path = "../librustc_ast" }
 rustc_expand = { path = "../librustc_expand" }
 rustc_span = { path = "../librustc_span" }
+rustc_session = { path = "../librustc_session" }
 
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["errhandlingapi", "libloaderapi"] }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 18b4c9ad504..f20cdfcba15 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -6,19 +6,18 @@ use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob
 use rustc::hir::map::Definitions;
 use rustc::middle::cstore::DepKind;
 use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn};
-use rustc::session::config;
-use rustc::session::search_paths::PathKind;
-use rustc::session::{CrateDisambiguator, Session};
 use rustc::ty::TyCtxt;
-use rustc_ast::ast;
-use rustc_ast::attr;
 use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind};
+use rustc_ast::{ast, attr};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_index::vec::IndexVec;
+use rustc_session::config;
+use rustc_session::search_paths::PathKind;
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -871,11 +870,11 @@ impl<'a> CrateLoader<'a> {
                 let cnum = self.resolve_crate(name, item.span, dep_kind, None);
 
                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
-                let path_len = definitions.def_path(def_id.index).data.len();
+                let path_len = definitions.def_path(def_id).data.len();
                 self.update_extern_crate(
                     cnum,
                     ExternCrate {
-                        src: ExternCrateSource::Extern(def_id),
+                        src: ExternCrateSource::Extern(def_id.to_def_id()),
                         span: item.span,
                         path_len,
                         dependency_of: LOCAL_CRATE,
diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs
index 9e71839dbfd..4cfaf03b7a5 100644
--- a/src/librustc_metadata/dependency_format.rs
+++ b/src/librustc_metadata/dependency_format.rs
@@ -56,10 +56,10 @@ use crate::creader::CStore;
 use rustc::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
 use rustc::middle::cstore::{self, DepKind};
 use rustc::middle::dependency_format::{Dependencies, DependencyList, Linkage};
-use rustc::session::config;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::CrateNum;
+use rustc_session::config;
 use rustc_target::spec::PanicStrategy;
 
 crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
@@ -97,7 +97,9 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
 
         // If the global prefer_dynamic switch is turned off, or the final
         // executable will be statically linked, prefer static crate linkage.
-        config::CrateType::Executable if !sess.opts.cg.prefer_dynamic || sess.crt_static() => {
+        config::CrateType::Executable
+            if !sess.opts.cg.prefer_dynamic || sess.crt_static(Some(ty)) =>
+        {
             Linkage::Static
         }
         config::CrateType::Executable => Linkage::Dynamic,
@@ -129,7 +131,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
         // If any are not found, generate some nice pretty errors.
         if ty == config::CrateType::Staticlib
             || (ty == config::CrateType::Executable
-                && sess.crt_static()
+                && sess.crt_static(Some(ty))
                 && !sess.target.target.options.crt_static_allows_dylibs)
         {
             for &cnum in tcx.crates().iter() {
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index d4cc3c32616..e401dc0f6e7 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -31,7 +31,7 @@ pub mod dynamic_lib;
 pub mod locator;
 
 pub fn validate_crate_name(
-    sess: Option<&rustc::session::Session>,
+    sess: Option<&rustc_session::Session>,
     s: &str,
     sp: Option<rustc_span::Span>,
 ) {
diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs
index 8d018b9bb94..13668b2423f 100644
--- a/src/librustc_metadata/link_args.rs
+++ b/src/librustc_metadata/link_args.rs
@@ -8,7 +8,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec<String> {
     let mut collector = Collector { args: Vec::new() };
     tcx.hir().krate().visit_all_item_likes(&mut collector);
 
-    for attr in tcx.hir().krate().attrs.iter() {
+    for attr in tcx.hir().krate().item.attrs.iter() {
         if attr.has_name(sym::link_args) {
             if let Some(linkarg) = attr.value_str() {
                 collector.add_link_args(&linkarg.as_str());
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index efa259d0c4e..1ede629e7ef 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -216,13 +216,13 @@ use crate::creader::Library;
 use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
 
 use rustc::middle::cstore::{CrateSource, MetadataLoader};
-use rustc::session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
-use rustc::session::search_paths::PathKind;
-use rustc::session::{config, CrateDisambiguator, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
+use rustc_session::search_paths::PathKind;
+use rustc_session::{config, CrateDisambiguator, Session};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index 2fa9cb099dd..64bbf393ba0 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -1,12 +1,12 @@
 use rustc::middle::cstore::{self, NativeLibrary};
-use rustc::session::parse::feature_err;
-use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::spec::abi::Abi;
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index f6b914761c2..2bf74fe272e 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -4,7 +4,7 @@ use crate::creader::CrateMetadataRef;
 use crate::rmeta::table::{FixedSizeEncoding, Table};
 use crate::rmeta::*;
 
-use rustc::dep_graph::{self, DepNodeIndex};
+use rustc::dep_graph::{self, DepNode, DepNodeIndex};
 use rustc::hir::exports::Export;
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
@@ -14,36 +14,35 @@ use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::middle::lang_items;
 use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc::mir::{self, interpret, BodyAndCache, Promoted};
-use rustc::session::Session;
 use rustc::ty::codec::TyDecoder;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::common::record_time;
+use rustc_ast::ast::{self, Ident};
+use rustc_attr as attr;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, Once};
+use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
+use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
+use rustc_session::Session;
+use rustc_span::source_map::{self, respan, Spanned};
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP};
 
+use log::debug;
+use proc_macro::bridge::client::ProcMacro;
 use std::io;
 use std::mem;
 use std::num::NonZeroUsize;
 use std::u32;
 
-use log::debug;
-use proc_macro::bridge::client::ProcMacro;
-use rustc_ast::ast::{self, Ident};
-use rustc_attr as attr;
-use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
-use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
-use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
-use rustc_span::source_map::{self, respan, Spanned};
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP};
-
 pub use cstore_impl::{provide, provide_extern};
 
 mod cstore_impl;
@@ -365,7 +364,7 @@ impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
 impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for DecodeContext<'a, 'tcx> {
     #[inline]
     fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
-        self.specialized_decode().map(|i| LocalDefId::from_def_id(i))
+        Ok(DefId::decode(self)?.expect_local())
     }
 }
 
@@ -387,7 +386,7 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
             return Ok(DUMMY_SP);
         }
 
-        debug_assert_eq!(tag, TAG_VALID_SPAN);
+        debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
 
         let lo = BytePos::decode(self)?;
         let len = BytePos::decode(self)?;
@@ -399,7 +398,68 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
             bug!("Cannot decode Span without Session.")
         };
 
-        let imported_source_files = self.cdata().imported_source_files(&sess.source_map());
+        // There are two possibilities here:
+        // 1. This is a 'local span', which is located inside a `SourceFile`
+        // that came from this crate. In this case, we use the source map data
+        // encoded in this crate. This branch should be taken nearly all of the time.
+        // 2. This is a 'foreign span', which is located inside a `SourceFile`
+        // that came from a *different* crate (some crate upstream of the one
+        // whose metadata we're looking at). For example, consider this dependency graph:
+        //
+        // A -> B -> C
+        //
+        // Suppose that we're currently compiling crate A, and start deserializing
+        // metadata from crate B. When we deserialize a Span from crate B's metadata,
+        // there are two posibilites:
+        //
+        // 1. The span references a file from crate B. This makes it a 'local' span,
+        // which means that we can use crate B's serialized source map information.
+        // 2. The span references a file from crate C. This makes it a 'foreign' span,
+        // which means we need to use Crate *C* (not crate B) to determine the source
+        // map information. We only record source map information for a file in the
+        // crate that 'owns' it, so deserializing a Span may require us to look at
+        // a transitive dependency.
+        //
+        // When we encode a foreign span, we adjust its 'lo' and 'high' values
+        // to be based on the *foreign* crate (e.g. crate C), not the crate
+        // we are writing metadata for (e.g. crate B). This allows us to
+        // treat the 'local' and 'foreign' cases almost identically during deserialization:
+        // we can call `imported_source_files` for the proper crate, and binary search
+        // through the returned slice using our span.
+        let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL {
+            self.cdata().imported_source_files(sess.source_map())
+        } else {
+            // FIXME: We don't decode dependencies of proc-macros.
+            // Remove this once #69976 is merged
+            if self.cdata().root.is_proc_macro_crate() {
+                debug!(
+                    "SpecializedDecoder<Span>::specialized_decode: skipping span for proc-macro crate {:?}",
+                    self.cdata().cnum
+                );
+                // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE
+                // since we don't have `cnum_map` populated.
+                // This advances the decoder position so that we can continue
+                // to read metadata.
+                let _ = u32::decode(self)?;
+                return Ok(DUMMY_SP);
+            }
+            // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above
+            let cnum = CrateNum::decode(self)?;
+            debug!(
+                "SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}",
+                cnum
+            );
+
+            // Decoding 'foreign' spans should be rare enough that it's
+            // not worth it to maintain a per-CrateNum cache for `last_source_file_index`.
+            // We just set it to 0, to ensure that we don't try to access something out
+            // of bounds for our initial 'guess'
+            self.last_source_file_index = 0;
+
+            let foreign_data = self.cdata().cstore.get_crate_data(cnum);
+            foreign_data.imported_source_files(sess.source_map())
+        };
+
         let source_file = {
             // Optimize for the case that most spans within a translated item
             // originate from the same source_file.
@@ -413,16 +473,32 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
                     .binary_search_by_key(&lo, |source_file| source_file.original_start_pos)
                     .unwrap_or_else(|index| index - 1);
 
-                self.last_source_file_index = index;
+                // Don't try to cache the index for foreign spans,
+                // as this would require a map from CrateNums to indices
+                if tag == TAG_VALID_SPAN_LOCAL {
+                    self.last_source_file_index = index;
+                }
                 &imported_source_files[index]
             }
         };
 
         // Make sure our binary search above is correct.
-        debug_assert!(lo >= source_file.original_start_pos && lo <= source_file.original_end_pos);
+        debug_assert!(
+            lo >= source_file.original_start_pos && lo <= source_file.original_end_pos,
+            "Bad binary search: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
+            lo,
+            source_file.original_start_pos,
+            source_file.original_end_pos
+        );
 
         // Make sure we correctly filtered out invalid spans during encoding
-        debug_assert!(hi >= source_file.original_start_pos && hi <= source_file.original_end_pos);
+        debug_assert!(
+            hi >= source_file.original_start_pos && hi <= source_file.original_end_pos,
+            "Bad binary search: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
+            hi,
+            source_file.original_start_pos,
+            source_file.original_end_pos
+        );
 
         let lo =
             (lo + source_file.translated_source_file.start_pos) - source_file.original_start_pos;
@@ -505,7 +581,7 @@ impl EntryKind {
             EntryKind::Struct(_, _) => DefKind::Struct,
             EntryKind::Union(_, _) => DefKind::Union,
             EntryKind::Fn(_) | EntryKind::ForeignFn(_) => DefKind::Fn,
-            EntryKind::Method(_) => DefKind::Method,
+            EntryKind::AssocFn(_) => DefKind::AssocFn,
             EntryKind::Type => DefKind::TyAlias,
             EntryKind::TypeParam => DefKind::TyParam,
             EntryKind::ConstParam => DefKind::ConstParam,
@@ -651,6 +727,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                     data.paren_sugar,
                     data.has_auto_impl,
                     data.is_marker,
+                    data.specialization_kind,
                     self.def_path_table.def_path_hash(item_id),
                 )
             }
@@ -660,6 +737,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 false,
                 false,
                 false,
+                ty::trait_def::TraitSpecializationKind::None,
                 self.def_path_table.def_path_hash(item_id),
             ),
             _ => bug!("def-index does not refer to trait or trait alias"),
@@ -1067,7 +1145,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
         let (kind, container, has_self) = match self.kind(id) {
             EntryKind::AssocConst(container, _, _) => (ty::AssocKind::Const, container, false),
-            EntryKind::Method(data) => {
+            EntryKind::AssocFn(data) => {
                 let data = data.decode(self);
                 (ty::AssocKind::Method, data.container, data.has_self)
             }
@@ -1249,7 +1327,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     fn get_fn_param_names(&self, id: DefIndex) -> Vec<ast::Name> {
         let param_names = match self.kind(id) {
             EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names,
-            EntryKind::Method(data) => data.decode(self).fn_data.param_names,
+            EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names,
             _ => Lazy::empty(),
         };
         param_names.decode(self).collect()
@@ -1286,7 +1364,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     // don't serialize constness for tuple variant and tuple struct constructors.
     fn is_const_fn_raw(&self, id: DefIndex) -> bool {
         let constness = match self.kind(id) {
-            EntryKind::Method(data) => data.decode(self).fn_data.constness,
+            EntryKind::AssocFn(data) => data.decode(self).fn_data.constness,
             EntryKind::Fn(data) => data.decode(self).constness,
             // Some intrinsics can be const fn. While we could recompute this (at least until we
             // stop having hardcoded whitelists and move to stability attributes), it seems cleaner
@@ -1301,7 +1379,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     fn asyncness(&self, id: DefIndex) -> hir::IsAsync {
         match self.kind(id) {
             EntryKind::Fn(data) => data.decode(self).asyncness,
-            EntryKind::Method(data) => data.decode(self).fn_data.asyncness,
+            EntryKind::AssocFn(data) => data.decode(self).fn_data.asyncness,
             EntryKind::ForeignFn(data) => data.decode(self).asyncness,
             _ => bug!("asyncness: expected function kind"),
         }
@@ -1424,14 +1502,16 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                     let local_version = local_source_map.new_imported_source_file(
                         name,
                         name_was_remapped,
-                        self.cnum.as_u32(),
                         src_hash,
                         name_hash,
                         source_length,
+                        self.cnum,
                         lines,
                         multibyte_chars,
                         non_narrow_chars,
                         normalized_pos,
+                        start_pos,
+                        end_pos,
                     );
                     debug!(
                         "CrateMetaData::imported_source_files alloc \
@@ -1607,7 +1687,8 @@ impl CrateMetadata {
             // would always write the same value.
 
             let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
-            let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata);
+            let dep_node =
+                DepNode::from_def_path_hash(def_path_hash, dep_graph::DepKind::CrateMetadata);
 
             dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
             assert!(dep_node_index != DepNodeIndex::INVALID);
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index dcbfed8972c..cc2bd51f92f 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -10,18 +10,16 @@ use rustc::hir::map::{DefKey, DefPath, DefPathHash};
 use rustc::middle::cstore::{CrateSource, CrateStore, EncodedMetadata, NativeLibraryKind};
 use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::middle::stability::DeprecationEntry;
-use rustc::session::{CrateDisambiguator, Session};
 use rustc::ty::query::Providers;
 use rustc::ty::query::QueryConfig;
 use rustc::ty::{self, TyCtxt};
 use rustc_ast::ast;
 use rustc_ast::attr;
 use rustc_ast::expand::allocator::AllocatorKind;
-use rustc_ast::ptr::P;
-use rustc_ast::tokenstream::DelimSpan;
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::Symbol;
 
@@ -142,7 +140,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
         cdata.get_deprecation(def_id.index).map(DeprecationEntry::external)
     }
     item_attrs => { cdata.get_item_attrs(def_id.index, tcx.sess) }
-    // FIXME(#38501) We've skipped a `read` on the `HirBody` of
+    // FIXME(#38501) We've skipped a `read` on the `hir_owner_items` of
     // a `fn` when encoding, so the dep-tracking wouldn't work.
     // This is only used by rustdoc anyway, which shouldn't have
     // incremental recompilation ever enabled.
@@ -415,8 +413,6 @@ impl CStore {
         }
 
         let span = data.get_span(id.index, sess);
-        let dspan = DelimSpan::from_single(span);
-        let rmeta::MacroDef { body, legacy } = data.get_macro(id.index, sess);
 
         // Mark the attrs as used
         let attrs = data.get_item_attrs(id.index, sess);
@@ -424,25 +420,21 @@ impl CStore {
             attr::mark_used(attr);
         }
 
-        let name = data
+        let ident = data
             .def_key(id.index)
             .disambiguated_data
             .data
             .get_opt_name()
+            .map(ast::Ident::with_dummy_span) // FIXME: cross-crate hygiene
             .expect("no name in load_macro");
-        sess.imported_macro_spans.borrow_mut().insert(span, (name.to_string(), span));
 
         LoadedMacro::MacroDef(
             ast::Item {
-                // FIXME: cross-crate hygiene
-                ident: ast::Ident::with_dummy_span(name),
+                ident,
                 id: ast::DUMMY_NODE_ID,
                 span,
                 attrs: attrs.iter().cloned().collect(),
-                kind: ast::ItemKind::MacroDef(ast::MacroDef {
-                    body: P(ast::MacArgs::Delimited(dspan, ast::MacDelimiter::Brace, body)),
-                    legacy,
-                }),
+                kind: ast::ItemKind::MacroDef(data.get_macro(id.index, sess)),
                 vis: source_map::respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 tokens: None,
             },
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 2b04918296d..6280fd62de9 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -1,6 +1,7 @@
 use crate::rmeta::table::FixedSizeEncoding;
 use crate::rmeta::*;
 
+use log::{debug, trace};
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::map::Map;
 use rustc::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLibrary};
@@ -12,33 +13,29 @@ use rustc::traits::specialization_graph;
 use rustc::ty::codec::{self as ty_codec, TyEncoder};
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::{self, SymbolName, Ty, TyCtxt};
+use rustc_ast::ast;
+use rustc_ast::attr;
 use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{AnonConst, GenericParamKind};
 use rustc_index::vec::Idx;
-
-use rustc::session::config::{self, CrateType};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_data_structures::sync::Lrc;
 use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
-
-use log::{debug, trace};
-use rustc_ast::ast;
-use rustc_ast::attr;
+use rustc_session::config::{self, CrateType};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{self, FileName, SourceFile, Span};
+use rustc_span::{self, ExternalSource, FileName, SourceFile, Span};
 use std::hash::Hash;
 use std::num::NonZeroUsize;
 use std::path::Path;
 use std::u32;
 
-use rustc_hir as hir;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
-
 struct EncodeContext<'tcx> {
     opaque: opaque::Encoder,
     tcx: TyCtxt<'tcx>,
@@ -167,20 +164,56 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
             return TAG_INVALID_SPAN.encode(self);
         }
 
-        // HACK(eddyb) there's no way to indicate which crate a Span is coming
-        // from right now, so decoding would fail to find the SourceFile if
-        // it's not local to the crate the Span is found in.
-        if self.source_file_cache.is_imported() {
-            return TAG_INVALID_SPAN.encode(self);
-        }
+        // There are two possible cases here:
+        // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
+        // crate we are writing metadata for. When the metadata for *this* crate gets
+        // deserialized, the deserializer will need to know which crate it originally came
+        // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should
+        // be deserialized after the rest of the span data, which tells the deserializer
+        // which crate contains the source map information.
+        // 2. This span comes from our own crate. No special hamdling is needed - we just
+        // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use
+        // our own source map information.
+        let (tag, lo, hi) = if self.source_file_cache.is_imported() {
+            // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
+            // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
+            // are relative to the source map information for the 'foreign' crate whose CrateNum
+            // we write into the metadata. This allows `imported_source_files` to binary
+            // search through the 'foreign' crate's source map information, using the
+            // deserialized 'lo' and 'hi' values directly.
+            //
+            // All of this logic ensures that the final result of deserialization is a 'normal'
+            // Span that can be used without any additional trouble.
+            let external_start_pos = {
+                // Introduce a new scope so that we drop the 'lock()' temporary
+                match &*self.source_file_cache.external_src.lock() {
+                    ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos,
+                    src => panic!("Unexpected external source {:?}", src),
+                }
+            };
+            let lo = (span.lo - self.source_file_cache.start_pos) + external_start_pos;
+            let hi = (span.hi - self.source_file_cache.start_pos) + external_start_pos;
 
-        TAG_VALID_SPAN.encode(self)?;
-        span.lo.encode(self)?;
+            (TAG_VALID_SPAN_FOREIGN, lo, hi)
+        } else {
+            (TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
+        };
+
+        tag.encode(self)?;
+        lo.encode(self)?;
 
         // Encode length which is usually less than span.hi and profits more
         // from the variable-length integer encoding that we use.
-        let len = span.hi - span.lo;
-        len.encode(self)
+        let len = hi - lo;
+        len.encode(self)?;
+
+        if tag == TAG_VALID_SPAN_FOREIGN {
+            // This needs to be two lines to avoid holding the `self.source_file_cache`
+            // while calling `cnum.encode(self)`
+            let cnum = self.source_file_cache.cnum;
+            cnum.encode(self)?;
+        }
+        Ok(())
 
         // Don't encode the expansion context.
     }
@@ -331,7 +364,7 @@ impl<'tcx> EncodeContext<'tcx> {
     fn encode_info_for_items(&mut self) {
         let krate = self.tcx.hir().krate();
         let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public };
-        self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis);
+        self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.attrs, &vis);
         krate.visit_all_item_likes(&mut self.as_deep_visitor());
         for macro_def in krate.exported_macros {
             self.visit_macro_def(macro_def);
@@ -805,12 +838,12 @@ impl EncodeContext<'tcx> {
                 )
             }
             ty::AssocKind::Method => {
-                let fn_data = if let hir::TraitItemKind::Method(m_sig, m) = &ast_item.kind {
+                let fn_data = if let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind {
                     let param_names = match *m {
-                        hir::TraitMethod::Required(ref names) => {
+                        hir::TraitFn::Required(ref names) => {
                             self.encode_fn_param_names(names)
                         }
-                        hir::TraitMethod::Provided(body) => {
+                        hir::TraitFn::Provided(body) => {
                             self.encode_fn_param_names_for_body(body)
                         }
                     };
@@ -822,7 +855,7 @@ impl EncodeContext<'tcx> {
                 } else {
                     bug!()
                 };
-                EntryKind::Method(self.lazy(MethodData {
+                EntryKind::AssocFn(self.lazy(AssocFnData {
                     fn_data,
                     container,
                     has_self: trait_item.method_has_self_argument,
@@ -894,7 +927,7 @@ impl EncodeContext<'tcx> {
                 }
             }
             ty::AssocKind::Method => {
-                let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.kind {
+                let fn_data = if let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind {
                     FnData {
                         asyncness: sig.header.asyncness,
                         constness: sig.header.constness,
@@ -903,7 +936,7 @@ impl EncodeContext<'tcx> {
                 } else {
                     bug!()
                 };
-                EntryKind::Method(self.lazy(MethodData {
+                EntryKind::AssocFn(self.lazy(AssocFnData {
                     fn_data,
                     container,
                     has_self: impl_item.method_has_self_argument,
@@ -928,7 +961,7 @@ impl EncodeContext<'tcx> {
         self.encode_inferred_outlives(def_id);
         let mir = match ast_item.kind {
             hir::ImplItemKind::Const(..) => true,
-            hir::ImplItemKind::Method(ref sig, _) => {
+            hir::ImplItemKind::Fn(ref sig, _) => {
                 let generics = self.tcx.generics_of(def_id);
                 let needs_inline = (generics.requires_monomorphization(self.tcx)
                     || tcx.codegen_fn_attrs(def_id).requests_inline())
@@ -1077,12 +1110,13 @@ impl EncodeContext<'tcx> {
                 let polarity = self.tcx.impl_polarity(def_id);
                 let parent = if let Some(trait_ref) = trait_ref {
                     let trait_def = self.tcx.trait_def(trait_ref.def_id);
-                    trait_def.ancestors(self.tcx, def_id).nth(1).and_then(|node| {
-                        match node {
-                            specialization_graph::Node::Impl(parent) => Some(parent),
-                            _ => None,
-                        }
-                    })
+                    trait_def.ancestors(self.tcx, def_id).ok()
+                        .and_then(|mut an| an.nth(1).and_then(|node| {
+                            match node {
+                                specialization_graph::Node::Impl(parent) => Some(parent),
+                                _ => None,
+                            }
+                        }))
                 } else {
                     None
                 };
@@ -1114,6 +1148,7 @@ impl EncodeContext<'tcx> {
                     paren_sugar: trait_def.paren_sugar,
                     has_auto_impl: self.tcx.trait_is_auto(def_id),
                     is_marker: trait_def.is_marker,
+                    specialization_kind: trait_def.specialization_kind,
                 };
 
                 EntryKind::Trait(self.lazy(data))
@@ -1236,10 +1271,7 @@ impl EncodeContext<'tcx> {
     /// Serialize the text of exported macros
     fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) {
         let def_id = self.tcx.hir().local_def_id(macro_def.hir_id);
-        record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(MacroDef {
-            body: macro_def.body.clone(),
-            legacy: macro_def.legacy,
-        })));
+        record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone())));
         record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
         record!(self.per_def.span[def_id] <- macro_def.span);
         record!(self.per_def.attributes[def_id] <- macro_def.attrs);
@@ -1318,7 +1350,7 @@ impl EncodeContext<'tcx> {
         let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
         if is_proc_macro {
             let tcx = self.tcx;
-            Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner)))
+            Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index)))
         } else {
             None
         }
@@ -1406,8 +1438,8 @@ impl EncodeContext<'tcx> {
             .into_iter()
             .map(|(trait_def_id, mut impls)| {
                 // Bring everything into deterministic order for hashing
-                impls.sort_by_cached_key(|&def_index| {
-                    tcx.hir().definitions().def_path_hash(def_index)
+                impls.sort_by_cached_key(|&index| {
+                    tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index })
                 });
 
                 TraitImpls {
@@ -1505,8 +1537,8 @@ impl EncodeContext<'tcx> {
 impl Visitor<'tcx> for EncodeContext<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         intravisit::walk_expr(self, ex);
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 89e26b15d50..05d834e5dee 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -7,11 +7,8 @@ use rustc::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLib
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::middle::lang_items;
 use rustc::mir;
-use rustc::session::config::SymbolManglingVersion;
-use rustc::session::CrateDisambiguator;
 use rustc::ty::{self, ReprOptions, Ty};
-use rustc_ast::ast;
-use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::ast::{self, MacroDef};
 use rustc_attr as attr;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
@@ -20,6 +17,8 @@ use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{DefId, DefIndex};
 use rustc_index::vec::IndexVec;
 use rustc_serialize::opaque::Encoder;
+use rustc_session::config::SymbolManglingVersion;
+use rustc_session::CrateDisambiguator;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::Symbol;
 use rustc_span::{self, Span};
@@ -306,7 +305,7 @@ enum EntryKind {
     Generator(hir::GeneratorKind),
     Trait(Lazy<TraitData>),
     Impl(Lazy<ImplData>),
-    Method(Lazy<MethodData>),
+    AssocFn(Lazy<AssocFnData>),
     AssocType(AssocContainer),
     AssocOpaqueTy(AssocContainer),
     AssocConst(AssocContainer, mir::ConstQualifs, Lazy<RenderedConst>),
@@ -324,12 +323,6 @@ struct ModData {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-struct MacroDef {
-    body: TokenStream,
-    legacy: bool,
-}
-
-#[derive(RustcEncodable, RustcDecodable)]
 struct FnData {
     asyncness: hir::IsAsync,
     constness: hir::Constness,
@@ -350,6 +343,7 @@ struct TraitData {
     paren_sugar: bool,
     has_auto_impl: bool,
     is_marker: bool,
+    specialization_kind: ty::trait_def::TraitSpecializationKind,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
@@ -399,7 +393,7 @@ impl AssocContainer {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-struct MethodData {
+struct AssocFnData {
     fn_data: FnData,
     container: AssocContainer,
     has_self: bool,
@@ -411,5 +405,6 @@ struct GeneratorData<'tcx> {
 }
 
 // Tags used for encoding Spans:
-const TAG_VALID_SPAN: u8 = 0;
-const TAG_INVALID_SPAN: u8 = 1;
+const TAG_VALID_SPAN_LOCAL: u8 = 0;
+const TAG_VALID_SPAN_FOREIGN: u8 = 1;
+const TAG_INVALID_SPAN: u8 = 2;
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 1ee581e64aa..256a80076b9 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -27,7 +27,9 @@ rustc_infer = { path = "../librustc_infer" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_macros = { path = "../librustc_macros" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
+rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
 rustc_apfloat = { path = "../librustc_apfloat" }
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 8d4afd2c3b3..e895eec5d52 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -10,9 +10,9 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc_index::vec::Idx;
-use rustc_infer::traits::error_reporting::suggest_constraining_type_param;
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::Span;
+use rustc_trait_selection::traits::error_reporting::suggest_constraining_type_param;
 
 use crate::dataflow::drop_flag_effects;
 use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index c6fe0dba80c..c462f934148 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -480,12 +480,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         }))
                         | Some(hir::Node::TraitItem(hir::TraitItem {
                             ident,
-                            kind: hir::TraitItemKind::Method(sig, _),
+                            kind: hir::TraitItemKind::Fn(sig, _),
                             ..
                         }))
                         | Some(hir::Node::ImplItem(hir::ImplItem {
                             ident,
-                            kind: hir::ImplItemKind::Method(sig, _),
+                            kind: hir::ImplItemKind::Fn(sig, _),
                             ..
                         })) => Some(
                             arg_pos
@@ -522,12 +522,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
                 | hir::Node::TraitItem(hir::TraitItem {
                     ident,
-                    kind: hir::TraitItemKind::Method(sig, _),
+                    kind: hir::TraitItemKind::Fn(sig, _),
                     ..
                 })
                 | hir::Node::ImplItem(hir::ImplItem {
                     ident,
-                    kind: hir::ImplItemKind::Method(sig, _),
+                    kind: hir::ImplItemKind::Fn(sig, _),
                     ..
                 }) => {
                     err.span_label(ident.span, "");
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 8cd75d4a2fd..494b6421fd5 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -4,7 +4,8 @@ use rustc::mir::ConstraintCategory;
 use rustc::ty::{self, RegionVid, Ty};
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_infer::infer::{
-    error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin,
+    error_reporting::nice_region_error::NiceRegionError,
+    error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin,
 };
 use rustc_span::symbol::kw;
 use rustc_span::Span;
@@ -197,7 +198,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
                     let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
                     let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
-                    opaque_types::unexpected_hidden_region_diagnostic(
+                    unexpected_hidden_region_diagnostic(
                         self.infcx.tcx,
                         Some(region_scope_tree),
                         span,
@@ -283,8 +284,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         debug!("report_region_error: category={:?} {:?}", category, span);
         // Check if we can use one of the "nice region errors".
         if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
-            let tables = self.infcx.tcx.typeck_tables_of(self.mir_def_id);
-            let nice = NiceRegionError::new_from_span(self.infcx, span, o, f, Some(tables));
+            let nice = NiceRegionError::new_from_span(self.infcx, span, o, f);
             if let Some(diag) = nice.try_report_from_nll() {
                 diag.buffer(&mut self.errors_buffer);
                 return;
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
index 01ace742876..7103fc596c9 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
@@ -651,7 +651,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                 if gen_move.is_some() { " of generator" } else { " of closure" },
             ),
             hir::Node::ImplItem(hir::ImplItem {
-                kind: hir::ImplItemKind::Method(method_sig, _),
+                kind: hir::ImplItemKind::Fn(method_sig, _),
                 ..
             }) => (method_sig.decl.output.span(), ""),
             _ => (self.body.span, ""),
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index a61d00b0120..6c1901455fd 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1,7 +1,5 @@
 //! This query borrow-checks the MIR to (further) ensure it is not broken.
 
-use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT;
-use rustc::lint::builtin::UNUSED_MUT;
 use rustc::mir::{
     read_only, traversal, Body, BodyAndCache, ClearCrossCrate, Local, Location, Mutability,
     Operand, Place, PlaceElem, PlaceRef, ReadOnlyBodyAndCache,
@@ -11,7 +9,7 @@ use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKi
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, RegionVid, TyCtxt};
-
+use rustc_ast::ast::Name;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
@@ -20,6 +18,8 @@ use rustc_hir::{def_id::DefId, HirId, Node};
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT};
+use rustc_span::{Span, DUMMY_SP};
 
 use either::Either;
 use smallvec::SmallVec;
@@ -28,9 +28,6 @@ use std::collections::BTreeMap;
 use std::mem;
 use std::rc::Rc;
 
-use rustc_ast::ast::Name;
-use rustc_span::{Span, DUMMY_SP};
-
 use crate::dataflow;
 use crate::dataflow::generic::{Analysis, BorrowckFlowState as Flows, BorrowckResults};
 use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex};
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs
index ba1b322524e..077ed49ed2c 100644
--- a/src/librustc_mir/borrow_check/nll.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -272,7 +272,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
     // Dump facts if requested.
     let polonius_output = all_facts.and_then(|all_facts| {
         if infcx.tcx.sess.opts.debugging_opts.nll_facts {
-            let def_path = infcx.tcx.hir().def_path(def_id);
+            let def_path = infcx.tcx.def_path(def_id);
             let dir_path =
                 PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate());
             all_facts.write_to_dir(dir_path, location_table).unwrap();
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index 144f655420b..fe96b3e34a2 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -7,6 +7,7 @@ use rustc::mir::{
 };
 use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::binary_search_util;
+use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_hir::def_id::DefId;
@@ -54,12 +55,12 @@ pub struct RegionInferenceContext<'tcx> {
     liveness_constraints: LivenessValues<RegionVid>,
 
     /// The outlives constraints computed by the type-check.
-    constraints: Rc<OutlivesConstraintSet>,
+    constraints: Frozen<OutlivesConstraintSet>,
 
     /// The constraint-set, but in graph form, making it easy to traverse
     /// the constraints adjacent to a particular region. Used to construct
     /// the SCC (see `constraint_sccs`) and for error reporting.
-    constraint_graph: Rc<NormalConstraintGraph>,
+    constraint_graph: Frozen<NormalConstraintGraph>,
 
     /// The SCC computed from `constraints` and the constraint
     /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
@@ -112,7 +113,7 @@ pub struct RegionInferenceContext<'tcx> {
 
     /// Information about how the universally quantified regions in
     /// scope on this function relate to one another.
-    universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+    universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
 }
 
 /// Each time that `apply_member_constraint` is successful, it appends
@@ -242,11 +243,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// The `outlives_constraints` and `type_tests` are an initial set
     /// of constraints produced by the MIR type check.
-    pub(crate) fn new(
+    pub(in crate::borrow_check) fn new(
         var_infos: VarInfos,
         universal_regions: Rc<UniversalRegions<'tcx>>,
         placeholder_indices: Rc<PlaceholderIndices>,
-        universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+        universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
         outlives_constraints: OutlivesConstraintSet,
         member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
         closure_bounds_mapping: FxHashMap<
@@ -263,8 +264,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             .map(|info| RegionDefinition::new(info.universe, info.origin))
             .collect();
 
-        let constraints = Rc::new(outlives_constraints); // freeze constraints
-        let constraint_graph = Rc::new(constraints.graph(definitions.len()));
+        let constraints = Frozen::freeze(outlives_constraints);
+        let constraint_graph = Frozen::freeze(constraints.graph(definitions.len()));
         let fr_static = universal_regions.fr_static;
         let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static));
 
diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
index 15bbc5677da..49b49437328 100644
--- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
+++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
@@ -3,6 +3,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::Span;
+use rustc_trait_selection::opaque_types::InferCtxtExt;
 
 use super::RegionInferenceContext;
 
diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
index 137216531a3..86951f93f0e 100644
--- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
@@ -1,13 +1,15 @@
 use rustc::mir::ConstraintCategory;
+use rustc::traits::query::OutlivesBound;
 use rustc::ty::free_region_map::FreeRegionRelations;
 use rustc::ty::{self, RegionVid, Ty, TyCtxt};
+use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::transitive_relation::TransitiveRelation;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
+use rustc_infer::infer::outlives;
 use rustc_infer::infer::region_constraints::GenericKind;
 use rustc_infer::infer::InferCtxt;
-use rustc_infer::traits::query::outlives_bounds::{self, OutlivesBound};
-use rustc_infer::traits::query::type_op::{self, TypeOp};
 use rustc_span::DUMMY_SP;
+use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
 use std::rc::Rc;
 
 use crate::borrow_check::{
@@ -52,7 +54,7 @@ type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>;
 type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
 
 crate struct CreateResult<'tcx> {
-    crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+    pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
     crate region_bound_pairs: RegionBoundPairs<'tcx>,
     crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
 }
@@ -266,7 +268,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
 
         // Insert the facts we know from the predicates. Why? Why not.
         let param_env = self.param_env;
-        self.add_outlives_bounds(outlives_bounds::explicit_outlives_bounds(param_env));
+        self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
 
         // Finally:
         // - outlives is reflexive, so `'r: 'r` for every region `'r`
@@ -297,7 +299,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
         }
 
         CreateResult {
-            universal_region_relations: Rc::new(self.relations),
+            universal_region_relations: Frozen::freeze(self.relations),
             region_bound_pairs: self.region_bound_pairs,
             normalized_inputs_and_output,
         }
diff --git a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs
index baa9d1d212e..0c49ee44f9a 100644
--- a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs
+++ b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs
@@ -3,9 +3,9 @@ use rustc::ty::{Ty, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_index::bit_set::HybridBitSet;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
-use rustc_infer::traits::query::dropck_outlives::DropckOutlivesResult;
-use rustc_infer::traits::query::type_op::outlives::DropckOutlives;
-use rustc_infer::traits::query::type_op::TypeOp;
+use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
+use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
+use rustc_trait_selection::traits::query::type_op::TypeOp;
 use std::rc::Rc;
 
 use crate::dataflow::generic::ResultsCursor;
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index ace92949814..05d4fc8880e 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -18,23 +18,26 @@ use rustc::ty::{
     self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPolyTraitRef, Ty,
     TyCtxt, UserType, UserTypeAnnotationIndex,
 };
+use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
-use rustc_infer::infer::opaque_types::GenerateMemberConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{
     InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin,
 };
-use rustc_infer::traits::query::type_op;
-use rustc_infer::traits::query::type_op::custom::CustomTypeOp;
-use rustc_infer::traits::query::{Fallible, NoSolution};
-use rustc_infer::traits::{self, ObligationCause, PredicateObligations};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::opaque_types::{GenerateMemberConstraints, InferCtxtExt};
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::query::type_op;
+use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
+use rustc_trait_selection::traits::query::{Fallible, NoSolution};
+use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations};
 
 use crate::dataflow::generic::ResultsCursor;
 use crate::dataflow::move_paths::MoveData;
@@ -828,7 +831,7 @@ struct BorrowCheckContext<'a, 'tcx> {
 
 crate struct MirTypeckResults<'tcx> {
     crate constraints: MirTypeckRegionConstraints<'tcx>,
-    crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+    pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
     crate opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
 }
 
@@ -2005,7 +2008,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 &traits::Obligation::new(
                                     ObligationCause::new(
                                         span,
-                                        self.tcx().hir().def_index_to_hir_id(self.mir_def_id.index),
+                                        self.tcx()
+                                            .hir()
+                                            .local_def_id_to_hir_id(self.mir_def_id.expect_local()),
                                         traits::ObligationCauseCode::RepeatVec(should_suggest),
                                     ),
                                     self.param_env,
diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs
index b0f048ff1a6..ebaafd40262 100644
--- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs
+++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs
@@ -3,8 +3,8 @@ use rustc::ty::relate::TypeRelation;
 use rustc::ty::{self, Ty};
 use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
 use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin};
-use rustc_infer::traits::query::Fallible;
-use rustc_infer::traits::DomainGoal;
+use rustc_trait_selection::traits::query::Fallible;
+use rustc_trait_selection::traits::DomainGoal;
 
 use crate::borrow_check::constraints::OutlivesConstraint;
 use crate::borrow_check::type_check::{BorrowCheckContext, Locations};
diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs
index 67b00e9ffdd..c1acd5bd9a6 100644
--- a/src/librustc_mir/borrow_check/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/universal_regions.rs
@@ -774,9 +774,9 @@ fn for_each_late_bound_region_defined_on<'tcx>(
     fn_def_id: DefId,
     mut f: impl FnMut(ty::Region<'tcx>),
 ) {
-    if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.index) {
+    if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
         for late_bound in late_bounds.iter() {
-            let hir_id = HirId { owner: fn_def_id.index, local_id: *late_bound };
+            let hir_id = HirId { owner: fn_def_id.expect_local(), local_id: *late_bound };
             let name = tcx.hir().name(hir_id);
             let region_def_id = tcx.hir().local_def_id(hir_id);
             let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
diff --git a/src/librustc_mir/const_eval/fn_queries.rs b/src/librustc_mir/const_eval/fn_queries.rs
index 27efcd50841..470e4e7ed25 100644
--- a/src/librustc_mir/const_eval/fn_queries.rs
+++ b/src/librustc_mir/const_eval/fn_queries.rs
@@ -85,7 +85,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
     let parent_id = tcx.hir().get_parent_did(hir_id);
     if !parent_id.is_top_level_module() {
-        is_const_impl_raw(tcx, LocalDefId::from_def_id(parent_id))
+        is_const_impl_raw(tcx, parent_id.expect_local())
     } else {
         false
     }
@@ -171,7 +171,7 @@ fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 pub fn provide(providers: &mut Providers<'_>) {
     *providers = Providers {
         is_const_fn_raw,
-        is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, LocalDefId::from_def_id(def_id)),
+        is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()),
         is_promotable_const_fn,
         const_fn_is_allowed_fn_ptr,
         ..*providers
diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs
index ed802983468..28889486c38 100644
--- a/src/librustc_mir/const_eval/machine.rs
+++ b/src/librustc_mir/const_eval/machine.rs
@@ -240,7 +240,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         Ok(Some(match ecx.load_mir(instance.def, None) {
             Ok(body) => *body,
             Err(err) => {
-                if let err_unsup!(NoMirFor(ref path)) = err.kind {
+                if let err_unsup!(NoMirFor(did)) = err.kind {
+                    let path = ecx.tcx.def_path_str(did);
                     return Err(ConstEvalErrKind::NeedsRfc(format!(
                         "calling extern function `{}`",
                         path
@@ -280,7 +281,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
     fn assert_panic(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        _span: Span,
         msg: &AssertMessage<'tcx>,
         _unwind: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx> {
diff --git a/src/librustc_mir/const_eval/mod.rs b/src/librustc_mir/const_eval/mod.rs
index cb658397625..605091d6c7d 100644
--- a/src/librustc_mir/const_eval/mod.rs
+++ b/src/librustc_mir/const_eval/mod.rs
@@ -43,7 +43,7 @@ pub(crate) fn const_field<'tcx>(
     op_to_const(&ecx, field)
 }
 
-pub(crate) fn const_caller_location<'tcx>(
+pub(crate) fn const_caller_location(
     tcx: TyCtxt<'tcx>,
     (file, line, col): (Symbol, u32, u32),
 ) -> ConstValue<'tcx> {
diff --git a/src/librustc_mir/dataflow/generic/cursor.rs b/src/librustc_mir/dataflow/generic/cursor.rs
index 8c0ab150528..170157aca5d 100644
--- a/src/librustc_mir/dataflow/generic/cursor.rs
+++ b/src/librustc_mir/dataflow/generic/cursor.rs
@@ -2,7 +2,7 @@
 
 use std::borrow::Borrow;
 
-use rustc::mir::{self, BasicBlock, Location};
+use rustc::mir::{self, BasicBlock, Location, TerminatorKind};
 use rustc_index::bit_set::BitSet;
 
 use super::{Analysis, Results};
@@ -29,14 +29,14 @@ where
 
     pos: CursorPosition,
 
-    /// When this flag is set, the cursor is pointing at a `Call` terminator whose call return
-    /// effect has been applied to `state`.
+    /// When this flag is set, the cursor is pointing at a `Call` or `Yield` terminator whose call
+    /// return or resume effect has been applied to `state`.
     ///
-    /// This flag helps to ensure that multiple calls to `seek_after_assume_call_returns` with the
+    /// This flag helps to ensure that multiple calls to `seek_after_assume_success` with the
     /// same target will result in exactly one invocation of `apply_call_return_effect`. It is
     /// sufficient to clear this only in `seek_to_block_start`, since seeking away from a
     /// terminator will always require a cursor reset.
-    call_return_effect_applied: bool,
+    success_effect_applied: bool,
 }
 
 impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
@@ -50,7 +50,7 @@ where
             body,
             pos: CursorPosition::BlockStart(mir::START_BLOCK),
             state: results.borrow().entry_sets[mir::START_BLOCK].clone(),
-            call_return_effect_applied: false,
+            success_effect_applied: false,
             results,
         }
     }
@@ -76,14 +76,14 @@ where
     pub fn seek_to_block_start(&mut self, block: BasicBlock) {
         self.state.overwrite(&self.results.borrow().entry_sets[block]);
         self.pos = CursorPosition::BlockStart(block);
-        self.call_return_effect_applied = false;
+        self.success_effect_applied = false;
     }
 
     /// Advances the cursor to hold all effects up to and including to the "before" effect of the
     /// statement (or terminator) at the given location.
     ///
     /// If you wish to observe the full effect of a statement or terminator, not just the "before"
-    /// effect, use `seek_after` or `seek_after_assume_call_returns`.
+    /// effect, use `seek_after` or `seek_after_assume_success`.
     pub fn seek_before(&mut self, target: Location) {
         assert!(target <= self.body.terminator_loc(target.block));
         self.seek_(target, false);
@@ -93,7 +93,7 @@ where
     /// terminators) up to and including the `target`.
     ///
     /// If the `target` is a `Call` terminator, any call return effect for that terminator will
-    /// **not** be observed. Use `seek_after_assume_call_returns` if you wish to observe the call
+    /// **not** be observed. Use `seek_after_assume_success` if you wish to observe the call
     /// return effect.
     pub fn seek_after(&mut self, target: Location) {
         assert!(target <= self.body.terminator_loc(target.block));
@@ -101,7 +101,7 @@ where
         // If we have already applied the call return effect, we are currently pointing at a `Call`
         // terminator. Unconditionally reset the dataflow cursor, since there is no way to "undo"
         // the call return effect.
-        if self.call_return_effect_applied {
+        if self.success_effect_applied {
             self.seek_to_block_start(target.block);
         }
 
@@ -111,25 +111,25 @@ where
     /// Advances the cursor to hold all effects up to and including of the statement (or
     /// terminator) at the given location.
     ///
-    /// If the `target` is a `Call` terminator, any call return effect for that terminator will
-    /// be observed. Use `seek_after` if you do **not** wish to observe the call return effect.
-    pub fn seek_after_assume_call_returns(&mut self, target: Location) {
+    /// If the `target` is a `Call` or `Yield` terminator, any call return or resume effect for that
+    /// terminator will be observed. Use `seek_after` if you do **not** wish to observe the
+    /// "success" effect.
+    pub fn seek_after_assume_success(&mut self, target: Location) {
         let terminator_loc = self.body.terminator_loc(target.block);
         assert!(target.statement_index <= terminator_loc.statement_index);
 
         self.seek_(target, true);
 
-        if target != terminator_loc {
+        if target != terminator_loc || self.success_effect_applied {
             return;
         }
 
+        // Apply the effect of the "success" path of the terminator.
+
+        self.success_effect_applied = true;
         let terminator = self.body.basic_blocks()[target.block].terminator();
-        if let mir::TerminatorKind::Call {
-            destination: Some((return_place, _)), func, args, ..
-        } = &terminator.kind
-        {
-            if !self.call_return_effect_applied {
-                self.call_return_effect_applied = true;
+        match &terminator.kind {
+            TerminatorKind::Call { destination: Some((return_place, _)), func, args, .. } => {
                 self.results.borrow().analysis.apply_call_return_effect(
                     &mut self.state,
                     target.block,
@@ -138,6 +138,14 @@ where
                     return_place,
                 );
             }
+            TerminatorKind::Yield { resume, resume_arg, .. } => {
+                self.results.borrow().analysis.apply_yield_resume_effect(
+                    &mut self.state,
+                    *resume,
+                    resume_arg,
+                );
+            }
+            _ => {}
         }
     }
 
@@ -172,7 +180,7 @@ where
                 self.seek_to_block_start(target.block)
             }
 
-            // N.B., `call_return_effect_applied` is checked in `seek_after`, not here.
+            // N.B., `success_effect_applied` is checked in `seek_after`, not here.
             _ => (),
         }
 
diff --git a/src/librustc_mir/dataflow/generic/engine.rs b/src/librustc_mir/dataflow/generic/engine.rs
index 8d800f2d0ba..d32072125b3 100644
--- a/src/librustc_mir/dataflow/generic/engine.rs
+++ b/src/librustc_mir/dataflow/generic/engine.rs
@@ -218,15 +218,18 @@ where
 
             Goto { target }
             | Assert { target, cleanup: None, .. }
-            | Yield { resume: target, drop: None, .. }
             | Drop { target, location: _, unwind: None }
             | DropAndReplace { target, value: _, location: _, unwind: None } => {
                 self.propagate_bits_into_entry_set_for(in_out, target, dirty_list)
             }
 
-            Yield { resume: target, drop: Some(drop), .. } => {
+            Yield { resume: target, drop, resume_arg, .. } => {
+                if let Some(drop) = drop {
+                    self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list);
+                }
+
+                self.analysis.apply_yield_resume_effect(in_out, target, &resume_arg);
                 self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
-                self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list);
             }
 
             Assert { target, cleanup: Some(unwind), .. }
diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs
index f8e1d3e9fe8..36decf7f5a9 100644
--- a/src/librustc_mir/dataflow/generic/graphviz.rs
+++ b/src/librustc_mir/dataflow/generic/graphviz.rs
@@ -241,7 +241,7 @@ where
                     )?;
 
                     let state_on_unwind = this.results.get().clone();
-                    this.results.seek_after_assume_call_returns(terminator_loc);
+                    this.results.seek_after_assume_success(terminator_loc);
                     write_diff(w, this.results.analysis(), &state_on_unwind, this.results.get())?;
 
                     write!(w, "</td>")
diff --git a/src/librustc_mir/dataflow/generic/mod.rs b/src/librustc_mir/dataflow/generic/mod.rs
index 9a102c9a3d0..fb4b7b9c5be 100644
--- a/src/librustc_mir/dataflow/generic/mod.rs
+++ b/src/librustc_mir/dataflow/generic/mod.rs
@@ -191,6 +191,20 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
         return_place: &mir::Place<'tcx>,
     );
 
+    /// Updates the current dataflow state with the effect of resuming from a `Yield` terminator.
+    ///
+    /// This is similar to `apply_call_return_effect` in that it only takes place after the
+    /// generator is resumed, not when it is dropped.
+    ///
+    /// By default, no effects happen.
+    fn apply_yield_resume_effect(
+        &self,
+        _state: &mut BitSet<Self::Idx>,
+        _resume_block: BasicBlock,
+        _resume_place: &mir::Place<'tcx>,
+    ) {
+    }
+
     /// Updates the current dataflow state with the effect of taking a particular branch in a
     /// `SwitchInt` terminator.
     ///
@@ -284,6 +298,15 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
         return_place: &mir::Place<'tcx>,
     );
 
+    /// See `Analysis::apply_yield_resume_effect`.
+    fn yield_resume_effect(
+        &self,
+        _trans: &mut BitSet<Self::Idx>,
+        _resume_block: BasicBlock,
+        _resume_place: &mir::Place<'tcx>,
+    ) {
+    }
+
     /// See `Analysis::apply_discriminant_switch_effect`.
     fn discriminant_switch_effect(
         &self,
@@ -347,6 +370,15 @@ where
         self.call_return_effect(state, block, func, args, return_place);
     }
 
+    fn apply_yield_resume_effect(
+        &self,
+        state: &mut BitSet<Self::Idx>,
+        resume_block: BasicBlock,
+        resume_place: &mir::Place<'tcx>,
+    ) {
+        self.yield_resume_effect(state, resume_block, resume_place);
+    }
+
     fn apply_discriminant_switch_effect(
         &self,
         state: &mut BitSet<Self::Idx>,
diff --git a/src/librustc_mir/dataflow/generic/tests.rs b/src/librustc_mir/dataflow/generic/tests.rs
index 50d4bdb67f7..8f07a10e1b0 100644
--- a/src/librustc_mir/dataflow/generic/tests.rs
+++ b/src/librustc_mir/dataflow/generic/tests.rs
@@ -294,7 +294,7 @@ fn cursor_seek() {
 
     cursor.seek_after(call_terminator_loc);
     assert!(!cursor.get().contains(call_return_effect));
-    cursor.seek_after_assume_call_returns(call_terminator_loc);
+    cursor.seek_after_assume_success(call_terminator_loc);
     assert!(cursor.get().contains(call_return_effect));
 
     let every_target = || {
@@ -310,7 +310,7 @@ fn cursor_seek() {
             BlockStart(block) => cursor.seek_to_block_start(block),
             Before(loc) => cursor.seek_before(loc),
             After(loc) => cursor.seek_after(loc),
-            AfterAssumeCallReturns(loc) => cursor.seek_after_assume_call_returns(loc),
+            AfterAssumeCallReturns(loc) => cursor.seek_after_assume_success(loc),
         }
 
         assert_eq!(cursor.get(), &cursor.analysis().expected_state_at_target(targ));
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index fabe562e68a..5341d661b1d 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -161,11 +161,16 @@ impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir,
         self.borrowed_locals.borrow().analysis().terminator_effect(trans, terminator, loc);
 
         match &terminator.kind {
-            TerminatorKind::Call { destination: Some((place, _)), .. }
-            | TerminatorKind::Yield { resume_arg: place, .. } => {
+            TerminatorKind::Call { destination: Some((place, _)), .. } => {
                 trans.gen(place.local);
             }
 
+            // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for
+            // that is that a `yield` will return from the function, and `resume_arg` is written
+            // only when the generator is later resumed. Unlike `Call`, this doesn't require the
+            // place to have storage *before* the yield, only after.
+            TerminatorKind::Yield { .. } => {}
+
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
             TerminatorKind::Call { destination: None, .. }
@@ -230,6 +235,15 @@ impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir,
     ) {
         trans.gen(return_place.local);
     }
+
+    fn yield_resume_effect(
+        &self,
+        trans: &mut BitSet<Self::Idx>,
+        _resume_block: BasicBlock,
+        resume_place: &mir::Place<'tcx>,
+    ) {
+        trans.gen(resume_place.local);
+    }
 }
 
 impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index b4e33b9502e..dd0f9ff75b9 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -1,16 +1,14 @@
+use rustc::mir::traversal;
+use rustc::mir::{self, BasicBlock, BasicBlockData, Body, Location, Statement, Terminator};
+use rustc::ty::{self, TyCtxt};
 use rustc_ast::ast::{self, MetaItem};
 use rustc_ast_pretty::pprust;
-use rustc_span::symbol::{sym, Symbol};
-
 use rustc_data_structures::work_queue::WorkQueue;
+use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::{BitSet, HybridBitSet};
 use rustc_index::vec::Idx;
-
-use rustc::mir::traversal;
-use rustc::mir::{self, BasicBlock, BasicBlockData, Body, Location, Statement, Terminator};
-use rustc::session::Session;
-use rustc::ty::{self, TyCtxt};
-use rustc_hir::def_id::DefId;
+use rustc_session::Session;
+use rustc_span::symbol::{sym, Symbol};
 
 use std::borrow::Borrow;
 use std::fmt;
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 85ac225bd2e..68a893dc4be 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -21,7 +21,7 @@ use rustc_span::source_map::{self, Span, DUMMY_SP};
 
 use super::{
     Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
-    ScalarMaybeUndef, StackPopInfo,
+    ScalarMaybeUndef, StackPopJump,
 };
 
 pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
@@ -98,10 +98,10 @@ pub enum StackPopCleanup {
     /// Jump to the next block in the caller, or cause UB if None (that's a function
     /// that may never return). Also store layout of return place so
     /// we can validate it at that layout.
-    /// `ret` stores the block we jump to on a normal return, while 'unwind'
-    /// stores the block used for cleanup during unwinding
+    /// `ret` stores the block we jump to on a normal return, while `unwind`
+    /// stores the block used for cleanup during unwinding.
     Goto { ret: Option<mir::BasicBlock>, unwind: Option<mir::BasicBlock> },
-    /// Just do nohing: Used by Main and for the box_alloc hook in miri.
+    /// Just do nothing: Used by Main and for the `box_alloc` hook in miri.
     /// `cleanup` says whether locals are deallocated. Static computation
     /// wants them leaked to intern what they need (and just throw away
     /// the entire `ecx` when it is done).
@@ -138,7 +138,7 @@ pub enum LocalValue<Tag = (), Id = AllocId> {
 impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
     pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
         match self.value {
-            LocalValue::Dead => throw_unsup!(DeadLocal),
+            LocalValue::Dead => throw_ub!(DeadLocal),
             LocalValue::Uninitialized => {
                 bug!("The type checker should prevent reading from a never-written local")
             }
@@ -152,7 +152,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
         &mut self,
     ) -> InterpResult<'tcx, Result<&mut LocalValue<Tag>, MemPlace<Tag>>> {
         match self.value {
-            LocalValue::Dead => throw_unsup!(DeadLocal),
+            LocalValue::Dead => throw_ub!(DeadLocal),
             LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)),
             ref mut local @ LocalValue::Live(Operand::Immediate(_))
             | ref mut local @ LocalValue::Uninitialized => Ok(Ok(local)),
@@ -326,7 +326,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 if self.tcx.is_mir_available(did) {
                     Ok(self.tcx.optimized_mir(did).unwrap_read_only())
                 } else {
-                    throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id)))
+                    throw_unsup!(NoMirFor(def_id))
                 }
             }
             _ => Ok(self.tcx.instance_mir(instance)),
@@ -630,23 +630,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         ::log_settings::settings().indentation -= 1;
         let frame = self.stack.pop().expect("tried to pop a stack frame, but there were none");
-        let stack_pop_info = M::stack_pop(self, frame.extra, unwinding)?;
-        if let (false, StackPopInfo::StopUnwinding) = (unwinding, stack_pop_info) {
-            bug!("Attempted to stop unwinding while there is no unwinding!");
-        }
 
         // Now where do we jump next?
 
-        // Determine if we leave this function normally or via unwinding.
-        let cur_unwinding =
-            if let StackPopInfo::StopUnwinding = stack_pop_info { false } else { unwinding };
-
         // Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
         // In that case, we return early. We also avoid validation in that case,
         // because this is CTFE and the final value will be thoroughly validated anyway.
         let (cleanup, next_block) = match frame.return_to_block {
             StackPopCleanup::Goto { ret, unwind } => {
-                (true, Some(if cur_unwinding { unwind } else { ret }))
+                (true, Some(if unwinding { unwind } else { ret }))
             }
             StackPopCleanup::None { cleanup, .. } => (cleanup, None),
         };
@@ -654,7 +646,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         if !cleanup {
             assert!(self.stack.is_empty(), "only the topmost frame should ever be leaked");
             assert!(next_block.is_none(), "tried to skip cleanup when we have a next block!");
-            // Leak the locals, skip validation.
+            assert!(!unwinding, "tried to skip cleanup during unwinding");
+            // Leak the locals, skip validation, skip machine hook.
             return Ok(());
         }
 
@@ -663,13 +656,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             self.deallocate_local(local.value)?;
         }
 
-        trace!(
-            "StackPopCleanup: {:?} StackPopInfo: {:?} cur_unwinding = {:?}",
-            frame.return_to_block,
-            stack_pop_info,
-            cur_unwinding
-        );
-        if cur_unwinding {
+        if M::stack_pop(self, frame.extra, unwinding)? == StackPopJump::NoJump {
+            // The hook already did everything.
+            // We want to skip the `info!` below, hence early return.
+            return Ok(());
+        }
+        // Normal return.
+        if unwinding {
             // Follow the unwind edge.
             let unwind = next_block.expect("Encountered StackPopCleanup::None when unwinding!");
             self.unwind_to_block(unwind);
@@ -704,7 +697,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 "CONTINUING({}) {} (unwinding = {})",
                 self.cur_frame(),
                 self.frame().instance,
-                cur_unwinding
+                unwinding
             );
         }
 
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 9b13db2289e..90b8a493299 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -327,7 +327,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
         if let Err(error) = interned {
             // This can happen when e.g. the tag of an enum is not a valid discriminant. We do have
             // to read enum discriminants in order to find references in enum variant fields.
-            if let err_unsup!(ValidationFailure(_)) = error.kind {
+            if let err_ub!(ValidationFailure(_)) = error.kind {
                 let err = crate::const_eval::error_to_const_error(&ecx, error);
                 match err.struct_error(
                     ecx.tcx,
@@ -390,7 +390,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
             }
         } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
             // dangling pointer
-            throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into()))
+            throw_ub_format!("encountered dangling pointer in final constant")
         } else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() {
             // We have hit an `AllocId` that is neither in local or global memory and isn't marked
             // as dangling by local memory.
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 1e5ed76c467..03aedad0d98 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -84,14 +84,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let substs = instance.substs;
         let intrinsic_name = self.tcx.item_name(instance.def_id());
 
-        // We currently do not handle any intrinsics that are *allowed* to diverge,
-        // but `transmute` could lack a return place in case of UB.
+        // First handle intrinsics without return place.
         let (dest, ret) = match ret {
-            Some(p) => p,
             None => match intrinsic_name {
-                sym::transmute => throw_ub!(Unreachable),
+                sym::transmute => throw_ub_format!("transmuting to uninhabited type"),
+                sym::abort => M::abort(self)?,
+                // Unsupported diverging intrinsic.
                 _ => return Ok(false),
             },
+            Some(p) => p,
         };
 
         // Keep the patterns in this match ordered the same as the list in
@@ -134,7 +135,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let bits = self.force_bits(val, layout_of.size)?;
                 let kind = match layout_of.abi {
                     ty::layout::Abi::Scalar(ref scalar) => scalar.value,
-                    _ => throw_unsup!(TypeNotPrimitive(ty)),
+                    _ => bug!("{} called on invalid type {:?}", intrinsic_name, ty),
                 };
                 let (nonzero, intrinsic_name) = match intrinsic_name {
                     sym::cttz_nonzero => (true, sym::cttz),
@@ -245,9 +246,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     let layout = self.layout_of(substs.type_at(0))?;
                     let r_val = self.force_bits(r.to_scalar()?, layout.size)?;
                     if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name {
-                        throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name);
+                        throw_ub_format!("overflowing shift by {} in `{}`", r_val, intrinsic_name);
                     } else {
-                        throw_ub_format!("Overflow executing `{}`", intrinsic_name);
+                        throw_ub_format!("overflow executing `{}`", intrinsic_name);
                     }
                 }
                 self.write_scalar(val, dest)?;
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index cd8bf7085d1..677dc697735 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -157,6 +157,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
         }
     }
 }
+
 impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
     fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool {
         false
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 6615cc608fb..c9d32f62400 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -17,16 +17,16 @@ use super::{
 /// Data returned by Machine::stack_pop,
 /// to provide further control over the popping of the stack frame
 #[derive(Eq, PartialEq, Debug, Copy, Clone)]
-pub enum StackPopInfo {
+pub enum StackPopJump {
     /// Indicates that no special handling should be
     /// done - we'll either return normally or unwind
     /// based on the terminator for the function
     /// we're leaving.
     Normal,
 
-    /// Indicates that we should stop unwinding,
-    /// as we've reached a catch frame
-    StopUnwinding,
+    /// Indicates that we should *not* jump to the return/unwind address, as the callback already
+    /// took care of everything.
+    NoJump,
 }
 
 /// Whether this kind of memory is allowed to leak
@@ -165,11 +165,15 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Called to evaluate `Assert` MIR terminators that trigger a panic.
     fn assert_panic(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        span: Span,
         msg: &mir::AssertMessage<'tcx>,
         unwind: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx>;
 
+    /// Called to evaluate `Abort` MIR terminator.
+    fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, !> {
+        throw_unsup_format!("aborting execution is not supported");
+    }
+
     /// Called for all binary operations where the LHS has pointer type.
     ///
     /// Returns a (value, overflowed) pair if the operation succeeded
@@ -272,9 +276,9 @@ pub trait Machine<'mir, 'tcx>: Sized {
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _extra: Self::FrameExtra,
         _unwinding: bool,
-    ) -> InterpResult<'tcx, StackPopInfo> {
+    ) -> InterpResult<'tcx, StackPopJump> {
         // By default, we do not support unwinding from panics
-        Ok(StackPopInfo::Normal)
+        Ok(StackPopJump::Normal)
     }
 
     fn int_to_ptr(
@@ -282,8 +286,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
         int: u64,
     ) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
         Err((if int == 0 {
-            err_unsup!(InvalidNullPointerUsage)
+            // This is UB, seriously.
+            err_ub!(InvalidIntPointerUsage(0))
         } else {
+            // This is just something we cannot support during const-eval.
             err_unsup!(ReadBytesAsPointer)
         })
         .into())
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 82a467c7ba9..5b2cd89a122 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -215,7 +215,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         kind: MemoryKind<M::MemoryKinds>,
     ) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
         if ptr.offset.bytes() != 0 {
-            throw_unsup!(ReallocateNonBasePtr)
+            throw_ub_format!(
+                "reallocating {:?} which does not point to the beginning of an object",
+                ptr
+            );
         }
 
         // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
@@ -251,7 +254,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         trace!("deallocating: {}", ptr.alloc_id);
 
         if ptr.offset.bytes() != 0 {
-            throw_unsup!(DeallocateNonBasePtr)
+            throw_ub_format!(
+                "deallocating {:?} which does not point to the beginning of an object",
+                ptr
+            );
         }
 
         let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) {
@@ -259,29 +265,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             None => {
                 // Deallocating static memory -- always an error
                 return Err(match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
-                    Some(GlobalAlloc::Function(..)) => err_unsup!(DeallocatedWrongMemoryKind(
-                        "function".to_string(),
-                        format!("{:?}", kind),
-                    )),
-                    Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => err_unsup!(
-                        DeallocatedWrongMemoryKind("static".to_string(), format!("{:?}", kind))
-                    ),
-                    None => err_unsup!(DoubleFree),
+                    Some(GlobalAlloc::Function(..)) => err_ub_format!("deallocating a function"),
+                    Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => {
+                        err_ub_format!("deallocating static memory")
+                    }
+                    None => err_ub!(PointerUseAfterFree(ptr.alloc_id)),
                 }
                 .into());
             }
         };
 
         if alloc_kind != kind {
-            throw_unsup!(DeallocatedWrongMemoryKind(
-                format!("{:?}", alloc_kind),
-                format!("{:?}", kind),
-            ))
+            throw_ub_format!(
+                "deallocating `{:?}` memory using `{:?}` deallocation operation",
+                alloc_kind,
+                kind
+            );
         }
         if let Some((size, align)) = old_size_and_align {
             if size != alloc.size || align != alloc.align {
-                let bytes = alloc.size;
-                throw_unsup!(IncorrectAllocationInformation(size, bytes, align, alloc.align))
+                throw_ub_format!(
+                    "incorrect layout on deallocation: allocation has size {} and alignment {}, but gave size {} and alignment {}",
+                    alloc.size.bytes(),
+                    alloc.align.bytes(),
+                    size.bytes(),
+                    align.bytes(),
+                )
             }
         }
 
@@ -338,7 +347,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             } else {
                 // The biggest power of two through which `offset` is divisible.
                 let offset_pow2 = 1 << offset.trailing_zeros();
-                throw_unsup!(AlignmentCheckFailed {
+                throw_ub!(AlignmentCheckFailed {
                     has: Align::from_bytes(offset_pow2).unwrap(),
                     required: align,
                 })
@@ -360,7 +369,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 assert!(size.bytes() == 0);
                 // Must be non-NULL.
                 if bits == 0 {
-                    throw_unsup!(InvalidNullPointerUsage)
+                    throw_ub!(InvalidIntPointerUsage(0))
                 }
                 // Must be aligned.
                 if let Some(align) = align {
@@ -375,7 +384,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 // It is sufficient to check this for the end pointer. The addition
                 // checks for overflow.
                 let end_ptr = ptr.offset(size, self)?;
-                end_ptr.check_inbounds_alloc(allocation_size, msg)?;
+                if end_ptr.offset > allocation_size {
+                    // equal is okay!
+                    throw_ub!(PointerOutOfBounds { ptr: end_ptr.erase_tag(), msg, allocation_size })
+                }
                 // Test align. Check this last; if both bounds and alignment are violated
                 // we want the error to be about the bounds.
                 if let Some(align) = align {
@@ -385,7 +397,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                         // got picked we might be aligned even if this check fails.
                         // We instead have to fall back to converting to an integer and checking
                         // the "real" alignment.
-                        throw_unsup!(AlignmentCheckFailed { has: alloc_align, required: align });
+                        throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align });
                     }
                     check_offset_align(ptr.offset.bytes(), align)?;
                 }
@@ -402,7 +414,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         let (size, _align) = self
             .get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)
             .expect("alloc info with MaybeDead cannot fail");
-        ptr.check_inbounds_alloc(size, CheckInAllocMsg::NullPointerTest).is_err()
+        // If the pointer is out-of-bounds, it may be null.
+        // Note that one-past-the-end (offset == size) is still inbounds, and never null.
+        ptr.offset > size
     }
 }
 
@@ -432,13 +446,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         let alloc = tcx.alloc_map.lock().get(id);
         let alloc = match alloc {
             Some(GlobalAlloc::Memory(mem)) => Cow::Borrowed(mem),
-            Some(GlobalAlloc::Function(..)) => throw_unsup!(DerefFunctionPointer),
-            None => throw_unsup!(DanglingPointerDeref),
+            Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)),
+            None => throw_ub!(PointerUseAfterFree(id)),
             Some(GlobalAlloc::Static(def_id)) => {
                 // We got a "lazy" static that has not been computed yet.
                 if tcx.is_foreign_item(def_id) {
                     trace!("get_static_alloc: foreign item {:?}", def_id);
-                    throw_unsup!(ReadForeignStatic)
+                    throw_unsup!(ReadForeignStatic(def_id))
                 }
                 trace!("get_static_alloc: Need to compute {:?}", def_id);
                 let instance = Instance::mono(tcx.tcx, def_id);
@@ -524,7 +538,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             // to give us a cheap reference.
             let alloc = Self::get_static_alloc(memory_extra, tcx, id)?;
             if alloc.mutability == Mutability::Not {
-                throw_unsup!(ModifiedConstantMemory)
+                throw_ub!(WriteToReadOnly(id))
             }
             match M::STATIC_KIND {
                 Some(kind) => Ok((MemoryKind::Machine(kind), alloc.into_owned())),
@@ -538,7 +552,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             Ok(a) => {
                 let a = &mut a.1;
                 if a.mutability == Mutability::Not {
-                    throw_unsup!(ModifiedConstantMemory)
+                    throw_ub!(WriteToReadOnly(id))
                 }
                 Ok(a)
             }
@@ -568,7 +582,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         if self.get_fn_alloc(id).is_some() {
             return if let AllocCheck::Dereferenceable = liveness {
                 // The caller requested no function pointers.
-                throw_unsup!(DerefFunctionPointer)
+                throw_ub!(DerefFunctionPointer(id))
             } else {
                 Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
             };
@@ -596,12 +610,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 if let AllocCheck::MaybeDead = liveness {
                     // Deallocated pointers are allowed, we should be able to find
                     // them in the map.
-                    Ok(*self.dead_alloc_map.get(&id).expect(
-                        "deallocated pointers should all be recorded in \
-                            `dead_alloc_map`",
-                    ))
+                    Ok(*self
+                        .dead_alloc_map
+                        .get(&id)
+                        .expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
                 } else {
-                    throw_unsup!(DanglingPointerDeref)
+                    throw_ub!(PointerUseAfterFree(id))
                 }
             }
         }
@@ -626,10 +640,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
         let ptr = self.force_ptr(ptr)?; // We definitely need a pointer value.
         if ptr.offset.bytes() != 0 {
-            throw_unsup!(InvalidFunctionPointer)
+            throw_ub!(InvalidFunctionPointer(ptr.erase_tag()))
         }
         let id = M::canonical_alloc_id(self, ptr.alloc_id);
-        self.get_fn_alloc(id).ok_or_else(|| err_unsup!(ExecuteMemory).into())
+        self.get_fn_alloc(id).ok_or_else(|| err_ub!(InvalidFunctionPointer(ptr.erase_tag())).into())
     }
 
     pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index a519f38e712..c3fd9682765 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -24,7 +24,7 @@ pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy};
 
 pub use self::memory::{AllocCheck, FnVal, Memory, MemoryKind};
 
-pub use self::machine::{AllocMap, Machine, MayLeak, StackPopInfo};
+pub use self::machine::{AllocMap, Machine, MayLeak, StackPopJump};
 
 pub use self::operand::{ImmTy, Immediate, OpTy, Operand, ScalarMaybeUndef};
 
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 79cd0824330..b39058405f5 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -3,18 +3,20 @@
 
 use std::convert::{TryFrom, TryInto};
 
-use rustc::ty::layout::{
-    self, HasDataLayout, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx,
-};
-use rustc::{mir, ty};
-
 use super::{InterpCx, MPlaceTy, Machine, MemPlace, Place, PlaceTy};
 pub use rustc::mir::interpret::ScalarMaybeUndef;
 use rustc::mir::interpret::{
     sign_extend, truncate, AllocId, ConstValue, GlobalId, InterpResult, Pointer, Scalar,
 };
-use rustc_ast::ast;
+use rustc::ty::layout::{
+    self, HasDataLayout, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx,
+};
+use rustc::ty::print::{FmtPrinter, PrettyPrinter, Printer};
+use rustc::ty::Ty;
+use rustc::{mir, ty};
+use rustc_hir::def::Namespace;
 use rustc_macros::HashStable;
+use std::fmt::Write;
 
 /// An `Immediate` represents a single immediate self-contained Rust value.
 ///
@@ -92,47 +94,44 @@ pub struct ImmTy<'tcx, Tag = ()> {
     pub layout: TyLayout<'tcx>,
 }
 
-// `Tag: Copy` because some methods on `Scalar` consume them by value
 impl<Tag: Copy> std::fmt::Display for ImmTy<'tcx, Tag> {
-    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match &self.imm {
-            // We cannot use `to_bits_or_ptr` as we do not have a `tcx`.
-            // So we use `is_bits` and circumvent a bunch of sanity checking -- but
-            // this is anyway only for printing.
-            Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) if s.is_ptr() => {
-                fmt.write_str("{pointer}")
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        /// Helper function for printing a scalar to a FmtPrinter
+        fn p<'a, 'tcx, F: std::fmt::Write, Tag>(
+            cx: FmtPrinter<'a, 'tcx, F>,
+            s: ScalarMaybeUndef<Tag>,
+            ty: Ty<'tcx>,
+        ) -> Result<FmtPrinter<'a, 'tcx, F>, std::fmt::Error> {
+            match s {
+                ScalarMaybeUndef::Scalar(s) => {
+                    cx.pretty_print_const_scalar(s.erase_tag(), ty, true)
+                }
+                ScalarMaybeUndef::Undef => cx.typed_value(
+                    |mut this| {
+                        this.write_str("{undef ")?;
+                        Ok(this)
+                    },
+                    |this| this.print_type(ty),
+                    " ",
+                ),
             }
-            Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => {
-                let s = s.assert_bits(self.layout.size);
-                match self.layout.ty.kind {
-                    ty::Int(_) => {
-                        return write!(fmt, "{}", super::sign_extend(s, self.layout.size) as i128,);
-                    }
-                    ty::Uint(_) => return write!(fmt, "{}", s),
-                    ty::Bool if s == 0 => return fmt.write_str("false"),
-                    ty::Bool if s == 1 => return fmt.write_str("true"),
-                    ty::Char => {
-                        if let Some(c) = u32::try_from(s).ok().and_then(std::char::from_u32) {
-                            return write!(fmt, "{}", c);
-                        }
-                    }
-                    ty::Float(ast::FloatTy::F32) => {
-                        if let Ok(u) = u32::try_from(s) {
-                            return write!(fmt, "{}", f32::from_bits(u));
-                        }
-                    }
-                    ty::Float(ast::FloatTy::F64) => {
-                        if let Ok(u) = u64::try_from(s) {
-                            return write!(fmt, "{}", f64::from_bits(u));
-                        }
+        }
+        ty::tls::with(|tcx| {
+            match self.imm {
+                Immediate::Scalar(s) => {
+                    if let Some(ty) = tcx.lift(&self.layout.ty) {
+                        let cx = FmtPrinter::new(tcx, f, Namespace::ValueNS);
+                        p(cx, s, ty)?;
+                        return Ok(());
                     }
-                    _ => {}
+                    write!(f, "{:?}: {}", s.erase_tag(), self.layout.ty)
+                }
+                Immediate::ScalarPair(a, b) => {
+                    // FIXME(oli-obk): at least print tuples and slices nicely
+                    write!(f, "({:?}, {:?}): {}", a.erase_tag(), b.erase_tag(), self.layout.ty,)
                 }
-                write!(fmt, "{:x}", s)
             }
-            Immediate::Scalar(ScalarMaybeUndef::Undef) => fmt.write_str("{undef}"),
-            Immediate::ScalarPair(..) => fmt.write_str("{wide pointer or tuple}"),
-        }
+        })
     }
 }
 
@@ -344,7 +343,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let len = mplace.len(self)?;
         let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?;
         let str = ::std::str::from_utf8(bytes)
-            .map_err(|err| err_unsup!(ValidationFailure(err.to_string())))?;
+            .map_err(|err| err_ub_format!("this string is not valid UTF-8: {}", err))?;
         Ok(str)
     }
 
@@ -356,7 +355,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let base = match op.try_as_mplace(self) {
             Ok(mplace) => {
-                // The easy case
+                // We can reuse the mplace field computation logic for indirect operands.
                 let field = self.mplace_field(mplace, field)?;
                 return Ok(field.into());
             }
@@ -458,7 +457,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         layout: Option<TyLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let base_op = match place.local {
-            mir::RETURN_PLACE => throw_unsup!(ReadFromReturnPointer),
+            mir::RETURN_PLACE => throw_ub!(ReadFromReturnPlace),
             local => {
                 // Do not use the layout passed in as argument if the base we are looking at
                 // here is not the entire place.
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index c0ec2e58448..5313446c253 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -410,14 +410,6 @@ where
                 stride * field
             }
             layout::FieldPlacement::Union(count) => {
-                // This is a narrow bug-fix for rust-lang/rust#69191: if we are
-                // trying to access absent field of uninhabited variant, then
-                // signal UB (but don't ICE the compiler).
-                // FIXME temporary hack to work around incoherence between
-                // layout computation and MIR building
-                if field >= count as u64 && base.layout.abi == layout::Abi::Uninhabited {
-                    throw_ub!(Unreachable);
-                }
                 assert!(
                     field < count as u64,
                     "Tried to access field {} of union {:#?} with {} fields",
@@ -928,7 +920,7 @@ where
             // most likey we *are* running `typeck` right now. Investigate whether we can bail out
             // on `typeck_tables().has_errors` at all const eval entry points.
             debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
-            throw_unsup!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
+            throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
         }
         // Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want
         // to avoid that here.
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index ea8378574a3..22a081a9c8e 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -95,10 +95,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 if expected == cond_val {
                     self.go_to_block(target);
                 } else {
-                    M::assert_panic(self, terminator.source_info.span, msg, cleanup)?;
+                    M::assert_panic(self, msg, cleanup)?;
                 }
             }
 
+            Abort => {
+                M::abort(self)?;
+            }
+
             // When we encounter Resume, we've finished unwinding
             // cleanup for the current stack frame. We pop it in order
             // to continue unwinding the next frame
@@ -114,15 +118,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Unreachable => throw_ub!(Unreachable),
 
             // These should never occur for MIR we actually run.
-            DropAndReplace { .. } | FalseEdges { .. } | FalseUnwind { .. } => {
+            DropAndReplace { .. }
+            | FalseEdges { .. }
+            | FalseUnwind { .. }
+            | Yield { .. }
+            | GeneratorDrop => {
                 bug!("{:#?} should have been eliminated by MIR pass", terminator.kind)
             }
-
-            // These are not (yet) supported. It is unclear if they even can occur in
-            // MIR that we actually run.
-            Yield { .. } | GeneratorDrop | Abort => {
-                throw_unsup_format!("Unsupported terminator kind: {:#?}", terminator.kind)
-            }
         }
 
         Ok(())
@@ -170,13 +172,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             trace!("Skipping callee ZST");
             return Ok(());
         }
-        let caller_arg = caller_arg.next().ok_or_else(|| err_unsup!(FunctionArgCountMismatch))?;
+        let caller_arg = caller_arg.next().ok_or_else(|| {
+            err_ub_format!("calling a function with fewer arguments than it requires")
+        })?;
         if rust_abi {
             assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
         }
         // Now, check
         if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) {
-            throw_unsup!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty))
+            throw_ub_format!(
+                "calling a function with argument of type {:?} passing data of type {:?}",
+                callee_arg.layout.ty,
+                caller_arg.layout.ty
+            )
         }
         // We allow some transmutes here
         self.copy_op_transmute(caller_arg, callee_arg)
@@ -221,7 +229,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 abi => abi,
             };
             if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
-                throw_unsup!(FunctionAbiMismatch(caller_abi, callee_abi))
+                throw_ub_format!(
+                    "calling a function with ABI {:?} using caller ABI {:?}",
+                    callee_abi,
+                    caller_abi
+                )
             }
         }
 
@@ -251,110 +263,108 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     StackPopCleanup::Goto { ret: ret.map(|p| p.1), unwind },
                 )?;
 
-                // We want to pop this frame again in case there was an error, to put
-                // the blame in the right location.  Until the 2018 edition is used in
-                // the compiler, we have to do this with an immediately invoked function.
-                let res =
-                    (|| {
-                        trace!(
-                            "caller ABI: {:?}, args: {:#?}",
-                            caller_abi,
-                            args.iter()
-                                .map(|arg| (arg.layout.ty, format!("{:?}", **arg)))
-                                .collect::<Vec<_>>()
-                        );
-                        trace!(
-                            "spread_arg: {:?}, locals: {:#?}",
-                            body.spread_arg,
-                            body.args_iter()
-                                .map(|local| (
-                                    local,
-                                    self.layout_of_local(self.frame(), local, None).unwrap().ty
-                                ))
-                                .collect::<Vec<_>>()
-                        );
-
-                        // Figure out how to pass which arguments.
-                        // The Rust ABI is special: ZST get skipped.
-                        let rust_abi = match caller_abi {
-                            Abi::Rust | Abi::RustCall => true,
-                            _ => false,
+                // If an error is raised here, pop the frame again to get an accurate backtrace.
+                // To this end, we wrap it all in a `try` block.
+                let res: InterpResult<'tcx> = try {
+                    trace!(
+                        "caller ABI: {:?}, args: {:#?}",
+                        caller_abi,
+                        args.iter()
+                            .map(|arg| (arg.layout.ty, format!("{:?}", **arg)))
+                            .collect::<Vec<_>>()
+                    );
+                    trace!(
+                        "spread_arg: {:?}, locals: {:#?}",
+                        body.spread_arg,
+                        body.args_iter()
+                            .map(|local| (
+                                local,
+                                self.layout_of_local(self.frame(), local, None).unwrap().ty
+                            ))
+                            .collect::<Vec<_>>()
+                    );
+
+                    // Figure out how to pass which arguments.
+                    // The Rust ABI is special: ZST get skipped.
+                    let rust_abi = match caller_abi {
+                        Abi::Rust | Abi::RustCall => true,
+                        _ => false,
+                    };
+                    // We have two iterators: Where the arguments come from,
+                    // and where they go to.
+
+                    // For where they come from: If the ABI is RustCall, we untuple the
+                    // last incoming argument.  These two iterators do not have the same type,
+                    // so to keep the code paths uniform we accept an allocation
+                    // (for RustCall ABI only).
+                    let caller_args: Cow<'_, [OpTy<'tcx, M::PointerTag>]> =
+                        if caller_abi == Abi::RustCall && !args.is_empty() {
+                            // Untuple
+                            let (&untuple_arg, args) = args.split_last().unwrap();
+                            trace!("eval_fn_call: Will pass last argument by untupling");
+                            Cow::from(
+                                args.iter()
+                                    .map(|&a| Ok(a))
+                                    .chain(
+                                        (0..untuple_arg.layout.fields.count())
+                                            .map(|i| self.operand_field(untuple_arg, i as u64)),
+                                    )
+                                    .collect::<InterpResult<'_, Vec<OpTy<'tcx, M::PointerTag>>>>(
+                                    )?,
+                            )
+                        } else {
+                            // Plain arg passing
+                            Cow::from(args)
                         };
-                        // We have two iterators: Where the arguments come from,
-                        // and where they go to.
-
-                        // For where they come from: If the ABI is RustCall, we untuple the
-                        // last incoming argument.  These two iterators do not have the same type,
-                        // so to keep the code paths uniform we accept an allocation
-                        // (for RustCall ABI only).
-                        let caller_args: Cow<'_, [OpTy<'tcx, M::PointerTag>]> =
-                            if caller_abi == Abi::RustCall && !args.is_empty() {
-                                // Untuple
-                                let (&untuple_arg, args) = args.split_last().unwrap();
-                                trace!("eval_fn_call: Will pass last argument by untupling");
-                                Cow::from(args.iter().map(|&a| Ok(a))
-                                .chain((0..untuple_arg.layout.fields.count())
-                                    .map(|i| self.operand_field(untuple_arg, i as u64))
-                                )
-                                .collect::<InterpResult<'_, Vec<OpTy<'tcx, M::PointerTag>>>>()?)
-                            } else {
-                                // Plain arg passing
-                                Cow::from(args)
-                            };
-                        // Skip ZSTs
-                        let mut caller_iter = caller_args
-                            .iter()
-                            .filter(|op| !rust_abi || !op.layout.is_zst())
-                            .copied();
-
-                        // Now we have to spread them out across the callee's locals,
-                        // taking into account the `spread_arg`.  If we could write
-                        // this is a single iterator (that handles `spread_arg`), then
-                        // `pass_argument` would be the loop body. It takes care to
-                        // not advance `caller_iter` for ZSTs
-                        for local in body.args_iter() {
-                            let dest = self.eval_place(&mir::Place::from(local))?;
-                            if Some(local) == body.spread_arg {
-                                // Must be a tuple
-                                for i in 0..dest.layout.fields.count() {
-                                    let dest = self.place_field(dest, i as u64)?;
-                                    self.pass_argument(rust_abi, &mut caller_iter, dest)?;
-                                }
-                            } else {
-                                // Normal argument
+                    // Skip ZSTs
+                    let mut caller_iter =
+                        caller_args.iter().filter(|op| !rust_abi || !op.layout.is_zst()).copied();
+
+                    // Now we have to spread them out across the callee's locals,
+                    // taking into account the `spread_arg`.  If we could write
+                    // this is a single iterator (that handles `spread_arg`), then
+                    // `pass_argument` would be the loop body. It takes care to
+                    // not advance `caller_iter` for ZSTs.
+                    for local in body.args_iter() {
+                        let dest = self.eval_place(&mir::Place::from(local))?;
+                        if Some(local) == body.spread_arg {
+                            // Must be a tuple
+                            for i in 0..dest.layout.fields.count() {
+                                let dest = self.place_field(dest, i as u64)?;
                                 self.pass_argument(rust_abi, &mut caller_iter, dest)?;
                             }
+                        } else {
+                            // Normal argument
+                            self.pass_argument(rust_abi, &mut caller_iter, dest)?;
                         }
-                        // Now we should have no more caller args
-                        if caller_iter.next().is_some() {
-                            trace!("Caller has passed too many args");
-                            throw_unsup!(FunctionArgCountMismatch)
+                    }
+                    // Now we should have no more caller args
+                    if caller_iter.next().is_some() {
+                        throw_ub_format!("calling a function with more arguments than it expected")
+                    }
+                    // Don't forget to check the return type!
+                    if let Some((caller_ret, _)) = ret {
+                        let callee_ret = self.eval_place(&mir::Place::return_place())?;
+                        if !Self::check_argument_compat(
+                            rust_abi,
+                            caller_ret.layout,
+                            callee_ret.layout,
+                        ) {
+                            throw_ub_format!(
+                                "calling a function with return type {:?} passing \
+                                     return place of type {:?}",
+                                callee_ret.layout.ty,
+                                caller_ret.layout.ty
+                            )
                         }
-                        // Don't forget to check the return type!
-                        if let Some((caller_ret, _)) = ret {
-                            let callee_ret = self.eval_place(&mir::Place::return_place())?;
-                            if !Self::check_argument_compat(
-                                rust_abi,
-                                caller_ret.layout,
-                                callee_ret.layout,
-                            ) {
-                                throw_unsup!(FunctionRetMismatch(
-                                    caller_ret.layout.ty,
-                                    callee_ret.layout.ty
-                                ))
-                            }
-                        } else {
-                            let local = mir::RETURN_PLACE;
-                            let callee_layout = self.layout_of_local(self.frame(), local, None)?;
-                            if !callee_layout.abi.is_uninhabited() {
-                                throw_unsup!(FunctionRetMismatch(
-                                    self.tcx.types.never,
-                                    callee_layout.ty
-                                ))
-                            }
+                    } else {
+                        let local = mir::RETURN_PLACE;
+                        let callee_layout = self.layout_of_local(self.frame(), local, None)?;
+                        if !callee_layout.abi.is_uninhabited() {
+                            throw_ub_format!("calling a returning function without a return place")
                         }
-                        Ok(())
-                    })();
+                    }
+                };
                 match res {
                     Err(err) => {
                         self.stack.pop();
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 05bb010959b..d93b78a5bd5 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -29,7 +29,7 @@ macro_rules! throw_validation_failure {
             write_path(&mut msg, where_);
         }
         write!(&mut msg, ", but expected {}", $details).unwrap();
-        throw_unsup!(ValidationFailure(msg))
+        throw_ub!(ValidationFailure(msg))
     }};
     ($what:expr, $where:expr) => {{
         let mut msg = format!("encountered {}", $what);
@@ -38,7 +38,7 @@ macro_rules! throw_validation_failure {
             msg.push_str(" at ");
             write_path(&mut msg, where_);
         }
-        throw_unsup!(ValidationFailure(msg))
+        throw_ub!(ValidationFailure(msg))
     }};
 }
 
@@ -353,31 +353,39 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
                     place.ptr, size, align
                 );
                 match err.kind {
-                    err_unsup!(InvalidNullPointerUsage) => {
+                    err_ub!(InvalidIntPointerUsage(0)) => {
                         throw_validation_failure!(format_args!("a NULL {}", kind), self.path)
                     }
-                    err_unsup!(AlignmentCheckFailed { required, has }) => {
-                        throw_validation_failure!(
-                            format_args!(
-                                "an unaligned {} \
-                                    (required {} byte alignment but found {})",
-                                kind,
-                                required.bytes(),
-                                has.bytes()
-                            ),
-                            self.path
-                        )
-                    }
+                    err_ub!(InvalidIntPointerUsage(i)) => throw_validation_failure!(
+                        format_args!("a {} to unallocated address {}", kind, i),
+                        self.path
+                    ),
+                    err_ub!(AlignmentCheckFailed { required, has }) => throw_validation_failure!(
+                        format_args!(
+                            "an unaligned {} (required {} byte alignment but found {})",
+                            kind,
+                            required.bytes(),
+                            has.bytes()
+                        ),
+                        self.path
+                    ),
                     err_unsup!(ReadBytesAsPointer) => throw_validation_failure!(
                         format_args!("a dangling {} (created from integer)", kind),
                         self.path
                     ),
-                    err_unsup!(PointerOutOfBounds { .. }) | err_unsup!(DanglingPointerDeref) => {
-                        throw_validation_failure!(
-                            format_args!("a dangling {} (not entirely in bounds)", kind),
-                            self.path
-                        )
-                    }
+                    err_ub!(PointerOutOfBounds { .. }) => throw_validation_failure!(
+                        format_args!(
+                            "a dangling {} (going beyond the bounds of its allocation)",
+                            kind
+                        ),
+                        self.path
+                    ),
+                    // This cannot happen during const-eval (because interning already detects
+                    // dangling pointers), but it can happen in Miri.
+                    err_ub!(PointerUseAfterFree(_)) => throw_validation_failure!(
+                        format_args!("a dangling {} (use-after-free)", kind),
+                        self.path
+                    ),
                     _ => bug!("Unexpected error during ptr inbounds test: {}", err),
                 }
             }
@@ -765,11 +773,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                     Err(err) => {
                         // For some errors we might be able to provide extra information
                         match err.kind {
-                            err_unsup!(ReadUndefBytes(offset)) => {
+                            err_ub!(InvalidUndefBytes(Some(ptr))) => {
                                 // Some byte was undefined, determine which
                                 // element that byte belongs to so we can
                                 // provide an index.
-                                let i = (offset.bytes() / layout.size.bytes()) as usize;
+                                let i = (ptr.offset.bytes() / layout.size.bytes()) as usize;
                                 self.path.push(PathElem::ArrayElem(i));
 
                                 throw_validation_failure!("undefined bytes", self.path)
@@ -817,7 +825,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Run it.
         match visitor.visit_value(op) {
             Ok(()) => Ok(()),
-            Err(err) if matches!(err.kind, err_unsup!(ValidationFailure { .. })) => Err(err),
+            Err(err) if matches!(err.kind, err_ub!(ValidationFailure { .. })) => Err(err),
             Err(err) if cfg!(debug_assertions) => {
                 bug!("Unexpected error during validation: {}", err)
             }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 284dd74ce99..7d3aba3ff03 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -9,6 +9,9 @@ Rust MIR: a lowered representation of Rust.
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
 #![feature(drain_filter)]
 #![feature(exhaustive_patterns)]
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index fbb7d8c6ee3..4dd037d93ce 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -183,7 +183,6 @@ use rustc::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
 use rustc::mir::mono::{InstantiationMode, MonoItem};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::{self, Local, Location};
-use rustc::session::config::EntryFnType;
 use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc::ty::print::obsolete::DefPathBasedNames;
 use rustc::ty::subst::InternalSubsts;
@@ -194,6 +193,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_index::bit_set::GrowableBitSet;
+use rustc_session::config::EntryFnType;
 use smallvec::SmallVec;
 use std::iter;
 
@@ -989,7 +989,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
 
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
         match ii.kind {
-            hir::ImplItemKind::Method(hir::FnSig { .. }, _) => {
+            hir::ImplItemKind::Fn(hir::FnSig { .. }, _) => {
                 let def_id = self.tcx.hir().local_def_id(ii.hir_id);
                 self.push_if_root(def_id);
             }
@@ -1094,9 +1094,9 @@ fn create_mono_items_for_default_impls<'tcx>(
                 let param_env = ty::ParamEnv::reveal_all();
                 let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
                 let overridden_methods: FxHashSet<_> =
-                    items.iter().map(|iiref| iiref.ident.modern()).collect();
+                    items.iter().map(|iiref| iiref.ident.normalize_to_macros_2_0()).collect();
                 for method in tcx.provided_trait_methods(trait_ref.def_id) {
-                    if overridden_methods.contains(&method.ident.modern()) {
+                    if overridden_methods.contains(&method.ident.normalize_to_macros_2_0()) {
                         continue;
                     }
 
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 1f7db2861a2..c1d969a4b51 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -2,13 +2,13 @@ use rustc::mir::*;
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 
 use rustc_index::vec::{Idx, IndexVec};
 
-use rustc_span::{sym, Span};
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 use std::fmt;
@@ -39,6 +39,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
             None,
         ),
         ty::InstanceDef::FnPtrShim(def_id, ty) => {
+            // FIXME(eddyb) support generating shims for a "shallow type",
+            // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
+            // `Foo<Bar>` or `[String]` etc.
+            assert!(!ty.needs_subst());
+
             let trait_ = tcx.trait_of_item(def_id).unwrap();
             let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) {
                 Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
@@ -81,17 +86,21 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
                 None,
             )
         }
-        ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty),
+        ty::InstanceDef::DropGlue(def_id, ty) => {
+            // FIXME(eddyb) support generating shims for a "shallow type",
+            // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
+            // `Foo<Bar>` or `[String]` etc.
+            assert!(!ty.needs_subst());
+
+            build_drop_shim(tcx, def_id, ty)
+        }
         ty::InstanceDef::CloneShim(def_id, ty) => {
-            let name = tcx.item_name(def_id);
-            if name == sym::clone {
-                build_clone_shim(tcx, def_id, ty)
-            } else if name == sym::clone_from {
-                debug!("make_shim({:?}: using default trait implementation", instance);
-                return tcx.optimized_mir(def_id);
-            } else {
-                bug!("builtin clone shim {:?} not supported", instance)
-            }
+            // FIXME(eddyb) support generating shims for a "shallow type",
+            // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
+            // `Foo<Bar>` or `[String]` etc.
+            assert!(!ty.needs_subst());
+
+            build_clone_shim(tcx, def_id, ty)
         }
         ty::InstanceDef::Virtual(..) => {
             bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index 2306177c14b..aa9cad7ffc1 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -34,7 +34,7 @@ fn is_stable(place: PlaceRef<'_>) -> bool {
 }
 
 /// Determine whether this type may be a reference (or box), and thus needs retagging.
-fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool {
+fn may_be_reference(ty: Ty<'tcx>) -> bool {
     match ty.kind {
         // Primitive types that are not references
         ty::Bool
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index 9ba44a4d18e..af7af7388bd 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -1,10 +1,9 @@
 //! Concrete error types for all operations which may be invalid in a certain const context.
 
-use rustc::session::config::nightly_options;
-use rustc::session::parse::feature_err;
-use rustc::ty::TyCtxt;
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::DefId;
+use rustc_session::config::nightly_options;
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
 
@@ -15,9 +14,9 @@ pub trait NonConstOp: std::fmt::Debug {
     /// Whether this operation can be evaluated by miri.
     const IS_SUPPORTED_IN_MIRI: bool = true;
 
-    /// Returns a boolean indicating whether the feature gate that would allow this operation is
-    /// enabled, or `None` if such a feature gate does not exist.
-    fn feature_gate(_tcx: TyCtxt<'tcx>) -> Option<bool> {
+    /// Returns the `Symbol` corresponding to the feature gate that would enable this operation,
+    /// or `None` if such a feature gate does not exist.
+    fn feature_gate() -> Option<Symbol> {
         None
     }
 
@@ -25,8 +24,11 @@ pub trait NonConstOp: std::fmt::Debug {
     ///
     /// This check should assume that we are not in a non-const `fn`, where all operations are
     /// legal.
+    ///
+    /// By default, it returns `true` if and only if this operation has a corresponding feature
+    /// gate and that gate is enabled.
     fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
-        Self::feature_gate(item.tcx).unwrap_or(false)
+        Self::feature_gate().map_or(false, |gate| item.tcx.features().enabled(gate))
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -55,8 +57,8 @@ pub trait NonConstOp: std::fmt::Debug {
 #[derive(Debug)]
 pub struct Downcast;
 impl NonConstOp for Downcast {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_if_match)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_if_match)
     }
 }
 
@@ -147,8 +149,8 @@ impl NonConstOp for HeapAllocation {
 #[derive(Debug)]
 pub struct IfOrMatch;
 impl NonConstOp for IfOrMatch {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_if_match)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_if_match)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -175,8 +177,8 @@ impl NonConstOp for LiveDrop {
 #[derive(Debug)]
 pub struct Loop;
 impl NonConstOp for Loop {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_loop)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_loop)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -203,8 +205,8 @@ impl NonConstOp for CellBorrow {
 #[derive(Debug)]
 pub struct MutBorrow;
 impl NonConstOp for MutBorrow {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_mut_refs)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_mut_refs)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -238,8 +240,8 @@ impl NonConstOp for MutBorrow {
 #[derive(Debug)]
 pub struct MutAddressOf;
 impl NonConstOp for MutAddressOf {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_mut_refs)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_mut_refs)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -256,16 +258,16 @@ impl NonConstOp for MutAddressOf {
 #[derive(Debug)]
 pub struct MutDeref;
 impl NonConstOp for MutDeref {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_mut_refs)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_mut_refs)
     }
 }
 
 #[derive(Debug)]
 pub struct Panic;
 impl NonConstOp for Panic {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_panic)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_panic)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -282,8 +284,8 @@ impl NonConstOp for Panic {
 #[derive(Debug)]
 pub struct RawPtrComparison;
 impl NonConstOp for RawPtrComparison {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_compare_raw_pointers)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_compare_raw_pointers)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -300,8 +302,8 @@ impl NonConstOp for RawPtrComparison {
 #[derive(Debug)]
 pub struct RawPtrDeref;
 impl NonConstOp for RawPtrDeref {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_raw_ptr_deref)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_raw_ptr_deref)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -318,8 +320,8 @@ impl NonConstOp for RawPtrDeref {
 #[derive(Debug)]
 pub struct RawPtrToIntCast;
 impl NonConstOp for RawPtrToIntCast {
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_raw_ptr_to_usize_cast)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_raw_ptr_to_usize_cast)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
@@ -386,11 +388,12 @@ pub struct UnionAccess;
 impl NonConstOp for UnionAccess {
     fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool {
         // Union accesses are stable in all contexts except `const fn`.
-        item.const_kind() != ConstKind::ConstFn || Self::feature_gate(item.tcx).unwrap()
+        item.const_kind() != ConstKind::ConstFn
+            || item.tcx.features().enabled(Self::feature_gate().unwrap())
     }
 
-    fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
-        Some(tcx.features().const_fn_union)
+    fn feature_gate() -> Option<Symbol> {
+        Some(sym::const_fn_union)
     }
 
     fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index baff8383c20..9359ec16533 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -1,7 +1,9 @@
-//! A copy of the `Qualif` trait in `qualify_consts.rs` that is suitable for the new validator.
+//! Structural const qualification.
+//!
+//! See the `Qualif` trait for more info.
 
 use rustc::mir::*;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, AdtDef, Ty};
 use rustc_span::DUMMY_SP;
 
 use super::Item as ConstCx;
@@ -14,11 +16,16 @@ pub fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> ConstQualifs
 }
 
 /// A "qualif"(-ication) is a way to look for something "bad" in the MIR that would disqualify some
-/// code for promotion or prevent it from evaluating at compile time. So `return true` means
-/// "I found something bad, no reason to go on searching". `false` is only returned if we
-/// definitely cannot find anything bad anywhere.
+/// code for promotion or prevent it from evaluating at compile time.
 ///
-/// The default implementations proceed structurally.
+/// Normally, we would determine what qualifications apply to each type and error when an illegal
+/// operation is performed on such a type. However, this was found to be too imprecise, especially
+/// in the presence of `enum`s. If only a single variant of an enum has a certain qualification, we
+/// needn't reject code unless it actually constructs and operates on the qualifed variant.
+///
+/// To accomplish this, const-checking and promotion use a value-based analysis (as opposed to a
+/// type-based one). Qualifications propagate structurally across variables: If a local (or a
+/// projection of a local) is assigned a qualifed value, that local itself becomes qualifed.
 pub trait Qualif {
     /// The name of the file used to debug the dataflow analysis that computes this qualif.
     const ANALYSIS_NAME: &'static str;
@@ -26,157 +33,27 @@ pub trait Qualif {
     /// Whether this `Qualif` is cleared when a local is moved from.
     const IS_CLEARED_ON_MOVE: bool = false;
 
+    /// Extracts the field of `ConstQualifs` that corresponds to this `Qualif`.
     fn in_qualifs(qualifs: &ConstQualifs) -> bool;
 
-    /// Return the qualification that is (conservatively) correct for any value
-    /// of the type.
-    fn in_any_value_of_ty(_cx: &ConstCx<'_, 'tcx>, _ty: Ty<'tcx>) -> bool;
-
-    fn in_projection_structurally(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'tcx>,
-    ) -> bool {
-        if let [proj_base @ .., elem] = place.projection {
-            let base_qualif = Self::in_place(
-                cx,
-                per_local,
-                PlaceRef { local: place.local, projection: proj_base },
-            );
-            let qualif = base_qualif
-                && Self::in_any_value_of_ty(
-                    cx,
-                    Place::ty_from(place.local, proj_base, *cx.body, cx.tcx)
-                        .projection_ty(cx.tcx, elem)
-                        .ty,
-                );
-            match elem {
-                ProjectionElem::Deref
-                | ProjectionElem::Subslice { .. }
-                | ProjectionElem::Field(..)
-                | ProjectionElem::ConstantIndex { .. }
-                | ProjectionElem::Downcast(..) => qualif,
-
-                ProjectionElem::Index(local) => qualif || per_local(*local),
-            }
-        } else {
-            bug!("This should be called if projection is not empty");
-        }
-    }
-
-    fn in_projection(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'tcx>,
-    ) -> bool {
-        Self::in_projection_structurally(cx, per_local, place)
-    }
-
-    fn in_place(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        place: PlaceRef<'tcx>,
-    ) -> bool {
-        match place {
-            PlaceRef { local, projection: [] } => per_local(local),
-            PlaceRef { local: _, projection: [.., _] } => Self::in_projection(cx, per_local, place),
-        }
-    }
-
-    fn in_operand(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        operand: &Operand<'tcx>,
-    ) -> bool {
-        match *operand {
-            Operand::Copy(ref place) | Operand::Move(ref place) => {
-                Self::in_place(cx, per_local, place.as_ref())
-            }
-
-            Operand::Constant(ref constant) => {
-                // Check the qualifs of the value of `const` items.
-                if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val {
-                    assert!(promoted.is_none());
-                    // Don't peek inside trait associated constants.
-                    if cx.tcx.trait_of_item(def_id).is_none() {
-                        let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id);
-                        if !Self::in_qualifs(&qualifs) {
-                            return false;
-                        }
-
-                        // Just in case the type is more specific than
-                        // the definition, e.g., impl associated const
-                        // with type parameters, take it into account.
-                    }
-                }
-                // Otherwise use the qualifs of the type.
-                Self::in_any_value_of_ty(cx, constant.literal.ty)
-            }
-        }
-    }
-
-    fn in_rvalue_structurally(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        rvalue: &Rvalue<'tcx>,
-    ) -> bool {
-        match *rvalue {
-            Rvalue::NullaryOp(..) => false,
-
-            Rvalue::Discriminant(ref place) | Rvalue::Len(ref place) => {
-                Self::in_place(cx, per_local, place.as_ref())
-            }
-
-            Rvalue::Use(ref operand)
-            | Rvalue::Repeat(ref operand, _)
-            | Rvalue::UnaryOp(_, ref operand)
-            | Rvalue::Cast(_, ref operand, _) => Self::in_operand(cx, per_local, operand),
-
-            Rvalue::BinaryOp(_, ref lhs, ref rhs)
-            | Rvalue::CheckedBinaryOp(_, ref lhs, ref rhs) => {
-                Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs)
-            }
-
-            Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => {
-                // Special-case reborrows to be more like a copy of the reference.
-                if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
-                    let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx).ty;
-                    if let ty::Ref(..) = base_ty.kind {
-                        return Self::in_place(
-                            cx,
-                            per_local,
-                            PlaceRef { local: place.local, projection: proj_base },
-                        );
-                    }
-                }
-
-                Self::in_place(cx, per_local, place.as_ref())
-            }
-
-            Rvalue::Aggregate(_, ref operands) => {
-                operands.iter().any(|o| Self::in_operand(cx, per_local, o))
-            }
-        }
-    }
-
-    fn in_rvalue(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        rvalue: &Rvalue<'tcx>,
-    ) -> bool {
-        Self::in_rvalue_structurally(cx, per_local, rvalue)
-    }
-
-    fn in_call(
-        cx: &ConstCx<'_, 'tcx>,
-        _per_local: &mut impl FnMut(Local) -> bool,
-        _callee: &Operand<'tcx>,
-        _args: &[Operand<'tcx>],
-        return_ty: Ty<'tcx>,
-    ) -> bool {
-        // Be conservative about the returned value of a const fn.
-        Self::in_any_value_of_ty(cx, return_ty)
-    }
+    /// Returns `true` if *any* value of the given type could possibly have this `Qualif`.
+    ///
+    /// This function determines `Qualif`s when we cannot do a value-based analysis. Since qualif
+    /// propagation is context-insenstive, this includes function arguments and values returned
+    /// from a call to another function.
+    ///
+    /// It also determines the `Qualif`s for primitive types.
+    fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool;
+
+    /// Returns `true` if this `Qualif` is inherent to the given struct or enum.
+    ///
+    /// By default, `Qualif`s propagate into ADTs in a structural way: An ADT only becomes
+    /// qualified if part of it is assigned a value with that `Qualif`. However, some ADTs *always*
+    /// have a certain `Qualif`, regardless of whether their fields have it. For example, a type
+    /// with a custom `Drop` impl is inherently `NeedsDrop`.
+    ///
+    /// Returning `true` for `in_adt_inherently` but `false` for `in_any_value_of_ty` is unsound.
+    fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool;
 }
 
 /// Constant containing interior mutability (`UnsafeCell<T>`).
@@ -197,26 +74,10 @@ impl Qualif for HasMutInterior {
         !ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP)
     }
 
-    fn in_rvalue(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        rvalue: &Rvalue<'tcx>,
-    ) -> bool {
-        match *rvalue {
-            Rvalue::Aggregate(ref kind, _) => {
-                if let AggregateKind::Adt(def, ..) = **kind {
-                    if Some(def.did) == cx.tcx.lang_items().unsafe_cell_type() {
-                        let ty = rvalue.ty(*cx.body, cx.tcx);
-                        assert_eq!(Self::in_any_value_of_ty(cx, ty), true);
-                        return true;
-                    }
-                }
-            }
-
-            _ => {}
-        }
-
-        Self::in_rvalue_structurally(cx, per_local, rvalue)
+    fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool {
+        // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
+        // It arises structurally for all other types.
+        Some(adt.did) == cx.tcx.lang_items().unsafe_cell_type()
     }
 }
 
@@ -238,19 +99,127 @@ impl Qualif for NeedsDrop {
         ty.needs_drop(cx.tcx, cx.param_env)
     }
 
-    fn in_rvalue(
-        cx: &ConstCx<'_, 'tcx>,
-        per_local: &mut impl FnMut(Local) -> bool,
-        rvalue: &Rvalue<'tcx>,
-    ) -> bool {
-        if let Rvalue::Aggregate(ref kind, _) = *rvalue {
+    fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool {
+        adt.has_dtor(cx.tcx)
+    }
+}
+
+// FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return.
+
+/// Returns `true` if this `Rvalue` contains qualif `Q`.
+pub fn in_rvalue<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue<'tcx>) -> bool
+where
+    Q: Qualif,
+    F: FnMut(Local) -> bool,
+{
+    match rvalue {
+        Rvalue::NullaryOp(..) => Q::in_any_value_of_ty(cx, rvalue.ty(*cx.body, cx.tcx)),
+
+        Rvalue::Discriminant(place) | Rvalue::Len(place) => {
+            in_place::<Q, _>(cx, in_local, place.as_ref())
+        }
+
+        Rvalue::Use(operand)
+        | Rvalue::Repeat(operand, _)
+        | Rvalue::UnaryOp(_, operand)
+        | Rvalue::Cast(_, operand, _) => in_operand::<Q, _>(cx, in_local, operand),
+
+        Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
+            in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)
+        }
+
+        Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
+            // Special-case reborrows to be more like a copy of the reference.
+            if let &[ref proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
+                let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx).ty;
+                if let ty::Ref(..) = base_ty.kind {
+                    return in_place::<Q, _>(
+                        cx,
+                        in_local,
+                        PlaceRef { local: place.local, projection: proj_base },
+                    );
+                }
+            }
+
+            in_place::<Q, _>(cx, in_local, place.as_ref())
+        }
+
+        Rvalue::Aggregate(kind, operands) => {
+            // Return early if we know that the struct or enum being constructed is always
+            // qualified.
             if let AggregateKind::Adt(def, ..) = **kind {
-                if def.has_dtor(cx.tcx) {
+                if Q::in_adt_inherently(cx, def) {
                     return true;
                 }
             }
+
+            // Otherwise, proceed structurally...
+            operands.iter().any(|o| in_operand::<Q, _>(cx, in_local, o))
         }
+    }
+}
 
-        Self::in_rvalue_structurally(cx, per_local, rvalue)
+/// Returns `true` if this `Place` contains qualif `Q`.
+pub fn in_place<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, place: PlaceRef<'tcx>) -> bool
+where
+    Q: Qualif,
+    F: FnMut(Local) -> bool,
+{
+    let mut projection = place.projection;
+    while let [ref proj_base @ .., proj_elem] = projection {
+        match *proj_elem {
+            ProjectionElem::Index(index) if in_local(index) => return true,
+
+            ProjectionElem::Deref
+            | ProjectionElem::Field(_, _)
+            | ProjectionElem::ConstantIndex { .. }
+            | ProjectionElem::Subslice { .. }
+            | ProjectionElem::Downcast(_, _)
+            | ProjectionElem::Index(_) => {}
+        }
+
+        let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx);
+        let proj_ty = base_ty.projection_ty(cx.tcx, proj_elem).ty;
+        if !Q::in_any_value_of_ty(cx, proj_ty) {
+            return false;
+        }
+
+        projection = proj_base;
+    }
+
+    assert!(projection.is_empty());
+    in_local(place.local)
+}
+
+/// Returns `true` if this `Operand` contains qualif `Q`.
+pub fn in_operand<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, operand: &Operand<'tcx>) -> bool
+where
+    Q: Qualif,
+    F: FnMut(Local) -> bool,
+{
+    let constant = match operand {
+        Operand::Copy(place) | Operand::Move(place) => {
+            return in_place::<Q, _>(cx, in_local, place.as_ref());
+        }
+
+        Operand::Constant(c) => c,
+    };
+
+    // Check the qualifs of the value of `const` items.
+    if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val {
+        assert!(promoted.is_none());
+        // Don't peek inside trait associated constants.
+        if cx.tcx.trait_of_item(def_id).is_none() {
+            let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id);
+            if !Q::in_qualifs(&qualifs) {
+                return false;
+            }
+
+            // Just in case the type is more specific than
+            // the definition, e.g., impl associated const
+            // with type parameters, take it into account.
+        }
     }
+    // Otherwise use the qualifs of the type.
+    Q::in_any_value_of_ty(cx, constant.literal.ty)
 }
diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs
index 3e14cc6d32a..e42f64b5c73 100644
--- a/src/librustc_mir/transform/check_consts/resolver.rs
+++ b/src/librustc_mir/transform/check_consts/resolver.rs
@@ -8,7 +8,7 @@ use rustc_index::bit_set::BitSet;
 
 use std::marker::PhantomData;
 
-use super::{Item, Qualif};
+use super::{qualifs, Item, Qualif};
 use crate::dataflow::{self as old_dataflow, generic as dataflow};
 
 /// A `Visitor` that propagates qualifs between locals. This defines the transfer function of
@@ -66,18 +66,15 @@ where
     fn apply_call_return_effect(
         &mut self,
         _block: BasicBlock,
-        func: &mir::Operand<'tcx>,
-        args: &[mir::Operand<'tcx>],
+        _func: &mir::Operand<'tcx>,
+        _args: &[mir::Operand<'tcx>],
         return_place: &mir::Place<'tcx>,
     ) {
+        // We cannot reason about another function's internals, so use conservative type-based
+        // qualification for the result of a function call.
         let return_ty = return_place.ty(*self.item.body, self.item.tcx).ty;
-        let qualif = Q::in_call(
-            self.item,
-            &mut |l| self.qualifs_per_local.contains(l),
-            func,
-            args,
-            return_ty,
-        );
+        let qualif = Q::in_any_value_of_ty(self.item, return_ty);
+
         if !return_place.is_indirect() {
             self.assign_qualif_direct(return_place, qualif);
         }
@@ -110,7 +107,11 @@ where
         rvalue: &mir::Rvalue<'tcx>,
         location: Location,
     ) {
-        let qualif = Q::in_rvalue(self.item, &mut |l| self.qualifs_per_local.contains(l), rvalue);
+        let qualif = qualifs::in_rvalue::<Q, _>(
+            self.item,
+            &mut |l| self.qualifs_per_local.contains(l),
+            rvalue,
+        );
         if !place.is_indirect() {
             self.assign_qualif_direct(place, qualif);
         }
@@ -125,8 +126,12 @@ where
         // here; that occurs in `apply_call_return_effect`.
 
         if let mir::TerminatorKind::DropAndReplace { value, location: dest, .. } = kind {
-            let qualif =
-                Q::in_operand(self.item, &mut |l| self.qualifs_per_local.contains(l), value);
+            let qualif = qualifs::in_operand::<Q, _>(
+                self.item,
+                &mut |l| self.qualifs_per_local.contains(l),
+                value,
+            );
+
             if !dest.is_indirect() {
                 self.assign_qualif_direct(dest, qualif);
             }
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 133772407c5..be461c0e03d 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -9,9 +9,10 @@ use rustc_errors::struct_span_err;
 use rustc_hir::{def_id::DefId, HirId};
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::{self, TraitEngine};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::{self, TraitEngine};
 
 use std::borrow::Cow;
 use std::ops::Deref;
@@ -212,7 +213,7 @@ impl Validator<'a, 'mir, 'tcx> {
 
         // If an operation is supported in miri (and is not already controlled by a feature gate) it
         // can be turned on with `-Zunleash-the-miri-inside-of-you`.
-        let is_unleashable = O::IS_SUPPORTED_IN_MIRI && O::feature_gate(self.tcx).is_none();
+        let is_unleashable = O::IS_SUPPORTED_IN_MIRI && O::feature_gate().is_none();
 
         if is_unleashable && self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
             self.tcx.sess.span_warn(span, "skipping const checks");
@@ -343,7 +344,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
             Rvalue::Ref(_, BorrowKind::Shared, ref place)
             | Rvalue::Ref(_, BorrowKind::Shallow, ref place)
             | Rvalue::AddressOf(Mutability::Not, ref place) => {
-                let borrowed_place_has_mut_interior = HasMutInterior::in_place(
+                let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
                     &self.item,
                     &mut |local| self.qualifs.has_mut_interior(local, location),
                     place.as_ref(),
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 4dcbcdcbae4..437a154a9b8 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -1,5 +1,3 @@
-use rustc::hir::map::Map;
-use rustc::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
 use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc::mir::*;
 use rustc::ty::cast::CastTy;
@@ -11,6 +9,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit;
 use rustc_hir::Node;
+use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
 use rustc_span::symbol::{sym, Symbol};
 
 use std::ops::Bound;
@@ -451,9 +450,9 @@ struct UnusedUnsafeVisitor<'a> {
 }
 
 impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
         intravisit::NestedVisitorMap::None
     }
 
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index a07c8575b30..ca23c44f646 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -4,7 +4,6 @@
 use std::borrow::Cow;
 use std::cell::Cell;
 
-use rustc::lint;
 use rustc::mir::interpret::{InterpResult, Scalar};
 use rustc::mir::visit::{
     MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
@@ -25,8 +24,9 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
 use rustc_hir::HirId;
 use rustc_index::vec::IndexVec;
-use rustc_infer::traits;
+use rustc_session::lint;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
 
 use crate::const_eval::error_to_const_error;
 use crate::interpret::{
@@ -197,7 +197,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
 
     fn assert_panic(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        _span: Span,
         _msg: &rustc::mir::AssertMessage<'tcx>,
         _unwind: Option<rustc::mir::BasicBlock>,
     ) -> InterpResult<'tcx> {
diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs
index 5dec2c6df99..795bcb57d06 100644
--- a/src/librustc_mir/transform/dump_mir.rs
+++ b/src/librustc_mir/transform/dump_mir.rs
@@ -8,8 +8,8 @@ use std::io;
 use crate::transform::{MirPass, MirSource};
 use crate::util as mir_util;
 use rustc::mir::{Body, BodyAndCache};
-use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::ty::TyCtxt;
+use rustc_session::config::{OutputFilenames, OutputType};
 
 pub struct Marker(pub &'static str);
 
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index d060a0eab3d..b2906739ff1 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -107,15 +107,15 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> {
     }
 
     fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) {
-        assert_ne!(*local, self_arg());
+        assert_ne!(*local, SELF_ARG);
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if place.local == self_arg() {
+        if place.local == SELF_ARG {
             replace_base(
                 place,
                 Place {
-                    local: self_arg(),
+                    local: SELF_ARG,
                     projection: self.tcx().intern_place_elems(&[ProjectionElem::Deref]),
                 },
                 self.tcx,
@@ -125,7 +125,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> {
 
             for elem in place.projection.iter() {
                 if let PlaceElem::Index(local) = elem {
-                    assert_ne!(*local, self_arg());
+                    assert_ne!(*local, SELF_ARG);
                 }
             }
         }
@@ -143,15 +143,15 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
     }
 
     fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) {
-        assert_ne!(*local, self_arg());
+        assert_ne!(*local, SELF_ARG);
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
-        if place.local == self_arg() {
+        if place.local == SELF_ARG {
             replace_base(
                 place,
                 Place {
-                    local: self_arg(),
+                    local: SELF_ARG,
                     projection: self.tcx().intern_place_elems(&[ProjectionElem::Field(
                         Field::new(0),
                         self.ref_gen_ty,
@@ -164,7 +164,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
 
             for elem in place.projection.iter() {
                 if let PlaceElem::Index(local) = elem {
-                    assert_ne!(*local, self_arg());
+                    assert_ne!(*local, SELF_ARG);
                 }
             }
         }
@@ -180,9 +180,7 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx
     place.projection = tcx.intern_place_elems(&new_projection);
 }
 
-fn self_arg() -> Local {
-    Local::new(1)
-}
+const SELF_ARG: Local = Local::from_u32(1);
 
 /// Generator has not been resumed yet.
 const UNRESUMED: usize = GeneratorSubsts::UNRESUMED;
@@ -237,7 +235,7 @@ impl TransformVisitor<'tcx> {
 
     // Create a Place referencing a generator struct field
     fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
-        let self_place = Place::from(self_arg());
+        let self_place = Place::from(SELF_ARG);
         let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index);
         let mut projection = base.projection.to_vec();
         projection.push(ProjectionElem::Field(Field::new(idx), ty));
@@ -247,7 +245,7 @@ impl TransformVisitor<'tcx> {
 
     // Create a statement which changes the discriminant
     fn set_discr(&self, state_disc: VariantIdx, source_info: SourceInfo) -> Statement<'tcx> {
-        let self_place = Place::from(self_arg());
+        let self_place = Place::from(SELF_ARG);
         Statement {
             source_info,
             kind: StatementKind::SetDiscriminant {
@@ -263,7 +261,7 @@ impl TransformVisitor<'tcx> {
         let local_decls_len = body.local_decls.push(temp_decl);
         let temp = Place::from(local_decls_len);
 
-        let self_place = Place::from(self_arg());
+        let self_place = Place::from(SELF_ARG);
         let assign = Statement {
             source_info: source_info(body),
             kind: StatementKind::Assign(box (temp, Rvalue::Discriminant(self_place))),
@@ -539,8 +537,8 @@ fn locals_live_across_suspend_points(
             let mut live_locals_here = storage_required;
             live_locals_here.intersect(&liveness.outs[block]);
 
-            // The generator argument is ignored
-            live_locals_here.remove(self_arg());
+            // The generator argument is ignored.
+            live_locals_here.remove(SELF_ARG);
 
             debug!("loc = {:?}, live_locals_here = {:?}", loc, live_locals_here);
 
@@ -837,7 +835,6 @@ fn elaborate_generator_drops<'tcx>(
     // generator's resume function.
 
     let param_env = tcx.param_env(def_id);
-    let gen = self_arg();
 
     let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env };
 
@@ -845,7 +842,7 @@ fn elaborate_generator_drops<'tcx>(
         let (target, unwind, source_info) = match block_data.terminator() {
             Terminator { source_info, kind: TerminatorKind::Drop { location, target, unwind } } => {
                 if let Some(local) = location.as_local() {
-                    if local == gen {
+                    if local == SELF_ARG {
                         (target, unwind, source_info)
                     } else {
                         continue;
@@ -864,7 +861,7 @@ fn elaborate_generator_drops<'tcx>(
         elaborate_drop(
             &mut elaborator,
             *source_info,
-            &Place::from(gen),
+            &Place::from(SELF_ARG),
             (),
             *target,
             unwind,
@@ -918,7 +915,7 @@ fn create_generator_drop_shim<'tcx>(
     make_generator_state_argument_indirect(tcx, def_id, &mut body);
 
     // Change the generator argument from &mut to *mut
-    body.local_decls[self_arg()] = LocalDecl {
+    body.local_decls[SELF_ARG] = LocalDecl {
         mutability: Mutability::Mut,
         ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
         user_ty: UserTypeProjections::none(),
@@ -933,7 +930,7 @@ fn create_generator_drop_shim<'tcx>(
             0,
             Statement {
                 source_info,
-                kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())),
+                kind: StatementKind::Retag(RetagKind::Raw, box Place::from(SELF_ARG)),
             },
         )
     }
@@ -944,7 +941,7 @@ fn create_generator_drop_shim<'tcx>(
     // unrelated code from the resume part of the function
     simplify::remove_dead_blocks(&mut body);
 
-    dump_mir(tcx, None, "generator_drop", &0, source, &mut body, |_, _| Ok(()));
+    dump_mir(tcx, None, "generator_drop", &0, source, &body, |_, _| Ok(()));
 
     body
 }
@@ -991,18 +988,101 @@ fn insert_panic_block<'tcx>(
     assert_block
 }
 
+fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
+    // Returning from a function with an uninhabited return type is undefined behavior.
+    if body.return_ty().conservative_is_privately_uninhabited(tcx) {
+        return false;
+    }
+
+    // If there's a return terminator the function may return.
+    for block in body.basic_blocks() {
+        if let TerminatorKind::Return = block.terminator().kind {
+            return true;
+        }
+    }
+
+    // Otherwise the function can't return.
+    false
+}
+
+fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
+    // Nothing can unwind when landing pads are off.
+    if tcx.sess.no_landing_pads() {
+        return false;
+    }
+
+    // Unwinds can only start at certain terminators.
+    for block in body.basic_blocks() {
+        match block.terminator().kind {
+            // These never unwind.
+            TerminatorKind::Goto { .. }
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::Abort
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseUnwind { .. } => {}
+
+            // Resume will *continue* unwinding, but if there's no other unwinding terminator it
+            // will never be reached.
+            TerminatorKind::Resume => {}
+
+            TerminatorKind::Yield { .. } => {
+                unreachable!("`can_unwind` called before generator transform")
+            }
+
+            // These may unwind.
+            TerminatorKind::Drop { .. }
+            | TerminatorKind::DropAndReplace { .. }
+            | TerminatorKind::Call { .. }
+            | TerminatorKind::Assert { .. } => return true,
+        }
+    }
+
+    // If we didn't find an unwinding terminator, the function cannot unwind.
+    false
+}
+
 fn create_generator_resume_function<'tcx>(
     tcx: TyCtxt<'tcx>,
     transform: TransformVisitor<'tcx>,
     def_id: DefId,
     source: MirSource<'tcx>,
     body: &mut BodyAndCache<'tcx>,
+    can_return: bool,
 ) {
+    let can_unwind = can_unwind(tcx, body);
+
     // Poison the generator when it unwinds
-    for block in body.basic_blocks_mut() {
-        let source_info = block.terminator().source_info;
-        if let &TerminatorKind::Resume = &block.terminator().kind {
-            block.statements.push(transform.set_discr(VariantIdx::new(POISONED), source_info));
+    if can_unwind {
+        let poison_block = BasicBlock::new(body.basic_blocks().len());
+        let source_info = source_info(body);
+        body.basic_blocks_mut().push(BasicBlockData {
+            statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)],
+            terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }),
+            is_cleanup: true,
+        });
+
+        for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() {
+            let source_info = block.terminator().source_info;
+
+            if let TerminatorKind::Resume = block.terminator().kind {
+                // An existing `Resume` terminator is redirected to jump to our dedicated
+                // "poisoning block" above.
+                if idx != poison_block {
+                    *block.terminator_mut() = Terminator {
+                        source_info,
+                        kind: TerminatorKind::Goto { target: poison_block },
+                    };
+                }
+            } else if !block.is_cleanup {
+                // Any terminators that *can* unwind but don't have an unwind target set are also
+                // pointed at our poisoning block (unless they're part of the cleanup path).
+                if let Some(unwind @ None) = block.terminator_mut().unwind_mut() {
+                    *unwind = Some(poison_block);
+                }
+            }
         }
     }
 
@@ -1015,8 +1095,20 @@ fn create_generator_resume_function<'tcx>(
 
     // Panic when resumed on the returned or poisoned state
     let generator_kind = body.generator_kind.unwrap();
-    cases.insert(1, (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))));
-    cases.insert(2, (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))));
+
+    if can_unwind {
+        cases.insert(
+            1,
+            (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))),
+        );
+    }
+
+    if can_return {
+        cases.insert(
+            1,
+            (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))),
+        );
+    }
 
     insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
 
@@ -1042,7 +1134,7 @@ fn insert_clean_drop(body: &mut BodyAndCache<'_>) -> BasicBlock {
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
     let drop_clean = BasicBlock::new(body.basic_blocks().len());
     let term = TerminatorKind::Drop {
-        location: Place::from(self_arg()),
+        location: Place::from(SELF_ARG),
         target: return_block,
         unwind: None,
     };
@@ -1200,6 +1292,8 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         let (remap, layout, storage_liveness) =
             compute_layout(tcx, source, &upvars, interior, movable, body);
 
+        let can_return = can_return(tcx, body);
+
         // Run the transformation which converts Places from Local to generator struct
         // accesses for locals in `remap`.
         // It also rewrites `return x` and `yield y` as writing a new generator state and returning
@@ -1243,6 +1337,6 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         body.generator_drop = Some(box drop_shim);
 
         // Create the Generator::resume function
-        create_generator_resume_function(tcx, transform, def_id, source, body);
+        create_generator_resume_function(tcx, transform, def_id, source, body, can_return);
     }
 }
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index b6802505df7..769f3fdcc01 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -1,25 +1,22 @@
 //! Inlining pass for MIR functions
 
-use rustc_hir::def_id::DefId;
-
-use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
-
 use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc::mir::visit::*;
 use rustc::mir::*;
-use rustc::session::config::Sanitizer;
 use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
+use rustc_attr as attr;
+use rustc_hir::def_id::DefId;
+use rustc_index::bit_set::BitSet;
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_session::config::Sanitizer;
+use rustc_target::spec::abi::Abi;
 
 use super::simplify::{remove_dead_blocks, CfgSimplifier};
 use crate::transform::{MirPass, MirSource};
 use std::collections::VecDeque;
 use std::iter;
 
-use rustc_attr as attr;
-use rustc_target::spec::abi::Abi;
-
 const DEFAULT_THRESHOLD: usize = 50;
 const HINT_THRESHOLD: usize = 100;
 
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 57e002bf3f3..3eb9d23a32a 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -1,5 +1,4 @@
 use crate::{shim, util};
-use rustc::hir::map::Map;
 use rustc::mir::{BodyAndCache, ConstQualifs, MirPhase, Promoted};
 use rustc::ty::query::Providers;
 use rustc::ty::steal::Steal;
@@ -86,8 +85,8 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet {
             }
             intravisit::walk_struct_def(self, v)
         }
-        type Map = Map<'tcx>;
-        fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, Self::Map> {
+        type Map = intravisit::ErasedMap<'tcx>;
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
     }
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 7dd134a35d9..1336206e186 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -407,15 +407,17 @@ impl<'tcx> Validator<'_, 'tcx> {
 
     // FIXME(eddyb) maybe cache this?
     fn qualif_local<Q: qualifs::Qualif>(&self, local: Local) -> bool {
-        let per_local = &mut |l| self.qualif_local::<Q>(l);
-
         if let TempState::Defined { location: loc, .. } = self.temps[local] {
             let num_stmts = self.body[loc.block].statements.len();
 
             if loc.statement_index < num_stmts {
                 let statement = &self.body[loc.block].statements[loc.statement_index];
                 match &statement.kind {
-                    StatementKind::Assign(box (_, rhs)) => Q::in_rvalue(&self.item, per_local, rhs),
+                    StatementKind::Assign(box (_, rhs)) => qualifs::in_rvalue::<Q, _>(
+                        &self.item,
+                        &mut |l| self.qualif_local::<Q>(l),
+                        rhs,
+                    ),
                     _ => {
                         span_bug!(
                             statement.source_info.span,
@@ -427,9 +429,9 @@ impl<'tcx> Validator<'_, 'tcx> {
             } else {
                 let terminator = self.body[loc.block].terminator();
                 match &terminator.kind {
-                    TerminatorKind::Call { func, args, .. } => {
+                    TerminatorKind::Call { .. } => {
                         let return_ty = self.body.local_decls[local].ty;
-                        Q::in_call(&self.item, per_local, func, args, return_ty)
+                        Q::in_any_value_of_ty(&self.item, return_ty)
                     }
                     kind => {
                         span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index 597d3f0237a..4c54a46642f 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -95,6 +95,11 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
 
         let mut start = START_BLOCK;
 
+        // Vec of the blocks that should be merged. We store the indices here, instead of the
+        // statements itself to avoid moving the (relatively) large statements twice.
+        // We do not push the statements directly into the target block (`bb`) as that is slower
+        // due to additional reallocations
+        let mut merged_blocks = Vec::new();
         loop {
             let mut changed = false;
 
@@ -114,18 +119,28 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
                     self.collapse_goto_chain(successor, &mut changed);
                 }
 
-                let mut new_stmts = vec![];
                 let mut inner_changed = true;
+                merged_blocks.clear();
                 while inner_changed {
                     inner_changed = false;
                     inner_changed |= self.simplify_branch(&mut terminator);
-                    inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator);
+                    inner_changed |= self.merge_successor(&mut merged_blocks, &mut terminator);
                     changed |= inner_changed;
                 }
 
-                let data = &mut self.basic_blocks[bb];
-                data.statements.extend(new_stmts);
-                data.terminator = Some(terminator);
+                let statements_to_merge =
+                    merged_blocks.iter().map(|&i| self.basic_blocks[i].statements.len()).sum();
+
+                if statements_to_merge > 0 {
+                    let mut statements = std::mem::take(&mut self.basic_blocks[bb].statements);
+                    statements.reserve(statements_to_merge);
+                    for &from in &merged_blocks {
+                        statements.append(&mut self.basic_blocks[from].statements);
+                    }
+                    self.basic_blocks[bb].statements = statements;
+                }
+
+                self.basic_blocks[bb].terminator = Some(terminator);
 
                 changed |= inner_changed;
             }
@@ -199,7 +214,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
     // merge a block with 1 `goto` predecessor to its parent
     fn merge_successor(
         &mut self,
-        new_stmts: &mut Vec<Statement<'tcx>>,
+        merged_blocks: &mut Vec<BasicBlock>,
         terminator: &mut Terminator<'tcx>,
     ) -> bool {
         let target = match terminator.kind {
@@ -216,7 +231,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
                 return false;
             }
         };
-        new_stmts.extend(self.basic_blocks[target].statements.drain(..));
+
+        merged_blocks.push(target);
         self.pred_count[target] = 0;
 
         true
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index b12ad1e4c15..f6c6f555495 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -293,7 +293,7 @@ fn dump_matched_mir_node<'tcx>(
         writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?;
         writeln!(file, "// source = {:?}", source)?;
         writeln!(file, "// pass_name = {}", pass_name)?;
-        writeln!(file, "")?;
+        writeln!(file)?;
         write_mir_fn(tcx, source, body, &mut file, result)?;
         Ok(())
     });
@@ -316,7 +316,7 @@ pub fn write_mir_fn<'tcx>(
         write_basic_block(tcx, block, body, &mut |_, _| Ok(()), w)?;
         print(w, "   ", &result.outs)?;
         if block.index() + 1 != body.basic_blocks().len() {
-            writeln!(w, "")?;
+            writeln!(w)?;
         }
     }
 
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 416a5bd7d22..f8dfddef2bb 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -134,7 +134,7 @@ fn dump_matched_mir_node<'tcx, F>(
         if let Some(ref layout) = body.generator_layout {
             writeln!(file, "// generator_layout = {:?}", layout)?;
         }
-        writeln!(file, "")?;
+        writeln!(file)?;
         extra_data(PassWhere::BeforeCFG, &mut file)?;
         write_user_type_annotations(body, &mut file)?;
         write_mir_fn(tcx, source, body, &mut extra_data, &mut file)?;
@@ -242,13 +242,13 @@ pub fn write_mir_pretty<'tcx>(
             first = false;
         } else {
             // Put empty lines between all items
-            writeln!(w, "")?;
+            writeln!(w)?;
         }
 
         write_mir_fn(tcx, MirSource::item(def_id), body, &mut |_, _| Ok(()), w)?;
 
         for (i, body) in tcx.promoted_mir(def_id).iter_enumerated() {
-            writeln!(w, "")?;
+            writeln!(w)?;
             let src = MirSource { instance: ty::InstanceDef::Item(def_id), promoted: Some(i) };
             write_mir_fn(tcx, src, body, &mut |_, _| Ok(()), w)?;
         }
@@ -271,7 +271,7 @@ where
         extra_data(PassWhere::BeforeBlock(block), w)?;
         write_basic_block(tcx, block, body, extra_data, w)?;
         if block.index() + 1 != body.basic_blocks().len() {
-            writeln!(w, "")?;
+            writeln!(w)?;
         }
     }
 
@@ -529,7 +529,7 @@ pub fn write_mir_intro<'tcx>(
     write_scope_tree(tcx, body, &scope_tree, w, OUTERMOST_SOURCE_SCOPE, 1)?;
 
     // Add an empty line before the first block is printed.
-    writeln!(w, "")?;
+    writeln!(w)?;
 
     Ok(())
 }
@@ -545,7 +545,7 @@ fn write_mir_sig(
     trace!("write_mir_sig: {:?}", src.instance);
     let kind = tcx.def_kind(src.def_id());
     let is_function = match kind {
-        Some(DefKind::Fn) | Some(DefKind::Method) | Some(DefKind::Ctor(..)) => true,
+        Some(DefKind::Fn) | Some(DefKind::AssocFn) | Some(DefKind::Ctor(..)) => true,
         _ => tcx.is_closure(src.def_id()),
     };
     match (kind, src.promoted) {
diff --git a/src/librustc_mir_build/Cargo.toml b/src/librustc_mir_build/Cargo.toml
index d53188a39e5..96716dbd604 100644
--- a/src/librustc_mir_build/Cargo.toml
+++ b/src/librustc_mir_build/Cargo.toml
@@ -25,5 +25,6 @@ rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rustc_target = { path = "../librustc_target" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
 rustc_ast = { path = "../librustc_ast" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/librustc_mir_build/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs
index 80fa0c44860..aea4f5f1b3a 100644
--- a/src/librustc_mir_build/build/matches/simplify.rs
+++ b/src/librustc_mir_build/build/matches/simplify.rs
@@ -209,7 +209,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     i == variant_index || {
                         self.hir.tcx().features().exhaustive_patterns
                             && !v
-                                .uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind())
+                                .uninhabited_from(
+                                    self.hir.tcx(),
+                                    substs,
+                                    adt_def.adt_kind(),
+                                    self.hir.param_env,
+                                )
                                 .is_empty()
                     }
                 }) && (adt_def.did.is_local()
diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs
index b60a637471e..821c4d68c7e 100644
--- a/src/librustc_mir_build/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -39,12 +39,12 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
             ..
         })
         | Node::ImplItem(hir::ImplItem {
-            kind: hir::ImplItemKind::Method(hir::FnSig { decl, .. }, body_id),
+            kind: hir::ImplItemKind::Fn(hir::FnSig { decl, .. }, body_id),
             ..
         })
         | Node::TraitItem(hir::TraitItem {
             kind:
-                hir::TraitItemKind::Method(hir::FnSig { decl, .. }, hir::TraitMethod::Provided(body_id)),
+                hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)),
             ..
         }) => (*body_id, decl.output.span()),
         Node::Item(hir::Item { kind: hir::ItemKind::Static(ty, _, body_id), .. })
diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
index 46d49b6b493..02b596863ab 100644
--- a/src/librustc_mir_build/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -10,7 +10,6 @@ use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::{self, AdtKind, Ty};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::def_id::LocalDefId;
 use rustc_index::vec::Idx;
 use rustc_span::Span;
 
@@ -600,7 +599,7 @@ fn user_substs_applied_to_res<'tcx>(
         // a tuple-struct or tuple-variant. This has the type of a
         // `Fn` but with the user-given substitutions.
         Res::Def(DefKind::Fn, _)
-        | Res::Def(DefKind::Method, _)
+        | Res::Def(DefKind::AssocFn, _)
         | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
         | Res::Def(DefKind::Const, _)
         | Res::Def(DefKind::AssocConst, _) => {
@@ -703,7 +702,7 @@ fn convert_path_expr<'a, 'tcx>(
     match res {
         // A regular function, constructor function or a constant.
         Res::Def(DefKind::Fn, _)
-        | Res::Def(DefKind::Method, _)
+        | Res::Def(DefKind::AssocFn, _)
         | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
         | Res::SelfCtor(..) => {
             let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res);
@@ -812,7 +811,7 @@ fn convert_var<'tcx>(
             let closure_def_id = cx.body_owner;
             let upvar_id = ty::UpvarId {
                 var_path: ty::UpvarPath { hir_id: var_hir_id },
-                closure_expr_id: LocalDefId::from_def_id(closure_def_id),
+                closure_expr_id: closure_def_id.expect_local(),
             };
             let var_ty = cx.tables().node_type(var_hir_id);
 
@@ -987,7 +986,7 @@ fn capture_upvar<'tcx>(
 ) -> ExprRef<'tcx> {
     let upvar_id = ty::UpvarId {
         var_path: ty::UpvarPath { hir_id: var_hir_id },
-        closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id).to_local(),
+        closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id).expect_local(),
     };
     let upvar_capture = cx.tables().upvar_capture(upvar_id);
     let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
diff --git a/src/librustc_mir_build/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs
index 449e2e74946..99caa6a0f95 100644
--- a/src/librustc_mir_build/hair/cx/mod.rs
+++ b/src/librustc_mir_build/hair/cx/mod.rs
@@ -19,6 +19,7 @@ use rustc_hir::Node;
 use rustc_index::vec::Idx;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::symbol::{sym, Symbol};
+use rustc_trait_selection::infer::InferCtxtExt;
 
 #[derive(Clone)]
 crate struct Cx<'a, 'tcx> {
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
index 37ad5f5ea4e..82810f35675 100644
--- a/src/librustc_mir_build/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -235,17 +235,15 @@ use rustc_index::vec::Idx;
 use super::{compare_const_vals, PatternFoldable, PatternFolder};
 use super::{FieldPat, Pat, PatKind, PatRange};
 
-use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx};
-use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
-use rustc_hir::def_id::DefId;
-use rustc_hir::{HirId, RangeEnd};
-
-use rustc::lint;
 use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
 use rustc::mir::Field;
+use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx};
+use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
 use rustc::util::common::ErrorReported;
-
 use rustc_attr::{SignedInt, UnsignedInt};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{HirId, RangeEnd};
+use rustc_session::lint;
 use rustc_span::{Span, DUMMY_SP};
 
 use arena::TypedArena;
@@ -598,7 +596,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
 
     fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
         if self.tcx.features().exhaustive_patterns {
-            self.tcx.is_ty_uninhabited_from(self.module, ty)
+            self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env)
         } else {
             false
         }
@@ -1267,7 +1265,7 @@ fn all_constructors<'a, 'tcx>(
                 def.variants
                     .iter()
                     .filter(|v| {
-                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind())
+                        !v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
                             .contains(cx.tcx, cx.module)
                     })
                     .map(|v| Variant(v.def_id))
diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs
index d0eefb2e4d1..9c86669cf9d 100644
--- a/src/librustc_mir_build/hair/pattern/check_match.rs
+++ b/src/librustc_mir_build/hair/pattern/check_match.rs
@@ -4,7 +4,6 @@ use super::_match::{expand_pattern, is_useful, MatchCheckCtxt, Matrix, PatStack}
 
 use super::{PatCtxt, PatKind, PatternError};
 
-use rustc::hir::map::Map;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_ast::ast::Mutability;
 use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
@@ -43,9 +42,9 @@ struct MatchVisitor<'a, 'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -87,6 +86,9 @@ impl PatCtxt<'_, '_> {
                 PatternError::AssocConstInPattern(span) => {
                     self.span_e0158(span, "associated consts cannot be referenced in patterns")
                 }
+                PatternError::ConstParamInPattern(span) => {
+                    self.span_e0158(span, "const parameters cannot be referenced in patterns")
+                }
                 PatternError::FloatBug => {
                     // FIXME(#31407) this is only necessary because float parsing is buggy
                     ::rustc::mir::interpret::struct_error(
@@ -143,7 +145,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
 
     fn check_in_cx(&self, hir_id: HirId, f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>)) {
         let module = self.tcx.parent_module(hir_id);
-        MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |cx| f(cx));
+        MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module.to_def_id(), |cx| f(cx));
     }
 
     fn check_match(
@@ -750,9 +752,9 @@ fn check_legality_of_bindings_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pa
     }
 
     impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> {
-        type Map = Map<'v>;
+        type Map = intravisit::ErasedMap<'v>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
index 27d1bce76ed..ae951e810e3 100644
--- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
@@ -1,14 +1,13 @@
-use rustc::lint;
 use rustc::mir::Field;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_hir as hir;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::predicate_for_trait_def;
-use rustc_infer::traits::{self, ObligationCause, PredicateObligation};
-
 use rustc_index::vec::Idx;
-
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_session::lint;
 use rustc_span::Span;
+use rustc_trait_selection::traits::predicate_for_trait_def;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation};
 
 use std::cell::Cell;
 
@@ -181,7 +180,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
         let kind = match cv.ty.kind {
             ty::Float(_) => {
                 tcx.struct_span_lint_hir(
-                    ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+                    lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
                     id,
                     span,
                     |lint| lint.build("floating-point types cannot be used in patterns").emit(),
diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs
index f58216fbb4e..6786c356293 100644
--- a/src/librustc_mir_build/hair/pattern/mod.rs
+++ b/src/librustc_mir_build/hair/pattern/mod.rs
@@ -31,6 +31,7 @@ use std::fmt;
 #[derive(Clone, Debug)]
 crate enum PatternError {
     AssocConstInPattern(Span),
+    ConstParamInPattern(Span),
     StaticInPattern(Span),
     FloatBug,
     NonConstPath(Span),
@@ -727,7 +728,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
 
             _ => {
-                self.errors.push(PatternError::NonConstPath(span));
+                let pattern_error = match res {
+                    Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
+                    _ => PatternError::NonConstPath(span),
+                };
+                self.errors.push(pattern_error);
                 PatKind::Wild
             }
         };
diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs
index 3c35827d15d..5a8b5a32963 100644
--- a/src/librustc_mir_build/lib.rs
+++ b/src/librustc_mir_build/lib.rs
@@ -4,6 +4,9 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
 #![feature(bool_to_option)]
 #![recursion_limit = "256"]
diff --git a/src/librustc_mir_build/lints.rs b/src/librustc_mir_build/lints.rs
index 0017f800de7..8b1ddf7461a 100644
--- a/src/librustc_mir_build/lints.rs
+++ b/src/librustc_mir_build/lints.rs
@@ -1,11 +1,11 @@
 use rustc::hir::map::blocks::FnLikeNode;
-use rustc::lint::builtin::UNCONDITIONAL_RECURSION;
 use rustc::mir::{self, Body, TerminatorKind};
 use rustc::ty::subst::InternalSubsts;
 use rustc::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::FnKind;
 use rustc_index::bit_set::BitSet;
+use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
 
 crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index 10d524776a1..c31cc1b4c9f 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -2,6 +2,8 @@
 
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
+#![feature(bindings_after_at)]
+#![feature(try_blocks)]
 
 use rustc_ast::ast;
 use rustc_ast::token::{self, Nonterminal};
@@ -12,7 +14,7 @@ use rustc_errors::{Diagnostic, FatalError, Level, PResult};
 use rustc_session::parse::ParseSess;
 use rustc_span::{FileName, SourceFile, Span};
 
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::str;
 
 use log::info;
@@ -24,24 +26,6 @@ pub mod parser;
 use parser::{emit_unclosed_delims, make_unclosed_delims_error, Parser};
 pub mod lexer;
 pub mod validate_attr;
-#[macro_use]
-pub mod config;
-
-#[derive(Clone)]
-pub struct Directory {
-    pub path: PathBuf,
-    pub ownership: DirectoryOwnership,
-}
-
-#[derive(Copy, Clone)]
-pub enum DirectoryOwnership {
-    Owned {
-        // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`.
-        relative: Option<ast::Ident>,
-    },
-    UnownedViaBlock,
-    UnownedViaMod,
-}
 
 // A bunch of utility functions of the form `parse_<thing>_from_<source>`
 // where <thing> includes crate, expr, item, stmt, tts, and one that
@@ -118,10 +102,7 @@ pub fn maybe_new_parser_from_source_str(
     name: FileName,
     source: String,
 ) -> Result<Parser<'_>, Vec<Diagnostic>> {
-    let mut parser =
-        maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))?;
-    parser.recurse_into_file_modules = false;
-    Ok(parser)
+    maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))
 }
 
 /// Creates a new parser, handling errors as appropriate if the file doesn't exist.
@@ -145,12 +126,10 @@ pub fn maybe_new_parser_from_file<'a>(
 pub fn new_sub_parser_from_file<'a>(
     sess: &'a ParseSess,
     path: &Path,
-    directory_ownership: DirectoryOwnership,
     module_name: Option<String>,
     sp: Span,
 ) -> Parser<'a> {
     let mut p = source_file_to_parser(sess, file_to_source_file(sess, path, Some(sp)));
-    p.directory.ownership = directory_ownership;
     p.root_module_name = module_name;
     p
 }
@@ -256,26 +235,7 @@ pub fn stream_to_parser<'a>(
     stream: TokenStream,
     subparser_name: Option<&'static str>,
 ) -> Parser<'a> {
-    Parser::new(sess, stream, None, true, false, subparser_name)
-}
-
-/// Given a stream, the `ParseSess` and the base directory, produces a parser.
-///
-/// Use this function when you are creating a parser from the token stream
-/// and also care about the current working directory of the parser (e.g.,
-/// you are trying to resolve modules defined inside a macro invocation).
-///
-/// # Note
-///
-/// The main usage of this function is outside of rustc, for those who uses
-/// librustc_ast as a library. Please do not remove this function while refactoring
-/// just because it is not used in rustc codebase!
-pub fn stream_to_parser_with_base_dir<'a>(
-    sess: &'a ParseSess,
-    stream: TokenStream,
-    base_dir: Directory,
-) -> Parser<'a> {
-    Parser::new(sess, stream, Some(base_dir), true, false, None)
+    Parser::new(sess, stream, false, subparser_name)
 }
 
 /// Runs the given subparser `f` on the tokens of the given `attr`'s item.
@@ -285,7 +245,7 @@ pub fn parse_in<'a, T>(
     name: &'static str,
     mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
 ) -> PResult<'a, T> {
-    let mut parser = Parser::new(sess, tts, None, false, false, Some(name));
+    let mut parser = Parser::new(sess, tts, false, Some(name));
     let result = f(&mut parser)?;
     if parser.token != token::Eof {
         parser.unexpected()?;
diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs
index bdd78e671a8..b56dd30739d 100644
--- a/src/librustc_parse/parser/attr.rs
+++ b/src/librustc_parse/parser/attr.rs
@@ -1,4 +1,4 @@
-use super::{Parser, PathStyle, TokenType};
+use super::{Parser, PathStyle};
 use rustc_ast::ast;
 use rustc_ast::attr;
 use rustc_ast::token::{self, Nonterminal};
@@ -10,14 +10,20 @@ use rustc_span::{Span, Symbol};
 use log::debug;
 
 #[derive(Debug)]
-enum InnerAttributeParsePolicy<'a> {
+pub(super) enum InnerAttrPolicy<'a> {
     Permitted,
-    NotPermitted { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
+    Forbidden { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
 }
 
 const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
                                                      permitted in this context";
 
+pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden {
+    reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
+    saw_doc_comment: false,
+    prev_attr_sp: None,
+};
+
 impl<'a> Parser<'a> {
     /// Parses attributes that appear before an item.
     pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
@@ -25,48 +31,44 @@ impl<'a> Parser<'a> {
         let mut just_parsed_doc_comment = false;
         loop {
             debug!("parse_outer_attributes: self.token={:?}", self.token);
-            match self.token.kind {
-                token::Pound => {
-                    let inner_error_reason = if just_parsed_doc_comment {
-                        "an inner attribute is not permitted following an outer doc comment"
-                    } else if !attrs.is_empty() {
-                        "an inner attribute is not permitted following an outer attribute"
-                    } else {
-                        DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
-                    };
-                    let inner_parse_policy = InnerAttributeParsePolicy::NotPermitted {
-                        reason: inner_error_reason,
-                        saw_doc_comment: just_parsed_doc_comment,
-                        prev_attr_sp: attrs.last().map(|a| a.span),
-                    };
-                    let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
-                    attrs.push(attr);
-                    just_parsed_doc_comment = false;
-                }
-                token::DocComment(s) => {
-                    let attr = self.mk_doc_comment(s);
-                    if attr.style != ast::AttrStyle::Outer {
-                        let span = self.token.span;
-                        let mut err = self.struct_span_err(span, "expected outer doc comment");
-                        err.note(
+            if self.check(&token::Pound) {
+                let inner_error_reason = if just_parsed_doc_comment {
+                    "an inner attribute is not permitted following an outer doc comment"
+                } else if !attrs.is_empty() {
+                    "an inner attribute is not permitted following an outer attribute"
+                } else {
+                    DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
+                };
+                let inner_parse_policy = InnerAttrPolicy::Forbidden {
+                    reason: inner_error_reason,
+                    saw_doc_comment: just_parsed_doc_comment,
+                    prev_attr_sp: attrs.last().map(|a| a.span),
+                };
+                let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
+                attrs.push(attr);
+                just_parsed_doc_comment = false;
+            } else if let token::DocComment(s) = self.token.kind {
+                let attr = self.mk_doc_comment(s);
+                if attr.style != ast::AttrStyle::Outer {
+                    self.struct_span_err(self.token.span, "expected outer doc comment")
+                        .note(
                             "inner doc comments like this (starting with \
-                                  `//!` or `/*!`) can only appear before items",
-                        );
-                        return Err(err);
-                    }
-                    attrs.push(attr);
-                    self.bump();
-                    just_parsed_doc_comment = true;
+                              `//!` or `/*!`) can only appear before items",
+                        )
+                        .emit();
                 }
-                _ => break,
+                attrs.push(attr);
+                self.bump();
+                just_parsed_doc_comment = true;
+            } else {
+                break;
             }
         }
         Ok(attrs)
     }
 
     fn mk_doc_comment(&self, s: Symbol) -> ast::Attribute {
-        let style = comments::doc_comment_style(&s.as_str());
-        attr::mk_doc_comment(style, s, self.token.span)
+        attr::mk_doc_comment(comments::doc_comment_style(&s.as_str()), s, self.token.span)
     }
 
     /// Matches `attribute = # ! [ meta_item ]`.
@@ -75,96 +77,67 @@ impl<'a> Parser<'a> {
     /// attribute.
     pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> {
         debug!("parse_attribute: permit_inner={:?} self.token={:?}", permit_inner, self.token);
-        let inner_parse_policy = if permit_inner {
-            InnerAttributeParsePolicy::Permitted
-        } else {
-            InnerAttributeParsePolicy::NotPermitted {
-                reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
-                saw_doc_comment: false,
-                prev_attr_sp: None,
-            }
-        };
+        let inner_parse_policy =
+            if permit_inner { InnerAttrPolicy::Permitted } else { DEFAULT_INNER_ATTR_FORBIDDEN };
         self.parse_attribute_with_inner_parse_policy(inner_parse_policy)
     }
 
-    /// The same as `parse_attribute`, except it takes in an `InnerAttributeParsePolicy`
+    /// The same as `parse_attribute`, except it takes in an `InnerAttrPolicy`
     /// that prescribes how to handle inner attributes.
     fn parse_attribute_with_inner_parse_policy(
         &mut self,
-        inner_parse_policy: InnerAttributeParsePolicy<'_>,
+        inner_parse_policy: InnerAttrPolicy<'_>,
     ) -> PResult<'a, ast::Attribute> {
         debug!(
             "parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}",
             inner_parse_policy, self.token
         );
-        let (span, item, style) = match self.token.kind {
-            token::Pound => {
-                let lo = self.token.span;
-                self.bump();
-
-                if let InnerAttributeParsePolicy::Permitted = inner_parse_policy {
-                    self.expected_tokens.push(TokenType::Token(token::Not));
-                }
-
-                let style = if self.token == token::Not {
-                    self.bump();
-                    ast::AttrStyle::Inner
-                } else {
-                    ast::AttrStyle::Outer
-                };
+        let lo = self.token.span;
+        let (span, item, style) = if self.eat(&token::Pound) {
+            let style =
+                if self.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
 
-                self.expect(&token::OpenDelim(token::Bracket))?;
-                let item = self.parse_attr_item()?;
-                self.expect(&token::CloseDelim(token::Bracket))?;
-                let hi = self.prev_token.span;
-
-                let attr_sp = lo.to(hi);
-
-                // Emit error if inner attribute is encountered and not permitted
-                if style == ast::AttrStyle::Inner {
-                    if let InnerAttributeParsePolicy::NotPermitted {
-                        reason,
-                        saw_doc_comment,
-                        prev_attr_sp,
-                    } = inner_parse_policy
-                    {
-                        let prev_attr_note = if saw_doc_comment {
-                            "previous doc comment"
-                        } else {
-                            "previous outer attribute"
-                        };
-
-                        let mut diagnostic = self.struct_span_err(attr_sp, reason);
-
-                        if let Some(prev_attr_sp) = prev_attr_sp {
-                            diagnostic
-                                .span_label(attr_sp, "not permitted following an outer attribute")
-                                .span_label(prev_attr_sp, prev_attr_note);
-                        }
-
-                        diagnostic
-                            .note(
-                                "inner attributes, like `#![no_std]`, annotate the item \
-                                   enclosing them, and are usually found at the beginning of \
-                                   source files. Outer attributes, like `#[test]`, annotate the \
-                                   item following them.",
-                            )
-                            .emit();
-                    }
-                }
+            self.expect(&token::OpenDelim(token::Bracket))?;
+            let item = self.parse_attr_item()?;
+            self.expect(&token::CloseDelim(token::Bracket))?;
+            let attr_sp = lo.to(self.prev_token.span);
 
-                (attr_sp, item, style)
-            }
-            _ => {
-                let token_str = pprust::token_to_string(&self.token);
-                let msg = &format!("expected `#`, found `{}`", token_str);
-                return Err(self.struct_span_err(self.token.span, msg));
+            // Emit error if inner attribute is encountered and forbidden.
+            if style == ast::AttrStyle::Inner {
+                self.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
             }
+
+            (attr_sp, item, style)
+        } else {
+            let token_str = pprust::token_to_string(&self.token);
+            let msg = &format!("expected `#`, found `{}`", token_str);
+            return Err(self.struct_span_err(self.token.span, msg));
         };
 
         Ok(attr::mk_attr_from_item(style, item, span))
     }
 
+    pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) {
+        if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy {
+            let prev_attr_note =
+                if saw_doc_comment { "previous doc comment" } else { "previous outer attribute" };
+
+            let mut diag = self.struct_span_err(attr_sp, reason);
+
+            if let Some(prev_attr_sp) = prev_attr_sp {
+                diag.span_label(attr_sp, "not permitted following an outer attribute")
+                    .span_label(prev_attr_sp, prev_attr_note);
+            }
+
+            diag.note(
+                "inner attributes, like `#![no_std]`, annotate the item enclosing them, \
+                and are usually found at the beginning of source files. \
+                Outer attributes, like `#[test]`, annotate the item following them.",
+            )
+            .emit();
+        }
+    }
+
     /// Parses an inner part of an attribute (the path and following tokens).
     /// The tokens must be either a delimited token stream, or empty token stream,
     /// or the "legacy" key-value form.
@@ -200,28 +173,22 @@ impl<'a> Parser<'a> {
     crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
         let mut attrs: Vec<ast::Attribute> = vec![];
         loop {
-            match self.token.kind {
-                token::Pound => {
-                    // Don't even try to parse if it's not an inner attribute.
-                    if !self.look_ahead(1, |t| t == &token::Not) {
-                        break;
-                    }
-
-                    let attr = self.parse_attribute(true)?;
-                    assert_eq!(attr.style, ast::AttrStyle::Inner);
+            // Only try to parse if it is an inner attribute (has `!`).
+            if self.check(&token::Pound) && self.look_ahead(1, |t| t == &token::Not) {
+                let attr = self.parse_attribute(true)?;
+                assert_eq!(attr.style, ast::AttrStyle::Inner);
+                attrs.push(attr);
+            } else if let token::DocComment(s) = self.token.kind {
+                // We need to get the position of this token before we bump.
+                let attr = self.mk_doc_comment(s);
+                if attr.style == ast::AttrStyle::Inner {
                     attrs.push(attr);
+                    self.bump();
+                } else {
+                    break;
                 }
-                token::DocComment(s) => {
-                    // We need to get the position of this token before we bump.
-                    let attr = self.mk_doc_comment(s);
-                    if attr.style == ast::AttrStyle::Inner {
-                        attrs.push(attr);
-                        self.bump();
-                    } else {
-                        break;
-                    }
-                }
-                _ => break,
+            } else {
+                break;
             }
         }
         Ok(attrs)
@@ -232,12 +199,10 @@ impl<'a> Parser<'a> {
         debug!("checking if {:?} is unusuffixed", lit);
 
         if !lit.kind.is_unsuffixed() {
-            let msg = "suffixed literals are not allowed in attributes";
-            self.struct_span_err(lit.span, msg)
+            self.struct_span_err(lit.span, "suffixed literals are not allowed in attributes")
                 .help(
-                    "instead of using a suffixed literal \
-                                    (`1u8`, `1.0f32`, etc.), use an unsuffixed version \
-                                    (`1`, `1.0`, etc.)",
+                    "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
+                    use an unsuffixed version (`1`, `1.0`, etc.)",
                 )
                 .emit();
         }
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 7c1df531ad1..87255386b9e 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -40,55 +40,12 @@ pub(super) fn dummy_arg(ident: Ident) -> Param {
 }
 
 pub enum Error {
-    FileNotFoundForModule {
-        mod_name: String,
-        default_path: String,
-        secondary_path: String,
-        dir_path: String,
-    },
-    DuplicatePaths {
-        mod_name: String,
-        default_path: String,
-        secondary_path: String,
-    },
     UselessDocComment,
 }
 
 impl Error {
     fn span_err(self, sp: impl Into<MultiSpan>, handler: &Handler) -> DiagnosticBuilder<'_> {
         match self {
-            Error::FileNotFoundForModule {
-                ref mod_name,
-                ref default_path,
-                ref secondary_path,
-                ref dir_path,
-            } => {
-                let mut err = struct_span_err!(
-                    handler,
-                    sp,
-                    E0583,
-                    "file not found for module `{}`",
-                    mod_name,
-                );
-                err.help(&format!(
-                    "name the file either {} or {} inside the directory \"{}\"",
-                    default_path, secondary_path, dir_path,
-                ));
-                err
-            }
-            Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => {
-                let mut err = struct_span_err!(
-                    handler,
-                    sp,
-                    E0584,
-                    "file for module `{}` found at both {} and {}",
-                    mod_name,
-                    default_path,
-                    secondary_path,
-                );
-                err.help("delete or rename one of them to remove the ambiguity");
-                err
-            }
             Error::UselessDocComment => {
                 let mut err = struct_span_err!(
                     handler,
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 16ea2773b20..c65e99842c5 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -4,8 +4,8 @@ use super::{BlockMode, Parser, PathStyle, Restrictions, TokenType};
 use super::{SemiColonMode, SeqSep, TokenExpectType};
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
-use rustc_ast::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Ident, Lit, DUMMY_NODE_ID};
-use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, Mac, Param, Ty, TyKind, UnOp};
+use rustc_ast::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Ident, Lit, UnOp, DUMMY_NODE_ID};
+use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
 use rustc_ast::ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token, TokenKind};
@@ -673,10 +673,28 @@ impl<'a> Parser<'a> {
     /// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
     fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
         self.expect_and()?;
+        let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
+        let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
         let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
         let expr = self.parse_prefix_expr(None);
-        let (span, expr) = self.interpolated_or_expr_span(expr)?;
-        Ok((lo.to(span), ExprKind::AddrOf(borrow_kind, mutbl, expr)))
+        let (hi, expr) = self.interpolated_or_expr_span(expr)?;
+        let span = lo.to(hi);
+        if let Some(lt) = lifetime {
+            self.error_remove_borrow_lifetime(span, lt.ident.span);
+        }
+        Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
+    }
+
+    fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
+        self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes")
+            .span_label(lt_span, "annotated with lifetime here")
+            .span_suggestion(
+                lt_span,
+                "remove the lifetime annotation",
+                String::new(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
     }
 
     /// Parse `mut?` or `raw [ const | mut ]`.
@@ -901,7 +919,7 @@ impl<'a> Parser<'a> {
         } else if self.eat_lt() {
             let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
             Ok(self.mk_expr(lo.to(path.span), ExprKind::Path(Some(qself), path), attrs))
-        } else if self.token.is_path_start() {
+        } else if self.check_path() {
             self.parse_path_start_expr(attrs)
         } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
             self.parse_closure_expr(attrs)
@@ -1047,12 +1065,12 @@ impl<'a> Parser<'a> {
         // `!`, as an operator, is prefix, so we know this isn't that.
         let (hi, kind) = if self.eat(&token::Not) {
             // MACRO INVOCATION expression
-            let mac = Mac {
+            let mac = MacCall {
                 path,
                 args: self.parse_mac_args()?,
                 prior_type_ascription: self.last_type_ascription,
             };
-            (self.prev_token.span, ExprKind::Mac(mac))
+            (self.prev_token.span, ExprKind::MacCall(mac))
         } else if self.check(&token::OpenDelim(token::Brace)) {
             if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
                 return expr;
@@ -1067,26 +1085,44 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(expr, true)
     }
 
+    /// Parse `'label: $expr`. The label is already parsed.
     fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = label.ident.span;
-        self.expect(&token::Colon)?;
-        if self.eat_keyword(kw::While) {
-            return self.parse_while_expr(Some(label), lo, attrs);
-        }
-        if self.eat_keyword(kw::For) {
-            return self.parse_for_expr(Some(label), lo, attrs);
-        }
-        if self.eat_keyword(kw::Loop) {
-            return self.parse_loop_expr(Some(label), lo, attrs);
-        }
-        if self.token == token::OpenDelim(token::Brace) {
-            return self.parse_block_expr(Some(label), lo, BlockCheckMode::Default, attrs);
+        let label = Some(label);
+        let ate_colon = self.eat(&token::Colon);
+        let expr = if self.eat_keyword(kw::While) {
+            self.parse_while_expr(label, lo, attrs)
+        } else if self.eat_keyword(kw::For) {
+            self.parse_for_expr(label, lo, attrs)
+        } else if self.eat_keyword(kw::Loop) {
+            self.parse_loop_expr(label, lo, attrs)
+        } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
+            self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs)
+        } else {
+            let msg = "expected `while`, `for`, `loop` or `{` after a label";
+            self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
+            // Continue as an expression in an effort to recover on `'label: non_block_expr`.
+            self.parse_expr()
+        }?;
+
+        if !ate_colon {
+            self.error_labeled_expr_must_be_followed_by_colon(lo, expr.span);
         }
 
-        let msg = "expected `while`, `for`, `loop` or `{` after a label";
-        self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
-        // Continue as an expression in an effort to recover on `'label: non_block_expr`.
-        self.parse_expr()
+        Ok(expr)
+    }
+
+    fn error_labeled_expr_must_be_followed_by_colon(&self, lo: Span, span: Span) {
+        self.struct_span_err(span, "labeled expression must be followed by `:`")
+            .span_label(lo, "the label")
+            .span_suggestion_short(
+                lo.shrink_to_hi(),
+                "add `:` after the label",
+                ": ".to_string(),
+                Applicability::MachineApplicable,
+            )
+            .note("labels are used before loops and blocks, allowing e.g., `break 'label` to them")
+            .emit();
     }
 
     /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
@@ -1363,18 +1399,20 @@ impl<'a> Parser<'a> {
         opt_label: Option<Label>,
         lo: Span,
         blk_mode: BlockCheckMode,
-        outer_attrs: AttrVec,
+        mut attrs: AttrVec,
     ) -> PResult<'a, P<Expr>> {
         if let Some(label) = opt_label {
             self.sess.gated_spans.gate(sym::label_break_value, label.ident.span);
         }
 
-        self.expect(&token::OpenDelim(token::Brace))?;
-
-        let mut attrs = outer_attrs;
-        attrs.extend(self.parse_inner_attributes()?);
+        if self.token.is_whole_block() {
+            self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here")
+                .span_label(lo.to(self.token.span), "the `block` fragment is within this context")
+                .emit();
+        }
 
-        let blk = self.parse_block_tail(lo, blk_mode)?;
+        let (inner_attrs, blk) = self.parse_block_common(lo, blk_mode)?;
+        attrs.extend(inner_attrs);
         Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
     }
 
@@ -1476,13 +1514,16 @@ impl<'a> Parser<'a> {
         let thn = if self.eat_keyword(kw::Else) || !cond.returns() {
             self.error_missing_if_cond(lo, cond.span)
         } else {
+            let attrs = self.parse_outer_attributes()?; // For recovery.
             let not_block = self.token != token::OpenDelim(token::Brace);
-            self.parse_block().map_err(|mut err| {
+            let block = self.parse_block().map_err(|mut err| {
                 if not_block {
                     err.span_label(lo, "this `if` expression has a condition, but no block");
                 }
                 err
-            })?
+            })?;
+            self.error_on_if_block_attrs(lo, false, block.span, &attrs);
+            block
         };
         let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None };
         Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs))
@@ -1524,12 +1565,40 @@ impl<'a> Parser<'a> {
 
     /// Parses an `else { ... }` expression (`else` token already eaten).
     fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
-        if self.eat_keyword(kw::If) {
-            self.parse_if_expr(AttrVec::new())
+        let ctx_span = self.prev_token.span; // `else`
+        let attrs = self.parse_outer_attributes()?; // For recovery.
+        let expr = if self.eat_keyword(kw::If) {
+            self.parse_if_expr(AttrVec::new())?
         } else {
             let blk = self.parse_block()?;
-            Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()))
-        }
+            self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())
+        };
+        self.error_on_if_block_attrs(ctx_span, true, expr.span, &attrs);
+        Ok(expr)
+    }
+
+    fn error_on_if_block_attrs(
+        &self,
+        ctx_span: Span,
+        is_ctx_else: bool,
+        branch_span: Span,
+        attrs: &[ast::Attribute],
+    ) {
+        let (span, last) = match attrs {
+            [] => return,
+            [x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
+        };
+        let ctx = if is_ctx_else { "else" } else { "if" };
+        self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches")
+            .span_label(branch_span, "the attributes are attached to this branch")
+            .span_label(ctx_span, format!("the branch belongs to this `{}`", ctx))
+            .span_suggestion(
+                span,
+                "remove the attributes",
+                String::new(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
     }
 
     /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index a9c4de04c0a..9d70f606f3e 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -5,17 +5,14 @@ use super::{FollowedByType, Parser, PathStyle};
 use crate::maybe_whole;
 
 use rustc_ast::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID};
-use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind};
-use rustc_ast::ast::{
-    Async, Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind,
-};
-use rustc_ast::ast::{
-    BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind,
-};
+use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, Mod};
+use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind};
+use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind};
 use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData};
-use rustc_ast::ast::{FnHeader, ForeignItem, Mutability, Visibility, VisibilityKind};
+use rustc_ast::ast::{FnHeader, ForeignItem, PathSegment, Visibility, VisibilityKind};
+use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter};
 use rustc_ast::ptr::P;
-use rustc_ast::token;
+use rustc_ast::token::{self, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
@@ -27,6 +24,61 @@ use log::debug;
 use std::convert::TryFrom;
 use std::mem;
 
+impl<'a> Parser<'a> {
+    /// Parses a source module as a crate. This is the main entry point for the parser.
+    pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
+        let lo = self.token.span;
+        let (module, attrs) = self.parse_mod(&token::Eof)?;
+        let span = lo.to(self.token.span);
+        let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`.
+        Ok(ast::Crate { attrs, module, span, proc_macros })
+    }
+
+    /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
+    fn parse_item_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
+        let id = self.parse_ident()?;
+        let (module, mut inner_attrs) = if self.eat(&token::Semi) {
+            Default::default()
+        } else {
+            self.expect(&token::OpenDelim(token::Brace))?;
+            self.parse_mod(&token::CloseDelim(token::Brace))?
+        };
+        attrs.append(&mut inner_attrs);
+        Ok((id, ItemKind::Mod(module)))
+    }
+
+    /// Parses the contents of a module (inner attributes followed by module items).
+    pub fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec<Attribute>)> {
+        let lo = self.token.span;
+        let attrs = self.parse_inner_attributes()?;
+        let module = self.parse_mod_items(term, lo)?;
+        Ok((module, attrs))
+    }
+
+    /// Given a termination token, parses all of the items in a module.
+    fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> {
+        let mut items = vec![];
+        while let Some(item) = self.parse_item()? {
+            items.push(item);
+            self.maybe_consume_incorrect_semicolon(&items);
+        }
+
+        if !self.eat(term) {
+            let token_str = super::token_descr(&self.token);
+            if !self.maybe_consume_incorrect_semicolon(&items) {
+                let msg = &format!("expected item, found {}", token_str);
+                let mut err = self.struct_span_err(self.token.span, msg);
+                err.span_label(self.token.span, "expected item");
+                return Err(err);
+            }
+        }
+
+        let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span };
+
+        Ok(Mod { inner: inner_lo.to(hi), items, inline: true })
+    }
+}
+
 pub(super) type ItemInfo = (Ident, ItemKind);
 
 impl<'a> Parser<'a> {
@@ -218,9 +270,9 @@ impl<'a> Parser<'a> {
         } else if vis.node.is_pub() && self.isnt_macro_invocation() {
             self.recover_missing_kw_before_item()?;
             return Ok(None);
-        } else if macros_allowed && self.token.is_path_start() {
+        } else if macros_allowed && self.check_path() {
             // MACRO INVOCATION ITEM
-            (Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?))
+            (Ident::invalid(), ItemKind::MacCall(self.parse_item_macro(vis)?))
         } else {
             return Ok(None);
         };
@@ -339,21 +391,20 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an item macro, e.g., `item!();`.
-    fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, Mac> {
+    fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
         let path = self.parse_path(PathStyle::Mod)?; // `foo::bar`
         self.expect(&token::Not)?; // `!`
         let args = self.parse_mac_args()?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
         self.eat_semi_for_macro_if_needed(&args);
         self.complain_if_pub_macro(vis, false);
-        Ok(Mac { path, args, prior_type_ascription: self.last_type_ascription })
+        Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription })
     }
 
     /// Recover if we parsed attributes and expected an item but there was none.
     fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
         let (start, end) = match attrs {
             [] => return Ok(()),
-            [x0] => (x0, x0),
-            [x0, .., xn] => (x0, xn),
+            [x0 @ xn] | [x0, .., xn] => (x0, xn),
         };
         let msg = if end.is_doc_comment() {
             "expected item after doc comment"
@@ -374,6 +425,16 @@ impl<'a> Parser<'a> {
         self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
     }
 
+    fn parse_polarity(&mut self) -> ast::ImplPolarity {
+        // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
+        if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
+            self.bump(); // `!`
+            ast::ImplPolarity::Negative(self.prev_token.span)
+        } else {
+            ast::ImplPolarity::Positive
+        }
+    }
+
     /// Parses an implementation item.
     ///
     /// ```
@@ -412,13 +473,7 @@ impl<'a> Parser<'a> {
             self.sess.gated_spans.gate(sym::const_trait_impl, span);
         }
 
-        // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
-        let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
-            self.bump(); // `!`
-            ast::ImplPolarity::Negative
-        } else {
-            ast::ImplPolarity::Positive
-        };
+        let polarity = self.parse_polarity();
 
         // Parse both types and traits as a type, then reinterpret if necessary.
         let err_path = |span| ast::Path::from_ident(Ident::new(kw::Invalid, span));
@@ -1261,7 +1316,7 @@ impl<'a> Parser<'a> {
         };
 
         self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
-        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false })))
+        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false })))
     }
 
     /// Is this unambiguously the start of a `macro_rules! foo` item defnition?
@@ -1271,7 +1326,7 @@ impl<'a> Parser<'a> {
             && self.look_ahead(2, |t| t.is_ident())
     }
 
-    /// Parses a legacy `macro_rules! foo { ... }` declarative macro.
+    /// Parses a `macro_rules! foo { ... }` declarative macro.
     fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> {
         self.expect_keyword(kw::MacroRules)?; // `macro_rules`
         self.expect(&token::Not)?; // `!`
@@ -1281,7 +1336,7 @@ impl<'a> Parser<'a> {
         self.eat_semi_for_macro_if_needed(&body);
         self.complain_if_pub_macro(vis, true);
 
-        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true })))
+        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: true })))
     }
 
     /// Item macro invocations or `macro_rules!` definitions need inherited visibility.
@@ -1411,23 +1466,28 @@ impl<'a> Parser<'a> {
     /// This can either be `;` when there's no body,
     /// or e.g. a block when the function is a provided one.
     fn parse_fn_body(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, Option<P<Block>>> {
-        let (inner_attrs, body) = match self.token.kind {
-            token::Semi => {
-                self.bump();
-                (Vec::new(), None)
-            }
-            token::OpenDelim(token::Brace) => {
-                let (attrs, body) = self.parse_inner_attrs_and_block()?;
-                (attrs, Some(body))
-            }
-            token::Interpolated(ref nt) => match **nt {
-                token::NtBlock(..) => {
-                    let (attrs, body) = self.parse_inner_attrs_and_block()?;
-                    (attrs, Some(body))
-                }
-                _ => return self.expected_semi_or_open_brace(),
-            },
-            _ => return self.expected_semi_or_open_brace(),
+        let (inner_attrs, body) = if self.check(&token::Semi) {
+            self.bump(); // `;`
+            (Vec::new(), None)
+        } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
+            self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))?
+        } else if self.token.kind == token::Eq {
+            // Recover `fn foo() = $expr;`.
+            self.bump(); // `=`
+            let eq_sp = self.prev_token.span;
+            let _ = self.parse_expr()?;
+            self.expect_semi()?; // `;`
+            let span = eq_sp.to(self.prev_token.span);
+            self.struct_span_err(span, "function body cannot be `= expression;`")
+                .multipart_suggestion(
+                    "surround the expression with `{` and `}` instead of `=` and `;`",
+                    vec![(eq_sp, "{".to_string()), (self.prev_token.span, " }".to_string())],
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+            (Vec::new(), Some(self.mk_block_err(span)))
+        } else {
+            return self.expected_semi_or_open_brace();
         };
         attrs.extend(inner_attrs);
         Ok(body)
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index 9376c7c1c72..bb6793d08aa 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -1,8 +1,6 @@
 pub mod attr;
 mod expr;
 mod item;
-mod module;
-pub use module::{ModulePath, ModulePathSuccess};
 mod pat;
 mod path;
 mod ty;
@@ -13,7 +11,6 @@ mod stmt;
 use diagnostics::Error;
 
 use crate::lexer::UnmatchedBrace;
-use crate::{Directory, DirectoryOwnership};
 
 use log::debug;
 use rustc_ast::ast::DUMMY_NODE_ID;
@@ -28,11 +25,9 @@ use rustc_ast::util::comments::{doc_comment_style, strip_doc_comment_decoration}
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult};
 use rustc_session::parse::ParseSess;
-use rustc_span::source_map::respan;
+use rustc_span::source_map::{respan, Span, DUMMY_SP};
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::{FileName, Span, DUMMY_SP};
 
-use std::path::PathBuf;
 use std::{cmp, mem, slice};
 
 bitflags::bitflags! {
@@ -93,11 +88,6 @@ pub struct Parser<'a> {
     /// The previous token.
     pub prev_token: Token,
     restrictions: Restrictions,
-    /// Used to determine the path to externally loaded source files.
-    pub(super) directory: Directory,
-    /// `true` to parse sub-modules in other files.
-    // Public for rustfmt usage.
-    pub recurse_into_file_modules: bool,
     /// Name of the root module this parser originated from. If `None`, then the
     /// name is not known. This does not change while the parser is descending
     /// into modules, and sub-parsers have new values for this name.
@@ -105,9 +95,6 @@ pub struct Parser<'a> {
     expected_tokens: Vec<TokenType>,
     token_cursor: TokenCursor,
     desugar_doc_comments: bool,
-    /// `true` we should configure out of line modules as we parse.
-    // Public for rustfmt usage.
-    pub cfg_mods: bool,
     /// This field is used to keep track of how many left angle brackets we have seen. This is
     /// required in order to detect extra leading left angle brackets (`<` characters) and error
     /// appropriately.
@@ -355,8 +342,6 @@ impl<'a> Parser<'a> {
     pub fn new(
         sess: &'a ParseSess,
         tokens: TokenStream,
-        directory: Option<Directory>,
-        recurse_into_file_modules: bool,
         desugar_doc_comments: bool,
         subparser_name: Option<&'static str>,
     ) -> Self {
@@ -365,11 +350,6 @@ impl<'a> Parser<'a> {
             token: Token::dummy(),
             prev_token: Token::dummy(),
             restrictions: Restrictions::empty(),
-            recurse_into_file_modules,
-            directory: Directory {
-                path: PathBuf::new(),
-                ownership: DirectoryOwnership::Owned { relative: None },
-            },
             root_module_name: None,
             expected_tokens: Vec::new(),
             token_cursor: TokenCursor {
@@ -377,7 +357,6 @@ impl<'a> Parser<'a> {
                 stack: Vec::new(),
             },
             desugar_doc_comments,
-            cfg_mods: true,
             unmatched_angle_bracket_count: 0,
             max_angle_bracket_count: 0,
             unclosed_delims: Vec::new(),
@@ -389,18 +368,6 @@ impl<'a> Parser<'a> {
         // Make parser point to the first token.
         parser.bump();
 
-        if let Some(directory) = directory {
-            parser.directory = directory;
-        } else if !parser.token.span.is_dummy() {
-            if let Some(FileName::Real(path)) =
-                &sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path
-            {
-                if let Some(directory_path) = path.parent() {
-                    parser.directory.path = directory_path.to_path_buf();
-                }
-            }
-        }
-
         parser
     }
 
diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs
deleted file mode 100644
index b436f1969bb..00000000000
--- a/src/librustc_parse/parser/module.rs
+++ /dev/null
@@ -1,306 +0,0 @@
-use super::diagnostics::Error;
-use super::item::ItemInfo;
-use super::Parser;
-
-use crate::{new_sub_parser_from_file, DirectoryOwnership};
-
-use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod};
-use rustc_ast::attr;
-use rustc_ast::token::{self, TokenKind};
-use rustc_errors::PResult;
-use rustc_span::source_map::{FileName, SourceMap, Span, DUMMY_SP};
-use rustc_span::symbol::sym;
-
-use std::path::{self, Path, PathBuf};
-
-/// Information about the path to a module.
-// Public for rustfmt usage.
-pub struct ModulePath {
-    name: String,
-    path_exists: bool,
-    pub result: Result<ModulePathSuccess, Error>,
-}
-
-// Public for rustfmt usage.
-pub struct ModulePathSuccess {
-    pub path: PathBuf,
-    pub directory_ownership: DirectoryOwnership,
-}
-
-impl<'a> Parser<'a> {
-    /// Parses a source module as a crate. This is the main entry point for the parser.
-    pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
-        let lo = self.token.span;
-        let krate = Ok(ast::Crate {
-            attrs: self.parse_inner_attributes()?,
-            module: self.parse_mod_items(&token::Eof, lo)?,
-            span: lo.to(self.token.span),
-            // Filled in by proc_macro_harness::inject()
-            proc_macros: Vec::new(),
-        });
-        krate
-    }
-
-    /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
-    pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
-        let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs);
-
-        let id_span = self.token.span;
-        let id = self.parse_ident()?;
-        let (module, mut inner_attrs) = if self.eat(&token::Semi) {
-            if in_cfg && self.recurse_into_file_modules {
-                // This mod is in an external file. Let's go get it!
-                let ModulePathSuccess { path, directory_ownership } =
-                    self.submod_path(id, &attrs, id_span)?;
-                self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?
-            } else {
-                (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new())
-            }
-        } else {
-            let old_directory = self.directory.clone();
-            self.push_directory(id, &attrs);
-
-            self.expect(&token::OpenDelim(token::Brace))?;
-            let mod_inner_lo = self.token.span;
-            let inner_attrs = self.parse_inner_attributes()?;
-            let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
-
-            self.directory = old_directory;
-            (module, inner_attrs)
-        };
-        attrs.append(&mut inner_attrs);
-        Ok((id, ItemKind::Mod(module)))
-    }
-
-    /// Given a termination token, parses all of the items in a module.
-    fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> {
-        let mut items = vec![];
-        while let Some(item) = self.parse_item()? {
-            items.push(item);
-            self.maybe_consume_incorrect_semicolon(&items);
-        }
-
-        if !self.eat(term) {
-            let token_str = super::token_descr(&self.token);
-            if !self.maybe_consume_incorrect_semicolon(&items) {
-                let msg = &format!("expected item, found {}", token_str);
-                let mut err = self.struct_span_err(self.token.span, msg);
-                err.span_label(self.token.span, "expected item");
-                return Err(err);
-            }
-        }
-
-        let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span };
-
-        Ok(Mod { inner: inner_lo.to(hi), items, inline: true })
-    }
-
-    fn submod_path(
-        &mut self,
-        id: ast::Ident,
-        outer_attrs: &[Attribute],
-        id_sp: Span,
-    ) -> PResult<'a, ModulePathSuccess> {
-        if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
-            return Ok(ModulePathSuccess {
-                directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
-                    // All `#[path]` files are treated as though they are a `mod.rs` file.
-                    // This means that `mod foo;` declarations inside `#[path]`-included
-                    // files are siblings,
-                    //
-                    // Note that this will produce weirdness when a file named `foo.rs` is
-                    // `#[path]` included and contains a `mod foo;` declaration.
-                    // If you encounter this, it's your own darn fault :P
-                    Some(_) => DirectoryOwnership::Owned { relative: None },
-                    _ => DirectoryOwnership::UnownedViaMod,
-                },
-                path,
-            });
-        }
-
-        let relative = match self.directory.ownership {
-            DirectoryOwnership::Owned { relative } => relative,
-            DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None,
-        };
-        let paths =
-            Parser::default_submod_path(id, relative, &self.directory.path, self.sess.source_map());
-
-        match self.directory.ownership {
-            DirectoryOwnership::Owned { .. } => {
-                paths.result.map_err(|err| self.span_fatal_err(id_sp, err))
-            }
-            DirectoryOwnership::UnownedViaBlock => {
-                let msg = "Cannot declare a non-inline module inside a block \
-                    unless it has a path attribute";
-                let mut err = self.struct_span_err(id_sp, msg);
-                if paths.path_exists {
-                    let msg = format!(
-                        "Maybe `use` the module `{}` instead of redeclaring it",
-                        paths.name
-                    );
-                    err.span_note(id_sp, &msg);
-                }
-                Err(err)
-            }
-            DirectoryOwnership::UnownedViaMod => {
-                let mut err =
-                    self.struct_span_err(id_sp, "cannot declare a new module at this location");
-                if !id_sp.is_dummy() {
-                    let src_path = self.sess.source_map().span_to_filename(id_sp);
-                    if let FileName::Real(src_path) = src_path {
-                        if let Some(stem) = src_path.file_stem() {
-                            let mut dest_path = src_path.clone();
-                            dest_path.set_file_name(stem);
-                            dest_path.push("mod.rs");
-                            err.span_note(
-                                id_sp,
-                                &format!(
-                                    "maybe move this module `{}` to its own \
-                                                directory via `{}`",
-                                    src_path.display(),
-                                    dest_path.display()
-                                ),
-                            );
-                        }
-                    }
-                }
-                if paths.path_exists {
-                    err.span_note(
-                        id_sp,
-                        &format!(
-                            "... or maybe `use` the module `{}` instead \
-                                            of possibly redeclaring it",
-                            paths.name
-                        ),
-                    );
-                }
-                Err(err)
-            }
-        }
-    }
-
-    // Public for rustfmt usage.
-    pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
-        if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) {
-            let s = s.as_str();
-
-            // On windows, the base path might have the form
-            // `\\?\foo\bar` in which case it does not tolerate
-            // mixed `/` and `\` separators, so canonicalize
-            // `/` to `\`.
-            #[cfg(windows)]
-            let s = s.replace("/", "\\");
-            Some(dir_path.join(&*s))
-        } else {
-            None
-        }
-    }
-
-    /// Returns a path to a module.
-    // Public for rustfmt usage.
-    pub fn default_submod_path(
-        id: ast::Ident,
-        relative: Option<ast::Ident>,
-        dir_path: &Path,
-        source_map: &SourceMap,
-    ) -> ModulePath {
-        // If we're in a foo.rs file instead of a mod.rs file,
-        // we need to look for submodules in
-        // `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than
-        // `./<id>.rs` and `./<id>/mod.rs`.
-        let relative_prefix_string;
-        let relative_prefix = if let Some(ident) = relative {
-            relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR);
-            &relative_prefix_string
-        } else {
-            ""
-        };
-
-        let mod_name = id.name.to_string();
-        let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
-        let secondary_path_str =
-            format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR);
-        let default_path = dir_path.join(&default_path_str);
-        let secondary_path = dir_path.join(&secondary_path_str);
-        let default_exists = source_map.file_exists(&default_path);
-        let secondary_exists = source_map.file_exists(&secondary_path);
-
-        let result = match (default_exists, secondary_exists) {
-            (true, false) => Ok(ModulePathSuccess {
-                path: default_path,
-                directory_ownership: DirectoryOwnership::Owned { relative: Some(id) },
-            }),
-            (false, true) => Ok(ModulePathSuccess {
-                path: secondary_path,
-                directory_ownership: DirectoryOwnership::Owned { relative: None },
-            }),
-            (false, false) => Err(Error::FileNotFoundForModule {
-                mod_name: mod_name.clone(),
-                default_path: default_path_str,
-                secondary_path: secondary_path_str,
-                dir_path: dir_path.display().to_string(),
-            }),
-            (true, true) => Err(Error::DuplicatePaths {
-                mod_name: mod_name.clone(),
-                default_path: default_path_str,
-                secondary_path: secondary_path_str,
-            }),
-        };
-
-        ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result }
-    }
-
-    /// Reads a module from a source file.
-    fn eval_src_mod(
-        &mut self,
-        path: PathBuf,
-        directory_ownership: DirectoryOwnership,
-        name: String,
-        id_sp: Span,
-    ) -> PResult<'a, (Mod, Vec<Attribute>)> {
-        let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
-        if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
-            let mut err = String::from("circular modules: ");
-            let len = included_mod_stack.len();
-            for p in &included_mod_stack[i..len] {
-                err.push_str(&p.to_string_lossy());
-                err.push_str(" -> ");
-            }
-            err.push_str(&path.to_string_lossy());
-            return Err(self.struct_span_err(id_sp, &err[..]));
-        }
-        included_mod_stack.push(path.clone());
-        drop(included_mod_stack);
-
-        let mut p0 =
-            new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp);
-        p0.cfg_mods = self.cfg_mods;
-        let mod_inner_lo = p0.token.span;
-        let mod_attrs = p0.parse_inner_attributes()?;
-        let mut m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;
-        m0.inline = false;
-        self.sess.included_mod_stack.borrow_mut().pop();
-        Ok((m0, mod_attrs))
-    }
-
-    fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
-        if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) {
-            self.directory.path.push(&*path.as_str());
-            self.directory.ownership = DirectoryOwnership::Owned { relative: None };
-        } else {
-            // We have to push on the current module name in the case of relative
-            // paths in order to ensure that any additional module paths from inline
-            // `mod x { ... }` come after the relative extension.
-            //
-            // For example, a `mod z { ... }` inside `x/y.rs` should set the current
-            // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
-            if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
-                if let Some(ident) = relative.take() {
-                    // remove the relative offset
-                    self.directory.path.push(&*ident.as_str());
-                }
-            }
-            self.directory.path.push(&*id.as_str());
-        }
-    }
-}
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index f52a91ff598..4585941943b 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -1,9 +1,7 @@
 use super::{Parser, PathStyle};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
-use rustc_ast::ast::{
-    self, AttrVec, Attribute, FieldPat, Mac, Pat, PatKind, RangeEnd, RangeSyntax,
-};
-use rustc_ast::ast::{BindingMode, Expr, ExprKind, Ident, Mutability, Path, QSelf};
+use rustc_ast::ast::{self, AttrVec, Attribute, FieldPat, MacCall, Pat, PatKind, RangeEnd};
+use rustc_ast::ast::{BindingMode, Expr, ExprKind, Ident, Mutability, Path, QSelf, RangeSyntax};
 use rustc_ast::mut_visit::{noop_visit_mac, noop_visit_pat, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
@@ -540,7 +538,7 @@ impl<'a> Parser<'a> {
     fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool {
         struct AddMut(bool);
         impl MutVisitor for AddMut {
-            fn visit_mac(&mut self, mac: &mut Mac) {
+            fn visit_mac(&mut self, mac: &mut MacCall) {
                 noop_visit_mac(mac, self);
             }
 
@@ -597,8 +595,8 @@ impl<'a> Parser<'a> {
     fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> {
         self.bump();
         let args = self.parse_mac_args()?;
-        let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription };
-        Ok(PatKind::Mac(mac))
+        let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription };
+        Ok(PatKind::MacCall(mac))
     }
 
     fn fatal_unexpected_non_pat(
@@ -704,7 +702,7 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
-        if self.token.is_path_start() {
+        if self.check_path() {
             let lo = self.token.span;
             let (qself, path) = if self.eat_lt() {
                 // Parse a qualified path
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index 3864ec3aaa1..d40597d8fcb 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -1,13 +1,13 @@
+use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN;
 use super::diagnostics::Error;
 use super::expr::LhsExpr;
 use super::pat::GateOr;
 use super::path::PathStyle;
 use super::{BlockMode, Parser, Restrictions, SemiColonMode};
 use crate::maybe_whole;
-use crate::DirectoryOwnership;
 
 use rustc_ast::ast;
-use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle};
+use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, MacCall, MacStmtStyle};
 use rustc_ast::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, TokenKind};
@@ -47,16 +47,13 @@ impl<'a> Parser<'a> {
             self.bump(); // `var`
             let msg = "write `let` instead of `var` to introduce a new variable";
             self.recover_stmt_local(lo, attrs.into(), msg, "let")?
-        } else if self.token.is_path_start()
-            && !self.token.is_qpath_start()
-            && !self.is_path_start_item()
-        {
+        } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
             // We have avoided contextual keywords like `union`, items with `crate` visibility,
             // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
             // that starts like a path (1 token), but it fact not a path.
             // Also, we avoid stealing syntax from `parse_item_`.
             self.parse_stmt_path_start(lo, attrs)?
-        } else if let Some(item) = self.parse_stmt_item(attrs.clone())? {
+        } else if let Some(item) = self.parse_item_common(attrs.clone(), false, true, |_| true)? {
             // FIXME: Bad copy of attrs
             self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))
         } else if self.eat(&token::Semi) {
@@ -74,13 +71,6 @@ impl<'a> Parser<'a> {
         Ok(Some(stmt))
     }
 
-    fn parse_stmt_item(&mut self, attrs: Vec<Attribute>) -> PResult<'a, Option<ast::Item>> {
-        let old = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
-        let item = self.parse_item_common(attrs, false, true, |_| true)?;
-        self.directory.ownership = old;
-        Ok(item)
-    }
-
     fn parse_stmt_path_start(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, Stmt> {
         let path = self.parse_path(PathStyle::Expr)?;
 
@@ -112,14 +102,14 @@ impl<'a> Parser<'a> {
         let style =
             if delim == token::Brace { MacStmtStyle::Braces } else { MacStmtStyle::NoBraces };
 
-        let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription };
+        let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription };
 
         let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof
         {
-            StmtKind::Mac(P((mac, style, attrs)))
+            StmtKind::MacCall(P((mac, style, attrs)))
         } else {
             // Since none of the above applied, this is an expression statement macro.
-            let e = self.mk_expr(lo.to(hi), ExprKind::Mac(mac), AttrVec::new());
+            let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
             let e = self.maybe_recover_from_bad_qpath(e, true)?;
             let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
             let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
@@ -238,15 +228,11 @@ impl<'a> Parser<'a> {
 
     /// Parses a block. No inner attributes are allowed.
     pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
-        maybe_whole!(self, NtBlock, |x| x);
-
-        let lo = self.token.span;
-
-        if !self.eat(&token::OpenDelim(token::Brace)) {
-            return self.error_block_no_opening_brace();
+        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);
         }
-
-        self.parse_block_tail(lo, BlockCheckMode::Default)
+        Ok(block)
     }
 
     fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
@@ -262,16 +248,14 @@ impl<'a> Parser<'a> {
         //
         // which is valid in other languages, but not Rust.
         match self.parse_stmt_without_recovery() {
-            Ok(Some(stmt)) => {
+            // If the next token is an open brace (e.g., `if a b {`), the place-
+            // inside-a-block suggestion would be more likely wrong than right.
+            Ok(Some(_))
                 if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
-                    || do_not_suggest_help
-                {
-                    // If the next token is an open brace (e.g., `if a b {`), the place-
-                    // inside-a-block suggestion would be more likely wrong than right.
-                    e.span_label(sp, "expected `{`");
-                    return Err(e);
-                }
-                let stmt_span = if self.eat(&token::Semi) {
+                    || do_not_suggest_help => {}
+            Ok(Some(stmt)) => {
+                let stmt_own_line = self.sess.source_map().is_line_before_span_empty(sp);
+                let stmt_span = if stmt_own_line && self.eat(&token::Semi) {
                     // Expand the span to include the semicolon.
                     stmt.span.with_hi(self.prev_token.span.hi())
                 } else {
@@ -301,20 +285,27 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_inner_attrs_and_block(
         &mut self,
     ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
+        self.parse_block_common(self.token.span, BlockCheckMode::Default)
+    }
+
+    /// Parses a block. Inner attributes are allowed.
+    pub(super) fn parse_block_common(
+        &mut self,
+        lo: Span,
+        blk_mode: BlockCheckMode,
+    ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
         maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
 
-        let lo = self.token.span;
-        self.expect(&token::OpenDelim(token::Brace))?;
-        Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, BlockCheckMode::Default)?))
+        if !self.eat(&token::OpenDelim(token::Brace)) {
+            return self.error_block_no_opening_brace();
+        }
+
+        Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, blk_mode)?))
     }
 
     /// Parses the rest of a block expression or function body.
     /// Precondition: already parsed the '{'.
-    pub(super) fn parse_block_tail(
-        &mut self,
-        lo: Span,
-        s: BlockCheckMode,
-    ) -> PResult<'a, P<Block>> {
+    fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
         let mut stmts = vec![];
         while !self.eat(&token::CloseDelim(token::Brace)) {
             if self.token == token::Eof {
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 16adf5c05a4..c21ac8d04f1 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -3,10 +3,8 @@ use super::{Parser, PathStyle, TokenType};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
 use rustc_ast::ast::{self, BareFnTy, FnRetTy, GenericParam, Lifetime, MutTy, Ty, TyKind};
-use rustc_ast::ast::{
-    GenericBound, GenericBounds, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax,
-};
-use rustc_ast::ast::{Mac, Mutability};
+use rustc_ast::ast::{GenericBound, GenericBounds, MacCall, Mutability};
+use rustc_ast::ast::{PolyTraitRef, TraitBoundModifier, TraitObjectSyntax};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token, TokenKind};
 use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
@@ -142,24 +140,20 @@ impl<'a> Parser<'a> {
             } else {
                 let path = self.parse_path(PathStyle::Type)?;
                 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
-                self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
+                self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
             }
         } else if self.eat_keyword(kw::Impl) {
             self.parse_impl_ty(&mut impl_dyn_multi)?
         } else if self.is_explicit_dyn_type() {
             self.parse_dyn_ty(&mut impl_dyn_multi)?
-        } else if self.check(&token::Question)
-            || self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus())
-        {
-            // Bound list (trait object type)
-            let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
-            TyKind::TraitObject(bounds, TraitObjectSyntax::None)
         } else if self.eat_lt() {
             // Qualified path
             let (qself, path) = self.parse_qpath(PathStyle::Type)?;
             TyKind::Path(Some(qself), path)
-        } else if self.token.is_path_start() {
+        } else if self.check_path() {
             self.parse_path_start_ty(lo, allow_plus)?
+        } else if self.can_begin_bound() {
+            self.parse_bare_trait_object(lo, allow_plus)?
         } else if self.eat(&token::DotDotDot) {
             if allow_c_variadic == AllowCVariadic::Yes {
                 TyKind::CVarArgs
@@ -203,21 +197,12 @@ impl<'a> Parser<'a> {
             match ty.kind {
                 // `(TY_BOUND_NOPAREN) + BOUND + ...`.
                 TyKind::Path(None, path) if maybe_bounds => {
-                    self.parse_remaining_bounds(Vec::new(), path, lo, true)
+                    self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
                 }
-                TyKind::TraitObject(mut bounds, TraitObjectSyntax::None)
+                TyKind::TraitObject(bounds, TraitObjectSyntax::None)
                     if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
                 {
-                    let path = match bounds.remove(0) {
-                        GenericBound::Trait(pt, ..) => pt.trait_ref.path,
-                        GenericBound::Outlives(..) => {
-                            return Err(self.struct_span_err(
-                                ty.span,
-                                "expected trait bound, not lifetime bound",
-                            ));
-                        }
-                    };
-                    self.parse_remaining_bounds(Vec::new(), path, lo, true)
+                    self.parse_remaining_bounds(bounds, true)
                 }
                 // `(TYPE)`
                 _ => Ok(TyKind::Paren(P(ty))),
@@ -227,18 +212,35 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_remaining_bounds(
+    fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
+        let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
+        let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
+        if lt_no_plus {
+            self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`").emit()
+        }
+        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
+    }
+
+    fn parse_remaining_bounds_path(
         &mut self,
         generic_params: Vec<GenericParam>,
         path: ast::Path,
         lo: Span,
         parse_plus: bool,
     ) -> PResult<'a, TyKind> {
-        assert_ne!(self.token, token::Question);
-
         let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span));
-        let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
-        if parse_plus {
+        let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
+        self.parse_remaining_bounds(bounds, parse_plus)
+    }
+
+    /// Parse the remainder of a bare trait object type given an already parsed list.
+    fn parse_remaining_bounds(
+        &mut self,
+        mut bounds: GenericBounds,
+        plus: bool,
+    ) -> PResult<'a, TyKind> {
+        assert_ne!(self.token, token::Question);
+        if plus {
             self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
             bounds.append(&mut self.parse_generic_bounds(Some(self.prev_token.span))?);
         }
@@ -351,14 +353,14 @@ impl<'a> Parser<'a> {
         let path = self.parse_path(PathStyle::Type)?;
         if self.eat(&token::Not) {
             // Macro invocation in type position
-            Ok(TyKind::Mac(Mac {
+            Ok(TyKind::MacCall(MacCall {
                 path,
                 args: self.parse_mac_args()?,
                 prior_type_ascription: self.last_type_ascription,
             }))
         } else if allow_plus == AllowPlus::Yes && self.check_plus() {
             // `Trait1 + Trait2 + 'a`
-            self.parse_remaining_bounds(Vec::new(), path, lo, true)
+            self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
         } else {
             // Just a type path.
             Ok(TyKind::Path(None, path))
diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs
index 029aa5ed2ba..2512878ec65 100644
--- a/src/librustc_parse/validate_attr.rs
+++ b/src/librustc_parse/validate_attr.rs
@@ -57,7 +57,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
     })
 }
 
-crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
+pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
     if let ast::MacDelimiter::Parenthesis = delim {
         return;
     }
diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml
index af8e7a5b71e..8acb88f58d3 100644
--- a/src/librustc_passes/Cargo.toml
+++ b/src/librustc_passes/Cargo.toml
@@ -22,3 +22,4 @@ rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs
index f1ed074d6ab..373b7c56d38 100644
--- a/src/librustc_passes/check_attr.rs
+++ b/src/librustc_passes/check_attr.rs
@@ -25,7 +25,7 @@ use rustc_span::Span;
 fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target {
     match impl_item.kind {
         hir::ImplItemKind::Const(..) => Target::AssocConst,
-        hir::ImplItemKind::Method(..) => {
+        hir::ImplItemKind::Fn(..) => {
             let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id);
             let containing_item = tcx.hir().expect_item(parent_hir_id);
             let containing_impl_is_for_trait = match &containing_item.kind {
@@ -418,8 +418,8 @@ impl CheckAttrVisitor<'tcx> {
 impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs
index 53e8213ae48..30737360b9c 100644
--- a/src/librustc_passes/check_const.rs
+++ b/src/librustc_passes/check_const.rs
@@ -8,9 +8,6 @@
 //! through, but errors for structured control flow in a `const` should be emitted here.
 
 use rustc::hir::map::Map;
-use rustc::hir::Hir;
-use rustc::session::config::nightly_options;
-use rustc::session::parse::feature_err;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_ast::ast::Mutability;
@@ -18,6 +15,8 @@ use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_session::config::nightly_options;
+use rustc_session::parse::feature_err;
 use rustc_span::{sym, Span, Symbol};
 
 use std::fmt;
@@ -75,7 +74,7 @@ enum ConstKind {
 }
 
 impl ConstKind {
-    fn for_body(body: &hir::Body<'_>, hir_map: Hir<'_>) -> Option<Self> {
+    fn for_body(body: &hir::Body<'_>, hir_map: Map<'_>) -> Option<Self> {
         let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const();
 
         let owner = hir_map.body_owner(body.id());
@@ -202,8 +201,8 @@ impl<'tcx> CheckConstVisitor<'tcx> {
 impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index bcf9fd5a535..4466dea89b0 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -210,9 +210,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -391,7 +391,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
                     let trait_item = self.krate.trait_item(trait_item_ref.id);
                     match trait_item.kind {
                         hir::TraitItemKind::Const(_, Some(_))
-                        | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
+                        | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => {
                             if has_allow_dead_code_or_lang_attr(
                                 self.tcx,
                                 trait_item.hir_id,
@@ -568,8 +568,8 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
     /// on inner functions when the outer function is already getting
     /// an error. We could do this also by checking the parents, but
     /// this is how the code is setup and it seems harmless enough.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -661,7 +661,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                 }
                 self.visit_nested_body(body_id)
             }
-            hir::ImplItemKind::Method(_, body_id) => {
+            hir::ImplItemKind::Fn(_, body_id) => {
                 if !self.symbol_is_live(impl_item.hir_id) {
                     let span = self.tcx.sess.source_map().def_span(impl_item.span);
                     self.warn_dead_code(
@@ -682,11 +682,11 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         match trait_item.kind {
             hir::TraitItemKind::Const(_, Some(body_id))
-            | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => {
+            | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => {
                 self.visit_nested_body(body_id)
             }
             hir::TraitItemKind::Const(_, None)
-            | hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_))
+            | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
             | hir::TraitItemKind::Type(..) => {}
         }
     }
diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs
index 86596e20556..7e0d0bfe9ab 100644
--- a/src/librustc_passes/entry.rs
+++ b/src/librustc_passes/entry.rs
@@ -1,6 +1,4 @@
-use rustc::hir::Hir;
-use rustc::session::config::EntryFnType;
-use rustc::session::{config, Session};
+use rustc::hir::map::Map;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_ast::attr;
@@ -9,13 +7,15 @@ use rustc_errors::struct_span_err;
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
+use rustc_session::config::EntryFnType;
+use rustc_session::{config, Session};
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
 
 struct EntryContext<'a, 'tcx> {
     session: &'a Session,
 
-    map: Hir<'tcx>,
+    map: Map<'tcx>,
 
     /// The top-level function called `main`.
     main_fn: Option<(HirId, Span)>,
@@ -34,7 +34,7 @@ struct EntryContext<'a, 'tcx> {
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
         let def_id = self.map.local_def_id(item.hir_id);
-        let def_key = self.map.def_key(def_id);
+        let def_key = self.map.def_key(def_id.expect_local());
         let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
         find_item(item, self, at_root);
     }
@@ -59,7 +59,7 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
     }
 
     // If the user wants no main function at all, then stop here.
-    if attr::contains_name(&tcx.hir().krate().attrs, sym::no_main) {
+    if attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_main) {
         return None;
     }
 
@@ -157,7 +157,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
 }
 
 fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
-    let sp = tcx.hir().krate().span;
+    let sp = tcx.hir().krate().item.span;
     if *tcx.sess.parse_sess.reached_eof.borrow() {
         // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about
         // the missing `fn main()` then as it might have been hidden inside an unclosed block.
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index c819809041f..8bfe58da78f 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -95,7 +95,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
 
     type Map = Map<'v>;
 
-    fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
         panic!("visit_nested_xxx must be manually implemented in this visitor")
     }
 
@@ -336,8 +336,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
         ast_visit::walk_lifetime(self, lifetime)
     }
 
-    fn visit_mac(&mut self, mac: &'v ast::Mac) {
-        self.record("Mac", Id::None, mac);
+    fn visit_mac(&mut self, mac: &'v ast::MacCall) {
+        self.record("MacCall", Id::None, mac);
     }
 
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v ast::PathSegment) {
diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs
index 782199003c7..1b46aaeefcb 100644
--- a/src/librustc_passes/intrinsicck.rs
+++ b/src/librustc_passes/intrinsicck.rs
@@ -1,4 +1,3 @@
-use rustc::hir::map::Map;
 use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
 use rustc::ty::query::Providers;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -122,9 +121,9 @@ impl ExprVisitor<'tcx> {
 }
 
 impl Visitor<'tcx> for ItemVisitor<'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -139,9 +138,9 @@ impl Visitor<'tcx> for ItemVisitor<'tcx> {
 }
 
 impl Visitor<'tcx> for ExprVisitor<'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_passes/lang_items.rs b/src/librustc_passes/lang_items.rs
index 5f5acc7fdf8..88e92bbdba1 100644
--- a/src/librustc_passes/lang_items.rs
+++ b/src/librustc_passes/lang_items.rs
@@ -143,7 +143,7 @@ impl LanguageItemCollector<'tcx> {
 }
 
 /// Traverses and collects all the lang items in all crates.
-fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems {
+fn collect(tcx: TyCtxt<'_>) -> LanguageItems {
     // Initialize the collector.
     let mut collector = LanguageItemCollector::new(tcx);
 
diff --git a/src/librustc_passes/lib_features.rs b/src/librustc_passes/lib_features.rs
index 172d7e7628e..133e30f6ff0 100644
--- a/src/librustc_passes/lib_features.rs
+++ b/src/librustc_passes/lib_features.rs
@@ -114,8 +114,8 @@ impl LibFeatureCollector<'tcx> {
 impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_attribute(&mut self, attr: &'tcx Attribute) {
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 5b6d0fc74e8..70b106f5d23 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -97,7 +97,6 @@ use self::LiveNodeKind::*;
 use self::VarKind::*;
 
 use rustc::hir::map::Map;
-use rustc::lint;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
 use rustc_ast::ast;
@@ -108,6 +107,7 @@ use rustc_hir::def::*;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node};
+use rustc_session::lint;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
@@ -156,8 +156,8 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
 impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_fn(
@@ -398,7 +398,7 @@ fn visit_fn<'tcx>(
     intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id);
 
     // compute liveness
-    let mut lsets = Liveness::new(&mut fn_maps, body_id);
+    let mut lsets = Liveness::new(&mut fn_maps, def_id);
     let entry_ln = lsets.compute(&body.value);
 
     // check for various error conditions
@@ -658,6 +658,7 @@ const ACC_USE: u32 = 4;
 struct Liveness<'a, 'tcx> {
     ir: &'a mut IrMaps<'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     s: Specials,
     successors: Vec<LiveNode>,
     rwu_table: RWUTable,
@@ -670,7 +671,7 @@ struct Liveness<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Liveness<'a, 'tcx> {
-    fn new(ir: &'a mut IrMaps<'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
+    fn new(ir: &'a mut IrMaps<'tcx>, def_id: DefId) -> Liveness<'a, 'tcx> {
         // Special nodes and variables:
         // - exit_ln represents the end of the fn, either by return or panic
         // - implicit_ret_var is a pseudo-variable that represents
@@ -681,7 +682,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             clean_exit_var: ir.add_variable(CleanExit),
         };
 
-        let tables = ir.tcx.body_tables(body);
+        let tables = ir.tcx.typeck_tables_of(def_id);
+        let param_env = ir.tcx.param_env(def_id);
 
         let num_live_nodes = ir.num_live_nodes;
         let num_vars = ir.num_vars;
@@ -689,6 +691,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         Liveness {
             ir,
             tables,
+            param_env,
             s: specials,
             successors: vec![invalid_node(); num_live_nodes],
             rwu_table: RWUTable::new(num_live_nodes * num_vars),
@@ -1125,8 +1128,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             }
 
             hir::ExprKind::Call(ref f, ref args) => {
-                let m = self.ir.tcx.parent_module(expr.hir_id);
-                let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) {
+                let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
+                let succ = if self.ir.tcx.is_ty_uninhabited_from(
+                    m,
+                    self.tables.expr_ty(expr),
+                    self.param_env,
+                ) {
                     self.s.exit_ln
                 } else {
                     succ
@@ -1136,8 +1143,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             }
 
             hir::ExprKind::MethodCall(.., ref args) => {
-                let m = self.ir.tcx.parent_module(expr.hir_id);
-                let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) {
+                let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
+                let succ = if self.ir.tcx.is_ty_uninhabited_from(
+                    m,
+                    self.tables.expr_ty(expr),
+                    self.param_env,
+                ) {
                     self.s.exit_ln
                 } else {
                     succ
@@ -1359,9 +1370,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 // Checking for error conditions
 
 impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index 2719057fb53..1daef45a1f5 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -24,15 +24,14 @@ enum Context {
 #[derive(Copy, Clone)]
 struct CheckLoopVisitor<'a, 'hir> {
     sess: &'a Session,
-    hir_map: &'a Map<'hir>,
+    hir_map: Map<'hir>,
     cx: Context,
 }
 
 fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(
         module_def_id,
-        &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: &tcx.hir(), cx: Normal }
-            .as_deep_visitor(),
+        &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal }.as_deep_visitor(),
     );
 }
 
@@ -43,8 +42,8 @@ pub(crate) fn provide(providers: &mut Providers<'_>) {
 impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
     type Map = Map<'hir>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.hir_map)
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.hir_map)
     }
 
     fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs
index 888f4370dd5..835e7cfb628 100644
--- a/src/librustc_passes/reachable.rs
+++ b/src/librustc_passes/reachable.rs
@@ -5,10 +5,8 @@
 // makes all other generics or inline functions that it references
 // reachable as well.
 
-use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::middle::privacy;
-use rustc::session::config;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
@@ -17,10 +15,10 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_hir::intravisit;
-use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirIdSet, Node};
+use rustc_session::config;
 use rustc_target::spec::abi::Abi;
 
 // Returns true if the given item must be inlined because it may be
@@ -48,12 +46,12 @@ fn method_might_be_inlined(
     impl_item: &hir::ImplItem<'_>,
     impl_src: DefId,
 ) -> bool {
-    let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
+    let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner.to_def_id());
     let generics = tcx.generics_of(tcx.hir().local_def_id(impl_item.hir_id));
     if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
         return true;
     }
-    if let hir::ImplItemKind::Method(method_sig, _) = &impl_item.kind {
+    if let hir::ImplItemKind::Fn(method_sig, _) = &impl_item.kind {
         if method_sig.header.is_const() {
             return true;
         }
@@ -83,9 +81,9 @@ struct ReachableContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -162,14 +160,14 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             },
             Some(Node::TraitItem(trait_method)) => match trait_method.kind {
                 hir::TraitItemKind::Const(_, ref default) => default.is_some(),
-                hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true,
-                hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_))
+                hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true,
+                hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
                 | hir::TraitItemKind::Type(..) => false,
             },
             Some(Node::ImplItem(impl_item)) => {
                 match impl_item.kind {
                     hir::ImplItemKind::Const(..) => true,
-                    hir::ImplItemKind::Method(..) => {
+                    hir::ImplItemKind::Fn(..) => {
                         let attrs = self.tcx.codegen_fn_attrs(def_id);
                         let generics = self.tcx.generics_of(def_id);
                         if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() {
@@ -278,11 +276,11 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             Node::TraitItem(trait_method) => {
                 match trait_method.kind {
                     hir::TraitItemKind::Const(_, None)
-                    | hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
+                    | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
                         // Keep going, nothing to get exported
                     }
                     hir::TraitItemKind::Const(_, Some(body_id))
-                    | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => {
+                    | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => {
                         self.visit_nested_body(body_id);
                     }
                     hir::TraitItemKind::Type(..) => {}
@@ -292,7 +290,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                 hir::ImplItemKind::Const(_, body) => {
                     self.visit_nested_body(body);
                 }
-                hir::ImplItemKind::Method(_, body) => {
+                hir::ImplItemKind::Fn(_, body) => {
                     let did = self.tcx.hir().get_parent_did(search_item);
                     if method_might_be_inlined(self.tcx, impl_item, did) {
                         self.visit_nested_body(body)
diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs
index 282bd20a9be..e771696a5b6 100644
--- a/src/librustc_passes/region.rs
+++ b/src/librustc_passes/region.rs
@@ -2,11 +2,10 @@
 //! the parent links in the region hierarchy.
 //!
 //! For more information about how MIR-based region-checking works,
-//! see the [rustc guide].
+//! see the [rustc dev guide].
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
 
-use rustc::hir::map::Map;
 use rustc::middle::region::*;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
@@ -696,9 +695,9 @@ impl<'tcx> RegionResolutionVisitor<'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs
index 7ea9ab5335d..11311a3e8aa 100644
--- a/src/librustc_passes/stability.rs
+++ b/src/librustc_passes/stability.rs
@@ -2,11 +2,8 @@
 //! propagating default levels lexically from parent to children ast nodes.
 
 use rustc::hir::map::Map;
-use rustc::lint;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability::{DeprecationEntry, Index};
-use rustc::session::parse::feature_err;
-use rustc::session::Session;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_ast::ast::Attribute;
@@ -18,9 +15,12 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Generics, HirId, Item, StructField, Variant};
-use rustc_infer::traits::misc::can_type_implement_copy;
+use rustc_session::lint;
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
+use rustc_trait_selection::traits::misc::can_type_implement_copy;
 
 use std::cmp::Ordering;
 use std::mem::replace;
@@ -259,8 +259,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
     /// deep-walking.
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
@@ -350,8 +350,8 @@ impl<'a, 'tcx> MissingStabilityAnnotations<'a, 'tcx> {
 impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
@@ -459,8 +459,8 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
 
         annotator.annotate(
             hir::CRATE_HIR_ID,
-            &krate.attrs,
-            krate.span,
+            &krate.item.attrs,
+            krate.item.span,
             AnnotationKind::Required,
             |v| intravisit::walk_crate(v, krate),
         );
@@ -492,8 +492,8 @@ impl Visitor<'tcx> for Checker<'tcx> {
     /// Because stability levels are scoped lexically, we want to walk
     /// nested items in the context of the outer item, so enable
     /// deep-walking.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -585,7 +585,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     if tcx.stability().staged_api[&LOCAL_CRATE] {
         let krate = tcx.hir().krate();
         let mut missing = MissingStabilityAnnotations { tcx, access_levels };
-        missing.check_missing_stability(hir::CRATE_HIR_ID, krate.span, "crate");
+        missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span, "crate");
         intravisit::walk_crate(&mut missing, krate);
         krate.visit_all_item_likes(&mut missing.as_deep_visitor());
     }
diff --git a/src/librustc_passes/upvars.rs b/src/librustc_passes/upvars.rs
index a2397f27338..43f39e6c610 100644
--- a/src/librustc_passes/upvars.rs
+++ b/src/librustc_passes/upvars.rs
@@ -1,6 +1,5 @@
 //! Upvar (closure capture) collection from cross-body HIR uses of `Res::Local`s.
 
-use rustc::hir::map::Map;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
@@ -44,9 +43,9 @@ struct LocalCollector {
 }
 
 impl Visitor<'tcx> for LocalCollector {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -73,9 +72,9 @@ impl CaptureCollector<'_, '_> {
 }
 
 impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs
index 1511742446b..cde489e8d2c 100644
--- a/src/librustc_passes/weak_lang_items.rs
+++ b/src/librustc_passes/weak_lang_items.rs
@@ -2,15 +2,13 @@
 
 use rustc::middle::lang_items;
 use rustc::middle::lang_items::whitelisted;
-use rustc::session::config;
-
-use rustc::hir::map::Map;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
+use rustc_session::config;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
@@ -28,9 +26,6 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
     if items.eh_personality().is_none() {
         items.missing.push(lang_items::EhPersonalityLangItem);
     }
-    if tcx.sess.target.target.options.custom_unwind_resume & items.eh_unwind_resume().is_none() {
-        items.missing.push(lang_items::EhUnwindResumeLangItem);
-    }
 
     {
         let mut cx = Context { tcx, items };
@@ -88,9 +83,9 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
-    type Map = Map<'v>;
+    type Map = intravisit::ErasedMap<'v>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'v>> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_plugin_impl/Cargo.toml b/src/librustc_plugin_impl/Cargo.toml
index 89313072590..372d6a534c8 100644
--- a/src/librustc_plugin_impl/Cargo.toml
+++ b/src/librustc_plugin_impl/Cargo.toml
@@ -17,4 +17,5 @@ rustc_hir = { path = "../librustc_hir" }
 rustc_lint = { path = "../librustc_lint" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_ast = { path = "../librustc_ast" }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs
index 9bd9bcb25ba..0810cf56d17 100644
--- a/src/librustc_plugin_impl/load.rs
+++ b/src/librustc_plugin_impl/load.rs
@@ -2,10 +2,10 @@
 
 use crate::Registry;
 use rustc::middle::cstore::MetadataLoader;
-use rustc::session::Session;
 use rustc_ast::ast::{Crate, Ident};
 use rustc_errors::struct_span_err;
 use rustc_metadata::locator;
+use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml
index 6d1272c117b..9854e0f6c53 100644
--- a/src/librustc_privacy/Cargo.toml
+++ b/src/librustc_privacy/Cargo.toml
@@ -14,6 +14,7 @@ rustc_attr = { path = "../librustc_attr" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_typeck = { path = "../librustc_typeck" }
+rustc_session = { path = "../librustc_session" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 24696b20332..c8c8c229930 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -5,7 +5,6 @@
 
 use rustc::bug;
 use rustc::hir::map::Map;
-use rustc::lint;
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::ty::fold::TypeVisitor;
 use rustc::ty::query::Providers;
@@ -20,6 +19,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
 use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind};
+use rustc_session::lint;
 use rustc_span::hygiene::Transparency;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -327,7 +327,7 @@ fn def_id_visibility<'tcx>(
                 }
                 Node::Expr(expr) => {
                     return (
-                        ty::Visibility::Restricted(tcx.parent_module(expr.hir_id)),
+                        ty::Visibility::Restricted(tcx.parent_module(expr.hir_id).to_def_id()),
                         expr.span,
                         "private",
                     );
@@ -373,8 +373,8 @@ struct PubRestrictedVisitor<'tcx> {
 impl Visitor<'tcx> for PubRestrictedVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
     fn visit_vis(&mut self, vis: &'tcx hir::Visibility<'tcx>) {
         self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted();
@@ -620,7 +620,7 @@ impl EmbargoVisitor<'tcx> {
             | DefKind::ForeignTy
             | DefKind::Fn
             | DefKind::OpaqueTy
-            | DefKind::Method
+            | DefKind::AssocFn
             | DefKind::Trait
             | DefKind::TyParam
             | DefKind::Variant => (),
@@ -678,8 +678,8 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
 
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -920,7 +920,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
     }
 
     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
-        if attr::find_transparency(&md.attrs, md.legacy).0 != Transparency::Opaque {
+        if attr::find_transparency(&md.attrs, md.ast.macro_rules).0 != Transparency::Opaque {
             self.update(md.hir_id, Some(AccessLevel::Public));
             return;
         }
@@ -1049,8 +1049,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
 
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
@@ -1191,8 +1191,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
 
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
@@ -1298,7 +1298,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
             _ => None,
         };
         let def = def.filter(|(kind, _)| match kind {
-            DefKind::Method
+            DefKind::AssocFn
             | DefKind::AssocConst
             | DefKind::AssocTy
             | DefKind::AssocOpaqueTy
@@ -1447,9 +1447,9 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
-    type Map = Map<'v>;
+    type Map = intravisit::ErasedMap<'v>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1479,8 +1479,8 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
 
     /// We want to visit items in the context of their containing
     /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -1556,7 +1556,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                     || items.iter().any(|impl_item_ref| {
                         let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                         match impl_item.kind {
-                            hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) => {
+                            hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => {
                                 self.access_levels.is_reachable(impl_item_ref.id.hir_id)
                             }
                             hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {
@@ -1578,8 +1578,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                                 // types in private items.
                                 let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                                 match impl_item.kind {
-                                    hir::ImplItemKind::Const(..)
-                                    | hir::ImplItemKind::Method(..)
+                                    hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..)
                                         if self
                                             .item_is_public(&impl_item.hir_id, &impl_item.vis) =>
                                     {
@@ -1925,8 +1924,8 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
 impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
index 11a3cedcc74..49f079ad270 100644
--- a/src/librustc_resolve/Cargo.toml
+++ b/src/librustc_resolve/Cargo.toml
@@ -24,7 +24,6 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_expand = { path = "../librustc_expand" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_hir = { path = "../librustc_hir" }
-rustc_infer = { path = "../librustc_infer" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index ec5a8c4a0b8..ce3b1233a74 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -7,7 +7,7 @@
 
 use crate::def_collector::collect_definitions;
 use crate::imports::{Import, ImportKind};
-use crate::macros::{LegacyBinding, LegacyScope};
+use crate::macros::{MacroRulesBinding, MacroRulesScope};
 use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
 use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError};
 use crate::{
@@ -165,11 +165,11 @@ impl<'a> Resolver<'a> {
         &mut self,
         fragment: &AstFragment,
         parent_scope: ParentScope<'a>,
-    ) -> LegacyScope<'a> {
+    ) -> MacroRulesScope<'a> {
         collect_definitions(&mut self.definitions, fragment, parent_scope.expansion);
         let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope };
         fragment.visit_with(&mut visitor);
-        visitor.parent_scope.legacy
+        visitor.parent_scope.macro_rules
     }
 
     crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
@@ -302,7 +302,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
         // If any statements are items, we need to create an anonymous module
         block.stmts.iter().any(|statement| match statement.kind {
-            StmtKind::Item(_) | StmtKind::Mac(_) => true,
+            StmtKind::Item(_) | StmtKind::MacCall(_) => true,
             _ => false,
         })
     }
@@ -624,7 +624,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                     self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
                 };
 
-                let used = self.process_legacy_macro_imports(item, module);
+                let used = self.process_macro_use_imports(item, module);
                 let binding =
                     (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
                 let import = self.r.arenas.alloc_import(Import {
@@ -645,7 +645,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 self.r.potentially_unused_imports.push(import);
                 let imported_binding = self.r.import(binding, import);
                 if ptr::eq(parent, self.r.graph_root) {
-                    if let Some(entry) = self.r.extern_prelude.get(&ident.modern()) {
+                    if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0())
+                    {
                         if expansion != ExpnId::root()
                             && orig_name.is_some()
                             && entry.extern_crate_item.is_none()
@@ -656,10 +657,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                         }
                     }
                     let entry =
-                        self.r.extern_prelude.entry(ident.modern()).or_insert(ExternPreludeEntry {
-                            extern_crate_item: None,
-                            introduced_by_item: true,
-                        });
+                        self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
+                            ExternPreludeEntry {
+                                extern_crate_item: None,
+                                introduced_by_item: true,
+                            },
+                        );
                     entry.extern_crate_item = Some(imported_binding);
                     if orig_name.is_some() {
                         entry.introduced_by_item = true;
@@ -803,7 +806,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             // These items do not add names to modules.
             ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
 
-            ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
+            ItemKind::MacroDef(..) | ItemKind::MacCall(_) => unreachable!(),
         }
     }
 
@@ -819,7 +822,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             ForeignItemKind::TyAlias(..) => {
                 (Res::Def(DefKind::ForeignTy, self.r.definitions.local_def_id(item.id)), TypeNS)
             }
-            ForeignItemKind::Macro(_) => unreachable!(),
+            ForeignItemKind::MacCall(_) => unreachable!(),
         };
         let parent = self.parent_scope.module;
         let expansion = self.parent_scope.expansion;
@@ -874,7 +877,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             | Res::PrimTy(..)
             | Res::ToolMod => self.r.define(parent, ident, TypeNS, (res, vis, span, expansion)),
             Res::Def(DefKind::Fn, _)
-            | Res::Def(DefKind::Method, _)
+            | Res::Def(DefKind::AssocFn, _)
             | Res::Def(DefKind::Static, _)
             | Res::Def(DefKind::Const, _)
             | Res::Def(DefKind::AssocConst, _)
@@ -898,7 +901,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 let field_names = cstore.struct_field_names_untracked(def_id, self.r.session);
                 self.insert_field_names(def_id, field_names);
             }
-            Res::Def(DefKind::Method, def_id) => {
+            Res::Def(DefKind::AssocFn, def_id) => {
                 if cstore.associated_item_cloned_untracked(def_id).method_has_self_argument {
                     self.r.has_self.insert(def_id);
                 }
@@ -913,7 +916,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         }
     }
 
-    fn legacy_import_macro(
+    fn add_macro_use_binding(
         &mut self,
         name: ast::Name,
         binding: &'a NameBinding<'a>,
@@ -929,7 +932,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     }
 
     /// Returns `true` if we should consider the underlying `extern crate` to be used.
-    fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> bool {
+    fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool {
         let mut import_all = None;
         let mut single_imports = Vec::new();
         for attr in &item.attrs {
@@ -1004,7 +1007,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             module.for_each_child(self, |this, ident, ns, binding| {
                 if ns == MacroNS {
                     let imported_binding = this.r.import(binding, import);
-                    this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
+                    this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing);
                 }
             });
         } else {
@@ -1021,7 +1024,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                     let import = macro_use_import(self, ident.span);
                     self.r.potentially_unused_imports.push(import);
                     let imported_binding = self.r.import(binding, import);
-                    self.legacy_import_macro(
+                    self.add_macro_use_binding(
                         ident.name,
                         imported_binding,
                         ident.span,
@@ -1060,7 +1063,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         false
     }
 
-    fn visit_invoc(&mut self, id: NodeId) -> LegacyScope<'a> {
+    fn visit_invoc(&mut self, id: NodeId) -> MacroRulesScope<'a> {
         let invoc_id = id.placeholder_to_expn_id();
 
         self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
@@ -1068,7 +1071,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
         assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
 
-        LegacyScope::Invocation(invoc_id)
+        MacroRulesScope::Invocation(invoc_id)
     }
 
     fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
@@ -1095,20 +1098,20 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         }
     }
 
-    fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> {
+    fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScope<'a> {
         let parent_scope = self.parent_scope;
         let expansion = parent_scope.expansion;
-        let (ext, ident, span, is_legacy) = match &item.kind {
+        let (ext, ident, span, macro_rules) = match &item.kind {
             ItemKind::MacroDef(def) => {
                 let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition()));
-                (ext, item.ident, item.span, def.legacy)
+                (ext, item.ident, item.span, def.macro_rules)
             }
             ItemKind::Fn(..) => match Self::proc_macro_stub(item) {
                 Some((macro_kind, ident, span)) => {
                     self.r.proc_macro_stubs.insert(item.id);
                     (self.r.dummy_ext(macro_kind), ident, span, false)
                 }
-                None => return parent_scope.legacy,
+                None => return parent_scope.macro_rules,
             },
             _ => unreachable!(),
         };
@@ -1118,8 +1121,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         self.r.macro_map.insert(def_id, ext);
         self.r.local_macro_def_scopes.insert(item.id, parent_scope.module);
 
-        if is_legacy {
-            let ident = ident.modern();
+        if macro_rules {
+            let ident = ident.normalize_to_macros_2_0();
             self.r.macro_names.insert(ident);
             let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
             let vis = if is_macro_export {
@@ -1137,8 +1140,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 self.r.check_reserved_macro_name(ident, res);
                 self.insert_unused_macro(ident, item.id, span);
             }
-            LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding {
-                parent_legacy_scope: parent_scope.legacy,
+            MacroRulesScope::Binding(self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding {
+                parent_macro_rules_scope: parent_scope.macro_rules,
                 binding,
                 ident,
             }))
@@ -1149,7 +1152,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 self.insert_unused_macro(ident, item.id, span);
             }
             self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
-            self.parent_scope.legacy
+            self.parent_scope.macro_rules
         }
     }
 }
@@ -1167,43 +1170,43 @@ macro_rules! method {
 }
 
 impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
-    method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr);
-    method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat);
-    method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty);
+    method!(visit_expr: ast::Expr, ast::ExprKind::MacCall, walk_expr);
+    method!(visit_pat: ast::Pat, ast::PatKind::MacCall, walk_pat);
+    method!(visit_ty: ast::Ty, ast::TyKind::MacCall, walk_ty);
 
     fn visit_item(&mut self, item: &'b Item) {
         let macro_use = match item.kind {
             ItemKind::MacroDef(..) => {
-                self.parent_scope.legacy = self.define_macro(item);
+                self.parent_scope.macro_rules = self.define_macro(item);
                 return;
             }
-            ItemKind::Mac(..) => {
-                self.parent_scope.legacy = self.visit_invoc(item.id);
+            ItemKind::MacCall(..) => {
+                self.parent_scope.macro_rules = self.visit_invoc(item.id);
                 return;
             }
             ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
             _ => false,
         };
         let orig_current_module = self.parent_scope.module;
-        let orig_current_legacy_scope = self.parent_scope.legacy;
+        let orig_current_macro_rules_scope = self.parent_scope.macro_rules;
         self.build_reduced_graph_for_item(item);
         visit::walk_item(self, item);
         self.parent_scope.module = orig_current_module;
         if !macro_use {
-            self.parent_scope.legacy = orig_current_legacy_scope;
+            self.parent_scope.macro_rules = orig_current_macro_rules_scope;
         }
     }
 
     fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
-        if let ast::StmtKind::Mac(..) = stmt.kind {
-            self.parent_scope.legacy = self.visit_invoc(stmt.id);
+        if let ast::StmtKind::MacCall(..) = stmt.kind {
+            self.parent_scope.macro_rules = self.visit_invoc(stmt.id);
         } else {
             visit::walk_stmt(self, stmt);
         }
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) {
-        if let ForeignItemKind::Macro(_) = foreign_item.kind {
+        if let ForeignItemKind::MacCall(_) = foreign_item.kind {
             self.visit_invoc(foreign_item.id);
             return;
         }
@@ -1214,17 +1217,17 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
 
     fn visit_block(&mut self, block: &'b Block) {
         let orig_current_module = self.parent_scope.module;
-        let orig_current_legacy_scope = self.parent_scope.legacy;
+        let orig_current_macro_rules_scope = self.parent_scope.macro_rules;
         self.build_reduced_graph_for_block(block);
         visit::walk_block(self, block);
         self.parent_scope.module = orig_current_module;
-        self.parent_scope.legacy = orig_current_legacy_scope;
+        self.parent_scope.macro_rules = orig_current_macro_rules_scope;
     }
 
     fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
         let parent = self.parent_scope.module;
 
-        if let AssocItemKind::Macro(_) = item.kind {
+        if let AssocItemKind::MacCall(_) = item.kind {
             self.visit_invoc(item.id);
             return;
         }
@@ -1243,10 +1246,10 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
                 if sig.decl.has_self() {
                     self.r.has_self.insert(item_def_id);
                 }
-                (Res::Def(DefKind::Method, item_def_id), ValueNS)
+                (Res::Def(DefKind::AssocFn, item_def_id), ValueNS)
             }
             AssocItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS),
-            AssocItemKind::Macro(_) => bug!(), // handled above
+            AssocItemKind::MacCall(_) => bug!(), // handled above
         };
 
         let vis = ty::Visibility::Public;
@@ -1259,7 +1262,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
     fn visit_token(&mut self, t: Token) {
         if let token::Interpolated(nt) = t.kind {
             if let token::NtExpr(ref expr) = *nt {
-                if let ast::ExprKind::Mac(..) = expr.kind {
+                if let ast::ExprKind::MacCall(..) = expr.kind {
                     self.visit_invoc(expr.id);
                 }
             }
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 722f843ab6e..35876176e3e 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -26,12 +26,13 @@
 use crate::imports::ImportKind;
 use crate::Resolver;
 
-use rustc::{lint, ty};
+use rustc::ty;
 use rustc_ast::ast;
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::visit::{self, Visitor};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::pluralize;
+use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS};
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 
@@ -232,7 +233,7 @@ impl Resolver<'_> {
                     if let ImportKind::MacroUse = import.kind {
                         if !import.span.is_dummy() {
                             self.lint_buffer.buffer_lint(
-                                lint::builtin::MACRO_USE_EXTERN_CRATE,
+                                MACRO_USE_EXTERN_CRATE,
                                 import.id,
                                 import.span,
                                 "deprecated `#[macro_use]` attribute used to \
@@ -247,9 +248,8 @@ impl Resolver<'_> {
                     self.maybe_unused_extern_crates.push((import.id, import.span));
                 }
                 ImportKind::MacroUse => {
-                    let lint = lint::builtin::UNUSED_IMPORTS;
                     let msg = "unused `#[macro_use]` import";
-                    self.lint_buffer.buffer_lint(lint, import.id, import.span, msg);
+                    self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
                 }
                 _ => {}
             }
@@ -314,7 +314,7 @@ impl Resolver<'_> {
             };
 
             visitor.r.lint_buffer.buffer_lint_with_diagnostic(
-                lint::builtin::UNUSED_IMPORTS,
+                UNUSED_IMPORTS,
                 unused.use_tree_id,
                 ms,
                 &msg,
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index 0d276e68614..505cd331a25 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -2,9 +2,9 @@ use log::debug;
 use rustc::hir::map::definitions::*;
 use rustc_ast::ast::*;
 use rustc_ast::token::{self, Token};
-use rustc_ast::visit;
+use rustc_ast::visit::{self, FnKind};
 use rustc_expand::expand::AstFragment;
-use rustc_hir::def_id::DefIndex;
+use rustc_hir::def_id::LocalDefId;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -21,59 +21,23 @@ crate fn collect_definitions(
 /// Creates `DefId`s for nodes in the AST.
 struct DefCollector<'a> {
     definitions: &'a mut Definitions,
-    parent_def: DefIndex,
+    parent_def: LocalDefId,
     expansion: ExpnId,
 }
 
 impl<'a> DefCollector<'a> {
-    fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> DefIndex {
+    fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId {
         let parent_def = self.parent_def;
         debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
         self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span)
     }
 
-    fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
+    fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
         let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def);
         f(self);
         self.parent_def = orig_parent_def;
     }
 
-    fn visit_async_fn(
-        &mut self,
-        id: NodeId,
-        name: Name,
-        span: Span,
-        header: &FnHeader,
-        generics: &'a Generics,
-        decl: &'a FnDecl,
-        body: Option<&'a Block>,
-    ) {
-        let (closure_id, return_impl_trait_id) = match header.asyncness {
-            Async::Yes { span: _, closure_id, return_impl_trait_id } => {
-                (closure_id, return_impl_trait_id)
-            }
-            _ => unreachable!(),
-        };
-
-        // For async functions, we need to create their inner defs inside of a
-        // closure to match their desugared representation.
-        let fn_def_data = DefPathData::ValueNs(name);
-        let fn_def = self.create_def(id, fn_def_data, span);
-        return self.with_parent(fn_def, |this| {
-            this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
-
-            visit::walk_generics(this, generics);
-            visit::walk_fn_decl(this, decl);
-
-            let closure_def = this.create_def(closure_id, DefPathData::ClosureExpr, span);
-            this.with_parent(closure_def, |this| {
-                if let Some(body) = body {
-                    visit::walk_block(this, body);
-                }
-            })
-        });
-    }
-
     fn collect_field(&mut self, field: &'a StructField, index: Option<usize>) {
         let index = |this: &Self| {
             index.unwrap_or_else(|| {
@@ -117,22 +81,11 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             | ItemKind::ExternCrate(..)
             | ItemKind::ForeignMod(..)
             | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
-            ItemKind::Fn(_, sig, generics, body) if sig.header.asyncness.is_async() => {
-                return self.visit_async_fn(
-                    i.id,
-                    i.ident.name,
-                    i.span,
-                    &sig.header,
-                    generics,
-                    &sig.decl,
-                    body.as_deref(),
-                );
-            }
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => {
                 DefPathData::ValueNs(i.ident.name)
             }
             ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name),
-            ItemKind::Mac(..) => return self.visit_macro_invoc(i.id),
+            ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(..) => {
                 return visit::walk_item(self, i);
@@ -154,13 +107,34 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         });
     }
 
+    fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
+        if let FnKind::Fn(_, _, sig, _, body) = fn_kind {
+            if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness {
+                self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
+
+                // For async functions, we need to create their inner defs inside of a
+                // closure to match their desugared representation. Besides that,
+                // we must mirror everything that `visit::walk_fn` below does.
+                self.visit_fn_header(&sig.header);
+                visit::walk_fn_decl(self, &sig.decl);
+                if let Some(body) = body {
+                    let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span);
+                    self.with_parent(closure_def, |this| this.visit_block(body));
+                }
+                return;
+            }
+        }
+
+        visit::walk_fn(self, fn_kind, span);
+    }
+
     fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
         self.create_def(id, DefPathData::Misc, use_tree.span);
         visit::walk_use_tree(self, use_tree, id);
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
-        if let ForeignItemKind::Macro(_) = foreign_item.kind {
+        if let ForeignItemKind::MacCall(_) = foreign_item.kind {
             return self.visit_macro_invoc(foreign_item.id);
         }
 
@@ -215,22 +189,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
         let def_data = match &i.kind {
-            AssocItemKind::Fn(_, FnSig { header, decl }, generics, body)
-                if header.asyncness.is_async() =>
-            {
-                return self.visit_async_fn(
-                    i.id,
-                    i.ident.name,
-                    i.span,
-                    header,
-                    generics,
-                    decl,
-                    body.as_deref(),
-                );
-            }
             AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name),
             AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
-            AssocItemKind::Macro(..) => return self.visit_macro_invoc(i.id),
+            AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
         };
 
         let def = self.create_def(i.id, def_data, i.span);
@@ -239,7 +200,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_pat(&mut self, pat: &'a Pat) {
         match pat.kind {
-            PatKind::Mac(..) => return self.visit_macro_invoc(pat.id),
+            PatKind::MacCall(..) => return self.visit_macro_invoc(pat.id),
             _ => visit::walk_pat(self, pat),
         }
     }
@@ -251,7 +212,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_expr(&mut self, expr: &'a Expr) {
         let parent_def = match expr.kind {
-            ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
+            ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
             ExprKind::Closure(_, asyncness, ..) => {
                 // Async closures desugar to closures inside of closures, so
                 // we must create two defs.
@@ -274,7 +235,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_ty(&mut self, ty: &'a Ty) {
         match ty.kind {
-            TyKind::Mac(..) => return self.visit_macro_invoc(ty.id),
+            TyKind::MacCall(..) => return self.visit_macro_invoc(ty.id),
             TyKind::ImplTrait(node_id, _) => {
                 self.create_def(node_id, DefPathData::ImplTrait, ty.span);
             }
@@ -285,7 +246,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_stmt(&mut self, stmt: &'a Stmt) {
         match stmt.kind {
-            StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id),
+            StmtKind::MacCall(..) => self.visit_macro_invoc(stmt.id),
             _ => visit::walk_stmt(self, stmt),
         }
     }
@@ -293,7 +254,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_token(&mut self, t: Token) {
         if let token::Interpolated(nt) = t.kind {
             if let token::NtExpr(ref expr) = *nt {
-                if let ExprKind::Mac(..) = expr.kind {
+                if let ExprKind::MacCall(..) = expr.kind {
                     self.visit_macro_invoc(expr.id);
                 }
             }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 47a05ec90d4..6f567ab65a7 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1,8 +1,8 @@
 use std::cmp::Reverse;
+use std::ptr;
 
 use log::debug;
 use rustc::bug;
-use rustc::session::Session;
 use rustc::ty::{self, DefIdTree};
 use rustc_ast::ast::{self, Ident, Path};
 use rustc_ast::util::lev_distance::find_best_match_for_name;
@@ -13,6 +13,7 @@ use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Symbol};
@@ -21,7 +22,9 @@ use rustc_span::{BytePos, MultiSpan, Span};
 use crate::imports::{Import, ImportKind, ImportResolver};
 use crate::path_names_to_string;
 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
-use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
+use crate::{
+    BindingError, CrateLint, HasGenericParams, MacroRulesScope, Module, ModuleOrUniformRoot,
+};
 use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
 use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment};
 
@@ -498,12 +501,12 @@ impl<'a> Resolver<'a> {
                         }
                     }
                 }
-                Scope::MacroRules(legacy_scope) => {
-                    if let LegacyScope::Binding(legacy_binding) = legacy_scope {
-                        let res = legacy_binding.binding.res();
+                Scope::MacroRules(macro_rules_scope) => {
+                    if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope {
+                        let res = macro_rules_binding.binding.res();
                         if filter_fn(res) {
                             suggestions
-                                .push(TypoSuggestion::from_res(legacy_binding.ident.name, res))
+                                .push(TypoSuggestion::from_res(macro_rules_binding.ident.name, res))
                         }
                     }
                 }
@@ -756,7 +759,7 @@ impl<'a> Resolver<'a> {
             let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
             err.span_note(ident.span, &msg);
         }
-        if self.macro_names.contains(&ident.modern()) {
+        if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
             err.help("have you added the `#[macro_use]` on the module/import?");
         }
     }
@@ -916,50 +919,81 @@ impl<'a> Resolver<'a> {
         err.emit();
     }
 
-    crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
-        let PrivacyError { ident, binding, .. } = *privacy_error;
-        let session = &self.session;
-        let mk_struct_span_error = |is_constructor| {
-            let mut descr = binding.res().descr().to_string();
-            if is_constructor {
-                descr += " constructor";
-            }
-            if binding.is_import() {
-                descr += " import";
-            }
-
-            let mut err =
-                struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident);
-
-            err.span_label(ident.span, &format!("this {} is private", descr));
-            err.span_note(
-                session.source_map().def_span(binding.span),
-                &format!("the {} `{}` is defined here", descr, ident),
-            );
-
-            err
-        };
-
-        let mut err = if let NameBindingKind::Res(
+    /// If the binding refers to a tuple struct constructor with fields,
+    /// returns the span of its fields.
+    fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> {
+        if let NameBindingKind::Res(
             Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
             _,
         ) = binding.kind
         {
             let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
             if let Some(fields) = self.field_names.get(&def_id) {
-                let mut err = mk_struct_span_error(true);
                 let first_field = fields.first().expect("empty field list in the map");
-                err.span_label(
-                    fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
-                    "a constructor is private if any of the fields is private",
-                );
-                err
-            } else {
-                mk_struct_span_error(false)
+                return Some(fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)));
             }
-        } else {
-            mk_struct_span_error(false)
-        };
+        }
+        None
+    }
+
+    crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
+        let PrivacyError { ident, binding, .. } = *privacy_error;
+
+        let res = binding.res();
+        let ctor_fields_span = self.ctor_fields_span(binding);
+        let plain_descr = res.descr().to_string();
+        let nonimport_descr =
+            if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
+        let import_descr = nonimport_descr.clone() + " import";
+        let get_descr =
+            |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
+
+        // Print the primary message.
+        let descr = get_descr(binding);
+        let mut err =
+            struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident);
+        err.span_label(ident.span, &format!("this {} is private", descr));
+        if let Some(span) = ctor_fields_span {
+            err.span_label(span, "a constructor is private if any of the fields is private");
+        }
+
+        // Print the whole import chain to make it easier to see what happens.
+        let first_binding = binding;
+        let mut next_binding = Some(binding);
+        let mut next_ident = ident;
+        while let Some(binding) = next_binding {
+            let name = next_ident;
+            next_binding = match binding.kind {
+                _ if res == Res::Err => None,
+                NameBindingKind::Import { binding, import, .. } => match import.kind {
+                    _ if binding.span.is_dummy() => None,
+                    ImportKind::Single { source, .. } => {
+                        next_ident = source;
+                        Some(binding)
+                    }
+                    ImportKind::Glob { .. } | ImportKind::MacroUse => Some(binding),
+                    ImportKind::ExternCrate { .. } => None,
+                },
+                _ => None,
+            };
+
+            let first = ptr::eq(binding, first_binding);
+            let descr = get_descr(binding);
+            let msg = format!(
+                "{and_refers_to}the {item} `{name}`{which} is defined here{dots}",
+                and_refers_to = if first { "" } else { "...and refers to " },
+                item = descr,
+                name = name,
+                which = if first { "" } else { " which" },
+                dots = if next_binding.is_some() { "..." } else { "" },
+            );
+            let def_span = self.session.source_map().def_span(binding.span);
+            let mut note_span = MultiSpan::from_span(def_span);
+            if !first && binding.vis == ty::Visibility::Public {
+                note_span.push_span_label(def_span, "consider importing it directly".into());
+            }
+            err.span_note(note_span, &msg);
+        }
 
         err.emit();
     }
diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs
index 485b86636a0..663e61ad2ad 100644
--- a/src/librustc_resolve/imports.rs
+++ b/src/librustc_resolve/imports.rs
@@ -10,7 +10,6 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet
 use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
 
 use rustc::hir::exports::Export;
-use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
 use rustc::ty;
 use rustc::{bug, span_bug};
 use rustc_ast::ast::{Ident, Name, NodeId};
@@ -21,6 +20,7 @@ use rustc_data_structures::ptr_key::PtrKey;
 use rustc_errors::{pluralize, struct_span_err, Applicability};
 use rustc_hir::def::{self, PartialRes};
 use rustc_hir::def_id::DefId;
+use rustc_session::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::DiagnosticMessageId;
 use rustc_span::hygiene::ExpnId;
@@ -416,7 +416,8 @@ impl<'a> Resolver<'a> {
                 None => return Err((Undetermined, Weak::Yes)),
             };
             let tmp_parent_scope;
-            let (mut adjusted_parent_scope, mut ident) = (parent_scope, ident.modern());
+            let (mut adjusted_parent_scope, mut ident) =
+                (parent_scope, ident.normalize_to_macros_2_0());
             match ident.span.glob_adjust(module.expansion, glob_import.span) {
                 Some(Some(def)) => {
                     tmp_parent_scope =
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 97d60e1a23d..4a3c9f338d9 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -11,7 +11,7 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
 use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
-use rustc::{bug, lint, span_bug};
+use rustc::{bug, span_bug};
 use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_ast::util::lev_distance::find_best_match_for_name;
@@ -23,6 +23,7 @@ use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::TraitCandidate;
+use rustc_session::lint;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
@@ -266,7 +267,7 @@ impl<'a> PathSource<'a> {
                 | Res::Def(DefKind::Static, _)
                 | Res::Local(..)
                 | Res::Def(DefKind::Fn, _)
-                | Res::Def(DefKind::Method, _)
+                | Res::Def(DefKind::AssocFn, _)
                 | Res::Def(DefKind::AssocConst, _)
                 | Res::SelfCtor(..)
                 | Res::Def(DefKind::ConstParam, _) => true,
@@ -293,7 +294,7 @@ impl<'a> PathSource<'a> {
                 _ => false,
             },
             PathSource::TraitItem(ns) => match res {
-                Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _)
+                Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocFn, _)
                     if ns == ValueNS =>
                 {
                     true
@@ -449,7 +450,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                     visit::walk_foreign_item(this, foreign_item);
                 });
             }
-            ForeignItemKind::Macro(..) => {
+            ForeignItemKind::MacCall(..) => {
                 visit::walk_foreign_item(self, foreign_item);
             }
         }
@@ -852,7 +853,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                     AssocItemKind::TyAlias(_, generics, _, _) => {
                                         walk_assoc_item(this, generics, item);
                                     }
-                                    AssocItemKind::Macro(_) => {
+                                    AssocItemKind::MacCall(_) => {
                                         panic!("unexpanded macro in resolve!")
                                     }
                                 };
@@ -897,7 +898,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 // do nothing, these are just around to be encoded
             }
 
-            ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
+            ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
         }
     }
 
@@ -935,7 +936,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 _ => unreachable!(),
             };
 
-            let ident = param.ident.modern();
+            let ident = param.ident.normalize_to_macros_2_0();
             debug!("with_generic_param_rib: {}", param.id);
 
             if seen_bindings.contains_key(&ident) {
@@ -1174,7 +1175,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                                 },
                                             );
                                         }
-                                        AssocItemKind::Macro(_) => {
+                                        AssocItemKind::MacCall(_) => {
                                             panic!("unexpanded macro in resolve!")
                                         }
                                     }
@@ -1464,7 +1465,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         // Add the binding to the local ribs, if it doesn't already exist in the bindings map.
         // (We must not add it if it's in the bindings map because that breaks the assumptions
         // later passes make about or-patterns.)
-        let ident = ident.modern_and_legacy();
+        let ident = ident.normalize_to_macro_rules();
 
         let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident));
         // Already bound in a product pattern? e.g. `(a, a)` which is not allowed.
@@ -1517,9 +1518,17 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         ident: Ident,
         has_sub: bool,
     ) -> Option<Res> {
-        let binding =
-            self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?;
-        let res = binding.res();
+        let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?;
+        let (res, binding) = match ls_binding {
+            LexicalScopeBinding::Item(binding) if binding.is_ambiguity() => {
+                // For ambiguous bindings we don't know all their definitions and cannot check
+                // whether they can be shadowed by fresh bindings or not, so force an error.
+                self.r.record_use(ident, ValueNS, binding, false);
+                return None;
+            }
+            LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
+            LexicalScopeBinding::Res(res) => (res, None),
+        };
 
         // An immutable (no `mut`) by-value (no `ref`) binding pattern without
         // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
@@ -1527,11 +1536,15 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not);
 
         match res {
-            Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::Def(DefKind::Const, _)
+            Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
+            | Res::Def(DefKind::Const, _)
+            | Res::Def(DefKind::ConstParam, _)
                 if is_syntactic_ambiguity =>
             {
                 // Disambiguate in favor of a unit struct/variant or constant pattern.
-                self.r.record_use(ident, ValueNS, binding, false);
+                if let Some(binding) = binding {
+                    self.r.record_use(ident, ValueNS, binding, false);
+                }
                 Some(res)
             }
             Res::Def(DefKind::Ctor(..), _)
@@ -1547,23 +1560,20 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     ResolutionError::BindingShadowsSomethingUnacceptable(
                         pat_src.descr(),
                         ident.name,
-                        binding,
+                        binding.expect("no binding for a ctor or static"),
                     ),
                 );
                 None
             }
-            Res::Def(DefKind::Fn, _) | Res::Err => {
+            Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => {
                 // These entities are explicitly allowed to be shadowed by fresh bindings.
                 None
             }
-            res => {
-                span_bug!(
-                    ident.span,
-                    "unexpected resolution for an \
-                                        identifier in pattern: {:?}",
-                    res
-                );
-            }
+            _ => span_bug!(
+                ident.span,
+                "unexpected resolution for an identifier in pattern: {:?}",
+                res
+            ),
         }
     }
 
@@ -1864,7 +1874,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 self.diagnostic_metadata.unused_labels.insert(id, label.ident.span);
             }
             self.with_label_rib(NormalRibKind, |this| {
-                let ident = label.ident.modern_and_legacy();
+                let ident = label.ident.normalize_to_macro_rules();
                 this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
                 f(this);
             });
@@ -1940,7 +1950,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
 
             ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
                 let node_id = self.search_label(label.ident, |rib, ident| {
-                    rib.bindings.get(&ident.modern_and_legacy()).cloned()
+                    rib.bindings.get(&ident.normalize_to_macro_rules()).cloned()
                 });
                 match node_id {
                     None => {
@@ -2106,7 +2116,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             }
         }
 
-        ident.span = ident.span.modern();
+        ident.span = ident.span.normalize_to_macros_2_0();
         let mut search_module = self.parent_scope.module;
         loop {
             self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits);
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index fd62c802934..41380b2a4b7 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -5,7 +5,6 @@ use crate::path_names_to_string;
 use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{PathResult, PathSource, Segment};
 
-use rustc::session::config::nightly_options;
 use rustc_ast::ast::{self, Expr, ExprKind, Ident, Item, ItemKind, NodeId, Path, Ty, TyKind};
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashSet;
@@ -15,6 +14,7 @@ use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::PrimTy;
+use rustc_session::config::nightly_options;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -124,7 +124,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                             .unwrap_or(false)
                     }
                     Res::Def(DefKind::Ctor(..), _)
-                    | Res::Def(DefKind::Method, _)
+                    | Res::Def(DefKind::AssocFn, _)
                     | Res::Def(DefKind::Const, _)
                     | Res::Def(DefKind::AssocConst, _)
                     | Res::SelfCtor(_)
@@ -1107,11 +1107,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                 }
             };
 
-            match (
-                lifetime_names.len(),
-                lifetime_names.iter().next(),
-                snippet.as_ref().map(|s| s.as_str()),
-            ) {
+            match (lifetime_names.len(), lifetime_names.iter().next(), snippet.as_deref()) {
                 (1, Some(name), Some("&")) => {
                     suggest_existing(err, format!("&{} ", name));
                 }
diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs
index d2c20451f36..51bf1f48439 100644
--- a/src/librustc_resolve/late/lifetimes.rs
+++ b/src/librustc_resolve/late/lifetimes.rs
@@ -7,7 +7,6 @@
 
 use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
 use rustc::hir::map::Map;
-use rustc::lint;
 use rustc::middle::resolve_lifetime::*;
 use rustc::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
 use rustc::{bug, span_bug};
@@ -18,10 +17,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath};
 use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind};
+use rustc_session::lint;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use std::borrow::Cow;
@@ -62,7 +62,7 @@ impl RegionExt for Region {
         let def_id = hir_map.local_def_id(param.hir_id);
         let origin = LifetimeDefOrigin::from_param(param);
         debug!("Region::early: index={} def_id={:?}", i, def_id);
-        (param.name.modern(), Region::EarlyBound(i, def_id, origin))
+        (param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id, origin))
     }
 
     fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) {
@@ -73,7 +73,7 @@ impl RegionExt for Region {
             "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}",
             param, depth, def_id, origin,
         );
-        (param.name.modern(), Region::LateBound(depth, def_id, origin))
+        (param.name.normalize_to_macros_2_0(), Region::LateBound(depth, def_id, origin))
     }
 
     fn late_anon(index: &Cell<u32>) -> Region {
@@ -280,25 +280,14 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
     *providers = ty::query::Providers {
         resolve_lifetimes,
 
-        named_region_map: |tcx, id| {
-            let id = LocalDefId::from_def_id(DefId::local(id)); // (*)
-            tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id)
-        },
-
-        is_late_bound_map: |tcx, id| {
-            let id = LocalDefId::from_def_id(DefId::local(id)); // (*)
-            tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id)
-        },
-
+        named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id),
+        is_late_bound_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id),
         object_lifetime_defaults_map: |tcx, id| {
-            let id = LocalDefId::from_def_id(DefId::local(id)); // (*)
             tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id)
         },
 
         ..*providers
     };
-
-    // (*) FIXME the query should be defined to take a LocalDefId
 }
 
 /// Computes the `ResolveLifetimes` map that contains data for the
@@ -313,15 +302,15 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> &ResolveLifetimes
     let mut rl = ResolveLifetimes::default();
 
     for (hir_id, v) in named_region_map.defs {
-        let map = rl.defs.entry(hir_id.owner_local_def_id()).or_default();
+        let map = rl.defs.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
     for hir_id in named_region_map.late_bound {
-        let map = rl.late_bound.entry(hir_id.owner_local_def_id()).or_default();
+        let map = rl.late_bound.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id);
     }
     for (hir_id, v) in named_region_map.object_lifetime_defaults {
-        let map = rl.object_lifetime_defaults.entry(hir_id.owner_local_def_id()).or_default();
+        let map = rl.object_lifetime_defaults.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
 
@@ -367,8 +356,8 @@ fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool {
 impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::All(self.tcx.hir())
     }
 
     // We want to nest trait/impl items in their parent, but nothing else.
@@ -713,7 +702,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         use self::hir::TraitItemKind::*;
         self.missing_named_lifetime_spots.push((&trait_item.generics).into());
         match trait_item.kind {
-            Method(ref sig, _) => {
+            Fn(ref sig, _) => {
                 let tcx = self.tcx;
                 self.visit_early_late(
                     Some(tcx.hir().get_parent_item(trait_item.hir_id)),
@@ -771,7 +760,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         use self::hir::ImplItemKind::*;
         self.missing_named_lifetime_spots.push((&impl_item.generics).into());
         match impl_item.kind {
-            Method(ref sig, _) => {
+            Fn(ref sig, _) => {
                 let tcx = self.tcx;
                 self.visit_early_late(
                     Some(tcx.hir().get_parent_item(impl_item.hir_id)),
@@ -1123,9 +1112,9 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) {
     gather.visit_body(body);
 
     impl<'v, 'a, 'tcx> Visitor<'v> for GatherLabels<'a, 'tcx> {
-        type Map = Map<'v>;
+        type Map = intravisit::ErasedMap<'v>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -1174,7 +1163,9 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) {
 
                 Scope::Binder { ref lifetimes, s, .. } => {
                     // FIXME (#24278): non-hygienic comparison
-                    if let Some(def) = lifetimes.get(&hir::ParamName::Plain(label.modern())) {
+                    if let Some(def) =
+                        lifetimes.get(&hir::ParamName::Plain(label.normalize_to_macros_2_0()))
+                    {
                         let hir_id = tcx.hir().as_local_hir_id(def.id().unwrap()).unwrap();
 
                         signal_shadowing_problem(
@@ -1253,7 +1244,7 @@ fn object_lifetime_defaults_for_item(
     fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::GenericBound<'_>]) {
         for bound in bounds {
             if let hir::GenericBound::Outlives(ref lifetime) = *bound {
-                set.insert(lifetime.name.modern());
+                set.insert(lifetime.name.normalize_to_macros_2_0());
             }
         }
     }
@@ -1466,7 +1457,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         }
                     }
                     Node::ImplItem(impl_item) => {
-                        if let hir::ImplItemKind::Method(sig, _) = &impl_item.kind {
+                        if let hir::ImplItemKind::Fn(sig, _) = &impl_item.kind {
                             find_arg_use_span(sig.decl.inputs);
                         }
                     }
@@ -1791,7 +1782,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 Scope::Binder { ref lifetimes, s, .. } => {
                     match lifetime_ref.name {
                         LifetimeName::Param(param_name) => {
-                            if let Some(&def) = lifetimes.get(&param_name.modern()) {
+                            if let Some(&def) = lifetimes.get(&param_name.normalize_to_macros_2_0())
+                            {
                                 break Some(def.shifted(late_depth));
                             }
                         }
@@ -1816,12 +1808,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 match self.tcx.hir().get(fn_id) {
                     Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. })
                     | Node::TraitItem(&hir::TraitItem {
-                        kind: hir::TraitItemKind::Method(..),
-                        ..
+                        kind: hir::TraitItemKind::Fn(..), ..
                     })
-                    | Node::ImplItem(&hir::ImplItem {
-                        kind: hir::ImplItemKind::Method(..), ..
-                    }) => {
+                    | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
                         let scope = self.tcx.hir().local_def_id(fn_id);
                         def = Region::Free(scope, def.id().unwrap());
                     }
@@ -2093,9 +2082,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             // `fn` definitions and methods.
             Node::Item(&hir::Item { kind: hir::ItemKind::Fn(.., body), .. }) => Some(body),
 
-            Node::TraitItem(&hir::TraitItem {
-                kind: hir::TraitItemKind::Method(_, ref m), ..
-            }) => {
+            Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => {
                 if let hir::ItemKind::Trait(.., ref trait_items) =
                     self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
                 {
@@ -2103,12 +2090,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         trait_items.iter().find(|ti| ti.id.hir_id == parent).map(|ti| ti.kind);
                 }
                 match *m {
-                    hir::TraitMethod::Required(_) => None,
-                    hir::TraitMethod::Provided(body) => Some(body),
+                    hir::TraitFn::Required(_) => None,
+                    hir::TraitFn::Provided(body) => Some(body),
                 }
             }
 
-            Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(_, body), .. }) => {
+            Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => {
                 if let hir::ItemKind::Impl { ref self_ty, ref items, .. } =
                     self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
                 {
@@ -2175,9 +2162,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             }
 
             impl<'a> Visitor<'a> for SelfVisitor<'a> {
-                type Map = Map<'a>;
+                type Map = intravisit::ErasedMap<'a>;
 
-                fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+                fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
                     NestedVisitorMap::None
                 }
 
@@ -2266,9 +2253,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         }
 
         impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> {
-            type Map = Map<'v>;
+            type Map = intravisit::ErasedMap<'v>;
 
-            fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+            fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
                 NestedVisitorMap::None
             }
 
@@ -2547,7 +2534,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         let lifetimes: Vec<_> = params
             .iter()
             .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => Some((param, param.name.modern())),
+                GenericParamKind::Lifetime { .. } => {
+                    Some((param, param.name.normalize_to_macros_2_0()))
+                }
                 _ => None,
             })
             .collect();
@@ -2664,7 +2653,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 }
 
                 Scope::Binder { ref lifetimes, s, .. } => {
-                    if let Some(&def) = lifetimes.get(&param.name.modern()) {
+                    if let Some(&def) = lifetimes.get(&param.name.normalize_to_macros_2_0()) {
                         let hir_id = self.tcx.hir().as_local_hir_id(def.id().unwrap()).unwrap();
 
                         signal_shadowing_problem(
@@ -2802,7 +2791,7 @@ fn insert_late_bound_lifetimes(
                 // `'a: 'b` means both `'a` and `'b` are referenced
                 appears_in_where_clause
                     .regions
-                    .insert(hir::LifetimeName::Param(param.name.modern()));
+                    .insert(hir::LifetimeName::Param(param.name.normalize_to_macros_2_0()));
             }
         }
     }
@@ -2824,7 +2813,7 @@ fn insert_late_bound_lifetimes(
             hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
         }
 
-        let lt_name = hir::LifetimeName::Param(param.name.modern());
+        let lt_name = hir::LifetimeName::Param(param.name.normalize_to_macros_2_0());
         // appears in the where clauses? early-bound.
         if appears_in_where_clause.regions.contains(&lt_name) {
             continue;
@@ -2855,9 +2844,9 @@ fn insert_late_bound_lifetimes(
     }
 
     impl<'v> Visitor<'v> for ConstrainedCollector {
-        type Map = Map<'v>;
+        type Map = intravisit::ErasedMap<'v>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -2888,7 +2877,7 @@ fn insert_late_bound_lifetimes(
         }
 
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
-            self.regions.insert(lifetime_ref.name.modern());
+            self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0());
         }
     }
 
@@ -2898,14 +2887,14 @@ fn insert_late_bound_lifetimes(
     }
 
     impl<'v> Visitor<'v> for AllCollector {
-        type Map = Map<'v>;
+        type Map = intravisit::ErasedMap<'v>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
-            self.regions.insert(lifetime_ref.name.modern());
+            self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0());
         }
     }
 }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 492ac6ed839..4a2a2a296fa 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -18,7 +18,6 @@ use Determinacy::*;
 
 use rustc::hir::exports::ExportMap;
 use rustc::hir::map::{DefKey, Definitions};
-use rustc::lint;
 use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn};
 use rustc::span_bug;
 use rustc::ty::query::Providers;
@@ -38,10 +37,11 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX};
 use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint};
 use rustc_hir::{GlobMap, TraitMap};
 use rustc_metadata::creader::{CStore, CrateLoader};
+use rustc_session::lint;
 use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
@@ -58,7 +58,7 @@ use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_ne
 use diagnostics::{ImportSuggestion, Suggestion};
 use imports::{Import, ImportKind, ImportResolver, NameResolution};
 use late::{HasGenericParams, PathSource, Rib, RibKind::*};
-use macros::{LegacyBinding, LegacyScope};
+use macros::{MacroRulesBinding, MacroRulesScope};
 
 type Res = def::Res<NodeId>;
 
@@ -94,7 +94,7 @@ impl Determinacy {
 enum Scope<'a> {
     DeriveHelpers(ExpnId),
     DeriveHelpersCompat,
-    MacroRules(LegacyScope<'a>),
+    MacroRules(MacroRulesScope<'a>),
     CrateRoot,
     Module(Module<'a>),
     RegisteredAttrs,
@@ -127,7 +127,7 @@ enum ScopeSet {
 pub struct ParentScope<'a> {
     module: Module<'a>,
     expansion: ExpnId,
-    legacy: LegacyScope<'a>,
+    macro_rules: MacroRulesScope<'a>,
     derives: &'a [ast::Path],
 }
 
@@ -135,7 +135,12 @@ impl<'a> ParentScope<'a> {
     /// Creates a parent scope with the passed argument used as the module scope component,
     /// and other scope components set to default empty values.
     pub fn module(module: Module<'a>) -> ParentScope<'a> {
-        ParentScope { module, expansion: ExpnId::root(), legacy: LegacyScope::Empty, derives: &[] }
+        ParentScope {
+            module,
+            expansion: ExpnId::root(),
+            macro_rules: MacroRulesScope::Empty,
+            derives: &[],
+        }
     }
 }
 
@@ -323,13 +328,6 @@ enum LexicalScopeBinding<'a> {
 }
 
 impl<'a> LexicalScopeBinding<'a> {
-    fn item(self) -> Option<&'a NameBinding<'a>> {
-        match self {
-            LexicalScopeBinding::Item(binding) => Some(binding),
-            _ => None,
-        }
-    }
-
     fn res(self) -> Res {
         match self {
             LexicalScopeBinding::Item(binding) => binding.res(),
@@ -426,7 +424,7 @@ impl ModuleKind {
 /// program) if all but one of them come from glob imports.
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 struct BindingKey {
-    /// The identifier for the binding, aways the `modern` version of the
+    /// The identifier for the binding, aways the `normalize_to_macros_2_0` version of the
     /// identifier.
     ident: Ident,
     ns: Namespace,
@@ -620,7 +618,7 @@ enum AmbiguityKind {
     Import,
     BuiltinAttr,
     DeriveHelper,
-    LegacyVsModern,
+    MacroRulesVsModularized,
     GlobVsOuter,
     GlobVsGlob,
     GlobVsExpanded,
@@ -633,7 +631,9 @@ impl AmbiguityKind {
             AmbiguityKind::Import => "name vs any other name during import resolution",
             AmbiguityKind::BuiltinAttr => "built-in attribute vs any other name",
             AmbiguityKind::DeriveHelper => "derive helper attribute vs any other name",
-            AmbiguityKind::LegacyVsModern => "`macro_rules` vs non-`macro_rules` from other module",
+            AmbiguityKind::MacroRulesVsModularized => {
+                "`macro_rules` vs non-`macro_rules` from other module"
+            }
             AmbiguityKind::GlobVsOuter => {
                 "glob import vs any other name from outer scope during import/macro resolution"
             }
@@ -741,7 +741,7 @@ impl<'a> NameBinding<'a> {
     fn is_importable(&self) -> bool {
         match self.res() {
             Res::Def(DefKind::AssocConst, _)
-            | Res::Def(DefKind::Method, _)
+            | Res::Def(DefKind::AssocFn, _)
             | Res::Def(DefKind::AssocTy, _) => false,
             _ => true,
         }
@@ -937,9 +937,9 @@ pub struct Resolver<'a> {
     /// Parent scopes in which the macros were invoked.
     /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere.
     invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>,
-    /// Legacy scopes *produced* by expanding the macro invocations,
+    /// `macro_rules` scopes *produced* by expanding the macro invocations,
     /// include all the `macro_rules` items and other invocations generated by them.
-    output_legacy_scopes: FxHashMap<ExpnId, LegacyScope<'a>>,
+    output_macro_rules_scopes: FxHashMap<ExpnId, MacroRulesScope<'a>>,
     /// Helper attributes that are in scope for the given expansion.
     helper_attrs: FxHashMap<ExpnId, Vec<Ident>>,
 
@@ -972,7 +972,7 @@ pub struct ResolverArenas<'a> {
     name_bindings: arena::TypedArena<NameBinding<'a>>,
     imports: arena::TypedArena<Import<'a>>,
     name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
-    legacy_bindings: arena::TypedArena<LegacyBinding<'a>>,
+    macro_rules_bindings: arena::TypedArena<MacroRulesBinding<'a>>,
     ast_paths: arena::TypedArena<ast::Path>,
 }
 
@@ -996,8 +996,11 @@ impl<'a> ResolverArenas<'a> {
     fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
         self.name_resolutions.alloc(Default::default())
     }
-    fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> {
-        self.legacy_bindings.alloc(binding)
+    fn alloc_macro_rules_binding(
+        &'a self,
+        binding: MacroRulesBinding<'a>,
+    ) -> &'a MacroRulesBinding<'a> {
+        self.macro_rules_bindings.alloc(binding)
     }
     fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] {
         self.ast_paths.alloc_from_iter(paths.iter().cloned())
@@ -1012,9 +1015,9 @@ impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
 
 impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
     fn parent(self, id: DefId) -> Option<DefId> {
-        match id.krate {
-            LOCAL_CRATE => self.definitions.def_key(id.index).parent,
-            _ => self.cstore().def_key(id).parent,
+        match id.as_local() {
+            Some(id) => self.definitions.def_key(id).parent,
+            None => self.cstore().def_key(id).parent,
         }
         .map(|index| DefId { index, ..id })
     }
@@ -1024,7 +1027,11 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
 /// the resolver is no longer needed as all the relevant information is inline.
 impl rustc_ast_lowering::Resolver for Resolver<'_> {
     fn def_key(&mut self, id: DefId) -> DefKey {
-        if id.is_local() { self.definitions().def_key(id.index) } else { self.cstore().def_key(id) }
+        if let Some(id) = id.as_local() {
+            self.definitions().def_key(id)
+        } else {
+            self.cstore().def_key(id)
+        }
     }
 
     fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
@@ -1217,7 +1224,7 @@ impl<'a> Resolver<'a> {
             dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())),
             non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
             invocation_parent_scopes,
-            output_legacy_scopes: Default::default(),
+            output_macro_rules_scopes: Default::default(),
             helper_attrs: Default::default(),
             macro_defs,
             local_macro_def_scopes: FxHashMap::default(),
@@ -1359,7 +1366,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
-        let ident = ident.modern();
+        let ident = ident.normalize_to_macros_2_0();
         let disambiguator = if ident.name == kw::Underscore {
             self.underscore_disambiguator += 1;
             self.underscore_disambiguator
@@ -1410,7 +1417,7 @@ impl<'a> Resolver<'a> {
             // Avoid marking `extern crate` items that refer to a name from extern prelude,
             // but not introduce it, as used if they are accessed from lexical scope.
             if is_lexical_scope {
-                if let Some(entry) = self.extern_prelude.get(&ident.modern()) {
+                if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
                     if let Some(crate_item) = entry.extern_crate_item {
                         if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item {
                             return;
@@ -1472,7 +1479,7 @@ impl<'a> Resolver<'a> {
         //    derives (you need to resolve the derive first to add helpers into scope), but they
         //    should be available before the derive is expanded for compatibility.
         //    It's mess in general, so we are being conservative for now.
-        // 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher
+        // 1-3. `macro_rules` (open, not controlled), loop through `macro_rules` scopes. Have higher
         //    priority than prelude macros, but create ambiguities with macros in modules.
         // 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
         //    (open, not controlled). Have higher priority than prelude macros, but create
@@ -1497,7 +1504,7 @@ impl<'a> Resolver<'a> {
             TypeNS | ValueNS => Scope::Module(module),
             MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
         };
-        let mut ident = ident.modern();
+        let mut ident = ident.normalize_to_macros_2_0();
         let mut use_prelude = !module.no_implicit_prelude;
 
         loop {
@@ -1537,16 +1544,18 @@ impl<'a> Resolver<'a> {
                     }
                 }
                 Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat,
-                Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.legacy),
-                Scope::MacroRules(legacy_scope) => match legacy_scope {
-                    LegacyScope::Binding(binding) => Scope::MacroRules(binding.parent_legacy_scope),
-                    LegacyScope::Invocation(invoc_id) => Scope::MacroRules(
-                        self.output_legacy_scopes
+                Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),
+                Scope::MacroRules(macro_rules_scope) => match macro_rules_scope {
+                    MacroRulesScope::Binding(binding) => {
+                        Scope::MacroRules(binding.parent_macro_rules_scope)
+                    }
+                    MacroRulesScope::Invocation(invoc_id) => Scope::MacroRules(
+                        self.output_macro_rules_scopes
                             .get(&invoc_id)
                             .cloned()
-                            .unwrap_or(self.invocation_parent_scopes[&invoc_id].legacy),
+                            .unwrap_or(self.invocation_parent_scopes[&invoc_id].macro_rules),
                     ),
-                    LegacyScope::Empty => Scope::Module(module),
+                    MacroRulesScope::Empty => Scope::Module(module),
                 },
                 Scope::CrateRoot => match ns {
                     TypeNS => {
@@ -1617,18 +1626,18 @@ impl<'a> Resolver<'a> {
         if ident.name == kw::Invalid {
             return Some(LexicalScopeBinding::Res(Res::Err));
         }
-        let (general_span, modern_span) = if ident.name == kw::SelfUpper {
+        let (general_span, normalized_span) = if ident.name == kw::SelfUpper {
             // FIXME(jseyfried) improve `Self` hygiene
             let empty_span = ident.span.with_ctxt(SyntaxContext::root());
             (empty_span, empty_span)
         } else if ns == TypeNS {
-            let modern_span = ident.span.modern();
-            (modern_span, modern_span)
+            let normalized_span = ident.span.normalize_to_macros_2_0();
+            (normalized_span, normalized_span)
         } else {
-            (ident.span.modern_and_legacy(), ident.span.modern())
+            (ident.span.normalize_to_macro_rules(), ident.span.normalize_to_macros_2_0())
         };
         ident.span = general_span;
-        let modern_ident = Ident { span: modern_span, ..ident };
+        let normalized_ident = Ident { span: normalized_span, ..ident };
 
         // Walk backwards up the ribs in scope.
         let record_used = record_used_id.is_some();
@@ -1636,8 +1645,8 @@ impl<'a> Resolver<'a> {
         for i in (0..ribs.len()).rev() {
             debug!("walk rib\n{:?}", ribs[i].bindings);
             // Use the rib kind to determine whether we are resolving parameters
-            // (modern hygiene) or local variables (legacy hygiene).
-            let rib_ident = if ribs[i].kind.contains_params() { modern_ident } else { ident };
+            // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
+            let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident };
             if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
@@ -1680,7 +1689,7 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        ident = modern_ident;
+        ident = normalized_ident;
         let mut poisoned = None;
         loop {
             let opt_module = if let Some(node_id) = record_used_id {
@@ -1849,14 +1858,14 @@ impl<'a> Resolver<'a> {
         let mut adjusted_parent_scope = parent_scope;
         match module {
             ModuleOrUniformRoot::Module(m) => {
-                if let Some(def) = ident.span.modernize_and_adjust(m.expansion) {
+                if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) {
                     tmp_parent_scope =
                         ParentScope { module: self.macro_def_scope(def), ..*parent_scope };
                     adjusted_parent_scope = &tmp_parent_scope;
                 }
             }
             ModuleOrUniformRoot::ExternPrelude => {
-                ident.span.modernize_and_adjust(ExpnId::root());
+                ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root());
             }
             ModuleOrUniformRoot::CrateRootAndExternPrelude | ModuleOrUniformRoot::CurrentScope => {
                 // No adjustments
@@ -1879,14 +1888,14 @@ impl<'a> Resolver<'a> {
         let mark = if ident.name == kw::DollarCrate {
             // When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
             // we don't want to pretend that the `macro_rules!` definition is in the `macro`
-            // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
+            // as described in `SyntaxContext::apply_mark`, so we ignore prepended opaque marks.
             // FIXME: This is only a guess and it doesn't work correctly for `macro_rules!`
             // definitions actually produced by `macro` and `macro` definitions produced by
             // `macro_rules!`, but at least such configurations are not stable yet.
-            ctxt = ctxt.modern_and_legacy();
+            ctxt = ctxt.normalize_to_macro_rules();
             let mut iter = ctxt.marks().into_iter().rev().peekable();
             let mut result = None;
-            // Find the last modern mark from the end if it exists.
+            // Find the last opaque mark from the end if it exists.
             while let Some(&(mark, transparency)) = iter.peek() {
                 if transparency == Transparency::Opaque {
                     result = Some(mark);
@@ -1895,7 +1904,7 @@ impl<'a> Resolver<'a> {
                     break;
                 }
             }
-            // Then find the last legacy mark from the end if it exists.
+            // Then find the last semi-transparent mark from the end if it exists.
             for (mark, transparency) in iter {
                 if transparency == Transparency::SemiTransparent {
                     result = Some(mark);
@@ -1905,7 +1914,7 @@ impl<'a> Resolver<'a> {
             }
             result
         } else {
-            ctxt = ctxt.modern();
+            ctxt = ctxt.normalize_to_macros_2_0();
             ctxt.adjust(ExpnId::root())
         };
         let module = match mark {
@@ -1917,7 +1926,7 @@ impl<'a> Resolver<'a> {
 
     fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> {
         let mut module = self.get_module(module.normal_ancestor_id);
-        while module.span.ctxt().modern() != *ctxt {
+        while module.span.ctxt().normalize_to_macros_2_0() != *ctxt {
             let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark()));
             module = self.get_module(parent.normal_ancestor_id);
         }
@@ -1985,7 +1994,7 @@ impl<'a> Resolver<'a> {
 
             if ns == TypeNS {
                 if allow_super && name == kw::Super {
-                    let mut ctxt = ident.span.ctxt().modern();
+                    let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
                     let self_module = match i {
                         0 => Some(self.resolve_self(&mut ctxt, parent_scope.module)),
                         _ => match module {
@@ -2011,7 +2020,7 @@ impl<'a> Resolver<'a> {
                 }
                 if i == 0 {
                     if name == kw::SelfLower {
-                        let mut ctxt = ident.span.ctxt().modern();
+                        let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
                         module = Some(ModuleOrUniformRoot::Module(
                             self.resolve_self(&mut ctxt, parent_scope.module),
                         ));
@@ -2183,11 +2192,8 @@ impl<'a> Resolver<'a> {
                                     Applicability::MaybeIncorrect,
                                 )),
                             )
-                        } else if !ident.is_reserved() {
-                            (format!("maybe a missing crate `{}`?", ident), None)
                         } else {
-                            // the parser will already have complained about the keyword being used
-                            return PathResult::NonModule(PartialRes::new(Res::Err));
+                            (format!("maybe a missing crate `{}`?", ident), None)
                         }
                     } else if i == 0 {
                         (format!("use of undeclared type or module `{}`", ident), None)
@@ -2420,21 +2426,21 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn disambiguate_legacy_vs_modern(
+    fn disambiguate_macro_rules_vs_modularized(
         &self,
-        legacy: &'a NameBinding<'a>,
-        modern: &'a NameBinding<'a>,
+        macro_rules: &'a NameBinding<'a>,
+        modularized: &'a NameBinding<'a>,
     ) -> bool {
-        // Some non-controversial subset of ambiguities "modern macro name" vs "macro_rules"
+        // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules"
         // is disambiguated to mitigate regressions from macro modularization.
         // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general.
         match (
-            self.binding_parent_modules.get(&PtrKey(legacy)),
-            self.binding_parent_modules.get(&PtrKey(modern)),
+            self.binding_parent_modules.get(&PtrKey(macro_rules)),
+            self.binding_parent_modules.get(&PtrKey(modularized)),
         ) {
-            (Some(legacy), Some(modern)) => {
-                legacy.normal_ancestor_id == modern.normal_ancestor_id
-                    && modern.is_ancestor_of(legacy)
+            (Some(macro_rules), Some(modularized)) => {
+                macro_rules.normal_ancestor_id == modularized.normal_ancestor_id
+                    && modularized.is_ancestor_of(macro_rules)
             }
             _ => false,
         }
@@ -2764,7 +2770,7 @@ impl<'a> Resolver<'a> {
             // Make sure `self`, `super` etc produce an error when passed to here.
             return None;
         }
-        self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| {
+        self.extern_prelude.get(&ident.normalize_to_macros_2_0()).cloned().and_then(|entry| {
             if let Some(binding) = entry.extern_crate_item {
                 if !speculative && entry.introduced_by_item {
                     self.record_use(ident, TypeNS, binding, false);
@@ -2773,12 +2779,8 @@ impl<'a> Resolver<'a> {
             } else {
                 let crate_id = if !speculative {
                     self.crate_loader.process_path_extern(ident.name, ident.span)
-                } else if let Some(crate_id) =
-                    self.crate_loader.maybe_process_path_extern(ident.name, ident.span)
-                {
-                    crate_id
                 } else {
-                    return None;
+                    self.crate_loader.maybe_process_path_extern(ident.name, ident.span)?
                 };
                 let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                 Some(
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index e11aec90669..6f2e0bce3ac 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -7,9 +7,7 @@ use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy};
 use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
 use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
 use rustc::middle::stability;
-use rustc::session::parse::feature_err;
-use rustc::session::Session;
-use rustc::{lint, span_bug, ty};
+use rustc::{span_bug, ty};
 use rustc_ast::ast::{self, Ident, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, StabilityLevel};
@@ -21,6 +19,9 @@ use rustc_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationK
 use rustc_feature::is_builtin_attr_name;
 use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
 use rustc_hir::def_id;
+use rustc_session::lint::builtin::UNUSED_MACROS;
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -33,26 +34,26 @@ use std::{mem, ptr};
 type Res = def::Res<NodeId>;
 
 /// Binding produced by a `macro_rules` item.
-/// Not modularized, can shadow previous legacy bindings, etc.
+/// Not modularized, can shadow previous `macro_rules` bindings, etc.
 #[derive(Debug)]
-pub struct LegacyBinding<'a> {
+pub struct MacroRulesBinding<'a> {
     crate binding: &'a NameBinding<'a>,
-    /// Legacy scope into which the `macro_rules` item was planted.
-    crate parent_legacy_scope: LegacyScope<'a>,
+    /// `macro_rules` scope into which the `macro_rules` item was planted.
+    crate parent_macro_rules_scope: MacroRulesScope<'a>,
     crate ident: Ident,
 }
 
 /// The scope introduced by a `macro_rules!` macro.
 /// This starts at the macro's definition and ends at the end of the macro's parent
 /// module (named or unnamed), or even further if it escapes with `#[macro_use]`.
-/// Some macro invocations need to introduce legacy scopes too because they
+/// Some macro invocations need to introduce `macro_rules` scopes too because they
 /// can potentially expand into macro definitions.
 #[derive(Copy, Clone, Debug)]
-pub enum LegacyScope<'a> {
+pub enum MacroRulesScope<'a> {
     /// Empty "root" scope at the crate start containing no names.
     Empty,
     /// The scope introduced by a `macro_rules!` macro definition.
-    Binding(&'a LegacyBinding<'a>),
+    Binding(&'a MacroRulesBinding<'a>),
     /// The scope introduced by a macro invocation that can potentially
     /// create a `macro_rules!` macro definition.
     Invocation(ExpnId),
@@ -159,8 +160,8 @@ impl<'a> base::Resolver for Resolver<'a> {
         // Integrate the new AST fragment into all the definition and module structures.
         // We are inside the `expansion` now, but other parent scope components are still the same.
         let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
-        let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope);
-        self.output_legacy_scopes.insert(expansion, output_legacy_scope);
+        let output_macro_rules_scope = self.build_reduced_graph(fragment, parent_scope);
+        self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope);
 
         parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion);
     }
@@ -258,7 +259,13 @@ impl<'a> base::Resolver for Resolver<'a> {
                             force,
                         ) {
                             Ok((Some(ext), _)) => {
-                                let span = path.segments.last().unwrap().ident.span.modern();
+                                let span = path
+                                    .segments
+                                    .last()
+                                    .unwrap()
+                                    .ident
+                                    .span
+                                    .normalize_to_macros_2_0();
                                 helper_attrs.extend(
                                     ext.helper_attrs.iter().map(|name| Ident::new(*name, span)),
                                 );
@@ -323,12 +330,7 @@ impl<'a> base::Resolver for Resolver<'a> {
 
     fn check_unused_macros(&mut self) {
         for (&node_id, &span) in self.unused_macros.iter() {
-            self.lint_buffer.buffer_lint(
-                lint::builtin::UNUSED_MACROS,
-                node_id,
-                span,
-                "unused macro definition",
-            );
+            self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition");
         }
     }
 
@@ -339,6 +341,42 @@ impl<'a> base::Resolver for Resolver<'a> {
     fn add_derive_copy(&mut self, expn_id: ExpnId) {
         self.containers_deriving_copy.insert(expn_id);
     }
+
+    // The function that implements the resolution logic of `#[cfg_accessible(path)]`.
+    // Returns true if the path can certainly be resolved in one of three namespaces,
+    // returns false if the path certainly cannot be resolved in any of the three namespaces.
+    // Returns `Indeterminate` if we cannot give a certain answer yet.
+    fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate> {
+        let span = path.span;
+        let path = &Segment::from_path(path);
+        let parent_scope = self.invocation_parent_scopes[&expn_id];
+
+        let mut indeterminate = false;
+        for ns in [TypeNS, ValueNS, MacroNS].iter().copied() {
+            match self.resolve_path(path, Some(ns), &parent_scope, false, span, CrateLint::No) {
+                PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
+                PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
+                    return Ok(true);
+                }
+                PathResult::Indeterminate => indeterminate = true,
+                // FIXME: `resolve_path` is not ready to report partially resolved paths
+                // correctly, so we just report an error if the path was reported as unresolved.
+                // This needs to be fixed for `cfg_accessible` to be useful.
+                PathResult::NonModule(..) | PathResult::Failed { .. } => {}
+                PathResult::Module(_) => panic!("unexpected path resolution"),
+            }
+        }
+
+        if indeterminate {
+            return Err(Indeterminate);
+        }
+
+        self.session
+            .struct_span_err(span, "not sure whether the path is accessible or not")
+            .span_note(span, "`cfg_accessible` is not fully implemented")
+            .emit();
+        Ok(false)
+    }
 }
 
 impl<'a> Resolver<'a> {
@@ -608,12 +646,14 @@ impl<'a> Resolver<'a> {
                         }
                         result
                     }
-                    Scope::MacroRules(legacy_scope) => match legacy_scope {
-                        LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident => {
-                            Ok((legacy_binding.binding, Flags::MACRO_RULES))
+                    Scope::MacroRules(macro_rules_scope) => match macro_rules_scope {
+                        MacroRulesScope::Binding(macro_rules_binding)
+                            if ident == macro_rules_binding.ident =>
+                        {
+                            Ok((macro_rules_binding.binding, Flags::MACRO_RULES))
                         }
-                        LegacyScope::Invocation(invoc_id)
-                            if !this.output_legacy_scopes.contains_key(&invoc_id) =>
+                        MacroRulesScope::Invocation(invoc_id)
+                            if !this.output_macro_rules_scopes.contains_key(&invoc_id) =>
                         {
                             Err(Determinacy::Undetermined)
                         }
@@ -759,16 +799,18 @@ impl<'a> Resolver<'a> {
                                     Some(AmbiguityKind::DeriveHelper)
                                 } else if innermost_flags.contains(Flags::MACRO_RULES)
                                     && flags.contains(Flags::MODULE)
-                                    && !this
-                                        .disambiguate_legacy_vs_modern(innermost_binding, binding)
+                                    && !this.disambiguate_macro_rules_vs_modularized(
+                                        innermost_binding,
+                                        binding,
+                                    )
                                     || flags.contains(Flags::MACRO_RULES)
                                         && innermost_flags.contains(Flags::MODULE)
-                                        && !this.disambiguate_legacy_vs_modern(
+                                        && !this.disambiguate_macro_rules_vs_modularized(
                                             binding,
                                             innermost_binding,
                                         )
                                 {
-                                    Some(AmbiguityKind::LegacyVsModern)
+                                    Some(AmbiguityKind::MacroRulesVsModularized)
                                 } else if innermost_binding.is_glob_import() {
                                     Some(AmbiguityKind::GlobVsOuter)
                                 } else if innermost_binding
diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml
index 0f4cc4192b6..4717664b6ba 100644
--- a/src/librustc_save_analysis/Cargo.toml
+++ b/src/librustc_save_analysis/Cargo.toml
@@ -18,6 +18,7 @@ rustc_hir = { path = "../librustc_hir" }
 rustc_parse = { path = "../librustc_parse" }
 serde_json = "1"
 rustc_ast = { path = "../librustc_ast" }
+rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rls-data = "0.19"
 rls-span = "0.5"
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 72c962749c8..8d1a39eab89 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -13,7 +13,6 @@
 //! DumpVisitor walks the AST and processes it, and Dumper is used for
 //! recording the output.
 
-use rustc::session::config::Input;
 use rustc::span_bug;
 use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc_ast::ast::{self, Attribute, NodeId, PatKind};
@@ -25,6 +24,7 @@ use rustc_ast_pretty::pprust::{bounds_to_string, generic_params_to_string, ty_to
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind as HirDefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_session::config::Input;
 use rustc_span::source_map::{respan, DUMMY_SP};
 use rustc_span::*;
 
@@ -1067,7 +1067,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     self.visit_ty(default_ty)
                 }
             }
-            ast::AssocItemKind::Macro(_) => {}
+            ast::AssocItemKind::MacCall(_) => {}
         }
     }
 
@@ -1103,7 +1103,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                 // trait.
                 self.visit_ty(ty)
             }
-            ast::AssocItemKind::Macro(_) => {}
+            ast::AssocItemKind::MacCall(_) => {}
         }
     }
 
@@ -1345,7 +1345,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                 walk_list!(self, visit_ty, ty);
                 self.process_generic_params(ty_params, &qualname, item.id);
             }
-            Mac(_) => (),
+            MacCall(_) => (),
             _ => visit::walk_item(self, item),
         }
     }
@@ -1549,7 +1549,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                     self.dumper.dump_def(&access, var_data);
                 }
             }
-            ast::ForeignItemKind::Macro(..) => {}
+            ast::ForeignItemKind::MacCall(..) => {}
         }
     }
 }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 88bfe7661e2..98d81c62522 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -10,7 +10,6 @@ mod sig;
 
 use rustc::middle::cstore::ExternCrate;
 use rustc::middle::privacy::AccessLevels;
-use rustc::session::config::{CrateType, Input, OutputType};
 use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc::{bug, span_bug};
 use rustc_ast::ast::{self, Attribute, NodeId, PatKind, DUMMY_NODE_ID};
@@ -22,6 +21,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind as HirDefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::Node;
+use rustc_session::config::{CrateType, Input, OutputType};
 use rustc_span::source_map::Spanned;
 use rustc_span::*;
 
@@ -174,7 +174,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
             }
             // FIXME(plietar): needs a new DefKind in rls-data
             ast::ForeignItemKind::TyAlias(..) => None,
-            ast::ForeignItemKind::Macro(..) => None,
+            ast::ForeignItemKind::MacCall(..) => None,
         }
     }
 
@@ -718,7 +718,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
             | Res::Def(HirDefKind::Ctor(..), _) => {
                 Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(res.def_id()) })
             }
-            Res::Def(HirDefKind::Method, decl_id) => {
+            Res::Def(HirDefKind::AssocFn, decl_id) => {
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.associated_item(decl_id);
 
@@ -794,19 +794,6 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
             ExpnKind::Root | ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => return None,
         };
 
-        // If the callee is an imported macro from an external crate, need to get
-        // the source span and name from the session, as their spans are localized
-        // when read in, and no longer correspond to the source.
-        if let Some(mac) = self.tcx.sess.imported_macro_spans.borrow().get(&callee.def_site) {
-            let &(ref mac_name, mac_span) = mac;
-            let mac_span = self.span_from_span(mac_span);
-            return Some(MacroRef {
-                span: callsite_span,
-                qualname: mac_name.clone(), // FIXME: generate the real qualname
-                callee_span: mac_span,
-            });
-        }
-
         let callee_span = self.span_from_span(callee.def_site);
         Some(MacroRef {
             span: callsite_span,
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 2005366f839..51434e93330 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -308,7 +308,7 @@ impl Sig for ast::Ty {
             | ast::TyKind::Infer
             | ast::TyKind::Err
             | ast::TyKind::ImplicitSelf
-            | ast::TyKind::Mac(_) => Err("Ty"),
+            | ast::TyKind::MacCall(_) => Err("Ty"),
         }
     }
 }
@@ -519,7 +519,7 @@ impl Sig for ast::Item {
                 text.push(' ');
 
                 let trait_sig = if let Some(ref t) = *of_trait {
-                    if polarity == ast::ImplPolarity::Negative {
+                    if let ast::ImplPolarity::Negative(_) = polarity {
                         text.push('!');
                     }
                     let trait_sig = t.path.make(offset + text.len(), id, scx)?;
@@ -544,7 +544,7 @@ impl Sig for ast::Item {
             ast::ItemKind::ExternCrate(_) => Err("extern crate"),
             // FIXME should implement this (e.g., pub use).
             ast::ItemKind::Use(_) => Err("import"),
-            ast::ItemKind::Mac(..) | ast::ItemKind::MacroDef(_) => Err("Macro"),
+            ast::ItemKind::MacCall(..) | ast::ItemKind::MacroDef(_) => Err("Macro"),
         }
     }
 }
@@ -795,7 +795,7 @@ impl Sig for ast::ForeignItem {
 
                 Ok(Signature { text, defs, refs: vec![] })
             }
-            ast::ForeignItemKind::Macro(..) => Err("macro"),
+            ast::ForeignItemKind::MacCall(..) => Err("macro"),
         }
     }
 }
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index 152435206fe..6620941c440 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -1,7 +1,7 @@
 use crate::generated_code;
-use rustc::session::Session;
 use rustc_ast::token::{self, TokenKind};
 use rustc_parse::lexer::{self, StringReader};
+use rustc_session::Session;
 use rustc_span::*;
 
 #[derive(Clone)]
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index 173b120e1f6..81281857dbc 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -49,6 +49,18 @@ pub struct OptimizationFuel {
     out_of_fuel: bool,
 }
 
+/// The behavior of the CTFE engine when an error occurs with regards to backtraces.
+#[derive(Clone, Copy)]
+pub enum CtfeBacktrace {
+    /// Do nothing special, return the error as usual without a backtrace.
+    Disabled,
+    /// Capture a backtrace at the point the error is created and return it in the error
+    /// (to be printed later if/when the error ever actually gets shown to the user).
+    Capture,
+    /// Capture a backtrace at the point the error is created and immediately print it out.
+    Immediate,
+}
+
 /// Represents the data associated with a compilation
 /// session for a single crate.
 pub struct Session {
@@ -91,11 +103,6 @@ pub struct Session {
     /// The maximum blocks a const expression can evaluate.
     pub const_eval_limit: Once<usize>,
 
-    /// Map from imported macro spans (which consist of
-    /// the localized span for the macro body) to the
-    /// macro name and definition span in the source crate.
-    pub imported_macro_spans: OneThread<RefCell<FxHashMap<Span, (String, Span)>>>,
-
     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
     /// Used for incremental compilation tests. Will only be populated if
     /// `-Zquery-dep-graph` is specified.
@@ -139,6 +146,11 @@ pub struct Session {
     /// Path for libraries that will take preference over libraries shipped by Rust.
     /// Used by windows-gnu targets to priortize system mingw-w64 libraries.
     pub system_library_path: OneThread<RefCell<Option<Option<PathBuf>>>>,
+
+    /// Tracks the current behavior of the CTFE engine when an error occurs.
+    /// Options range from returning the error without a backtrace to returning an error
+    /// and immediately printing the backtrace to stderr.
+    pub ctfe_backtrace: Lock<CtfeBacktrace>,
 }
 
 pub struct PerfStats {
@@ -543,25 +555,34 @@ impl Session {
             .unwrap_or(self.opts.debug_assertions)
     }
 
-    pub fn crt_static(&self) -> bool {
+    /// Check whether this compile session and crate type use static crt.
+    pub fn crt_static(&self, crate_type: Option<config::CrateType>) -> bool {
         // If the target does not opt in to crt-static support, use its default.
         if self.target.target.options.crt_static_respected {
-            self.crt_static_feature()
+            self.crt_static_feature(crate_type)
         } else {
             self.target.target.options.crt_static_default
         }
     }
 
-    pub fn crt_static_feature(&self) -> bool {
+    /// Check whether this compile session and crate type use `crt-static` feature.
+    pub fn crt_static_feature(&self, crate_type: Option<config::CrateType>) -> bool {
         let requested_features = self.opts.cg.target_feature.split(',');
         let found_negative = requested_features.clone().any(|r| r == "-crt-static");
         let found_positive = requested_features.clone().any(|r| r == "+crt-static");
 
-        // If the target we're compiling for requests a static crt by default,
-        // then see if the `-crt-static` feature was passed to disable that.
-        // Otherwise if we don't have a static crt by default then see if the
-        // `+crt-static` feature was passed.
-        if self.target.target.options.crt_static_default { !found_negative } else { found_positive }
+        if found_positive || found_negative {
+            found_positive
+        } else if crate_type == Some(config::CrateType::ProcMacro)
+            || crate_type == None && self.opts.crate_types.contains(&config::CrateType::ProcMacro)
+        {
+            // FIXME: When crate_type is not available,
+            // we use compiler options to determine the crate_type.
+            // We can't check `#![crate_type = "proc-macro"]` here.
+            false
+        } else {
+            self.target.target.options.crt_static_default
+        }
     }
 
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
@@ -1040,6 +1061,12 @@ fn build_session_(
         sopts.debugging_opts.time_passes,
     );
 
+    let ctfe_backtrace = Lock::new(match env::var("RUSTC_CTFE_BACKTRACE") {
+        Ok(ref val) if val == "immediate" => CtfeBacktrace::Immediate,
+        Ok(ref val) if val != "0" => CtfeBacktrace::Capture,
+        _ => CtfeBacktrace::Disabled,
+    });
+
     let sess = Session {
         target: target_cfg,
         host,
@@ -1057,7 +1084,6 @@ fn build_session_(
         recursion_limit: Once::new(),
         type_length_limit: Once::new(),
         const_eval_limit: Once::new(),
-        imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         cgu_reuse_tracker,
         prof,
@@ -1078,6 +1104,7 @@ fn build_session_(
         trait_methods_not_found: Lock::new(Default::default()),
         confused_type_with_std_module: Lock::new(Default::default()),
         system_library_path: OneThread::new(RefCell::new(Default::default())),
+        ctfe_backtrace,
     };
 
     validate_commandline_args_with_session_available(&sess);
diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs
index 66cdf46bd4e..29561c91f33 100644
--- a/src/librustc_span/def_id.rs
+++ b/src/librustc_span/def_id.rs
@@ -1,8 +1,11 @@
 use crate::HashStableContext;
+use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::AtomicRef;
 use rustc_index::vec::Idx;
+use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Decoder, Encoder};
+use std::borrow::Borrow;
 use std::fmt;
 use std::{u32, u64};
 
@@ -22,7 +25,7 @@ pub enum CrateNum {
 
 /// Item definitions in the currently-compiled crate would have the `CrateNum`
 /// `LOCAL_CRATE` in their `DefId`.
-pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0));
+pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32(0));
 
 impl Idx for CrateNum {
     #[inline]
@@ -102,6 +105,28 @@ impl ::std::fmt::Debug for CrateNum {
     }
 }
 
+#[derive(
+    Copy,
+    Clone,
+    Hash,
+    PartialEq,
+    Eq,
+    PartialOrd,
+    Ord,
+    Debug,
+    RustcEncodable,
+    RustcDecodable,
+    HashStable_Generic
+)]
+pub struct DefPathHash(pub Fingerprint);
+
+impl Borrow<Fingerprint> for DefPathHash {
+    #[inline]
+    fn borrow(&self) -> &Fingerprint {
+        &self.0
+    }
+}
+
 rustc_index::newtype_index! {
     /// A DefIndex is an index into the hir-map for a crate, identifying a
     /// particular definition. It should really be considered an interned
@@ -139,8 +164,13 @@ impl DefId {
     }
 
     #[inline]
-    pub fn to_local(self) -> LocalDefId {
-        LocalDefId::from_def_id(self)
+    pub fn as_local(self) -> Option<LocalDefId> {
+        if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None }
+    }
+
+    #[inline]
+    pub fn expect_local(self) -> LocalDefId {
+        self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self))
     }
 
     pub fn is_top_level_module(self) -> bool {
@@ -185,19 +215,26 @@ rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId);
 /// few cases where we know that only DefIds from the local crate are expected
 /// and a DefId from a different crate would signify a bug somewhere. This
 /// is when LocalDefId comes in handy.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct LocalDefId(DefIndex);
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct LocalDefId {
+    pub local_def_index: DefIndex,
+}
 
-impl LocalDefId {
+impl Idx for LocalDefId {
     #[inline]
-    pub fn from_def_id(def_id: DefId) -> LocalDefId {
-        assert!(def_id.is_local());
-        LocalDefId(def_id.index)
+    fn new(idx: usize) -> Self {
+        LocalDefId { local_def_index: Idx::new(idx) }
     }
+    #[inline]
+    fn index(self) -> usize {
+        self.local_def_index.index()
+    }
+}
 
+impl LocalDefId {
     #[inline]
     pub fn to_def_id(self) -> DefId {
-        DefId { krate: LOCAL_CRATE, index: self.0 }
+        DefId { krate: LOCAL_CRATE, index: self.local_def_index }
     }
 }
 
diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs
index a368a881674..e073d735a12 100644
--- a/src/librustc_span/hygiene.rs
+++ b/src/librustc_span/hygiene.rs
@@ -201,11 +201,11 @@ impl HygieneData {
         true
     }
 
-    fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext {
+    fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
         self.syntax_context_data[ctxt.0 as usize].opaque
     }
 
-    fn modern_and_legacy(&self, ctxt: SyntaxContext) -> SyntaxContext {
+    fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
         self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent
     }
 
@@ -266,9 +266,9 @@ impl HygieneData {
 
         let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
         let mut call_site_ctxt = if transparency == Transparency::SemiTransparent {
-            self.modern(call_site_ctxt)
+            self.normalize_to_macros_2_0(call_site_ctxt)
         } else {
-            self.modern_and_legacy(call_site_ctxt)
+            self.normalize_to_macro_rules(call_site_ctxt)
         };
 
         if call_site_ctxt == SyntaxContext::root() {
@@ -491,10 +491,10 @@ impl SyntaxContext {
         HygieneData::with(|data| data.adjust(self, expn_id))
     }
 
-    /// Like `SyntaxContext::adjust`, but also modernizes `self`.
-    pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
+    /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0.
+    pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         HygieneData::with(|data| {
-            *self = data.modern(*self);
+            *self = data.normalize_to_macros_2_0(*self);
             data.adjust(self, expn_id)
         })
     }
@@ -527,7 +527,7 @@ impl SyntaxContext {
     pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
         HygieneData::with(|data| {
             let mut scope = None;
-            let mut glob_ctxt = data.modern(glob_span.ctxt());
+            let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
             while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) {
                 scope = Some(data.remove_mark(&mut glob_ctxt).0);
                 if data.remove_mark(self).0 != scope.unwrap() {
@@ -558,7 +558,7 @@ impl SyntaxContext {
                 return None;
             }
 
-            let mut glob_ctxt = data.modern(glob_span.ctxt());
+            let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
             let mut marks = Vec::new();
             while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) {
                 marks.push(data.remove_mark(&mut glob_ctxt));
@@ -574,20 +574,20 @@ impl SyntaxContext {
 
     pub fn hygienic_eq(self, other: SyntaxContext, expn_id: ExpnId) -> bool {
         HygieneData::with(|data| {
-            let mut self_modern = data.modern(self);
-            data.adjust(&mut self_modern, expn_id);
-            self_modern == data.modern(other)
+            let mut self_normalized = data.normalize_to_macros_2_0(self);
+            data.adjust(&mut self_normalized, expn_id);
+            self_normalized == data.normalize_to_macros_2_0(other)
         })
     }
 
     #[inline]
-    pub fn modern(self) -> SyntaxContext {
-        HygieneData::with(|data| data.modern(self))
+    pub fn normalize_to_macros_2_0(self) -> SyntaxContext {
+        HygieneData::with(|data| data.normalize_to_macros_2_0(self))
     }
 
     #[inline]
-    pub fn modern_and_legacy(self) -> SyntaxContext {
-        HygieneData::with(|data| data.modern_and_legacy(self))
+    pub fn normalize_to_macro_rules(self) -> SyntaxContext {
+        HygieneData::with(|data| data.normalize_to_macro_rules(self))
     }
 
     #[inline]
diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs
index 1d493da9e5b..dbc180114f1 100644
--- a/src/librustc_span/lib.rs
+++ b/src/librustc_span/lib.rs
@@ -6,6 +6,9 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(crate_visibility_modifier)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
 #![feature(specialization)]
@@ -24,7 +27,7 @@ pub mod hygiene;
 use hygiene::Transparency;
 pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, MacroKind, SyntaxContext};
 pub mod def_id;
-use def_id::DefId;
+use def_id::{CrateNum, DefId, LOCAL_CRATE};
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
 
@@ -548,9 +551,9 @@ impl Span {
     }
 
     #[inline]
-    pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
+    pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         let mut span = self.data();
-        let mark = span.ctxt.modernize_and_adjust(expn_id);
+        let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id);
         *self = Span::new(span.lo, span.hi, span.ctxt);
         mark
     }
@@ -576,15 +579,15 @@ impl Span {
     }
 
     #[inline]
-    pub fn modern(self) -> Span {
+    pub fn normalize_to_macros_2_0(self) -> Span {
         let span = self.data();
-        span.with_ctxt(span.ctxt.modern())
+        span.with_ctxt(span.ctxt.normalize_to_macros_2_0())
     }
 
     #[inline]
-    pub fn modern_and_legacy(self) -> Span {
+    pub fn normalize_to_macro_rules(self) -> Span {
         let span = self.data();
-        span.with_ctxt(span.ctxt.modern_and_legacy())
+        span.with_ctxt(span.ctxt.normalize_to_macro_rules())
     }
 }
 
@@ -836,30 +839,42 @@ pub struct NormalizedPos {
     pub diff: u32,
 }
 
-/// The state of the lazy external source loading mechanism of a `SourceFile`.
-#[derive(PartialEq, Eq, Clone)]
+#[derive(PartialEq, Eq, Clone, Debug)]
 pub enum ExternalSource {
+    /// No external source has to be loaded, since the `SourceFile` represents a local crate.
+    Unneeded,
+    Foreign {
+        kind: ExternalSourceKind,
+        /// This SourceFile's byte-offset within the source_map of its original crate
+        original_start_pos: BytePos,
+        /// The end of this SourceFile within the source_map of its original crate
+        original_end_pos: BytePos,
+    },
+}
+
+/// The state of the lazy external source loading mechanism of a `SourceFile`.
+#[derive(PartialEq, Eq, Clone, Debug)]
+pub enum ExternalSourceKind {
     /// The external source has been loaded already.
     Present(String),
     /// No attempt has been made to load the external source.
     AbsentOk,
     /// A failed attempt has been made to load the external source.
     AbsentErr,
-    /// No external source has to be loaded, since the `SourceFile` represents a local crate.
     Unneeded,
 }
 
 impl ExternalSource {
     pub fn is_absent(&self) -> bool {
-        match *self {
-            ExternalSource::Present(_) => false,
+        match self {
+            ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. } => false,
             _ => true,
         }
     }
 
     pub fn get_source(&self) -> Option<&str> {
-        match *self {
-            ExternalSource::Present(ref src) => Some(src),
+        match self {
+            ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src),
             _ => None,
         }
     }
@@ -880,8 +895,6 @@ pub struct SourceFile {
     /// The unmapped path of the file that the source came from.
     /// Set to `None` if the `SourceFile` was imported from an external crate.
     pub unmapped_path: Option<FileName>,
-    /// Indicates which crate this `SourceFile` was imported from.
-    pub crate_of_origin: u32,
     /// The complete source code.
     pub src: Option<Lrc<String>>,
     /// The source code's hash.
@@ -903,6 +916,8 @@ pub struct SourceFile {
     pub normalized_pos: Vec<NormalizedPos>,
     /// A hash of the filename, used for speeding up hashing in incremental compilation.
     pub name_hash: u128,
+    /// Indicates which crate this `SourceFile` was imported from.
+    pub cnum: CrateNum,
 }
 
 impl Encodable for SourceFile {
@@ -969,7 +984,8 @@ impl Encodable for SourceFile {
             s.emit_struct_field("multibyte_chars", 6, |s| self.multibyte_chars.encode(s))?;
             s.emit_struct_field("non_narrow_chars", 7, |s| self.non_narrow_chars.encode(s))?;
             s.emit_struct_field("name_hash", 8, |s| self.name_hash.encode(s))?;
-            s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s))
+            s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s))?;
+            s.emit_struct_field("cnum", 10, |s| self.cnum.encode(s))
         })
     }
 }
@@ -1019,24 +1035,24 @@ impl Decodable for SourceFile {
             let name_hash: u128 = d.read_struct_field("name_hash", 8, |d| Decodable::decode(d))?;
             let normalized_pos: Vec<NormalizedPos> =
                 d.read_struct_field("normalized_pos", 9, |d| Decodable::decode(d))?;
+            let cnum: CrateNum = d.read_struct_field("cnum", 10, |d| Decodable::decode(d))?;
             Ok(SourceFile {
                 name,
                 name_was_remapped,
                 unmapped_path: None,
-                // `crate_of_origin` has to be set by the importer.
-                // This value matches up with `rustc_hir::def_id::INVALID_CRATE`.
-                // That constant is not available here, unfortunately.
-                crate_of_origin: std::u32::MAX - 1,
                 start_pos,
                 end_pos,
                 src: None,
                 src_hash,
-                external_src: Lock::new(ExternalSource::AbsentOk),
+                // Unused - the metadata decoder will construct
+                // a new SourceFile, filling in `external_src` properly
+                external_src: Lock::new(ExternalSource::Unneeded),
                 lines,
                 multibyte_chars,
                 non_narrow_chars,
                 normalized_pos,
                 name_hash,
+                cnum,
             })
         })
     }
@@ -1078,7 +1094,6 @@ impl SourceFile {
             name,
             name_was_remapped,
             unmapped_path: Some(unmapped_path),
-            crate_of_origin: 0,
             src: Some(Lrc::new(src)),
             src_hash,
             external_src: Lock::new(ExternalSource::Unneeded),
@@ -1089,6 +1104,7 @@ impl SourceFile {
             non_narrow_chars,
             normalized_pos,
             name_hash,
+            cnum: LOCAL_CRATE,
         }
     }
 
@@ -1106,21 +1122,27 @@ impl SourceFile {
     where
         F: FnOnce() -> Option<String>,
     {
-        if *self.external_src.borrow() == ExternalSource::AbsentOk {
+        if matches!(
+            *self.external_src.borrow(),
+            ExternalSource::Foreign { kind: ExternalSourceKind::AbsentOk, .. }
+        ) {
             let src = get_src();
             let mut external_src = self.external_src.borrow_mut();
             // Check that no-one else have provided the source while we were getting it
-            if *external_src == ExternalSource::AbsentOk {
+            if let ExternalSource::Foreign {
+                kind: src_kind @ ExternalSourceKind::AbsentOk, ..
+            } = &mut *external_src
+            {
                 if let Some(src) = src {
                     let mut hasher: StableHasher = StableHasher::new();
                     hasher.write(src.as_bytes());
 
                     if hasher.finish::<u128>() == self.src_hash {
-                        *external_src = ExternalSource::Present(src);
+                        *src_kind = ExternalSourceKind::Present(src);
                         return true;
                     }
                 } else {
-                    *external_src = ExternalSource::AbsentErr;
+                    *src_kind = ExternalSourceKind::AbsentErr;
                 }
 
                 false
@@ -1147,11 +1169,7 @@ impl SourceFile {
         }
 
         let begin = {
-            let line = if let Some(line) = self.lines.get(line_number) {
-                line
-            } else {
-                return None;
-            };
+            let line = self.lines.get(line_number)?;
             let begin: BytePos = *line - self.start_pos;
             begin.to_usize()
         };
diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs
index 65095c6f131..7dd9e2f6316 100644
--- a/src/librustc_span/source_map.rs
+++ b/src/librustc_span/source_map.rs
@@ -296,14 +296,16 @@ impl SourceMap {
         &self,
         filename: FileName,
         name_was_remapped: bool,
-        crate_of_origin: u32,
         src_hash: u128,
         name_hash: u128,
         source_len: usize,
+        cnum: CrateNum,
         mut file_local_lines: Vec<BytePos>,
         mut file_local_multibyte_chars: Vec<MultiByteChar>,
         mut file_local_non_narrow_chars: Vec<NonNarrowChar>,
         mut file_local_normalized_pos: Vec<NormalizedPos>,
+        original_start_pos: BytePos,
+        original_end_pos: BytePos,
     ) -> Lrc<SourceFile> {
         let start_pos = self
             .allocate_address_space(source_len)
@@ -332,10 +334,13 @@ impl SourceMap {
             name: filename,
             name_was_remapped,
             unmapped_path: None,
-            crate_of_origin,
             src: None,
             src_hash,
-            external_src: Lock::new(ExternalSource::AbsentOk),
+            external_src: Lock::new(ExternalSource::Foreign {
+                kind: ExternalSourceKind::AbsentOk,
+                original_start_pos,
+                original_end_pos,
+            }),
             start_pos,
             end_pos,
             lines: file_local_lines,
@@ -343,6 +348,7 @@ impl SourceMap {
             non_narrow_chars: file_local_non_narrow_chars,
             normalized_pos: file_local_normalized_pos,
             name_hash,
+            cnum,
         });
 
         let mut files = self.files.borrow_mut();
@@ -517,6 +523,13 @@ impl SourceMap {
         Ok((lo, hi))
     }
 
+    pub fn is_line_before_span_empty(&self, sp: Span) -> bool {
+        match self.span_to_prev_source(sp) {
+            Ok(s) => s.split('\n').last().map(|l| l.trim_start().is_empty()).unwrap_or(false),
+            Err(_) => false,
+        }
+    }
+
     pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
         debug!("span_to_lines(sp={:?})", sp);
         let (lo, hi) = self.is_valid_span(sp)?;
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index d8ce9bbdfb3..5685505f694 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -120,6 +120,7 @@ symbols! {
         abi_unadjusted,
         abi_vectorcall,
         abi_x86_interrupt,
+        abort,
         aborts,
         address,
         add_with_overflow,
@@ -181,6 +182,7 @@ symbols! {
         caller_location,
         cdylib,
         cfg,
+        cfg_accessible,
         cfg_attr,
         cfg_attr_multi,
         cfg_doctest,
@@ -288,7 +290,6 @@ symbols! {
         dylib,
         dyn_trait,
         eh_personality,
-        eh_unwind_resume,
         enable,
         Encodable,
         env,
@@ -453,6 +454,7 @@ symbols! {
         min_align_of,
         min_const_fn,
         min_const_unsafe_fn,
+        min_specialization,
         mips_target_feature,
         mmx_target_feature,
         module,
@@ -654,6 +656,8 @@ symbols! {
         rustc_proc_macro_decls,
         rustc_promotable,
         rustc_regions,
+        rustc_unsafe_specialization_marker,
+        rustc_specialization_trait,
         rustc_stable,
         rustc_std_internal_symbol,
         rustc_symbol_name,
@@ -664,7 +668,6 @@ symbols! {
         rustc_variance,
         rustfmt,
         rust_eh_personality,
-        rust_eh_unwind_resume,
         rust_oom,
         rvalue_static_promotion,
         sanitize,
@@ -854,12 +857,12 @@ impl Ident {
     }
 
     /// "Normalize" ident for use in comparisons using "item hygiene".
-    /// Identifiers with same string value become same if they came from the same "modern" macro
+    /// Identifiers with same string value become same if they came from the same macro 2.0 macro
     /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from
-    /// different "modern" macros.
+    /// different macro 2.0 macros.
     /// Technically, this operation strips all non-opaque marks from ident's syntactic context.
-    pub fn modern(self) -> Ident {
-        Ident::new(self.name, self.span.modern())
+    pub fn normalize_to_macros_2_0(self) -> Ident {
+        Ident::new(self.name, self.span.normalize_to_macros_2_0())
     }
 
     /// "Normalize" ident for use in comparisons using "local variable hygiene".
@@ -867,8 +870,8 @@ impl Ident {
     /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different
     /// non-transparent macros.
     /// Technically, this operation strips all transparent marks from ident's syntactic context.
-    pub fn modern_and_legacy(self) -> Ident {
-        Ident::new(self.name, self.span.modern_and_legacy())
+    pub fn normalize_to_macro_rules(self) -> Ident {
+        Ident::new(self.name, self.span.normalize_to_macro_rules())
     }
 
     /// Convert the name to a `SymbolStr`. This is a slowish operation because
@@ -980,6 +983,31 @@ impl fmt::Display for IdentPrinter {
     }
 }
 
+/// An newtype around `Ident` that calls [Ident::normalize_to_macro_rules] on
+/// construction.
+// FIXME(matthewj, petrochenkov) Use this more often, add a similar
+// `ModernIdent` struct and use that as well.
+#[derive(Copy, Clone, Eq, PartialEq, Hash)]
+pub struct MacroRulesNormalizedIdent(Ident);
+
+impl MacroRulesNormalizedIdent {
+    pub fn new(ident: Ident) -> Self {
+        Self(ident.normalize_to_macro_rules())
+    }
+}
+
+impl fmt::Debug for MacroRulesNormalizedIdent {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&self.0, f)
+    }
+}
+
+impl fmt::Display for MacroRulesNormalizedIdent {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&self.0, f)
+    }
+}
+
 /// An interned string.
 ///
 /// Internally, a `Symbol` is implemented as an index, and all operations
@@ -998,7 +1026,7 @@ rustc_index::newtype_index! {
 
 impl Symbol {
     const fn new(n: u32) -> Self {
-        Symbol(SymbolIndex::from_u32_const(n))
+        Symbol(SymbolIndex::from_u32(n))
     }
 
     /// Maps a string to its interned representation.
diff --git a/src/librustc_target/README.md b/src/librustc_target/README.md
index a22000ea9d2..ac1e03385d1 100644
--- a/src/librustc_target/README.md
+++ b/src/librustc_target/README.md
@@ -1,6 +1,6 @@
 `librustc_target` contains some very low-level details that are
 specific to different compilation targets and so forth.
 
-For more information about how rustc works, see the [rustc guide].
+For more information about how rustc works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 2f8bbd66c32..afa30e7e632 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -660,7 +660,10 @@ impl FieldPlacement {
 
     pub fn offset(&self, i: usize) -> Size {
         match *self {
-            FieldPlacement::Union(_) => Size::ZERO,
+            FieldPlacement::Union(count) => {
+                assert!(i < count, "tried to access field {} of union with {} fields", i, count);
+                Size::ZERO
+            }
             FieldPlacement::Array { stride, count } => {
                 let i = i as u64;
                 assert!(i < count);
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index 3c397eb444d..98190867d49 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -9,6 +9,9 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(bool_to_option)]
+#![feature(const_if_match)]
+#![feature(const_fn)]
+#![feature(const_panic)]
 #![feature(nll)]
 #![feature(never_type)]
 #![feature(associated_type_bounds)]
diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs
index 6549be41ea9..e896b46da9a 100644
--- a/src/librustc_target/spec/aarch64_apple_ios.rs
+++ b/src/librustc_target/spec/aarch64_apple_ios.rs
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::Arm64)?;
+    let base = opts(Arch::Arm64, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "arm64-apple-ios".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs
new file mode 100644
index 00000000000..794bc7900e7
--- /dev/null
+++ b/src/librustc_target/spec/aarch64_apple_tvos.rs
@@ -0,0 +1,25 @@
+use super::apple_sdk_base::{opts, AppleOS, Arch};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let base = opts(Arch::Arm64, AppleOS::tvOS)?;
+    Ok(Target {
+        llvm_target: "arm64-apple-tvos".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        target_os: "tvos".to_string(),
+        target_env: String::new(),
+        target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            features: "+neon,+fp-armv8,+cyclone".to_string(),
+            eliminate_frame_pointer: false,
+            max_atomic_width: Some(128),
+            abi_blacklist: super::arm_base::abi_blacklist(),
+            ..base
+        },
+    })
+}
diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_sdk_base.rs
index 2673748321d..513754352fb 100644
--- a/src/librustc_target/spec/apple_ios_base.rs
+++ b/src/librustc_target/spec/apple_sdk_base.rs
@@ -5,7 +5,6 @@ use std::path::Path;
 use std::process::Command;
 
 use Arch::*;
-
 #[allow(non_camel_case_types)]
 #[derive(Copy, Clone)]
 pub enum Arch {
@@ -17,6 +16,13 @@ pub enum Arch {
     X86_64_macabi,
 }
 
+#[allow(non_camel_case_types)]
+#[derive(Copy, Clone)]
+pub enum AppleOS {
+    tvOS,
+    iOS,
+}
+
 impl Arch {
     pub fn to_string(self) -> &'static str {
         match self {
@@ -41,6 +47,17 @@ pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
         let p = Path::new(&sdkroot);
         match sdk_name {
             // Ignore `SDKROOT` if it's clearly set for the wrong platform.
+            "appletvos"
+                if sdkroot.contains("TVSimulator.platform")
+                    || sdkroot.contains("MacOSX.platform") =>
+            {
+                ()
+            }
+            "appletvsimulator"
+                if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") =>
+            {
+                ()
+            }
             "iphoneos"
                 if sdkroot.contains("iPhoneSimulator.platform")
                     || sdkroot.contains("MacOSX.platform") =>
@@ -82,11 +99,17 @@ pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
     }
 }
 
-fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
-    let sdk_name = match arch {
-        Armv7 | Armv7s | Arm64 => "iphoneos",
-        I386 | X86_64 => "iphonesimulator",
-        X86_64_macabi => "macosx10.15",
+fn build_pre_link_args(arch: Arch, os: AppleOS) -> Result<LinkArgs, String> {
+    let sdk_name = match (arch, os) {
+        (Arm64, AppleOS::tvOS) => "appletvos",
+        (X86_64, AppleOS::tvOS) => "appletvsimulator",
+        (Armv7, AppleOS::iOS) => "iphoneos",
+        (Armv7s, AppleOS::iOS) => "iphoneos",
+        (Arm64, AppleOS::iOS) => "iphoneos",
+        (I386, AppleOS::iOS) => "iphonesimulator",
+        (X86_64, AppleOS::iOS) => "iphonesimulator",
+        (X86_64_macabi, AppleOS::iOS) => "macosx10.15",
+        _ => unreachable!(),
     };
 
     let arch_name = arch.to_string();
@@ -128,8 +151,8 @@ fn link_env_remove(arch: Arch) -> Vec<String> {
     }
 }
 
-pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
-    let pre_link_args = build_pre_link_args(arch)?;
+pub fn opts(arch: Arch, os: AppleOS) -> Result<TargetOptions, String> {
+    let pre_link_args = build_pre_link_args(arch, os)?;
     Ok(TargetOptions {
         cpu: target_cpu(arch),
         dynamic_linking: false,
diff --git a/src/librustc_target/spec/armv7_apple_ios.rs b/src/librustc_target/spec/armv7_apple_ios.rs
index aa2d32e2d79..c0c2ae909f8 100644
--- a/src/librustc_target/spec/armv7_apple_ios.rs
+++ b/src/librustc_target/spec/armv7_apple_ios.rs
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::Armv7)?;
+    let base = opts(Arch::Armv7, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "armv7-apple-ios".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/armv7s_apple_ios.rs b/src/librustc_target/spec/armv7s_apple_ios.rs
index 6514643a64d..6a5654f10d4 100644
--- a/src/librustc_target/spec/armv7s_apple_ios.rs
+++ b/src/librustc_target/spec/armv7s_apple_ios.rs
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::Armv7s)?;
+    let base = opts(Arch::Armv7s, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "armv7s-apple-ios".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/i386_apple_ios.rs b/src/librustc_target/spec/i386_apple_ios.rs
index a6c1d24fa62..a121d49769d 100644
--- a/src/librustc_target/spec/i386_apple_ios.rs
+++ b/src/librustc_target/spec/i386_apple_ios.rs
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::I386)?;
+    let base = opts(Arch::I386, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "i386-apple-ios".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 67f45d3d230..6e5111bd701 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -47,7 +47,7 @@ use rustc_macros::HashStable_Generic;
 pub mod abi;
 mod android_base;
 mod apple_base;
-mod apple_ios_base;
+mod apple_sdk_base;
 mod arm_base;
 mod cloudabi_base;
 mod dragonfly_base;
@@ -434,6 +434,8 @@ supported_targets! {
     ("armv7-apple-ios", armv7_apple_ios),
     ("armv7s-apple-ios", armv7s_apple_ios),
     ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
+    ("aarch64-apple-tvos", aarch64_apple_tvos),
+    ("x86_64-apple-tvos", x86_64_apple_tvos),
 
     ("armebv7r-none-eabi", armebv7r_none_eabi),
     ("armebv7r-none-eabihf", armebv7r_none_eabihf),
@@ -579,6 +581,12 @@ pub struct TargetOptions {
     /// user-defined but before post_link_objects. Standard platform
     /// libraries that should be always be linked to, usually go here.
     pub late_link_args: LinkArgs,
+    /// Linker arguments used in addition to `late_link_args` if at least one
+    /// Rust dependency is dynamically linked.
+    pub late_link_args_dynamic: LinkArgs,
+    /// Linker arguments used in addition to `late_link_args` if aall Rust
+    /// dependencies are statically linked.
+    pub late_link_args_static: LinkArgs,
     /// Objects to link after all others, always found within the
     /// sysroot folder.
     pub post_link_objects: Vec<String>, // ... unconditionally
@@ -692,11 +700,6 @@ pub struct TargetOptions {
     pub archive_format: String,
     /// Is asm!() allowed? Defaults to true.
     pub allow_asm: bool,
-    /// Whether the target uses a custom unwind resumption routine.
-    /// By default LLVM lowers `resume` instructions into calls to `_Unwind_Resume`
-    /// defined in libgcc. If this option is enabled, the target must provide
-    /// `eh_unwind_resume` lang item.
-    pub custom_unwind_resume: bool,
     /// Whether the runtime startup code requires the `main` function be passed
     /// `argc` and `argv` values.
     pub main_needs_argc_argv: bool,
@@ -863,10 +866,11 @@ impl Default for TargetOptions {
             post_link_objects: Vec::new(),
             post_link_objects_crt: Vec::new(),
             late_link_args: LinkArgs::new(),
+            late_link_args_dynamic: LinkArgs::new(),
+            late_link_args_static: LinkArgs::new(),
             link_env: Vec::new(),
             link_env_remove: Vec::new(),
             archive_format: "gnu".to_string(),
-            custom_unwind_resume: false,
             main_needs_argc_argv: true,
             allow_asm: true,
             has_elf_tls: false,
@@ -1142,6 +1146,8 @@ impl Target {
         key!(pre_link_objects_exe_crt, list);
         key!(pre_link_objects_dll, list);
         key!(late_link_args, link_args);
+        key!(late_link_args_dynamic, link_args);
+        key!(late_link_args_static, link_args);
         key!(post_link_objects, list);
         key!(post_link_objects_crt, list);
         key!(post_link_args, link_args);
@@ -1182,7 +1188,6 @@ impl Target {
         key!(relro_level, RelroLevel)?;
         key!(archive_format);
         key!(allow_asm, bool);
-        key!(custom_unwind_resume, bool);
         key!(main_needs_argc_argv, bool);
         key!(has_elf_tls, bool);
         key!(obj_is_bitcode, bool);
@@ -1370,6 +1375,8 @@ impl ToJson for Target {
         target_option_val!(pre_link_objects_exe_crt);
         target_option_val!(pre_link_objects_dll);
         target_option_val!(link_args - late_link_args);
+        target_option_val!(link_args - late_link_args_dynamic);
+        target_option_val!(link_args - late_link_args_static);
         target_option_val!(post_link_objects);
         target_option_val!(post_link_objects_crt);
         target_option_val!(link_args - post_link_args);
@@ -1410,7 +1417,6 @@ impl ToJson for Target {
         target_option_val!(relro_level);
         target_option_val!(archive_format);
         target_option_val!(allow_asm);
-        target_option_val!(custom_unwind_resume);
         target_option_val!(main_needs_argc_argv);
         target_option_val!(has_elf_tls);
         target_option_val!(obj_is_bitcode);
diff --git a/src/librustc_target/spec/windows_base.rs b/src/librustc_target/spec/windows_base.rs
index 693a343d5a5..188548b41fe 100644
--- a/src/librustc_target/spec/windows_base.rs
+++ b/src/librustc_target/spec/windows_base.rs
@@ -17,12 +17,13 @@ pub fn opts() -> TargetOptions {
     );
 
     let mut late_link_args = LinkArgs::new();
+    let mut late_link_args_dynamic = LinkArgs::new();
+    let mut late_link_args_static = LinkArgs::new();
     late_link_args.insert(
         LinkerFlavor::Gcc,
         vec![
             "-lmingwex".to_string(),
             "-lmingw32".to_string(),
-            "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
             "-lmsvcrt".to_string(),
             // mingw's msvcrt is a weird hybrid import library and static library.
             // And it seems that the linker fails to use import symbols from msvcrt
@@ -37,6 +38,31 @@ pub fn opts() -> TargetOptions {
             "-lkernel32".to_string(),
         ],
     );
+    late_link_args_dynamic.insert(
+        LinkerFlavor::Gcc,
+        vec![
+            // If any of our crates are dynamically linked then we need to use
+            // the shared libgcc_s-dw2-1.dll. This is required to support
+            // unwinding across DLL boundaries.
+            "-lgcc_s".to_string(),
+            "-lgcc".to_string(),
+            "-lkernel32".to_string(),
+        ],
+    );
+    late_link_args_static.insert(
+        LinkerFlavor::Gcc,
+        vec![
+            // If all of our crates are statically linked then we can get away
+            // with statically linking the libgcc unwinding code. This allows
+            // binaries to be redistributed without the libgcc_s-dw2-1.dll
+            // dependency, but unfortunately break unwinding across DLL
+            // boundaries when unwinding across FFI boundaries.
+            "-lgcc".to_string(),
+            "-lgcc_eh".to_string(),
+            "-lpthread".to_string(),
+            "-lkernel32".to_string(),
+        ],
+    );
 
     TargetOptions {
         // FIXME(#13846) this should be enabled for windows
@@ -63,8 +89,9 @@ pub fn opts() -> TargetOptions {
             "rsbegin.o".to_string(),
         ],
         late_link_args,
+        late_link_args_dynamic,
+        late_link_args_static,
         post_link_objects: vec!["rsend.o".to_string()],
-        custom_unwind_resume: true,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
         requires_uwtable: true,
diff --git a/src/librustc_target/spec/windows_uwp_base.rs b/src/librustc_target/spec/windows_uwp_base.rs
index b19c4dd7eb1..3f7eb442bbc 100644
--- a/src/librustc_target/spec/windows_uwp_base.rs
+++ b/src/librustc_target/spec/windows_uwp_base.rs
@@ -54,7 +54,6 @@ pub fn opts() -> TargetOptions {
         pre_link_objects_dll: vec!["rsbegin.o".to_string()],
         late_link_args,
         post_link_objects: vec!["rsend.o".to_string()],
-        custom_unwind_resume: true,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
         requires_uwtable: true,
diff --git a/src/librustc_target/spec/x86_64_apple_ios.rs b/src/librustc_target/spec/x86_64_apple_ios.rs
index ca02e2deabc..cfcf856836b 100644
--- a/src/librustc_target/spec/x86_64_apple_ios.rs
+++ b/src/librustc_target/spec/x86_64_apple_ios.rs
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::X86_64)?;
+    let base = opts(Arch::X86_64, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "x86_64-apple-ios".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
index 5f4f6ade682..c42d0911725 100644
--- a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
+++ b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs
@@ -1,8 +1,8 @@
-use super::apple_ios_base::{opts, Arch};
+use super::apple_sdk_base::{opts, AppleOS, Arch};
 use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let base = opts(Arch::X86_64_macabi)?;
+    let base = opts(Arch::X86_64_macabi, AppleOS::iOS)?;
     Ok(Target {
         llvm_target: "x86_64-apple-ios13.0-macabi".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_target/spec/x86_64_apple_tvos.rs b/src/librustc_target/spec/x86_64_apple_tvos.rs
new file mode 100644
index 00000000000..a56062c0b2b
--- /dev/null
+++ b/src/librustc_target/spec/x86_64_apple_tvos.rs
@@ -0,0 +1,19 @@
+use super::apple_sdk_base::{opts, AppleOS, Arch};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let base = opts(Arch::X86_64, AppleOS::iOS)?;
+    Ok(Target {
+        llvm_target: "x86_64-apple-tvos".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "tvos".to_string(),
+        target_env: String::new(),
+        target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions { max_atomic_width: Some(64), stack_probes: true, ..base },
+    })
+}
diff --git a/src/librustc_trait_selection/Cargo.toml b/src/librustc_trait_selection/Cargo.toml
new file mode 100644
index 00000000000..5b2da41d066
--- /dev/null
+++ b/src/librustc_trait_selection/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_trait_selection"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_trait_selection"
+path = "lib.rs"
+doctest = false
+
+[dependencies]
+fmt_macros = { path = "../libfmt_macros" }
+log = { version = "0.4", features = ["release_max_level_info", "std"] }
+rustc_attr = { path = "../librustc_attr" }
+rustc = { path = "../librustc" }
+rustc_ast = { path = "../librustc_ast" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
+rustc_index = { path = "../librustc_index" }
+rustc_infer = { path = "../librustc_infer" }
+rustc_macros = { path = "../librustc_macros" }
+rustc_session = { path = "../librustc_session" }
+rustc_span = { path = "../librustc_span" }
+rustc_target = { path = "../librustc_target" }
+smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/librustc_trait_selection/infer.rs b/src/librustc_trait_selection/infer.rs
new file mode 100644
index 00000000000..7abcbf45277
--- /dev/null
+++ b/src/librustc_trait_selection/infer.rs
@@ -0,0 +1,182 @@
+use crate::traits::query::outlives_bounds::InferCtxtExt as _;
+use crate::traits::{self, TraitEngine, TraitEngineExt};
+
+use rustc::arena::ArenaAllocatable;
+use rustc::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
+use rustc::middle::lang_items;
+use rustc::traits::query::Fallible;
+use rustc::ty::{self, Ty, TypeFoldable};
+use rustc_hir as hir;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::traits::ObligationCause;
+use rustc_span::{Span, DUMMY_SP};
+
+use std::fmt::Debug;
+
+pub use rustc_infer::infer::*;
+
+pub trait InferCtxtExt<'tcx> {
+    fn type_is_copy_modulo_regions(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+        span: Span,
+    ) -> bool;
+
+    fn partially_normalize_associated_types_in<T>(
+        &self,
+        span: Span,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+    ) -> InferOk<'tcx, T>
+    where
+        T: TypeFoldable<'tcx>;
+}
+
+impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+    fn type_is_copy_modulo_regions(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+        span: Span,
+    ) -> bool {
+        let ty = self.resolve_vars_if_possible(&ty);
+
+        if !(param_env, ty).has_local_value() {
+            return ty.is_copy_modulo_regions(self.tcx, param_env, span);
+        }
+
+        let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
+
+        // This can get called from typeck (by euv), and `moves_by_default`
+        // rightly refuses to work with inference variables, but
+        // moves_by_default has a cache, which we want to use in other
+        // cases.
+        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
+    }
+
+    /// Normalizes associated types in `value`, potentially returning
+    /// new obligations that must further be processed.
+    fn partially_normalize_associated_types_in<T>(
+        &self,
+        span: Span,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+    ) -> InferOk<'tcx, T>
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        debug!("partially_normalize_associated_types_in(value={:?})", value);
+        let mut selcx = traits::SelectionContext::new(self);
+        let cause = ObligationCause::misc(span, body_id);
+        let traits::Normalized { value, obligations } =
+            traits::normalize(&mut selcx, param_env, cause, value);
+        debug!(
+            "partially_normalize_associated_types_in: result={:?} predicates={:?}",
+            value, obligations
+        );
+        InferOk { value, obligations }
+    }
+}
+
+pub trait InferCtxtBuilderExt<'tcx> {
+    fn enter_canonical_trait_query<K, R>(
+        &mut self,
+        canonical_key: &Canonical<'tcx, K>,
+        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
+    where
+        K: TypeFoldable<'tcx>,
+        R: Debug + TypeFoldable<'tcx>,
+        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable;
+}
+
+impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
+    /// The "main method" for a canonicalized trait query. Given the
+    /// canonical key `canonical_key`, this method will create a new
+    /// inference context, instantiate the key, and run your operation
+    /// `op`. The operation should yield up a result (of type `R`) as
+    /// well as a set of trait obligations that must be fully
+    /// satisfied. These obligations will be processed and the
+    /// canonical result created.
+    ///
+    /// Returns `NoSolution` in the event of any error.
+    ///
+    /// (It might be mildly nicer to implement this on `TyCtxt`, and
+    /// not `InferCtxtBuilder`, but that is a bit tricky right now.
+    /// In part because we would need a `for<'tcx>` sort of
+    /// bound for the closure and in part because it is convenient to
+    /// have `'tcx` be free on this function so that we can talk about
+    /// `K: TypeFoldable<'tcx>`.)
+    fn enter_canonical_trait_query<K, R>(
+        &mut self,
+        canonical_key: &Canonical<'tcx, K>,
+        operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
+    ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
+    where
+        K: TypeFoldable<'tcx>,
+        R: Debug + TypeFoldable<'tcx>,
+        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable,
+    {
+        self.enter_with_canonical(
+            DUMMY_SP,
+            canonical_key,
+            |ref infcx, key, canonical_inference_vars| {
+                let mut fulfill_cx = TraitEngine::new(infcx.tcx);
+                let value = operation(infcx, &mut *fulfill_cx, key)?;
+                infcx.make_canonicalized_query_response(
+                    canonical_inference_vars,
+                    value,
+                    &mut *fulfill_cx,
+                )
+            },
+        )
+    }
+}
+
+pub trait OutlivesEnvironmentExt<'tcx> {
+    fn add_implied_bounds(
+        &mut self,
+        infcx: &InferCtxt<'a, 'tcx>,
+        fn_sig_tys: &[Ty<'tcx>],
+        body_id: hir::HirId,
+        span: Span,
+    );
+}
+
+impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
+    /// This method adds "implied bounds" into the outlives environment.
+    /// Implied bounds are outlives relationships that we can deduce
+    /// on the basis that certain types must be well-formed -- these are
+    /// either the types that appear in the function signature or else
+    /// the input types to an impl. For example, if you have a function
+    /// like
+    ///
+    /// ```
+    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
+    /// ```
+    ///
+    /// we can assume in the caller's body that `'b: 'a` and that `T:
+    /// 'b` (and hence, transitively, that `T: 'a`). This method would
+    /// add those assumptions into the outlives-environment.
+    ///
+    /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
+    fn add_implied_bounds(
+        &mut self,
+        infcx: &InferCtxt<'a, 'tcx>,
+        fn_sig_tys: &[Ty<'tcx>],
+        body_id: hir::HirId,
+        span: Span,
+    ) {
+        debug!("add_implied_bounds()");
+
+        for &ty in fn_sig_tys {
+            let ty = infcx.resolve_vars_if_possible(&ty);
+            debug!("add_implied_bounds: ty = {}", ty);
+            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
+            self.add_outlives_bounds(Some(infcx), implied_bounds)
+        }
+    }
+}
diff --git a/src/librustc_trait_selection/lib.rs b/src/librustc_trait_selection/lib.rs
new file mode 100644
index 00000000000..739aff4fb94
--- /dev/null
+++ b/src/librustc_trait_selection/lib.rs
@@ -0,0 +1,32 @@
+//! This crates defines the trait resolution method.
+//!
+//! - **Traits.** Trait resolution is implemented in the `traits` module.
+//!
+//! For more information about how rustc works, see the [rustc guide].
+//!
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
+#![feature(drain_filter)]
+#![feature(in_band_lifetimes)]
+#![feature(crate_visibility_modifier)]
+#![recursion_limit = "512"] // For rustdoc
+
+#[macro_use]
+extern crate rustc_macros;
+#[cfg(target_arch = "x86_64")]
+#[macro_use]
+extern crate rustc_data_structures;
+#[macro_use]
+extern crate log;
+#[macro_use]
+extern crate rustc;
+
+pub mod infer;
+pub mod opaque_types;
+pub mod traits;
diff --git a/src/librustc_infer/infer/opaque_types/mod.rs b/src/librustc_trait_selection/opaque_types.rs
index 4d264008ee3..785d8b892be 100644
--- a/src/librustc_infer/infer/opaque_types/mod.rs
+++ b/src/librustc_trait_selection/opaque_types.rs
@@ -1,18 +1,18 @@
-use crate::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region};
-use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::InferCtxtExt as _;
 use crate::traits::{self, PredicateObligation};
-use rustc::middle::region;
-use rustc::session::config::nightly_options;
 use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
 use rustc::ty::free_region_map::FreeRegionRelations;
 use rustc::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
 use rustc::ty::{self, GenericParamDefKind, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_hir::Node;
+use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::{self, InferCtxt, InferOk};
+use rustc_session::config::nightly_options;
 use rustc_span::Span;
 
 pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
@@ -105,7 +105,58 @@ pub enum GenerateMemberConstraints {
     IfNoStaticBound,
 }
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+pub trait InferCtxtExt<'tcx> {
+    fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
+        &self,
+        parent_def_id: DefId,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+        value_span: Span,
+    ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>;
+
+    fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
+        &self,
+        opaque_types: &OpaqueTypeMap<'tcx>,
+        free_region_relations: &FRR,
+    );
+
+    fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
+        &self,
+        def_id: DefId,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        mode: GenerateMemberConstraints,
+        free_region_relations: &FRR,
+    );
+
+    /*private*/
+    fn generate_member_constraint(
+        &self,
+        concrete_ty: Ty<'tcx>,
+        opaque_type_generics: &ty::Generics,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        opaque_type_def_id: DefId,
+    );
+
+    /*private*/
+    fn member_constraint_feature_gate(
+        &self,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        opaque_type_def_id: DefId,
+        conflict1: ty::Region<'tcx>,
+        conflict2: ty::Region<'tcx>,
+    ) -> bool;
+
+    fn infer_opaque_definition_from_instantiation(
+        &self,
+        def_id: DefId,
+        substs: SubstsRef<'tcx>,
+        instantiated_ty: Ty<'tcx>,
+        span: Span,
+    ) -> Ty<'tcx>;
+}
+
+impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     /// Replaces all opaque types in `value` with fresh inference variables
     /// and creates appropriate obligations. For example, given the input:
     ///
@@ -131,7 +182,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     ///   obligations
     /// - `value` -- the value within which we are instantiating opaque types
     /// - `value_span` -- the span where the value came from, used in error reporting
-    pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
+    fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
         &self,
         parent_def_id: DefId,
         body_id: hir::HirId,
@@ -319,7 +370,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// - `opaque_types` -- the map produced by `instantiate_opaque_types`
     /// - `free_region_relations` -- something that can be used to relate
     ///   the free regions (`'a`) that appear in the impl trait.
-    pub fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
+    fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
         &self,
         opaque_types: &OpaqueTypeMap<'tcx>,
         free_region_relations: &FRR,
@@ -337,7 +388,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     /// See `constrain_opaque_types` for documentation.
-    pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
+    fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         &self,
         def_id: DefId,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
@@ -579,7 +630,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// - `substs`, the substs  used to instantiate this opaque type
     /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
     ///   `opaque_defn.concrete_ty`
-    pub fn infer_opaque_definition_from_instantiation(
+    fn infer_opaque_definition_from_instantiation(
         &self,
         def_id: DefId,
         substs: SubstsRef<'tcx>,
@@ -618,86 +669,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 }
 
-pub fn unexpected_hidden_region_diagnostic(
-    tcx: TyCtxt<'tcx>,
-    region_scope_tree: Option<&region::ScopeTree>,
-    span: Span,
-    hidden_ty: Ty<'tcx>,
-    hidden_region: ty::Region<'tcx>,
-) -> DiagnosticBuilder<'tcx> {
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0700,
-        "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
-    );
-
-    // Explain the region we are capturing.
-    if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region {
-        // Assuming regionck succeeded (*), we ought to always be
-        // capturing *some* region from the fn header, and hence it
-        // ought to be free. So under normal circumstances, we will go
-        // down this path which gives a decent human readable
-        // explanation.
-        //
-        // (*) if not, the `tainted_by_errors` flag would be set to
-        // true in any case, so we wouldn't be here at all.
-        note_and_explain_free_region(
-            tcx,
-            &mut err,
-            &format!("hidden type `{}` captures ", hidden_ty),
-            hidden_region,
-            "",
-        );
-    } else {
-        // Ugh. This is a painful case: the hidden region is not one
-        // that we can easily summarize or explain. This can happen
-        // in a case like
-        // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
-        //
-        // ```
-        // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
-        //   if condition() { a } else { b }
-        // }
-        // ```
-        //
-        // Here the captured lifetime is the intersection of `'a` and
-        // `'b`, which we can't quite express.
-
-        if let Some(region_scope_tree) = region_scope_tree {
-            // If the `region_scope_tree` is available, this is being
-            // invoked from the "region inferencer error". We can at
-            // least report a really cryptic error for now.
-            note_and_explain_region(
-                tcx,
-                region_scope_tree,
-                &mut err,
-                &format!("hidden type `{}` captures ", hidden_ty),
-                hidden_region,
-                "",
-            );
-        } else {
-            // If the `region_scope_tree` is *unavailable*, this is
-            // being invoked by the code that comes *after* region
-            // inferencing. This is a bug, as the region inferencer
-            // ought to have noticed the failed constraint and invoked
-            // error reporting, which in turn should have prevented us
-            // from getting trying to infer the hidden type
-            // completely.
-            tcx.sess.delay_span_bug(
-                span,
-                &format!(
-                    "hidden type captures unexpected lifetime `{:?}` \
-                     but no region inference failure",
-                    hidden_region,
-                ),
-            );
-        }
-    }
-
-    err
-}
-
 // Visitor that requires that (almost) all regions in the type visited outlive
 // `least_region`. We cannot use `push_outlives_components` because regions in
 // closure signatures are not included in their outlives components. We need to
diff --git a/src/librustc_infer/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs
index 39be8fc1c0f..d221d6886e9 100644
--- a/src/librustc_infer/traits/auto_trait.rs
+++ b/src/librustc_trait_selection/traits/auto_trait.rs
@@ -113,7 +113,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             return AutoTraitResult::ExplicitImpl;
         }
 
-        return tcx.infer_ctxt().enter(|mut infcx| {
+        return tcx.infer_ctxt().enter(|infcx| {
             let mut fresh_preds = FxHashSet::default();
 
             // Due to the way projections are handled by SelectionContext, we need to run
@@ -164,7 +164,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
 
             let (full_env, full_user_env) = self
                 .evaluate_predicates(
-                    &mut infcx,
+                    &infcx,
                     trait_did,
                     ty,
                     new_env,
diff --git a/src/librustc_infer/traits/codegen/mod.rs b/src/librustc_trait_selection/traits/codegen/mod.rs
index f499565e919..5c2fc3f305c 100644
--- a/src/librustc_infer/traits/codegen/mod.rs
+++ b/src/librustc_trait_selection/traits/codegen/mod.rs
@@ -72,7 +72,7 @@ pub fn codegen_fulfill_obligation<'tcx>(
             debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
             fulfill_cx.register_predicate_obligation(&infcx, predicate);
         });
-        let vtable = infcx.drain_fulfillment_cx_or_panic(&mut fulfill_cx, &vtable);
+        let vtable = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, &vtable);
 
         info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
         Some(vtable)
@@ -81,34 +81,32 @@ pub fn codegen_fulfill_obligation<'tcx>(
 
 // # Global Cache
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    /// Finishes processes any obligations that remain in the
-    /// fulfillment context, and then returns the result with all type
-    /// variables removed and regions erased. Because this is intended
-    /// for use after type-check has completed, if any errors occur,
-    /// it will panic. It is used during normalization and other cases
-    /// where processing the obligations in `fulfill_cx` may cause
-    /// type inference variables that appear in `result` to be
-    /// unified, and hence we need to process those obligations to get
-    /// the complete picture of the type.
-    fn drain_fulfillment_cx_or_panic<T>(
-        &self,
-        fulfill_cx: &mut FulfillmentContext<'tcx>,
-        result: &T,
-    ) -> T
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        debug!("drain_fulfillment_cx_or_panic()");
+/// Finishes processes any obligations that remain in the
+/// fulfillment context, and then returns the result with all type
+/// variables removed and regions erased. Because this is intended
+/// for use after type-check has completed, if any errors occur,
+/// it will panic. It is used during normalization and other cases
+/// where processing the obligations in `fulfill_cx` may cause
+/// type inference variables that appear in `result` to be
+/// unified, and hence we need to process those obligations to get
+/// the complete picture of the type.
+fn drain_fulfillment_cx_or_panic<T>(
+    infcx: &InferCtxt<'_, 'tcx>,
+    fulfill_cx: &mut FulfillmentContext<'tcx>,
+    result: &T,
+) -> T
+where
+    T: TypeFoldable<'tcx>,
+{
+    debug!("drain_fulfillment_cx_or_panic()");
 
-        // In principle, we only need to do this so long as `result`
-        // contains unbound type parameters. It could be a slight
-        // optimization to stop iterating early.
-        if let Err(errors) = fulfill_cx.select_all_or_error(self) {
-            bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors);
-        }
-
-        let result = self.resolve_vars_if_possible(result);
-        self.tcx.erase_regions(&result)
+    // In principle, we only need to do this so long as `result`
+    // contains unbound type parameters. It could be a slight
+    // optimization to stop iterating early.
+    if let Err(errors) = fulfill_cx.select_all_or_error(infcx) {
+        bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors);
     }
+
+    let result = infcx.resolve_vars_if_possible(result);
+    infcx.tcx.erase_regions(&result)
 }
diff --git a/src/librustc_infer/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs
index 15c5f4d402a..5f542e7e13b 100644
--- a/src/librustc_infer/traits/coherence.rs
+++ b/src/librustc_trait_selection/traits/coherence.rs
@@ -1,8 +1,8 @@
-//! See Rustc Guide chapters on [trait-resolution] and [trait-specialization] for more info on how
-//! this works.
+//! See Rustc Dev Guide chapters on [trait-resolution] and [trait-specialization] for more info on
+//! how this works.
 //!
-//! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
-//! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
+//! [trait-resolution]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
+//! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
 
 use crate::infer::{CombinedSnapshot, InferOk, TyCtxtInferExt};
 use crate::traits::select::IntercrateAmbiguityCause;
@@ -451,7 +451,7 @@ fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool {
     }
 }
 
-fn ty_is_non_local_constructor<'tcx>(ty: Ty<'tcx>, in_crate: InCrate) -> Option<Ty<'tcx>> {
+fn ty_is_non_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> Option<Ty<'_>> {
     debug!("ty_is_non_local_constructor({:?})", ty);
 
     match ty.kind {
diff --git a/src/librustc_trait_selection/traits/engine.rs b/src/librustc_trait_selection/traits/engine.rs
new file mode 100644
index 00000000000..ee4715e0c20
--- /dev/null
+++ b/src/librustc_trait_selection/traits/engine.rs
@@ -0,0 +1,14 @@
+use rustc::ty::TyCtxt;
+
+use super::FulfillmentContext;
+use super::TraitEngine;
+
+pub trait TraitEngineExt<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>) -> Box<Self>;
+}
+
+impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
+    fn new(_tcx: TyCtxt<'tcx>) -> Box<Self> {
+        Box::new(FulfillmentContext::new())
+    }
+}
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
new file mode 100644
index 00000000000..ef62958a3f7
--- /dev/null
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -0,0 +1,1900 @@
+pub mod on_unimplemented;
+pub mod suggestions;
+
+use super::{
+    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
+    MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
+    OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
+    PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
+};
+
+use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{self, InferCtxt, TyCtxtInferExt};
+use rustc::mir::interpret::ErrorHandled;
+use rustc::ty::error::ExpectedFound;
+use rustc::ty::fast_reject;
+use rustc::ty::fold::TypeFolder;
+use rustc::ty::SubtypePredicate;
+use rustc::ty::{
+    self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
+};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::{Node, QPath, TyKind, WhereBoundPredicate, WherePredicate};
+use rustc_session::DiagnosticMessageId;
+use rustc_span::source_map::SourceMap;
+use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use std::fmt;
+
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use crate::traits::query::normalize::AtExt as _;
+use on_unimplemented::InferCtxtExt as _;
+use suggestions::InferCtxtExt as _;
+
+pub use rustc_infer::traits::error_reporting::*;
+
+pub trait InferCtxtExt<'tcx> {
+    fn report_fulfillment_errors(
+        &self,
+        errors: &[FulfillmentError<'tcx>],
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    );
+
+    fn report_overflow_error<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: fmt::Display + TypeFoldable<'tcx>;
+
+    fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
+
+    fn report_selection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &SelectionError<'tcx>,
+        fallback_has_occurred: bool,
+        points_at_arg: bool,
+    );
+
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>);
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+    ) -> DiagnosticBuilder<'tcx>;
+}
+
+impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+    fn report_fulfillment_errors(
+        &self,
+        errors: &[FulfillmentError<'tcx>],
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        #[derive(Debug)]
+        struct ErrorDescriptor<'tcx> {
+            predicate: ty::Predicate<'tcx>,
+            index: Option<usize>, // None if this is an old error
+        }
+
+        let mut error_map: FxHashMap<_, Vec<_>> = self
+            .reported_trait_errors
+            .borrow()
+            .iter()
+            .map(|(&span, predicates)| {
+                (
+                    span,
+                    predicates
+                        .iter()
+                        .map(|&predicate| ErrorDescriptor { predicate, index: None })
+                        .collect(),
+                )
+            })
+            .collect();
+
+        for (index, error) in errors.iter().enumerate() {
+            // We want to ignore desugarings here: spans are equivalent even
+            // if one is the result of a desugaring and the other is not.
+            let mut span = error.obligation.cause.span;
+            let expn_data = span.ctxt().outer_expn_data();
+            if let ExpnKind::Desugaring(_) = expn_data.kind {
+                span = expn_data.call_site;
+            }
+
+            error_map.entry(span).or_default().push(ErrorDescriptor {
+                predicate: error.obligation.predicate,
+                index: Some(index),
+            });
+
+            self.reported_trait_errors
+                .borrow_mut()
+                .entry(span)
+                .or_default()
+                .push(error.obligation.predicate.clone());
+        }
+
+        // We do this in 2 passes because we want to display errors in order, though
+        // maybe it *is* better to sort errors by span or something.
+        let mut is_suppressed = vec![false; errors.len()];
+        for (_, error_set) in error_map.iter() {
+            // We want to suppress "duplicate" errors with the same span.
+            for error in error_set {
+                if let Some(index) = error.index {
+                    // Suppress errors that are either:
+                    // 1) strictly implied by another error.
+                    // 2) implied by an error with a smaller index.
+                    for error2 in error_set {
+                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
+                            // Avoid errors being suppressed by already-suppressed
+                            // errors, to prevent all errors from being suppressed
+                            // at once.
+                            continue;
+                        }
+
+                        if self.error_implies(&error2.predicate, &error.predicate)
+                            && !(error2.index >= error.index
+                                && self.error_implies(&error.predicate, &error2.predicate))
+                        {
+                            info!("skipping {:?} (implied by {:?})", error, error2);
+                            is_suppressed[index] = true;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        for (error, suppressed) in errors.iter().zip(is_suppressed) {
+            if !suppressed {
+                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
+            }
+        }
+    }
+
+    /// Reports that an overflow has occurred and halts compilation. We
+    /// halt compilation unconditionally because it is important that
+    /// overflows never be masked -- they basically represent computations
+    /// whose result could not be truly determined and thus we can't say
+    /// if the program type checks or not -- and they are unusual
+    /// occurrences in any case.
+    fn report_overflow_error<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: fmt::Display + TypeFoldable<'tcx>,
+    {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            obligation.cause.span,
+            E0275,
+            "overflow evaluating the requirement `{}`",
+            predicate
+        );
+
+        if suggest_increasing_limit {
+            self.suggest_new_overflow_limit(&mut err);
+        }
+
+        self.note_obligation_cause_code(
+            &mut err,
+            &obligation.predicate,
+            &obligation.cause.code,
+            &mut vec![],
+        );
+
+        err.emit();
+        self.tcx.sess.abort_if_errors();
+        bug!();
+    }
+
+    /// Reports that a cycle was detected which led to overflow and halts
+    /// compilation. This is equivalent to `report_overflow_error` except
+    /// that we can give a more helpful error message (and, in particular,
+    /// we do not suggest increasing the overflow limit, which is not
+    /// going to help).
+    fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
+        assert!(!cycle.is_empty());
+
+        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
+
+        self.report_overflow_error(&cycle[0], false);
+    }
+
+    fn report_selection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &SelectionError<'tcx>,
+        fallback_has_occurred: bool,
+        points_at_arg: bool,
+    ) {
+        let tcx = self.tcx;
+        let span = obligation.cause.span;
+
+        let mut err = match *error {
+            SelectionError::Unimplemented => {
+                if let ObligationCauseCode::CompareImplMethodObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                }
+                | ObligationCauseCode::CompareImplTypeObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                } = obligation.cause.code
+                {
+                    self.report_extra_impl_obligation(
+                        span,
+                        item_name,
+                        impl_item_def_id,
+                        trait_item_def_id,
+                        &format!("`{}`", obligation.predicate),
+                    )
+                    .emit();
+                    return;
+                }
+                match obligation.predicate {
+                    ty::Predicate::Trait(ref trait_predicate, _) => {
+                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
+
+                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
+                            return;
+                        }
+                        let trait_ref = trait_predicate.to_poly_trait_ref();
+                        let (post_message, pre_message, type_def) = self
+                            .get_parent_trait_ref(&obligation.cause.code)
+                            .map(|(t, s)| {
+                                (
+                                    format!(" in `{}`", t),
+                                    format!("within `{}`, ", t),
+                                    s.map(|s| (format!("within this `{}`", t), s)),
+                                )
+                            })
+                            .unwrap_or_default();
+
+                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
+                            self.on_unimplemented_note(trait_ref, obligation);
+                        let have_alt_message = message.is_some() || label.is_some();
+                        let is_try = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_to_snippet(span)
+                            .map(|s| &s == "?")
+                            .unwrap_or(false);
+                        let is_from = format!("{}", trait_ref.print_only_trait_path())
+                            .starts_with("std::convert::From<");
+                        let (message, note) = if is_try && is_from {
+                            (
+                                Some(format!(
+                                    "`?` couldn't convert the error to `{}`",
+                                    trait_ref.self_ty(),
+                                )),
+                                Some(
+                                    "the question mark operation (`?`) implicitly performs a \
+                                     conversion on the error value using the `From` trait"
+                                        .to_owned(),
+                                ),
+                            )
+                        } else {
+                            (message, note)
+                        };
+
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0277,
+                            "{}",
+                            message.unwrap_or_else(|| format!(
+                                "the trait bound `{}` is not satisfied{}",
+                                trait_ref.without_const().to_predicate(),
+                                post_message,
+                            ))
+                        );
+
+                        let explanation =
+                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
+                                "consider using `()`, or a `Result`".to_owned()
+                            } else {
+                                format!(
+                                    "{}the trait `{}` is not implemented for `{}`",
+                                    pre_message,
+                                    trait_ref.print_only_trait_path(),
+                                    trait_ref.self_ty(),
+                                )
+                            };
+
+                        if self.suggest_add_reference_to_arg(
+                            &obligation,
+                            &mut err,
+                            &trait_ref,
+                            points_at_arg,
+                            have_alt_message,
+                        ) {
+                            self.note_obligation_cause(&mut err, obligation);
+                            err.emit();
+                            return;
+                        }
+                        if let Some(ref s) = label {
+                            // If it has a custom `#[rustc_on_unimplemented]`
+                            // error message, let's display it as the label!
+                            err.span_label(span, s.as_str());
+                            err.help(&explanation);
+                        } else {
+                            err.span_label(span, explanation);
+                        }
+                        if let Some((msg, span)) = type_def {
+                            err.span_label(span, &msg);
+                        }
+                        if let Some(ref s) = note {
+                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
+                            err.note(s.as_str());
+                        }
+                        if let Some(ref s) = enclosing_scope {
+                            let enclosing_scope_span = tcx.def_span(
+                                tcx.hir()
+                                    .opt_local_def_id(obligation.cause.body_id)
+                                    .unwrap_or_else(|| {
+                                        tcx.hir().body_owner_def_id(hir::BodyId {
+                                            hir_id: obligation.cause.body_id,
+                                        })
+                                    }),
+                            );
+
+                            err.span_label(enclosing_scope_span, s.as_str());
+                        }
+
+                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
+                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
+                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
+                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
+                        self.note_version_mismatch(&mut err, &trait_ref);
+                        if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
+                            err.emit();
+                            return;
+                        }
+
+                        // Try to report a help message
+                        if !trait_ref.has_infer_types_or_consts()
+                            && self.predicate_can_apply(obligation.param_env, trait_ref)
+                        {
+                            // If a where-clause may be useful, remind the
+                            // user that they can add it.
+                            //
+                            // don't display an on-unimplemented note, as
+                            // these notes will often be of the form
+                            //     "the type `T` can't be frobnicated"
+                            // which is somewhat confusing.
+                            self.suggest_restricting_param_bound(
+                                &mut err,
+                                &trait_ref,
+                                obligation.cause.body_id,
+                            );
+                        } else {
+                            if !have_alt_message {
+                                // Can't show anything else useful, try to find similar impls.
+                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
+                                self.report_similar_impl_candidates(impl_candidates, &mut err);
+                            }
+                            self.suggest_change_mut(
+                                &obligation,
+                                &mut err,
+                                &trait_ref,
+                                points_at_arg,
+                            );
+                        }
+
+                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
+                        // implemented, and fallback has occurred, then it could be due to a
+                        // variable that used to fallback to `()` now falling back to `!`. Issue a
+                        // note informing about the change in behaviour.
+                        if trait_predicate.skip_binder().self_ty().is_never()
+                            && fallback_has_occurred
+                        {
+                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
+                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
+                                    self.tcx.mk_unit(),
+                                    &trait_pred.trait_ref.substs[1..],
+                                );
+                                trait_pred
+                            });
+                            let unit_obligation = Obligation {
+                                predicate: ty::Predicate::Trait(
+                                    predicate,
+                                    hir::Constness::NotConst,
+                                ),
+                                ..obligation.clone()
+                            };
+                            if self.predicate_may_hold(&unit_obligation) {
+                                err.note(
+                                    "the trait is implemented for `()`. \
+                                     Possibly this error has been caused by changes to \
+                                     Rust's type-inference algorithm (see issue #48950 \
+                                     <https://github.com/rust-lang/rust/issues/48950> \
+                                     for more information). Consider whether you meant to use \
+                                     the type `()` here instead.",
+                                );
+                            }
+                        }
+
+                        err
+                    }
+
+                    ty::Predicate::Subtype(ref predicate) => {
+                        // Errors for Subtype predicates show up as
+                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // not selection error.
+                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
+                    }
+
+                    ty::Predicate::RegionOutlives(ref predicate) => {
+                        let predicate = self.resolve_vars_if_possible(predicate);
+                        let err = self
+                            .region_outlives_predicate(&obligation.cause, &predicate)
+                            .err()
+                            .unwrap();
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0279,
+                            "the requirement `{}` is not satisfied (`{}`)",
+                            predicate,
+                            err,
+                        )
+                    }
+
+                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
+                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0280,
+                            "the requirement `{}` is not satisfied",
+                            predicate
+                        )
+                    }
+
+                    ty::Predicate::ObjectSafe(trait_def_id) => {
+                        let violations = self.tcx.object_safety_violations(trait_def_id);
+                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
+                    }
+
+                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
+                        let closure_span = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
+                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            closure_span,
+                            E0525,
+                            "expected a closure that implements the `{}` trait, \
+                             but this closure only implements `{}`",
+                            kind,
+                            found_kind
+                        );
+
+                        err.span_label(
+                            closure_span,
+                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
+                        );
+                        err.span_label(
+                            obligation.cause.span,
+                            format!("the requirement to implement `{}` derives from here", kind),
+                        );
+
+                        // Additional context information explaining why the closure only implements
+                        // a particular trait.
+                        if let Some(tables) = self.in_progress_tables {
+                            let tables = tables.borrow();
+                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
+                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnOnce` because it moves the \
+                                         variable `{}` out of its environment",
+                                            name
+                                        ),
+                                    );
+                                }
+                                (ty::ClosureKind::FnMut, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnMut` because it mutates the \
+                                         variable `{}` here",
+                                            name
+                                        ),
+                                    );
+                                }
+                                _ => {}
+                            }
+                        }
+
+                        err.emit();
+                        return;
+                    }
+
+                    ty::Predicate::WellFormed(ty) => {
+                        // WF predicates cannot themselves make
+                        // errors. They can only block due to
+                        // ambiguity; otherwise, they always
+                        // degenerate into other obligations
+                        // (which may fail).
+                        span_bug!(span, "WF predicate not satisfied for {:?}", ty);
+                    }
+
+                    ty::Predicate::ConstEvaluatable(..) => {
+                        // Errors for `ConstEvaluatable` predicates show up as
+                        // `SelectionError::ConstEvalFailure`,
+                        // not `Unimplemented`.
+                        span_bug!(
+                            span,
+                            "const-evaluatable requirement gave wrong error: `{:?}`",
+                            obligation
+                        )
+                    }
+                }
+            }
+
+            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
+                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
+                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
+
+                if expected_trait_ref.self_ty().references_error() {
+                    return;
+                }
+
+                let found_trait_ty = found_trait_ref.self_ty();
+
+                let found_did = match found_trait_ty.kind {
+                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
+                    ty::Adt(def, _) => Some(def.did),
+                    _ => None,
+                };
+
+                let found_span = found_did
+                    .and_then(|did| self.tcx.hir().span_if_local(did))
+                    .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
+
+                if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
+                    // We check closures twice, with obligations flowing in different directions,
+                    // but we want to complain about them only once.
+                    return;
+                }
+
+                self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
+
+                let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
+                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
+                    _ => vec![ArgKind::empty()],
+                };
+
+                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
+                let expected = match expected_ty.kind {
+                    ty::Tuple(ref tys) => tys
+                        .iter()
+                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
+                        .collect(),
+                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
+                };
+
+                if found.len() == expected.len() {
+                    self.report_closure_arg_mismatch(
+                        span,
+                        found_span,
+                        found_trait_ref,
+                        expected_trait_ref,
+                    )
+                } else {
+                    let (closure_span, found) = found_did
+                        .and_then(|did| self.tcx.hir().get_if_local(did))
+                        .map(|node| {
+                            let (found_span, found) = self.get_fn_like_arguments(node);
+                            (Some(found_span), found)
+                        })
+                        .unwrap_or((found_span, found));
+
+                    self.report_arg_count_mismatch(
+                        span,
+                        closure_span,
+                        expected,
+                        found,
+                        found_trait_ty.is_closure(),
+                    )
+                }
+            }
+
+            TraitNotObjectSafe(did) => {
+                let violations = self.tcx.object_safety_violations(did);
+                report_object_safety_error(self.tcx, span, did, violations)
+            }
+
+            ConstEvalFailure(ErrorHandled::TooGeneric) => {
+                // In this instance, we have a const expression containing an unevaluated
+                // generic parameter. We have no idea whether this expression is valid or
+                // not (e.g. it might result in an error), but we don't want to just assume
+                // that it's okay, because that might result in post-monomorphisation time
+                // errors. The onus is really on the caller to provide values that it can
+                // prove are well-formed.
+                let mut err = self
+                    .tcx
+                    .sess
+                    .struct_span_err(span, "constant expression depends on a generic parameter");
+                // FIXME(const_generics): we should suggest to the user how they can resolve this
+                // issue. However, this is currently not actually possible
+                // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
+                err.note("this may fail depending on what value the parameter takes");
+                err
+            }
+
+            // Already reported in the query.
+            ConstEvalFailure(ErrorHandled::Reported) => {
+                self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
+                return;
+            }
+
+            Overflow => {
+                bug!("overflow should be handled before the `report_selection_error` path");
+            }
+        };
+
+        self.note_obligation_cause(&mut err, obligation);
+        self.point_at_returns_when_relevant(&mut err, &obligation);
+
+        err.emit();
+    }
+
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
+        match node {
+            Node::Expr(&hir::Expr {
+                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                self.tcx
+                    .hir()
+                    .body(id)
+                    .params
+                    .iter()
+                    .map(|arg| {
+                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
+                            *arg.pat
+                        {
+                            ArgKind::Tuple(
+                                Some(span),
+                                args.iter()
+                                    .map(|pat| {
+                                        let snippet = self
+                                            .tcx
+                                            .sess
+                                            .source_map()
+                                            .span_to_snippet(pat.span)
+                                            .unwrap();
+                                        (snippet, "_".to_owned())
+                                    })
+                                    .collect::<Vec<_>>(),
+                            )
+                        } else {
+                            let name =
+                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
+                            ArgKind::Arg(name, "_".to_owned())
+                        }
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
+            | Node::ImplItem(&hir::ImplItem {
+                span,
+                kind: hir::ImplItemKind::Fn(ref sig, _),
+                ..
+            })
+            | Node::TraitItem(&hir::TraitItem {
+                span,
+                kind: hir::TraitItemKind::Fn(ref sig, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                sig.decl
+                    .inputs
+                    .iter()
+                    .map(|arg| match arg.clone().kind {
+                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
+                            Some(arg.span),
+                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
+                        ),
+                        _ => ArgKind::empty(),
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Ctor(ref variant_data) => {
+                let span = variant_data
+                    .ctor_hir_id()
+                    .map(|hir_id| self.tcx.hir().span(hir_id))
+                    .unwrap_or(DUMMY_SP);
+                let span = self.tcx.sess.source_map().def_span(span);
+
+                (span, vec![ArgKind::empty(); variant_data.fields().len()])
+            }
+            _ => panic!("non-FnLike node found: {:?}", node),
+        }
+    }
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+    ) -> DiagnosticBuilder<'tcx> {
+        let kind = if is_closure { "closure" } else { "function" };
+
+        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
+            let arg_length = arguments.len();
+            let distinct = match &other[..] {
+                &[ArgKind::Tuple(..)] => true,
+                _ => false,
+            };
+            match (arg_length, arguments.get(0)) {
+                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+                    format!("a single {}-tuple as argument", fields.len())
+                }
+                _ => format!(
+                    "{} {}argument{}",
+                    arg_length,
+                    if distinct && arg_length > 1 { "distinct " } else { "" },
+                    pluralize!(arg_length)
+                ),
+            }
+        };
+
+        let expected_str = args_str(&expected_args, &found_args);
+        let found_str = args_str(&found_args, &expected_args);
+
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0593,
+            "{} is expected to take {}, but it takes {}",
+            kind,
+            expected_str,
+            found_str,
+        );
+
+        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
+
+        if let Some(found_span) = found_span {
+            err.span_label(found_span, format!("takes {}", found_str));
+
+            // move |_| { ... }
+            // ^^^^^^^^-- def_span
+            //
+            // move |_| { ... }
+            // ^^^^^-- prefix
+            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
+            // move |_| { ... }
+            //      ^^^-- pipe_span
+            let pipe_span =
+                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
+
+            // Suggest to take and ignore the arguments with expected_args_length `_`s if
+            // found arguments is empty (assume the user just wants to ignore args in this case).
+            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
+            if found_args.is_empty() && is_closure {
+                let underscores = vec!["_"; expected_args.len()].join(", ");
+                err.span_suggestion(
+                    pipe_span,
+                    &format!(
+                        "consider changing the closure to take and ignore the expected argument{}",
+                        if expected_args.len() < 2 { "" } else { "s" }
+                    ),
+                    format!("|{}|", underscores),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+                if fields.len() == expected_args.len() {
+                    let sugg = fields
+                        .iter()
+                        .map(|(name, _)| name.to_owned())
+                        .collect::<Vec<String>>()
+                        .join(", ");
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to take multiple arguments instead of a single tuple",
+                        format!("|{}|", sugg),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
+                if fields.len() == found_args.len() && is_closure {
+                    let sugg = format!(
+                        "|({}){}|",
+                        found_args
+                            .iter()
+                            .map(|arg| match arg {
+                                ArgKind::Arg(name, _) => name.to_owned(),
+                                _ => "_".to_owned(),
+                            })
+                            .collect::<Vec<String>>()
+                            .join(", "),
+                        // add type annotations if available
+                        if found_args.iter().any(|arg| match arg {
+                            ArgKind::Arg(_, ty) => ty != "_",
+                            _ => false,
+                        }) {
+                            format!(
+                                ": ({})",
+                                fields
+                                    .iter()
+                                    .map(|(_, ty)| ty.to_owned())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            )
+                        } else {
+                            String::new()
+                        },
+                    );
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to accept a tuple instead of individual arguments",
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+        }
+
+        err
+    }
+}
+
+trait InferCtxtPrivExt<'tcx> {
+    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
+    // `error` occurring implies that `cond` occurs.
+    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool;
+
+    fn report_fulfillment_error(
+        &self,
+        error: &FulfillmentError<'tcx>,
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    );
+
+    fn report_projection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &MismatchedProjectionTypes<'tcx>,
+    );
+
+    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool;
+
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
+
+    fn find_similar_impl_candidates(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<ty::TraitRef<'tcx>>;
+
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: Vec<ty::TraitRef<'tcx>>,
+        err: &mut DiagnosticBuilder<'_>,
+    );
+
+    /// Gets the parent trait chain start
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)>;
+
+    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
+    /// with the same path as `trait_ref`, a help message about
+    /// a probable version mismatch is added to `err`
+    fn note_version_mismatch(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    );
+
+    fn mk_obligation_for_def_id(
+        &self,
+        def_id: DefId,
+        output_ty: Ty<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> PredicateObligation<'tcx>;
+
+    fn maybe_report_ambiguity(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        body_id: Option<hir::BodyId>,
+    );
+
+    fn predicate_can_apply(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitRef<'tcx>,
+    ) -> bool;
+
+    fn note_obligation_cause(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    );
+
+    fn suggest_unsized_bound_if_applicable(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    );
+
+    fn is_recursive_obligation(
+        &self,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+        cause_code: &ObligationCauseCode<'tcx>,
+    ) -> bool;
+}
+
+impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
+    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
+    // `error` occurring implies that `cond` occurs.
+    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
+        if cond == error {
+            return true;
+        }
+
+        let (cond, error) = match (cond, error) {
+            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
+            _ => {
+                // FIXME: make this work in other cases too.
+                return false;
+            }
+        };
+
+        for implication in super::elaborate_predicates(self.tcx, vec![*cond]) {
+            if let ty::Predicate::Trait(implication, _) = implication {
+                let error = error.to_poly_trait_ref();
+                let implication = implication.to_poly_trait_ref();
+                // FIXME: I'm just not taking associated types at all here.
+                // Eventually I'll need to implement param-env-aware
+                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
+                let param_env = ty::ParamEnv::empty();
+                if self.can_sub(param_env, error, implication).is_ok() {
+                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
+                    return true;
+                }
+            }
+        }
+
+        false
+    }
+
+    fn report_fulfillment_error(
+        &self,
+        error: &FulfillmentError<'tcx>,
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        debug!("report_fulfillment_error({:?})", error);
+        match error.code {
+            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
+                self.report_selection_error(
+                    &error.obligation,
+                    selection_error,
+                    fallback_has_occurred,
+                    error.points_at_arg_span,
+                );
+            }
+            FulfillmentErrorCode::CodeProjectionError(ref e) => {
+                self.report_projection_error(&error.obligation, e);
+            }
+            FulfillmentErrorCode::CodeAmbiguity => {
+                self.maybe_report_ambiguity(&error.obligation, body_id);
+            }
+            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+                self.report_mismatched_types(
+                    &error.obligation.cause,
+                    expected_found.expected,
+                    expected_found.found,
+                    err.clone(),
+                )
+                .emit();
+            }
+        }
+    }
+
+    fn report_projection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &MismatchedProjectionTypes<'tcx>,
+    ) {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+
+        if predicate.references_error() {
+            return;
+        }
+
+        self.probe(|_| {
+            let err_buf;
+            let mut err = &error.err;
+            let mut values = None;
+
+            // try to find the mismatched types to report the error with.
+            //
+            // this can fail if the problem was higher-ranked, in which
+            // cause I have no idea for a good error message.
+            if let ty::Predicate::Projection(ref data) = predicate {
+                let mut selcx = SelectionContext::new(self);
+                let (data, _) = self.replace_bound_vars_with_fresh_vars(
+                    obligation.cause.span,
+                    infer::LateBoundRegionConversionTime::HigherRankedType,
+                    data,
+                );
+                let mut obligations = vec![];
+                let normalized_ty = super::normalize_projection_type(
+                    &mut selcx,
+                    obligation.param_env,
+                    data.projection_ty,
+                    obligation.cause.clone(),
+                    0,
+                    &mut obligations,
+                );
+
+                debug!(
+                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
+                    obligation.cause, obligation.param_env
+                );
+
+                debug!(
+                    "report_projection_error normalized_ty={:?} data.ty={:?}",
+                    normalized_ty, data.ty
+                );
+
+                let is_normalized_ty_expected = match &obligation.cause.code {
+                    ObligationCauseCode::ItemObligation(_)
+                    | ObligationCauseCode::BindingObligation(_, _)
+                    | ObligationCauseCode::ObjectCastObligation(_) => false,
+                    _ => true,
+                };
+
+                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
+                    is_normalized_ty_expected,
+                    normalized_ty,
+                    data.ty,
+                ) {
+                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
+                        is_normalized_ty_expected,
+                        normalized_ty,
+                        data.ty,
+                    )));
+
+                    err_buf = error;
+                    err = &err_buf;
+                }
+            }
+
+            let msg = format!("type mismatch resolving `{}`", predicate);
+            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
+            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+            if fresh {
+                let mut diag = struct_span_err!(
+                    self.tcx.sess,
+                    obligation.cause.span,
+                    E0271,
+                    "type mismatch resolving `{}`",
+                    predicate
+                );
+                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
+                self.note_obligation_cause(&mut diag, obligation);
+                diag.emit();
+            }
+        });
+    }
+
+    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+        /// returns the fuzzy category of a given type, or None
+        /// if the type can be equated to any type.
+        fn type_category(t: Ty<'_>) -> Option<u32> {
+            match t.kind {
+                ty::Bool => Some(0),
+                ty::Char => Some(1),
+                ty::Str => Some(2),
+                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
+                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
+                ty::Ref(..) | ty::RawPtr(..) => Some(5),
+                ty::Array(..) | ty::Slice(..) => Some(6),
+                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
+                ty::Dynamic(..) => Some(8),
+                ty::Closure(..) => Some(9),
+                ty::Tuple(..) => Some(10),
+                ty::Projection(..) => Some(11),
+                ty::Param(..) => Some(12),
+                ty::Opaque(..) => Some(13),
+                ty::Never => Some(14),
+                ty::Adt(adt, ..) => match adt.adt_kind() {
+                    AdtKind::Struct => Some(15),
+                    AdtKind::Union => Some(16),
+                    AdtKind::Enum => Some(17),
+                },
+                ty::Generator(..) => Some(18),
+                ty::Foreign(..) => Some(19),
+                ty::GeneratorWitness(..) => Some(20),
+                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+            }
+        }
+
+        match (type_category(a), type_category(b)) {
+            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
+                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
+                _ => cat_a == cat_b,
+            },
+            // infer and error can be equated to all types
+            _ => true,
+        }
+    }
+
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
+        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
+            hir::GeneratorKind::Gen => "a generator",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
+        })
+    }
+
+    fn find_similar_impl_candidates(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<ty::TraitRef<'tcx>> {
+        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
+        let all_impls = self.tcx.all_impls(trait_ref.def_id());
+
+        match simp {
+            Some(simp) => all_impls
+                .iter()
+                .filter_map(|&def_id| {
+                    let imp = self.tcx.impl_trait_ref(def_id).unwrap();
+                    let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
+                    if let Some(imp_simp) = imp_simp {
+                        if simp != imp_simp {
+                            return None;
+                        }
+                    }
+
+                    Some(imp)
+                })
+                .collect(),
+            None => {
+                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
+            }
+        }
+    }
+
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: Vec<ty::TraitRef<'tcx>>,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        if impl_candidates.is_empty() {
+            return;
+        }
+
+        let len = impl_candidates.len();
+        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
+
+        let normalize = |candidate| {
+            self.tcx.infer_ctxt().enter(|ref infcx| {
+                let normalized = infcx
+                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+                    .normalize(candidate)
+                    .ok();
+                match normalized {
+                    Some(normalized) => format!("\n  {:?}", normalized.value),
+                    None => format!("\n  {:?}", candidate),
+                }
+            })
+        };
+
+        // Sort impl candidates so that ordering is consistent for UI tests.
+        let mut normalized_impl_candidates =
+            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
+
+        // Sort before taking the `..end` range,
+        // because the ordering of `impl_candidates` may not be deterministic:
+        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
+        normalized_impl_candidates.sort();
+
+        err.help(&format!(
+            "the following implementations were found:{}{}",
+            normalized_impl_candidates[..end].join(""),
+            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
+        ));
+    }
+
+    /// Gets the parent trait chain start
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)> {
+        match code {
+            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                match self.get_parent_trait_ref(&data.parent_code) {
+                    Some(t) => Some(t),
+                    None => {
+                        let ty = parent_trait_ref.skip_binder().self_ty();
+                        let span =
+                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
+                        Some((ty.to_string(), span))
+                    }
+                }
+            }
+            _ => None,
+        }
+    }
+
+    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
+    /// with the same path as `trait_ref`, a help message about
+    /// a probable version mismatch is added to `err`
+    fn note_version_mismatch(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    ) {
+        let get_trait_impl = |trait_def_id| {
+            let mut trait_impl = None;
+            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
+                if trait_impl.is_none() {
+                    trait_impl = Some(impl_def_id);
+                }
+            });
+            trait_impl
+        };
+        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
+        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
+        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
+            .iter()
+            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
+            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
+            .collect();
+        for trait_with_same_path in traits_with_same_path {
+            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
+                let impl_span = self.tcx.def_span(impl_def_id);
+                err.span_help(impl_span, "trait impl with same name found");
+                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
+                let crate_msg = format!(
+                    "perhaps two different versions of crate `{}` are being used?",
+                    trait_crate
+                );
+                err.note(&crate_msg);
+            }
+        }
+    }
+
+    fn mk_obligation_for_def_id(
+        &self,
+        def_id: DefId,
+        output_ty: Ty<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> PredicateObligation<'tcx> {
+        let new_trait_ref =
+            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
+        Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
+    }
+
+    fn maybe_report_ambiguity(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        body_id: Option<hir::BodyId>,
+    ) {
+        // Unable to successfully determine, probably means
+        // insufficient type information, but could mean
+        // ambiguous impls. The latter *ought* to be a
+        // coherence violation, so we don't report it here.
+
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let span = obligation.cause.span;
+
+        debug!(
+            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
+            predicate, obligation, body_id, obligation.cause.code,
+        );
+
+        // Ambiguity errors are often caused as fallout from earlier
+        // errors. So just ignore them if this infcx is tainted.
+        if self.is_tainted_by_errors() {
+            return;
+        }
+
+        let mut err = match predicate {
+            ty::Predicate::Trait(ref data, _) => {
+                let trait_ref = data.to_poly_trait_ref();
+                let self_ty = trait_ref.self_ty();
+                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
+
+                if predicate.references_error() {
+                    return;
+                }
+                // Typically, this ambiguity should only happen if
+                // there are unresolved type inference variables
+                // (otherwise it would suggest a coherence
+                // failure). But given #21974 that is not necessarily
+                // the case -- we can have multiple where clauses that
+                // are only distinguished by a region, which results
+                // in an ambiguity even when all types are fully
+                // known, since we don't dispatch based on region
+                // relationships.
+
+                // This is kind of a hack: it frequently happens that some earlier
+                // error prevents types from being fully inferred, and then we get
+                // a bunch of uninteresting errors saying something like "<generic
+                // #0> doesn't implement Sized".  It may even be true that we
+                // could just skip over all checks where the self-ty is an
+                // inference variable, but I was afraid that there might be an
+                // inference variable created, registered as an obligation, and
+                // then never forced by writeback, and hence by skipping here we'd
+                // be ignoring the fact that we don't KNOW the type works
+                // out. Though even that would probably be harmless, given that
+                // we're only talking about builtin traits, which are known to be
+                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
+                // avoid inundating the user with unnecessary errors, but we now
+                // check upstream for type errors and don't add the obligations to
+                // begin with in those cases.
+                if self
+                    .tcx
+                    .lang_items()
+                    .sized_trait()
+                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
+                {
+                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
+                } else if let (
+                    Ok(ref snippet),
+                    ObligationCauseCode::BindingObligation(ref def_id, _),
+                ) =
+                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
+                {
+                    let generics = self.tcx.generics_of(*def_id);
+                    if !generics.params.is_empty() && !snippet.ends_with('>') {
+                        // FIXME: To avoid spurious suggestions in functions where type arguments
+                        // where already supplied, we check the snippet to make sure it doesn't
+                        // end with a turbofish. Ideally we would have access to a `PathSegment`
+                        // instead. Otherwise we would produce the following output:
+                        //
+                        // error[E0283]: type annotations needed
+                        //   --> $DIR/issue-54954.rs:3:24
+                        //    |
+                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
+                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+                        //    |                        |
+                        //    |                        cannot infer type
+                        //    |                        help: consider specifying the type argument
+                        //    |                        in the function call:
+                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
+                        // ...
+                        // LL |     const fn const_val<T: Sized>() -> usize {
+                        //    |              --------- - required by this bound in `Tt::const_val`
+                        //    |
+                        //    = note: cannot resolve `_: Tt`
+
+                        err.span_suggestion(
+                            span,
+                            &format!(
+                                "consider specifying the type argument{} in the function call",
+                                if generics.params.len() > 1 { "s" } else { "" },
+                            ),
+                            format!(
+                                "{}::<{}>",
+                                snippet,
+                                generics
+                                    .params
+                                    .iter()
+                                    .map(|p| p.name.to_string())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            ),
+                            Applicability::HasPlaceholders,
+                        );
+                    }
+                }
+                err
+            }
+
+            ty::Predicate::WellFormed(ty) => {
+                // Same hacky approach as above to avoid deluging user
+                // with error messages.
+                if ty.references_error() || self.tcx.sess.has_errors() {
+                    return;
+                }
+                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
+            }
+
+            ty::Predicate::Subtype(ref data) => {
+                if data.references_error() || self.tcx.sess.has_errors() {
+                    // no need to overload user in such cases
+                    return;
+                }
+                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                // both must be type variables, or the other would've been instantiated
+                assert!(a.is_ty_var() && b.is_ty_var());
+                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
+            }
+            ty::Predicate::Projection(ref data) => {
+                let trait_ref = data.to_poly_trait_ref(self.tcx);
+                let self_ty = trait_ref.self_ty();
+                if predicate.references_error() {
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                err
+            }
+
+            _ => {
+                if self.tcx.sess.has_errors() {
+                    return;
+                }
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0284,
+                    "type annotations needed: cannot resolve `{}`",
+                    predicate,
+                );
+                err.span_label(span, &format!("cannot resolve `{}`", predicate));
+                err
+            }
+        };
+        self.note_obligation_cause(&mut err, obligation);
+        err.emit();
+    }
+
+    /// Returns `true` if the trait predicate may apply for *some* assignment
+    /// to the type parameters.
+    fn predicate_can_apply(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitRef<'tcx>,
+    ) -> bool {
+        struct ParamToVarFolder<'a, 'tcx> {
+            infcx: &'a InferCtxt<'a, 'tcx>,
+            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+        }
+
+        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
+            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+                self.infcx.tcx
+            }
+
+            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
+                    let infcx = self.infcx;
+                    self.var_map.entry(ty).or_insert_with(|| {
+                        infcx.next_ty_var(TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
+                            span: DUMMY_SP,
+                        })
+                    })
+                } else {
+                    ty.super_fold_with(self)
+                }
+            }
+        }
+
+        self.probe(|_| {
+            let mut selcx = SelectionContext::new(self);
+
+            let cleaned_pred =
+                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
+
+            let cleaned_pred = super::project::normalize(
+                &mut selcx,
+                param_env,
+                ObligationCause::dummy(),
+                &cleaned_pred,
+            )
+            .value;
+
+            let obligation = Obligation::new(
+                ObligationCause::dummy(),
+                param_env,
+                cleaned_pred.without_const().to_predicate(),
+            );
+
+            self.predicate_may_hold(&obligation)
+        })
+    }
+
+    fn note_obligation_cause(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        // First, attempt to add note to this error with an async-await-specific
+        // message, and fall back to regular note otherwise.
+        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
+            self.note_obligation_cause_code(
+                err,
+                &obligation.predicate,
+                &obligation.cause.code,
+                &mut vec![],
+            );
+            self.suggest_unsized_bound_if_applicable(err, obligation);
+        }
+    }
+
+    fn suggest_unsized_bound_if_applicable(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        if let (
+            ty::Predicate::Trait(pred, _),
+            ObligationCauseCode::BindingObligation(item_def_id, span),
+        ) = (&obligation.predicate, &obligation.cause.code)
+        {
+            if let (Some(generics), true) = (
+                self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()),
+                Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
+            ) {
+                for param in generics.params {
+                    if param.span == *span
+                        && !param.bounds.iter().any(|bound| {
+                            bound.trait_def_id() == self.tcx.lang_items().sized_trait()
+                        })
+                    {
+                        let (span, separator) = match param.bounds {
+                            [] => (span.shrink_to_hi(), ":"),
+                            [.., bound] => (bound.span().shrink_to_hi(), " + "),
+                        };
+                        err.span_suggestion(
+                            span,
+                            "consider relaxing the implicit `Sized` restriction",
+                            format!("{} ?Sized", separator),
+                            Applicability::MachineApplicable,
+                        );
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    fn is_recursive_obligation(
+        &self,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+        cause_code: &ObligationCauseCode<'tcx>,
+    ) -> bool {
+        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
+            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+
+            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
+                return true;
+            }
+        }
+        false
+    }
+}
+
+pub fn recursive_type_with_infinite_size_error(
+    tcx: TyCtxt<'tcx>,
+    type_def_id: DefId,
+) -> DiagnosticBuilder<'tcx> {
+    assert!(type_def_id.is_local());
+    let span = tcx.hir().span_if_local(type_def_id).unwrap();
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0072,
+        "recursive type `{}` has infinite size",
+        tcx.def_path_str(type_def_id)
+    );
+    err.span_label(span, "recursive type has infinite size");
+    err.help(&format!(
+        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
+                           at some point to make `{}` representable",
+        tcx.def_path_str(type_def_id)
+    ));
+    err
+}
+
+/// Summarizes information
+#[derive(Clone)]
+pub enum ArgKind {
+    /// An argument of non-tuple type. Parameters are (name, ty)
+    Arg(String, String),
+
+    /// An argument of tuple type. For a "found" argument, the span is
+    /// the locationo in the source of the pattern. For a "expected"
+    /// argument, it will be None. The vector is a list of (name, ty)
+    /// strings for the components of the tuple.
+    Tuple(Option<Span>, Vec<(String, String)>),
+}
+
+impl ArgKind {
+    fn empty() -> ArgKind {
+        ArgKind::Arg("_".to_owned(), "_".to_owned())
+    }
+
+    /// Creates an `ArgKind` from the expected type of an
+    /// argument. It has no name (`_`) and an optional source span.
+    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
+        match t.kind {
+            ty::Tuple(ref tys) => ArgKind::Tuple(
+                span,
+                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
+            ),
+            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
+        }
+    }
+}
+
+/// Suggest restricting a type param with a new bound.
+pub fn suggest_constraining_type_param(
+    tcx: TyCtxt<'_>,
+    generics: &hir::Generics<'_>,
+    err: &mut DiagnosticBuilder<'_>,
+    param_name: &str,
+    constraint: &str,
+    source_map: &SourceMap,
+    span: Span,
+    def_id: Option<DefId>,
+) -> bool {
+    const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound with";
+    const MSG_RESTRICT_TYPE: &str = "consider restricting this type parameter with";
+    const MSG_RESTRICT_TYPE_FURTHER: &str = "consider further restricting this type parameter with";
+
+    let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
+
+    let param = if let Some(param) = param {
+        param
+    } else {
+        return false;
+    };
+
+    if def_id == tcx.lang_items().sized_trait() {
+        // Type parameters are already `Sized` by default.
+        err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint));
+        return true;
+    }
+
+    if param_name.starts_with("impl ") {
+        // If there's an `impl Trait` used in argument position, suggest
+        // restricting it:
+        //
+        //   fn foo(t: impl Foo) { ... }
+        //             --------
+        //             |
+        //             help: consider further restricting this bound with `+ Bar`
+        //
+        // Suggestion for tools in this case is:
+        //
+        //   fn foo(t: impl Foo) { ... }
+        //             --------
+        //             |
+        //             replace with: `impl Foo + Bar`
+
+        err.span_help(param.span, &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint));
+
+        err.tool_only_span_suggestion(
+            param.span,
+            MSG_RESTRICT_BOUND_FURTHER,
+            format!("{} + {}", param_name, constraint),
+            Applicability::MachineApplicable,
+        );
+
+        return true;
+    }
+
+    if generics.where_clause.predicates.is_empty() {
+        if let Some(bounds_span) = param.bounds_span() {
+            // If user has provided some bounds, suggest restricting them:
+            //
+            //   fn foo<T: Foo>(t: T) { ... }
+            //             ---
+            //             |
+            //             help: consider further restricting this bound with `+ Bar`
+            //
+            // Suggestion for tools in this case is:
+            //
+            //   fn foo<T: Foo>(t: T) { ... }
+            //          --
+            //          |
+            //          replace with: `T: Bar +`
+
+            err.span_help(
+                bounds_span,
+                &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
+            );
+
+            let span_hi = param.span.with_hi(span.hi());
+            let span_with_colon = source_map.span_through_char(span_hi, ':');
+
+            if span_hi != param.span && span_with_colon != span_hi {
+                err.tool_only_span_suggestion(
+                    span_with_colon,
+                    MSG_RESTRICT_BOUND_FURTHER,
+                    format!("{}: {} + ", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            }
+        } else {
+            // If user hasn't provided any bounds, suggest adding a new one:
+            //
+            //   fn foo<T>(t: T) { ... }
+            //          - help: consider restricting this type parameter with `T: Foo`
+
+            err.span_help(
+                param.span,
+                &format!("{} `{}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
+            );
+
+            err.tool_only_span_suggestion(
+                param.span,
+                MSG_RESTRICT_TYPE,
+                format!("{}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        }
+
+        true
+    } else {
+        // This part is a bit tricky, because using the `where` clause user can
+        // provide zero, one or many bounds for the same type parameter, so we
+        // have following cases to consider:
+        //
+        // 1) When the type parameter has been provided zero bounds
+        //
+        //    Message:
+        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
+        //             - help: consider restricting this type parameter with `where X: Bar`
+        //
+        //    Suggestion:
+        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
+        //                                           - insert: `, X: Bar`
+        //
+        //
+        // 2) When the type parameter has been provided one bound
+        //
+        //    Message:
+        //      fn foo<T>(t: T) where T: Foo { ... }
+        //                            ^^^^^^
+        //                            |
+        //                            help: consider further restricting this bound with `+ Bar`
+        //
+        //    Suggestion:
+        //      fn foo<T>(t: T) where T: Foo { ... }
+        //                            ^^
+        //                            |
+        //                            replace with: `T: Bar +`
+        //
+        //
+        // 3) When the type parameter has been provided many bounds
+        //
+        //    Message:
+        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
+        //             - help: consider further restricting this type parameter with `where T: Zar`
+        //
+        //    Suggestion:
+        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
+        //                                          - insert: `, T: Zar`
+
+        let mut param_spans = Vec::new();
+
+        for predicate in generics.where_clause.predicates {
+            if let WherePredicate::BoundPredicate(WhereBoundPredicate {
+                span, bounded_ty, ..
+            }) = predicate
+            {
+                if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
+                    if let Some(segment) = path.segments.first() {
+                        if segment.ident.to_string() == param_name {
+                            param_spans.push(span);
+                        }
+                    }
+                }
+            }
+        }
+
+        let where_clause_span =
+            generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi();
+
+        match &param_spans[..] {
+            &[] => {
+                err.span_help(
+                    param.span,
+                    &format!("{} `where {}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
+                );
+
+                err.tool_only_span_suggestion(
+                    where_clause_span,
+                    MSG_RESTRICT_TYPE,
+                    format!(", {}: {}", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            &[&param_span] => {
+                err.span_help(
+                    param_span,
+                    &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
+                );
+
+                let span_hi = param_span.with_hi(span.hi());
+                let span_with_colon = source_map.span_through_char(span_hi, ':');
+
+                if span_hi != param_span && span_with_colon != span_hi {
+                    err.tool_only_span_suggestion(
+                        span_with_colon,
+                        MSG_RESTRICT_BOUND_FURTHER,
+                        format!("{}: {} +", param_name, constraint),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+
+            _ => {
+                err.span_help(
+                    param.span,
+                    &format!(
+                        "{} `where {}: {}`",
+                        MSG_RESTRICT_TYPE_FURTHER, param_name, constraint,
+                    ),
+                );
+
+                err.tool_only_span_suggestion(
+                    where_clause_span,
+                    MSG_RESTRICT_BOUND_FURTHER,
+                    format!(", {}: {}", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+
+        true
+    }
+}
diff --git a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs
index 87c1107bd42..3d0dd73f03c 100644
--- a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs
@@ -8,7 +8,27 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::sym;
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+use super::InferCtxtPrivExt;
+
+crate trait InferCtxtExt<'tcx> {
+    /*private*/
+    fn impl_similar_to(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Option<DefId>;
+
+    /*private*/
+    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>;
+
+    fn on_unimplemented_note(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> OnUnimplementedNote;
+}
+
+impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     fn impl_similar_to(
         &self,
         trait_ref: ty::PolyTraitRef<'tcx>,
@@ -70,11 +90,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 })
             }
             hir::Node::TraitItem(hir::TraitItem {
-                kind: hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)),
+                kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)),
                 ..
             }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")),
             hir::Node::ImplItem(hir::ImplItem {
-                kind: hir::ImplItemKind::Method(sig, body_id),
+                kind: hir::ImplItemKind::Fn(sig, body_id),
                 ..
             }) => self.describe_generator(*body_id).or_else(|| {
                 Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
@@ -101,7 +121,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    crate fn on_unimplemented_note(
+    fn on_unimplemented_note(
         &self,
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index d05955fb858..0523a201986 100644
--- a/src/librustc_infer/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -1,6 +1,5 @@
 use super::{
-    ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode,
-    PredicateObligation,
+    EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
 };
 
 use crate::infer::InferCtxt;
@@ -8,9 +7,7 @@ use crate::traits::error_reporting::suggest_constraining_type_param;
 
 use rustc::ty::TypeckTables;
 use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
-use rustc_errors::{
-    error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
-};
+use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
@@ -20,8 +17,136 @@ use rustc_span::symbol::{kw, sym};
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use std::fmt;
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    crate fn suggest_restricting_param_bound(
+use super::InferCtxtPrivExt;
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+
+crate trait InferCtxtExt<'tcx> {
+    fn suggest_restricting_param_bound(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'_>,
+        body_id: hir::HirId,
+    );
+
+    fn suggest_borrow_on_unsized_slice(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+    );
+
+    fn get_closure_name(
+        &self,
+        def_id: DefId,
+        err: &mut DiagnosticBuilder<'_>,
+        msg: &str,
+    ) -> Option<String>;
+
+    fn suggest_fn_call(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    );
+
+    fn suggest_add_reference_to_arg(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+        has_custom_message: bool,
+    ) -> bool;
+
+    fn suggest_remove_reference(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    );
+
+    fn suggest_change_mut(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    );
+
+    fn suggest_semicolon_removal(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    );
+
+    fn suggest_impl_trait(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        obligation: &PredicateObligation<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) -> bool;
+
+    fn point_at_returns_when_relevant(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    );
+
+    fn report_closure_arg_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_ref: ty::PolyTraitRef<'tcx>,
+        found: ty::PolyTraitRef<'tcx>,
+    ) -> DiagnosticBuilder<'tcx>;
+
+    fn suggest_fully_qualified_path(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        def_id: DefId,
+        span: Span,
+        trait_ref: DefId,
+    );
+
+    fn maybe_note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool;
+
+    fn note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        target_span: Span,
+        scope_span: &Option<Span>,
+        expr: Option<hir::HirId>,
+        snippet: String,
+        first_generator: DefId,
+        last_generator: Option<DefId>,
+        trait_ref: ty::TraitRef<'_>,
+        target_ty: Ty<'tcx>,
+        tables: &ty::TypeckTables<'_>,
+        obligation: &PredicateObligation<'tcx>,
+        next_code: Option<&ObligationCauseCode<'tcx>>,
+    );
+
+    fn note_obligation_cause_code<T>(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        predicate: &T,
+        cause_code: &ObligationCauseCode<'tcx>,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+    ) where
+        T: fmt::Display;
+
+    fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>);
+}
+
+impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+    fn suggest_restricting_param_bound(
         &self,
         mut err: &mut DiagnosticBuilder<'_>,
         trait_ref: &ty::PolyTraitRef<'_>,
@@ -62,7 +187,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             match node {
                 hir::Node::TraitItem(hir::TraitItem {
                     generics,
-                    kind: hir::TraitItemKind::Method(..),
+                    kind: hir::TraitItemKind::Fn(..),
                     ..
                 }) if param_ty && self_ty == self.tcx.types.self_param => {
                     // Restricting `Self` for a single method.
@@ -73,12 +198,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
                 | hir::Node::TraitItem(hir::TraitItem {
                     generics,
-                    kind: hir::TraitItemKind::Method(..),
+                    kind: hir::TraitItemKind::Fn(..),
                     ..
                 })
                 | hir::Node::ImplItem(hir::ImplItem {
                     generics,
-                    kind: hir::ImplItemKind::Method(..),
+                    kind: hir::ImplItemKind::Fn(..),
                     ..
                 })
                 | hir::Node::Item(hir::Item {
@@ -157,7 +282,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     }
                 }
 
-                hir::Node::Crate => return,
+                hir::Node::Crate(..) => return,
 
                 _ => {}
             }
@@ -168,7 +293,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
     /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
     /// suggestion to borrow the initializer in order to use have a slice instead.
-    crate fn suggest_borrow_on_unsized_slice(
+    fn suggest_borrow_on_unsized_slice(
         &self,
         code: &ObligationCauseCode<'tcx>,
         err: &mut DiagnosticBuilder<'tcx>,
@@ -195,7 +320,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// Given a closure's `DefId`, return the given name of the closure.
     ///
     /// This doesn't account for reassignments, but it's only used for suggestions.
-    crate fn get_closure_name(
+    fn get_closure_name(
         &self,
         def_id: DefId,
         err: &mut DiagnosticBuilder<'_>,
@@ -233,7 +358,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
     /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
     /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
-    crate fn suggest_fn_call(
+    fn suggest_fn_call(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
@@ -317,7 +442,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    crate fn suggest_add_reference_to_arg(
+    fn suggest_add_reference_to_arg(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'tcx>,
@@ -389,7 +514,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
     /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
     /// suggest removing these references until we reach a type that implements the trait.
-    crate fn suggest_remove_reference(
+    fn suggest_remove_reference(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'tcx>,
@@ -451,7 +576,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
     /// Check if the trait bound is implemented for a different mutability and note it in the
     /// final error.
-    crate fn suggest_change_mut(
+    fn suggest_change_mut(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'tcx>,
@@ -513,7 +638,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    crate fn suggest_semicolon_removal(
+    fn suggest_semicolon_removal(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'tcx>,
@@ -549,7 +674,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
     /// applicable and signal that the error has been expanded appropriately and needs to be
     /// emitted.
-    crate fn suggest_impl_trait(
+    fn suggest_impl_trait(
         &self,
         err: &mut DiagnosticBuilder<'tcx>,
         span: Span,
@@ -723,7 +848,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         true
     }
 
-    crate fn point_at_returns_when_relevant(
+    fn point_at_returns_when_relevant(
         &self,
         err: &mut DiagnosticBuilder<'tcx>,
         obligation: &PredicateObligation<'tcx>,
@@ -753,220 +878,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
-        match node {
-            Node::Expr(&hir::Expr {
-                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                self.tcx
-                    .hir()
-                    .body(id)
-                    .params
-                    .iter()
-                    .map(|arg| {
-                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
-                            *arg.pat
-                        {
-                            ArgKind::Tuple(
-                                Some(span),
-                                args.iter()
-                                    .map(|pat| {
-                                        let snippet = self
-                                            .tcx
-                                            .sess
-                                            .source_map()
-                                            .span_to_snippet(pat.span)
-                                            .unwrap();
-                                        (snippet, "_".to_owned())
-                                    })
-                                    .collect::<Vec<_>>(),
-                            )
-                        } else {
-                            let name =
-                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
-                            ArgKind::Arg(name, "_".to_owned())
-                        }
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
-            | Node::ImplItem(&hir::ImplItem {
-                span,
-                kind: hir::ImplItemKind::Method(ref sig, _),
-                ..
-            })
-            | Node::TraitItem(&hir::TraitItem {
-                span,
-                kind: hir::TraitItemKind::Method(ref sig, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                sig.decl
-                    .inputs
-                    .iter()
-                    .map(|arg| match arg.clone().kind {
-                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
-                            Some(arg.span),
-                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
-                        ),
-                        _ => ArgKind::empty(),
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Ctor(ref variant_data) => {
-                let span = variant_data
-                    .ctor_hir_id()
-                    .map(|hir_id| self.tcx.hir().span(hir_id))
-                    .unwrap_or(DUMMY_SP);
-                let span = self.tcx.sess.source_map().def_span(span);
-
-                (span, vec![ArgKind::empty(); variant_data.fields().len()])
-            }
-            _ => panic!("non-FnLike node found: {:?}", node),
-        }
-    }
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    pub fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-    ) -> DiagnosticBuilder<'tcx> {
-        let kind = if is_closure { "closure" } else { "function" };
-
-        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
-            let arg_length = arguments.len();
-            let distinct = match &other[..] {
-                &[ArgKind::Tuple(..)] => true,
-                _ => false,
-            };
-            match (arg_length, arguments.get(0)) {
-                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
-                    format!("a single {}-tuple as argument", fields.len())
-                }
-                _ => format!(
-                    "{} {}argument{}",
-                    arg_length,
-                    if distinct && arg_length > 1 { "distinct " } else { "" },
-                    pluralize!(arg_length)
-                ),
-            }
-        };
-
-        let expected_str = args_str(&expected_args, &found_args);
-        let found_str = args_str(&found_args, &expected_args);
-
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0593,
-            "{} is expected to take {}, but it takes {}",
-            kind,
-            expected_str,
-            found_str,
-        );
-
-        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
-
-        if let Some(found_span) = found_span {
-            err.span_label(found_span, format!("takes {}", found_str));
-
-            // move |_| { ... }
-            // ^^^^^^^^-- def_span
-            //
-            // move |_| { ... }
-            // ^^^^^-- prefix
-            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
-            // move |_| { ... }
-            //      ^^^-- pipe_span
-            let pipe_span =
-                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
-
-            // Suggest to take and ignore the arguments with expected_args_length `_`s if
-            // found arguments is empty (assume the user just wants to ignore args in this case).
-            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
-            if found_args.is_empty() && is_closure {
-                let underscores = vec!["_"; expected_args.len()].join(", ");
-                err.span_suggestion(
-                    pipe_span,
-                    &format!(
-                        "consider changing the closure to take and ignore the expected argument{}",
-                        if expected_args.len() < 2 { "" } else { "s" }
-                    ),
-                    format!("|{}|", underscores),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
-                if fields.len() == expected_args.len() {
-                    let sugg = fields
-                        .iter()
-                        .map(|(name, _)| name.to_owned())
-                        .collect::<Vec<String>>()
-                        .join(", ");
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to take multiple arguments instead of a single tuple",
-                        format!("|{}|", sugg),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
-                if fields.len() == found_args.len() && is_closure {
-                    let sugg = format!(
-                        "|({}){}|",
-                        found_args
-                            .iter()
-                            .map(|arg| match arg {
-                                ArgKind::Arg(name, _) => name.to_owned(),
-                                _ => "_".to_owned(),
-                            })
-                            .collect::<Vec<String>>()
-                            .join(", "),
-                        // add type annotations if available
-                        if found_args.iter().any(|arg| match arg {
-                            ArgKind::Arg(_, ty) => ty != "_",
-                            _ => false,
-                        }) {
-                            format!(
-                                ": ({})",
-                                fields
-                                    .iter()
-                                    .map(|(_, ty)| ty.to_owned())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            )
-                        } else {
-                            String::new()
-                        },
-                    );
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to accept a tuple instead of individual arguments",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-        }
-
-        err
-    }
-
-    crate fn report_closure_arg_mismatch(
+    fn report_closure_arg_mismatch(
         &self,
         span: Span,
         found_span: Option<Span>,
@@ -1022,10 +934,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         err
     }
-}
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    crate fn suggest_fully_qualified_path(
+    fn suggest_fully_qualified_path(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         def_id: DefId,
@@ -1091,7 +1001,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// ```
     ///
     /// Returns `true` if an async-await specific note was added to the diagnostic.
-    crate fn maybe_note_obligation_cause_for_async_await(
+    fn maybe_note_obligation_cause_for_async_await(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         obligation: &PredicateObligation<'tcx>,
@@ -1271,7 +1181,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
     /// Unconditionally adds the diagnostic note described in
     /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
-    crate fn note_obligation_cause_for_async_await(
+    fn note_obligation_cause_for_async_await(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         target_span: Span,
@@ -1377,7 +1287,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             let parent = hir.get_parent_node(expr_id);
             if let Some(hir::Node::Expr(e)) = hir.find(parent) {
                 let parent_span = hir.span(parent);
-                let parent_did = parent.owner_def_id();
+                let parent_did = parent.owner.to_def_id();
                 // ```rust
                 // impl T {
                 //     fn foo(&self) -> i32 {}
@@ -1423,7 +1333,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         );
     }
 
-    crate fn note_obligation_cause_code<T>(
+    fn note_obligation_cause_code<T>(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         predicate: &T,
@@ -1638,7 +1548,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
+    fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
         let current_limit = self.tcx.sess.recursion_limit.get();
         let suggested_limit = current_limit * 2;
         err.help(&format!(
@@ -1657,9 +1567,9 @@ struct ReturnsVisitor<'v> {
 }
 
 impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
-    type Map = rustc::hir::map::Map<'v>;
+    type Map = hir::intravisit::ErasedMap<'v>;
 
-    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
         hir::intravisit::NestedVisitorMap::None
     }
 
diff --git a/src/librustc_infer/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs
index ac9ff484a02..5def77ce732 100644
--- a/src/librustc_infer/traits/fulfill.rs
+++ b/src/librustc_trait_selection/traits/fulfill.rs
@@ -4,9 +4,9 @@ use rustc::ty::{self, ToPolyTraitRef, Ty, TypeFoldable};
 use rustc_data_structures::obligation_forest::ProcessResult;
 use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation};
 use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
+use rustc_infer::traits::{TraitEngine, TraitEngineExt as _};
 use std::marker::PhantomData;
 
-use super::engine::{TraitEngine, TraitEngineExt};
 use super::project;
 use super::select::SelectionContext;
 use super::wf;
@@ -17,6 +17,9 @@ use super::{ConstEvalFailure, Unimplemented};
 use super::{FulfillmentError, FulfillmentErrorCode};
 use super::{ObligationCause, PredicateObligation};
 
+use crate::traits::error_reporting::InferCtxtExt as _;
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+
 impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
     /// Note that we include both the `ParamEnv` and the `Predicate`,
     /// as the `ParamEnv` can influence whether fulfillment succeeds
diff --git a/src/librustc_infer/traits/misc.rs b/src/librustc_trait_selection/traits/misc.rs
index 7ab918c159e..d500cff67c6 100644
--- a/src/librustc_infer/traits/misc.rs
+++ b/src/librustc_trait_selection/traits/misc.rs
@@ -1,10 +1,13 @@
 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
 
-use crate::infer::TyCtxtInferExt;
+use crate::infer::InferCtxtExt as _;
 use crate::traits::{self, ObligationCause};
 
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_hir as hir;
+use rustc_infer::infer::TyCtxtInferExt;
+
+use crate::traits::error_reporting::InferCtxtExt;
 
 #[derive(Clone)]
 pub enum CopyImplementationError<'tcx> {
diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs
new file mode 100644
index 00000000000..43a90c4a6c1
--- /dev/null
+++ b/src/librustc_trait_selection/traits/mod.rs
@@ -0,0 +1,533 @@
+//! Trait Resolution. See the [rustc dev guide] for more information on how this works.
+//!
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
+
+#[allow(dead_code)]
+pub mod auto_trait;
+pub mod codegen;
+mod coherence;
+mod engine;
+pub mod error_reporting;
+mod fulfill;
+pub mod misc;
+mod object_safety;
+mod on_unimplemented;
+mod project;
+pub mod query;
+mod select;
+mod specialize;
+mod structural_match;
+mod util;
+pub mod wf;
+
+use crate::infer::outlives::env::OutlivesEnvironment;
+use crate::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
+use crate::traits::error_reporting::InferCtxtExt as _;
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use rustc::middle::region;
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::subst::{InternalSubsts, SubstsRef};
+use rustc::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc::util::common::ErrorReported;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::{Span, DUMMY_SP};
+
+use std::fmt::Debug;
+
+pub use self::FulfillmentErrorCode::*;
+pub use self::ObligationCauseCode::*;
+pub use self::SelectionError::*;
+pub use self::Vtable::*;
+
+pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
+pub use self::coherence::{OrphanCheckErr, OverlapResult};
+pub use self::engine::TraitEngineExt;
+pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
+pub use self::object_safety::astconv_object_safety_violations;
+pub use self::object_safety::is_vtable_safe_method;
+pub use self::object_safety::MethodViolationCode;
+pub use self::object_safety::ObjectSafetyViolation;
+pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
+pub use self::project::{
+    normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type,
+};
+pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
+pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
+pub use self::specialize::find_associated_item;
+pub use self::specialize::specialization_graph::FutureCompatOverlapError;
+pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
+pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
+pub use self::structural_match::search_for_structural_match_violation;
+pub use self::structural_match::type_marked_structural;
+pub use self::structural_match::NonStructuralMatchTy;
+pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
+pub use self::util::{expand_trait_aliases, TraitAliasExpander};
+pub use self::util::{
+    get_vtable_index_of_object_method, impl_is_default, impl_item_is_final,
+    predicate_for_trait_def, upcast_choices,
+};
+pub use self::util::{
+    supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
+};
+
+pub use rustc_infer::traits::*;
+
+/// Whether to skip the leak check, as part of a future compatibility warning step.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum SkipLeakCheck {
+    Yes,
+    No,
+}
+
+impl SkipLeakCheck {
+    fn is_yes(self) -> bool {
+        self == SkipLeakCheck::Yes
+    }
+}
+
+/// The "default" for skip-leak-check corresponds to the current
+/// behavior (do not skip the leak check) -- not the behavior we are
+/// transitioning into.
+impl Default for SkipLeakCheck {
+    fn default() -> Self {
+        SkipLeakCheck::No
+    }
+}
+
+/// The mode that trait queries run in.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum TraitQueryMode {
+    // Standard/un-canonicalized queries get accurate
+    // spans etc. passed in and hence can do reasonable
+    // error reporting on their own.
+    Standard,
+    // Canonicalized queries get dummy spans and hence
+    // must generally propagate errors to
+    // pre-canonicalization callsites.
+    Canonical,
+}
+
+/// Creates predicate obligations from the generic bounds.
+pub fn predicates_for_generics<'tcx>(
+    cause: ObligationCause<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
+) -> PredicateObligations<'tcx> {
+    util::predicates_for_generics(cause, 0, param_env, generic_bounds)
+}
+
+/// Determines whether the type `ty` is known to meet `bound` and
+/// returns true if so. Returns false if `ty` either does not meet
+/// `bound` or is not known to meet bound (note that this is
+/// conservative towards *no impl*, which is the opposite of the
+/// `evaluate` methods).
+pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+    def_id: DefId,
+    span: Span,
+) -> bool {
+    debug!(
+        "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})",
+        ty,
+        infcx.tcx.def_path_str(def_id)
+    );
+
+    let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
+    let obligation = Obligation {
+        param_env,
+        cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
+        recursion_depth: 0,
+        predicate: trait_ref.without_const().to_predicate(),
+    };
+
+    let result = infcx.predicate_must_hold_modulo_regions(&obligation);
+    debug!(
+        "type_known_to_meet_ty={:?} bound={} => {:?}",
+        ty,
+        infcx.tcx.def_path_str(def_id),
+        result
+    );
+
+    if result && ty.has_infer_types_or_consts() {
+        // Because of inference "guessing", selection can sometimes claim
+        // to succeed while the success requires a guess. To ensure
+        // this function's result remains infallible, we must confirm
+        // that guess. While imperfect, I believe this is sound.
+
+        // The handling of regions in this area of the code is terrible,
+        // see issue #29149. We should be able to improve on this with
+        // NLL.
+        let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
+
+        // We can use a dummy node-id here because we won't pay any mind
+        // to region obligations that arise (there shouldn't really be any
+        // anyhow).
+        let cause = ObligationCause::misc(span, hir::DUMMY_HIR_ID);
+
+        fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause);
+
+        // Note: we only assume something is `Copy` if we can
+        // *definitively* show that it implements `Copy`. Otherwise,
+        // assume it is move; linear is always ok.
+        match fulfill_cx.select_all_or_error(infcx) {
+            Ok(()) => {
+                debug!(
+                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
+                    ty,
+                    infcx.tcx.def_path_str(def_id)
+                );
+                true
+            }
+            Err(e) => {
+                debug!(
+                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
+                    ty,
+                    infcx.tcx.def_path_str(def_id),
+                    e
+                );
+                false
+            }
+        }
+    } else {
+        result
+    }
+}
+
+fn do_normalize_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    region_context: DefId,
+    cause: ObligationCause<'tcx>,
+    elaborated_env: ty::ParamEnv<'tcx>,
+    predicates: Vec<ty::Predicate<'tcx>>,
+) -> Result<Vec<ty::Predicate<'tcx>>, ErrorReported> {
+    debug!(
+        "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})",
+        predicates, region_context, cause,
+    );
+    let span = cause.span;
+    tcx.infer_ctxt().enter(|infcx| {
+        // FIXME. We should really... do something with these region
+        // obligations. But this call just continues the older
+        // behavior (i.e., doesn't cause any new bugs), and it would
+        // take some further refactoring to actually solve them. In
+        // particular, we would have to handle implied bounds
+        // properly, and that code is currently largely confined to
+        // regionck (though I made some efforts to extract it
+        // out). -nmatsakis
+        //
+        // @arielby: In any case, these obligations are checked
+        // by wfcheck anyway, so I'm not sure we have to check
+        // them here too, and we will remove this function when
+        // we move over to lazy normalization *anyway*.
+        let fulfill_cx = FulfillmentContext::new_ignoring_regions();
+        let predicates =
+            match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, &predicates) {
+                Ok(predicates) => predicates,
+                Err(errors) => {
+                    infcx.report_fulfillment_errors(&errors, None, false);
+                    return Err(ErrorReported);
+                }
+            };
+
+        debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
+
+        let region_scope_tree = region::ScopeTree::default();
+
+        // We can use the `elaborated_env` here; the region code only
+        // cares about declarations like `'a: 'b`.
+        let outlives_env = OutlivesEnvironment::new(elaborated_env);
+
+        infcx.resolve_regions_and_report_errors(
+            region_context,
+            &region_scope_tree,
+            &outlives_env,
+            RegionckMode::default(),
+        );
+
+        let predicates = match infcx.fully_resolve(&predicates) {
+            Ok(predicates) => predicates,
+            Err(fixup_err) => {
+                // If we encounter a fixup error, it means that some type
+                // variable wound up unconstrained. I actually don't know
+                // if this can happen, and I certainly don't expect it to
+                // happen often, but if it did happen it probably
+                // represents a legitimate failure due to some kind of
+                // unconstrained variable, and it seems better not to ICE,
+                // all things considered.
+                tcx.sess.span_err(span, &fixup_err.to_string());
+                return Err(ErrorReported);
+            }
+        };
+        if predicates.has_local_value() {
+            // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
+            Err(ErrorReported)
+        } else {
+            Ok(predicates)
+        }
+    })
+}
+
+// FIXME: this is gonna need to be removed ...
+/// Normalizes the parameter environment, reporting errors if they occur.
+pub fn normalize_param_env_or_error<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    region_context: DefId,
+    unnormalized_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+) -> ty::ParamEnv<'tcx> {
+    // I'm not wild about reporting errors here; I'd prefer to
+    // have the errors get reported at a defined place (e.g.,
+    // during typeck). Instead I have all parameter
+    // environments, in effect, going through this function
+    // and hence potentially reporting errors. This ensures of
+    // course that we never forget to normalize (the
+    // alternative seemed like it would involve a lot of
+    // manual invocations of this fn -- and then we'd have to
+    // deal with the errors at each of those sites).
+    //
+    // In any case, in practice, typeck constructs all the
+    // parameter environments once for every fn as it goes,
+    // and errors will get reported then; so after typeck we
+    // can be sure that no errors should occur.
+
+    debug!(
+        "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})",
+        region_context, unnormalized_env, cause
+    );
+
+    let mut predicates: Vec<_> =
+        util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()).collect();
+
+    debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
+
+    let elaborated_env = ty::ParamEnv::new(
+        tcx.intern_predicates(&predicates),
+        unnormalized_env.reveal,
+        unnormalized_env.def_id,
+    );
+
+    // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
+    // normalization expects its param-env to be already normalized, which means we have
+    // a circularity.
+    //
+    // The way we handle this is by normalizing the param-env inside an unnormalized version
+    // of the param-env, which means that if the param-env contains unnormalized projections,
+    // we'll have some normalization failures. This is unfortunate.
+    //
+    // Lazy normalization would basically handle this by treating just the
+    // normalizing-a-trait-ref-requires-itself cycles as evaluation failures.
+    //
+    // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated
+    // types, so to make the situation less bad, we normalize all the predicates *but*
+    // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and
+    // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment.
+    //
+    // This works fairly well because trait matching  does not actually care about param-env
+    // TypeOutlives predicates - these are normally used by regionck.
+    let outlives_predicates: Vec<_> = predicates
+        .drain_filter(|predicate| match predicate {
+            ty::Predicate::TypeOutlives(..) => true,
+            _ => false,
+        })
+        .collect();
+
+    debug!(
+        "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
+        predicates, outlives_predicates
+    );
+    let non_outlives_predicates = match do_normalize_predicates(
+        tcx,
+        region_context,
+        cause.clone(),
+        elaborated_env,
+        predicates,
+    ) {
+        Ok(predicates) => predicates,
+        // An unnormalized env is better than nothing.
+        Err(ErrorReported) => {
+            debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
+            return elaborated_env;
+        }
+    };
+
+    debug!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates);
+
+    // Not sure whether it is better to include the unnormalized TypeOutlives predicates
+    // here. I believe they should not matter, because we are ignoring TypeOutlives param-env
+    // predicates here anyway. Keeping them here anyway because it seems safer.
+    let outlives_env: Vec<_> =
+        non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
+    let outlives_env =
+        ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal, None);
+    let outlives_predicates = match do_normalize_predicates(
+        tcx,
+        region_context,
+        cause,
+        outlives_env,
+        outlives_predicates,
+    ) {
+        Ok(predicates) => predicates,
+        // An unnormalized env is better than nothing.
+        Err(ErrorReported) => {
+            debug!("normalize_param_env_or_error: errored resolving outlives predicates");
+            return elaborated_env;
+        }
+    };
+    debug!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates);
+
+    let mut predicates = non_outlives_predicates;
+    predicates.extend(outlives_predicates);
+    debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
+    ty::ParamEnv::new(
+        tcx.intern_predicates(&predicates),
+        unnormalized_env.reveal,
+        unnormalized_env.def_id,
+    )
+}
+
+pub fn fully_normalize<'a, 'tcx, T>(
+    infcx: &InferCtxt<'a, 'tcx>,
+    mut fulfill_cx: FulfillmentContext<'tcx>,
+    cause: ObligationCause<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    value: &T,
+) -> Result<T, Vec<FulfillmentError<'tcx>>>
+where
+    T: TypeFoldable<'tcx>,
+{
+    debug!("fully_normalize_with_fulfillcx(value={:?})", value);
+    let selcx = &mut SelectionContext::new(infcx);
+    let Normalized { value: normalized_value, obligations } =
+        project::normalize(selcx, param_env, cause, value);
+    debug!(
+        "fully_normalize: normalized_value={:?} obligations={:?}",
+        normalized_value, obligations
+    );
+    for obligation in obligations {
+        fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
+    }
+
+    debug!("fully_normalize: select_all_or_error start");
+    fulfill_cx.select_all_or_error(infcx)?;
+    debug!("fully_normalize: select_all_or_error complete");
+    let resolved_value = infcx.resolve_vars_if_possible(&normalized_value);
+    debug!("fully_normalize: resolved_value={:?}", resolved_value);
+    Ok(resolved_value)
+}
+
+/// Normalizes the predicates and checks whether they hold in an empty
+/// environment. If this returns false, then either normalize
+/// encountered an error or one of the predicates did not hold. Used
+/// when creating vtables to check for unsatisfiable methods.
+pub fn normalize_and_test_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    predicates: Vec<ty::Predicate<'tcx>>,
+) -> bool {
+    debug!("normalize_and_test_predicates(predicates={:?})", predicates);
+
+    let result = tcx.infer_ctxt().enter(|infcx| {
+        let param_env = ty::ParamEnv::reveal_all();
+        let mut selcx = SelectionContext::new(&infcx);
+        let mut fulfill_cx = FulfillmentContext::new();
+        let cause = ObligationCause::dummy();
+        let Normalized { value: predicates, obligations } =
+            normalize(&mut selcx, param_env, cause.clone(), &predicates);
+        for obligation in obligations {
+            fulfill_cx.register_predicate_obligation(&infcx, obligation);
+        }
+        for predicate in predicates {
+            let obligation = Obligation::new(cause.clone(), param_env, predicate);
+            fulfill_cx.register_predicate_obligation(&infcx, obligation);
+        }
+
+        fulfill_cx.select_all_or_error(&infcx).is_ok()
+    });
+    debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", predicates, result);
+    result
+}
+
+fn substitute_normalize_and_test_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: (DefId, SubstsRef<'tcx>),
+) -> bool {
+    debug!("substitute_normalize_and_test_predicates(key={:?})", key);
+
+    let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
+    let result = normalize_and_test_predicates(tcx, predicates);
+
+    debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result);
+    result
+}
+
+/// Given a trait `trait_ref`, iterates the vtable entries
+/// that come from `trait_ref`, including its supertraits.
+#[inline] // FIXME(#35870): avoid closures being unexported due to `impl Trait`.
+fn vtable_methods<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
+    debug!("vtable_methods({:?})", trait_ref);
+
+    tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
+        let trait_methods = tcx
+            .associated_items(trait_ref.def_id())
+            .in_definition_order()
+            .filter(|item| item.kind == ty::AssocKind::Method);
+
+        // Now list each method's DefId and InternalSubsts (for within its trait).
+        // If the method can never be called from this object, produce None.
+        trait_methods.map(move |trait_method| {
+            debug!("vtable_methods: trait_method={:?}", trait_method);
+            let def_id = trait_method.def_id;
+
+            // Some methods cannot be called on an object; skip those.
+            if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
+                debug!("vtable_methods: not vtable safe");
+                return None;
+            }
+
+            // The method may have some early-bound lifetimes; add regions for those.
+            let substs = trait_ref.map_bound(|trait_ref| {
+                InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+                        trait_ref.substs[param.index as usize]
+                    }
+                })
+            });
+
+            // The trait type may have higher-ranked lifetimes in it;
+            // erase them if they appear, so that we get the type
+            // at some particular call site.
+            let substs =
+                tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &substs);
+
+            // It's possible that the method relies on where-clauses that
+            // do not hold for this particular set of type parameters.
+            // Note that this method could then never be called, so we
+            // do not want to try and codegen it, in that case (see #23435).
+            let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+            if !normalize_and_test_predicates(tcx, predicates.predicates) {
+                debug!("vtable_methods: predicates do not hold");
+                return None;
+            }
+
+            Some((def_id, substs))
+        })
+    }))
+}
+
+pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    object_safety::provide(providers);
+    *providers = ty::query::Providers {
+        specialization_graph_of: specialize::specialization_graph_provider,
+        specializes: specialize::specializes,
+        codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
+        vtable_methods,
+        substitute_normalize_and_test_predicates,
+        ..*providers
+    };
+}
diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs
index 6f20f5ac47e..452f965014b 100644
--- a/src/librustc_infer/traits/object_safety.rs
+++ b/src/librustc_trait_selection/traits/object_safety.rs
@@ -11,6 +11,7 @@
 use super::elaborate_predicates;
 
 use crate::infer::TyCtxtInferExt;
+use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{self, Obligation, ObligationCause};
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
@@ -184,7 +185,7 @@ fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]>
                     .filter_map(|pred| {
                         match pred {
                             hir::WherePredicate::BoundPredicate(pred)
-                                if pred.bounded_ty.hir_id.owner_def_id() == trait_def_id =>
+                                if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id =>
                             {
                                 // Fetch spans for trait bounds that are Sized:
                                 // `trait T where Self: Pred`
diff --git a/src/librustc_infer/traits/on_unimplemented.rs b/src/librustc_trait_selection/traits/on_unimplemented.rs
index 19260293ee6..19260293ee6 100644
--- a/src/librustc_infer/traits/on_unimplemented.rs
+++ b/src/librustc_trait_selection/traits/on_unimplemented.rs
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
new file mode 100644
index 00000000000..1ad91574212
--- /dev/null
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -0,0 +1,1515 @@
+//! Code for projecting associated types out of trait references.
+
+use super::elaborate_predicates;
+use super::specialization_graph;
+use super::translate_substs;
+use super::util;
+use super::MismatchedProjectionTypes;
+use super::Obligation;
+use super::ObligationCause;
+use super::PredicateObligation;
+use super::Selection;
+use super::SelectionContext;
+use super::SelectionError;
+use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
+use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableImplData};
+
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
+use crate::traits::error_reporting::InferCtxtExt;
+use rustc::ty::fold::{TypeFoldable, TypeFolder};
+use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_ast::ast::Ident;
+use rustc_errors::ErrorReported;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::sym;
+use rustc_span::DUMMY_SP;
+
+pub use rustc::traits::Reveal;
+
+pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
+
+pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
+
+pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
+
+/// When attempting to resolve `<T as TraitRef>::Name` ...
+#[derive(Debug)]
+pub enum ProjectionTyError<'tcx> {
+    /// ...we found multiple sources of information and couldn't resolve the ambiguity.
+    TooManyCandidates,
+
+    /// ...an error occurred matching `T : TraitRef`
+    TraitSelectionError(SelectionError<'tcx>),
+}
+
+#[derive(PartialEq, Eq, Debug)]
+enum ProjectionTyCandidate<'tcx> {
+    // from a where-clause in the env or object type
+    ParamEnv(ty::PolyProjectionPredicate<'tcx>),
+
+    // from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
+    TraitDef(ty::PolyProjectionPredicate<'tcx>),
+
+    // from a "impl" (or a "pseudo-impl" returned by select)
+    Select(Selection<'tcx>),
+}
+
+enum ProjectionTyCandidateSet<'tcx> {
+    None,
+    Single(ProjectionTyCandidate<'tcx>),
+    Ambiguous,
+    Error(SelectionError<'tcx>),
+}
+
+impl<'tcx> ProjectionTyCandidateSet<'tcx> {
+    fn mark_ambiguous(&mut self) {
+        *self = ProjectionTyCandidateSet::Ambiguous;
+    }
+
+    fn mark_error(&mut self, err: SelectionError<'tcx>) {
+        *self = ProjectionTyCandidateSet::Error(err);
+    }
+
+    // Returns true if the push was successful, or false if the candidate
+    // was discarded -- this could be because of ambiguity, or because
+    // a higher-priority candidate is already there.
+    fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
+        use self::ProjectionTyCandidate::*;
+        use self::ProjectionTyCandidateSet::*;
+
+        // This wacky variable is just used to try and
+        // make code readable and avoid confusing paths.
+        // It is assigned a "value" of `()` only on those
+        // paths in which we wish to convert `*self` to
+        // ambiguous (and return false, because the candidate
+        // was not used). On other paths, it is not assigned,
+        // and hence if those paths *could* reach the code that
+        // comes after the match, this fn would not compile.
+        let convert_to_ambiguous;
+
+        match self {
+            None => {
+                *self = Single(candidate);
+                return true;
+            }
+
+            Single(current) => {
+                // Duplicates can happen inside ParamEnv. In the case, we
+                // perform a lazy deduplication.
+                if current == &candidate {
+                    return false;
+                }
+
+                // Prefer where-clauses. As in select, if there are multiple
+                // candidates, we prefer where-clause candidates over impls.  This
+                // may seem a bit surprising, since impls are the source of
+                // "truth" in some sense, but in fact some of the impls that SEEM
+                // applicable are not, because of nested obligations. Where
+                // clauses are the safer choice. See the comment on
+                // `select::SelectionCandidate` and #21974 for more details.
+                match (current, candidate) {
+                    (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
+                    (ParamEnv(..), _) => return false,
+                    (_, ParamEnv(..)) => unreachable!(),
+                    (_, _) => convert_to_ambiguous = (),
+                }
+            }
+
+            Ambiguous | Error(..) => {
+                return false;
+            }
+        }
+
+        // We only ever get here when we moved from a single candidate
+        // to ambiguous.
+        let () = convert_to_ambiguous;
+        *self = Ambiguous;
+        false
+    }
+}
+
+/// Evaluates constraints of the form:
+///
+///     for<...> <T as Trait>::U == V
+///
+/// If successful, this may result in additional obligations. Also returns
+/// the projection cache key used to track these additional obligations.
+pub fn poly_project_and_unify_type<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &PolyProjectionObligation<'tcx>,
+) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
+    debug!("poly_project_and_unify_type(obligation={:?})", obligation);
+
+    let infcx = selcx.infcx();
+    infcx.commit_if_ok(|snapshot| {
+        let (placeholder_predicate, placeholder_map) =
+            infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
+
+        let placeholder_obligation = obligation.with(placeholder_predicate);
+        let result = project_and_unify_type(selcx, &placeholder_obligation)?;
+        infcx
+            .leak_check(false, &placeholder_map, snapshot)
+            .map_err(|err| MismatchedProjectionTypes { err })?;
+        Ok(result)
+    })
+}
+
+/// Evaluates constraints of the form:
+///
+///     <T as Trait>::U == V
+///
+/// If successful, this may result in additional obligations.
+fn project_and_unify_type<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionObligation<'tcx>,
+) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
+    debug!("project_and_unify_type(obligation={:?})", obligation);
+
+    let mut obligations = vec![];
+    let normalized_ty = match opt_normalize_projection_type(
+        selcx,
+        obligation.param_env,
+        obligation.predicate.projection_ty,
+        obligation.cause.clone(),
+        obligation.recursion_depth,
+        &mut obligations,
+    ) {
+        Some(n) => n,
+        None => return Ok(None),
+    };
+
+    debug!(
+        "project_and_unify_type: normalized_ty={:?} obligations={:?}",
+        normalized_ty, obligations
+    );
+
+    let infcx = selcx.infcx();
+    match infcx
+        .at(&obligation.cause, obligation.param_env)
+        .eq(normalized_ty, obligation.predicate.ty)
+    {
+        Ok(InferOk { obligations: inferred_obligations, value: () }) => {
+            obligations.extend(inferred_obligations);
+            Ok(Some(obligations))
+        }
+        Err(err) => {
+            debug!("project_and_unify_type: equating types encountered error {:?}", err);
+            Err(MismatchedProjectionTypes { err })
+        }
+    }
+}
+
+/// Normalizes any associated type projections in `value`, replacing
+/// them with a fully resolved type where possible. The return value
+/// combines the normalized result and any additional obligations that
+/// were incurred as result.
+pub fn normalize<'a, 'b, 'tcx, T>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    value: &T,
+) -> Normalized<'tcx, T>
+where
+    T: TypeFoldable<'tcx>,
+{
+    let mut obligations = Vec::new();
+    let value = normalize_to(selcx, param_env, cause, value, &mut obligations);
+    Normalized { value, obligations }
+}
+
+pub fn normalize_to<'a, 'b, 'tcx, T>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    value: &T,
+    obligations: &mut Vec<PredicateObligation<'tcx>>,
+) -> T
+where
+    T: TypeFoldable<'tcx>,
+{
+    normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations)
+}
+
+/// As `normalize`, but with a custom depth.
+pub fn normalize_with_depth<'a, 'b, 'tcx, T>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+    value: &T,
+) -> Normalized<'tcx, T>
+where
+    T: TypeFoldable<'tcx>,
+{
+    let mut obligations = Vec::new();
+    let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations);
+    Normalized { value, obligations }
+}
+
+pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+    value: &T,
+    obligations: &mut Vec<PredicateObligation<'tcx>>,
+) -> T
+where
+    T: TypeFoldable<'tcx>,
+{
+    debug!("normalize_with_depth(depth={}, value={:?})", depth, value);
+    let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
+    let result = normalizer.fold(value);
+    debug!(
+        "normalize_with_depth: depth={} result={:?} with {} obligations",
+        depth,
+        result,
+        normalizer.obligations.len()
+    );
+    debug!("normalize_with_depth: depth={} obligations={:?}", depth, normalizer.obligations);
+    result
+}
+
+struct AssocTypeNormalizer<'a, 'b, 'tcx> {
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    obligations: &'a mut Vec<PredicateObligation<'tcx>>,
+    depth: usize,
+}
+
+impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
+    fn new(
+        selcx: &'a mut SelectionContext<'b, 'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        cause: ObligationCause<'tcx>,
+        depth: usize,
+        obligations: &'a mut Vec<PredicateObligation<'tcx>>,
+    ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
+        AssocTypeNormalizer { selcx, param_env, cause, obligations, depth }
+    }
+
+    fn fold<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
+        let value = self.selcx.infcx().resolve_vars_if_possible(value);
+
+        if !value.has_projections() { value } else { value.fold_with(self) }
+    }
+}
+
+impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
+    fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
+        self.selcx.tcx()
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if !ty.has_projections() {
+            return ty;
+        }
+        // We don't want to normalize associated types that occur inside of region
+        // binders, because they may contain bound regions, and we can't cope with that.
+        //
+        // Example:
+        //
+        //     for<'a> fn(<T as Foo<&'a>>::A)
+        //
+        // Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
+        // normalize it when we instantiate those bound regions (which
+        // should occur eventually).
+
+        let ty = ty.super_fold_with(self);
+        match ty.kind {
+            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+                // (*)
+                // Only normalize `impl Trait` after type-checking, usually in codegen.
+                match self.param_env.reveal {
+                    Reveal::UserFacing => ty,
+
+                    Reveal::All => {
+                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
+                        if self.depth >= recursion_limit {
+                            let obligation = Obligation::with_depth(
+                                self.cause.clone(),
+                                recursion_limit,
+                                self.param_env,
+                                ty,
+                            );
+                            self.selcx.infcx().report_overflow_error(&obligation, true);
+                        }
+
+                        let generic_ty = self.tcx().type_of(def_id);
+                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
+                        self.depth += 1;
+                        let folded_ty = self.fold_ty(concrete_ty);
+                        self.depth -= 1;
+                        folded_ty
+                    }
+                }
+            }
+
+            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
+                // (*)
+
+                // (*) This is kind of hacky -- we need to be able to
+                // handle normalization within binders because
+                // otherwise we wind up a need to normalize when doing
+                // trait matching (since you can have a trait
+                // obligation like `for<'a> T::B : Fn(&'a int)`), but
+                // we can't normalize with bound regions in scope. So
+                // far now we just ignore binders but only normalize
+                // if all bound regions are gone (and then we still
+                // have to renormalize whenever we instantiate a
+                // binder). It would be better to normalize in a
+                // binding-aware fashion.
+
+                let normalized_ty = normalize_projection_type(
+                    self.selcx,
+                    self.param_env,
+                    *data,
+                    self.cause.clone(),
+                    self.depth,
+                    &mut self.obligations,
+                );
+                debug!(
+                    "AssocTypeNormalizer: depth={} normalized {:?} to {:?}, \
+                     now with {} obligations",
+                    self.depth,
+                    ty,
+                    normalized_ty,
+                    self.obligations.len()
+                );
+                normalized_ty
+            }
+
+            _ => ty,
+        }
+    }
+
+    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        constant.eval(self.selcx.tcx(), self.param_env)
+    }
+}
+
+/// The guts of `normalize`: normalize a specific projection like `<T
+/// as Trait>::Item`. The result is always a type (and possibly
+/// additional obligations). If ambiguity arises, which implies that
+/// there are unresolved type variables in the projection, we will
+/// substitute a fresh type variable `$X` and generate a new
+/// obligation `<T as Trait>::Item == $X` for later.
+pub fn normalize_projection_type<'a, 'b, 'tcx>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+    obligations: &mut Vec<PredicateObligation<'tcx>>,
+) -> Ty<'tcx> {
+    opt_normalize_projection_type(
+        selcx,
+        param_env,
+        projection_ty,
+        cause.clone(),
+        depth,
+        obligations,
+    )
+    .unwrap_or_else(move || {
+        // if we bottom out in ambiguity, create a type variable
+        // and a deferred predicate to resolve this when more type
+        // information is available.
+
+        let tcx = selcx.infcx().tcx;
+        let def_id = projection_ty.item_def_id;
+        let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin {
+            kind: TypeVariableOriginKind::NormalizeProjectionType,
+            span: tcx.def_span(def_id),
+        });
+        let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
+        let obligation =
+            Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate());
+        obligations.push(obligation);
+        ty_var
+    })
+}
+
+/// The guts of `normalize`: normalize a specific projection like `<T
+/// as Trait>::Item`. The result is always a type (and possibly
+/// additional obligations). Returns `None` in the case of ambiguity,
+/// which indicates that there are unbound type variables.
+///
+/// This function used to return `Option<NormalizedTy<'tcx>>`, which contains a
+/// `Ty<'tcx>` and an obligations vector. But that obligation vector was very
+/// often immediately appended to another obligations vector. So now this
+/// function takes an obligations vector and appends to it directly, which is
+/// slightly uglier but avoids the need for an extra short-lived allocation.
+fn opt_normalize_projection_type<'a, 'b, 'tcx>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+    obligations: &mut Vec<PredicateObligation<'tcx>>,
+) -> Option<Ty<'tcx>> {
+    let infcx = selcx.infcx();
+
+    let projection_ty = infcx.resolve_vars_if_possible(&projection_ty);
+    let cache_key = ProjectionCacheKey::new(projection_ty);
+
+    debug!(
+        "opt_normalize_projection_type(\
+         projection_ty={:?}, \
+         depth={})",
+        projection_ty, depth
+    );
+
+    // FIXME(#20304) For now, I am caching here, which is good, but it
+    // means we don't capture the type variables that are created in
+    // the case of ambiguity. Which means we may create a large stream
+    // of such variables. OTOH, if we move the caching up a level, we
+    // would not benefit from caching when proving `T: Trait<U=Foo>`
+    // bounds. It might be the case that we want two distinct caches,
+    // or else another kind of cache entry.
+
+    let cache_result = infcx.inner.borrow_mut().projection_cache.try_start(cache_key);
+    match cache_result {
+        Ok(()) => {}
+        Err(ProjectionCacheEntry::Ambiguous) => {
+            // If we found ambiguity the last time, that means we will continue
+            // to do so until some type in the key changes (and we know it
+            // hasn't, because we just fully resolved it).
+            debug!(
+                "opt_normalize_projection_type: \
+                 found cache entry: ambiguous"
+            );
+            return None;
+        }
+        Err(ProjectionCacheEntry::InProgress) => {
+            // If while normalized A::B, we are asked to normalize
+            // A::B, just return A::B itself. This is a conservative
+            // answer, in the sense that A::B *is* clearly equivalent
+            // to A::B, though there may be a better value we can
+            // find.
+
+            // Under lazy normalization, this can arise when
+            // bootstrapping.  That is, imagine an environment with a
+            // where-clause like `A::B == u32`. Now, if we are asked
+            // to normalize `A::B`, we will want to check the
+            // where-clauses in scope. So we will try to unify `A::B`
+            // with `A::B`, which can trigger a recursive
+            // normalization. In that case, I think we will want this code:
+            //
+            // ```
+            // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id,
+            //                                    projection_ty.substs;
+            // return Some(NormalizedTy { value: v, obligations: vec![] });
+            // ```
+
+            debug!(
+                "opt_normalize_projection_type: \
+                 found cache entry: in-progress"
+            );
+
+            // But for now, let's classify this as an overflow:
+            let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
+            let obligation =
+                Obligation::with_depth(cause, recursion_limit, param_env, projection_ty);
+            selcx.infcx().report_overflow_error(&obligation, false);
+        }
+        Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
+            // This is the hottest path in this function.
+            //
+            // If we find the value in the cache, then return it along
+            // with the obligations that went along with it. Note
+            // that, when using a fulfillment context, these
+            // obligations could in principle be ignored: they have
+            // already been registered when the cache entry was
+            // created (and hence the new ones will quickly be
+            // discarded as duplicated). But when doing trait
+            // evaluation this is not the case, and dropping the trait
+            // evaluations can causes ICEs (e.g., #43132).
+            debug!(
+                "opt_normalize_projection_type: \
+                 found normalized ty `{:?}`",
+                ty
+            );
+
+            // Once we have inferred everything we need to know, we
+            // can ignore the `obligations` from that point on.
+            if infcx.unresolved_type_vars(&ty.value).is_none() {
+                infcx.inner.borrow_mut().projection_cache.complete_normalized(cache_key, &ty);
+            // No need to extend `obligations`.
+            } else {
+                obligations.extend(ty.obligations);
+            }
+
+            obligations.push(get_paranoid_cache_value_obligation(
+                infcx,
+                param_env,
+                projection_ty,
+                cause,
+                depth,
+            ));
+            return Some(ty.value);
+        }
+        Err(ProjectionCacheEntry::Error) => {
+            debug!(
+                "opt_normalize_projection_type: \
+                 found error"
+            );
+            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
+            obligations.extend(result.obligations);
+            return Some(result.value);
+        }
+    }
+
+    let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
+    match project_type(selcx, &obligation) {
+        Ok(ProjectedTy::Progress(Progress {
+            ty: projected_ty,
+            obligations: mut projected_obligations,
+        })) => {
+            // if projection succeeded, then what we get out of this
+            // is also non-normalized (consider: it was derived from
+            // an impl, where-clause etc) and hence we must
+            // re-normalize it
+
+            debug!(
+                "opt_normalize_projection_type: \
+                 projected_ty={:?} \
+                 depth={} \
+                 projected_obligations={:?}",
+                projected_ty, depth, projected_obligations
+            );
+
+            let result = if projected_ty.has_projections() {
+                let mut normalizer = AssocTypeNormalizer::new(
+                    selcx,
+                    param_env,
+                    cause,
+                    depth + 1,
+                    &mut projected_obligations,
+                );
+                let normalized_ty = normalizer.fold(&projected_ty);
+
+                debug!(
+                    "opt_normalize_projection_type: \
+                     normalized_ty={:?} depth={}",
+                    normalized_ty, depth
+                );
+
+                Normalized { value: normalized_ty, obligations: projected_obligations }
+            } else {
+                Normalized { value: projected_ty, obligations: projected_obligations }
+            };
+
+            let cache_value = prune_cache_value_obligations(infcx, &result);
+            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, cache_value);
+            obligations.extend(result.obligations);
+            Some(result.value)
+        }
+        Ok(ProjectedTy::NoProgress(projected_ty)) => {
+            debug!(
+                "opt_normalize_projection_type: \
+                 projected_ty={:?} no progress",
+                projected_ty
+            );
+            let result = Normalized { value: projected_ty, obligations: vec![] };
+            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, result.clone());
+            // No need to extend `obligations`.
+            Some(result.value)
+        }
+        Err(ProjectionTyError::TooManyCandidates) => {
+            debug!(
+                "opt_normalize_projection_type: \
+                 too many candidates"
+            );
+            infcx.inner.borrow_mut().projection_cache.ambiguous(cache_key);
+            None
+        }
+        Err(ProjectionTyError::TraitSelectionError(_)) => {
+            debug!("opt_normalize_projection_type: ERROR");
+            // if we got an error processing the `T as Trait` part,
+            // just return `ty::err` but add the obligation `T :
+            // Trait`, which when processed will cause the error to be
+            // reported later
+
+            infcx.inner.borrow_mut().projection_cache.error(cache_key);
+            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
+            obligations.extend(result.obligations);
+            Some(result.value)
+        }
+    }
+}
+
+/// If there are unresolved type variables, then we need to include
+/// any subobligations that bind them, at least until those type
+/// variables are fully resolved.
+fn prune_cache_value_obligations<'a, 'tcx>(
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    result: &NormalizedTy<'tcx>,
+) -> NormalizedTy<'tcx> {
+    if infcx.unresolved_type_vars(&result.value).is_none() {
+        return NormalizedTy { value: result.value, obligations: vec![] };
+    }
+
+    let mut obligations: Vec<_> = result
+        .obligations
+        .iter()
+        .filter(|obligation| match obligation.predicate {
+            // We found a `T: Foo<X = U>` predicate, let's check
+            // if `U` references any unresolved type
+            // variables. In principle, we only care if this
+            // projection can help resolve any of the type
+            // variables found in `result.value` -- but we just
+            // check for any type variables here, for fear of
+            // indirect obligations (e.g., we project to `?0`,
+            // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
+            // ?0>`).
+            ty::Predicate::Projection(ref data) => infcx.unresolved_type_vars(&data.ty()).is_some(),
+
+            // We are only interested in `T: Foo<X = U>` predicates, whre
+            // `U` references one of `unresolved_type_vars`. =)
+            _ => false,
+        })
+        .cloned()
+        .collect();
+
+    obligations.shrink_to_fit();
+
+    NormalizedTy { value: result.value, obligations }
+}
+
+/// Whenever we give back a cache result for a projection like `<T as
+/// Trait>::Item ==> X`, we *always* include the obligation to prove
+/// that `T: Trait` (we may also include some other obligations). This
+/// may or may not be necessary -- in principle, all the obligations
+/// that must be proven to show that `T: Trait` were also returned
+/// when the cache was first populated. But there are some vague concerns,
+/// and so we take the precautionary measure of including `T: Trait` in
+/// the result:
+///
+/// Concern #1. The current setup is fragile. Perhaps someone could
+/// have failed to prove the concerns from when the cache was
+/// populated, but also not have used a snapshot, in which case the
+/// cache could remain populated even though `T: Trait` has not been
+/// shown. In this case, the "other code" is at fault -- when you
+/// project something, you are supposed to either have a snapshot or
+/// else prove all the resulting obligations -- but it's still easy to
+/// get wrong.
+///
+/// Concern #2. Even within the snapshot, if those original
+/// obligations are not yet proven, then we are able to do projections
+/// that may yet turn out to be wrong. This *may* lead to some sort
+/// of trouble, though we don't have a concrete example of how that
+/// can occur yet. But it seems risky at best.
+fn get_paranoid_cache_value_obligation<'a, 'tcx>(
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+) -> PredicateObligation<'tcx> {
+    let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
+    Obligation {
+        cause,
+        recursion_depth: depth,
+        param_env,
+        predicate: trait_ref.without_const().to_predicate(),
+    }
+}
+
+/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
+/// hold. In various error cases, we cannot generate a valid
+/// normalized projection. Therefore, we create an inference variable
+/// return an associated obligation that, when fulfilled, will lead to
+/// an error.
+///
+/// Note that we used to return `Error` here, but that was quite
+/// dubious -- the premise was that an error would *eventually* be
+/// reported, when the obligation was processed. But in general once
+/// you see a `Error` you are supposed to be able to assume that an
+/// error *has been* reported, so that you can take whatever heuristic
+/// paths you want to take. To make things worse, it was possible for
+/// cycles to arise, where you basically had a setup like `<MyType<$0>
+/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
+/// Trait>::Foo> to `[type error]` would lead to an obligation of
+/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
+/// an error for this obligation, but we legitimately should not,
+/// because it contains `[type error]`. Yuck! (See issue #29857 for
+/// one case where this arose.)
+fn normalize_to_error<'a, 'tcx>(
+    selcx: &mut SelectionContext<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+) -> NormalizedTy<'tcx> {
+    let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref();
+    let trait_obligation = Obligation {
+        cause,
+        recursion_depth: depth,
+        param_env,
+        predicate: trait_ref.without_const().to_predicate(),
+    };
+    let tcx = selcx.infcx().tcx;
+    let def_id = projection_ty.item_def_id;
+    let new_value = selcx.infcx().next_ty_var(TypeVariableOrigin {
+        kind: TypeVariableOriginKind::NormalizeProjectionType,
+        span: tcx.def_span(def_id),
+    });
+    Normalized { value: new_value, obligations: vec![trait_obligation] }
+}
+
+enum ProjectedTy<'tcx> {
+    Progress(Progress<'tcx>),
+    NoProgress(Ty<'tcx>),
+}
+
+struct Progress<'tcx> {
+    ty: Ty<'tcx>,
+    obligations: Vec<PredicateObligation<'tcx>>,
+}
+
+impl<'tcx> Progress<'tcx> {
+    fn error(tcx: TyCtxt<'tcx>) -> Self {
+        Progress { ty: tcx.types.err, obligations: vec![] }
+    }
+
+    fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
+        debug!(
+            "with_addl_obligations: self.obligations.len={} obligations.len={}",
+            self.obligations.len(),
+            obligations.len()
+        );
+
+        debug!(
+            "with_addl_obligations: self.obligations={:?} obligations={:?}",
+            self.obligations, obligations
+        );
+
+        self.obligations.append(&mut obligations);
+        self
+    }
+}
+
+/// Computes the result of a projection type (if we can).
+///
+/// IMPORTANT:
+/// - `obligation` must be fully normalized
+fn project_type<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
+    debug!("project(obligation={:?})", obligation);
+
+    let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
+    if obligation.recursion_depth >= recursion_limit {
+        debug!("project: overflow!");
+        return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
+    }
+
+    let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
+
+    debug!("project: obligation_trait_ref={:?}", obligation_trait_ref);
+
+    if obligation_trait_ref.references_error() {
+        return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx())));
+    }
+
+    let mut candidates = ProjectionTyCandidateSet::None;
+
+    // Make sure that the following procedures are kept in order. ParamEnv
+    // needs to be first because it has highest priority, and Select checks
+    // the return value of push_candidate which assumes it's ran at last.
+    assemble_candidates_from_param_env(selcx, obligation, &obligation_trait_ref, &mut candidates);
+
+    assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
+
+    assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
+
+    match candidates {
+        ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress(
+            confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate),
+        )),
+        ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
+            selcx
+                .tcx()
+                .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs),
+        )),
+        // Error occurred while trying to processing impls.
+        ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)),
+        // Inherent ambiguity that prevents us from even enumerating the
+        // candidates.
+        ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates),
+    }
+}
+
+/// The first thing we have to do is scan through the parameter
+/// environment to see whether there are any projection predicates
+/// there that can answer this question.
+fn assemble_candidates_from_param_env<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+) {
+    debug!("assemble_candidates_from_param_env(..)");
+    assemble_candidates_from_predicates(
+        selcx,
+        obligation,
+        obligation_trait_ref,
+        candidate_set,
+        ProjectionTyCandidate::ParamEnv,
+        obligation.param_env.caller_bounds.iter().cloned(),
+    );
+}
+
+/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
+/// that the definition of `Foo` has some clues:
+///
+/// ```
+/// trait Foo {
+///     type FooT : Bar<BarT=i32>
+/// }
+/// ```
+///
+/// Here, for example, we could conclude that the result is `i32`.
+fn assemble_candidates_from_trait_def<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+) {
+    debug!("assemble_candidates_from_trait_def(..)");
+
+    let tcx = selcx.tcx();
+    // Check whether the self-type is itself a projection.
+    let (def_id, substs) = match obligation_trait_ref.self_ty().kind {
+        ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs),
+        ty::Opaque(def_id, substs) => (def_id, substs),
+        ty::Infer(ty::TyVar(_)) => {
+            // If the self-type is an inference variable, then it MAY wind up
+            // being a projected type, so induce an ambiguity.
+            candidate_set.mark_ambiguous();
+            return;
+        }
+        _ => return,
+    };
+
+    // If so, extract what we know from the trait and try to come up with a good answer.
+    let trait_predicates = tcx.predicates_of(def_id);
+    let bounds = trait_predicates.instantiate(tcx, substs);
+    let bounds = elaborate_predicates(tcx, bounds.predicates);
+    assemble_candidates_from_predicates(
+        selcx,
+        obligation,
+        obligation_trait_ref,
+        candidate_set,
+        ProjectionTyCandidate::TraitDef,
+        bounds,
+    )
+}
+
+fn assemble_candidates_from_predicates<'cx, 'tcx, I>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+    ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
+    env_predicates: I,
+) where
+    I: IntoIterator<Item = ty::Predicate<'tcx>>,
+{
+    debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
+    let infcx = selcx.infcx();
+    for predicate in env_predicates {
+        debug!("assemble_candidates_from_predicates: predicate={:?}", predicate);
+        if let ty::Predicate::Projection(data) = predicate {
+            let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
+
+            let is_match = same_def_id
+                && infcx.probe(|_| {
+                    let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx);
+                    let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
+                    infcx
+                        .at(&obligation.cause, obligation.param_env)
+                        .sup(obligation_poly_trait_ref, data_poly_trait_ref)
+                        .map(|InferOk { obligations: _, value: () }| {
+                            // FIXME(#32730) -- do we need to take obligations
+                            // into account in any way? At the moment, no.
+                        })
+                        .is_ok()
+                });
+
+            debug!(
+                "assemble_candidates_from_predicates: candidate={:?} \
+                 is_match={} same_def_id={}",
+                data, is_match, same_def_id
+            );
+
+            if is_match {
+                candidate_set.push_candidate(ctor(data));
+            }
+        }
+    }
+}
+
+fn assemble_candidates_from_impls<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+) {
+    // If we are resolving `<T as TraitRef<...>>::Item == Type`,
+    // start out by selecting the predicate `T as TraitRef<...>`:
+    let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
+    let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
+    let _ = selcx.infcx().commit_if_ok(|_| {
+        let vtable = match selcx.select(&trait_obligation) {
+            Ok(Some(vtable)) => vtable,
+            Ok(None) => {
+                candidate_set.mark_ambiguous();
+                return Err(());
+            }
+            Err(e) => {
+                debug!("assemble_candidates_from_impls: selection error {:?}", e);
+                candidate_set.mark_error(e);
+                return Err(());
+            }
+        };
+
+        let eligible = match &vtable {
+            super::VtableClosure(_)
+            | super::VtableGenerator(_)
+            | super::VtableFnPointer(_)
+            | super::VtableObject(_)
+            | super::VtableTraitAlias(_) => {
+                debug!("assemble_candidates_from_impls: vtable={:?}", vtable);
+                true
+            }
+            super::VtableImpl(impl_data) => {
+                // We have to be careful when projecting out of an
+                // impl because of specialization. If we are not in
+                // codegen (i.e., projection mode is not "any"), and the
+                // impl's type is declared as default, then we disable
+                // projection (even if the trait ref is fully
+                // monomorphic). In the case where trait ref is not
+                // fully monomorphic (i.e., includes type parameters),
+                // this is because those type parameters may
+                // ultimately be bound to types from other crates that
+                // may have specialized impls we can't see. In the
+                // case where the trait ref IS fully monomorphic, this
+                // is a policy decision that we made in the RFC in
+                // order to preserve flexibility for the crate that
+                // defined the specializable impl to specialize later
+                // for existing types.
+                //
+                // In either case, we handle this by not adding a
+                // candidate for an impl if it contains a `default`
+                // type.
+                //
+                // NOTE: This should be kept in sync with the similar code in
+                // `rustc::ty::instance::resolve_associated_item()`.
+                let node_item =
+                    assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
+                        .map_err(|ErrorReported| ())?;
+
+                let is_default = if node_item.node.is_from_trait() {
+                    // If true, the impl inherited a `type Foo = Bar`
+                    // given in the trait, which is implicitly default.
+                    // Otherwise, the impl did not specify `type` and
+                    // neither did the trait:
+                    //
+                    // ```rust
+                    // trait Foo { type T; }
+                    // impl Foo for Bar { }
+                    // ```
+                    //
+                    // This is an error, but it will be
+                    // reported in `check_impl_items_against_trait`.
+                    // We accept it here but will flag it as
+                    // an error when we confirm the candidate
+                    // (which will ultimately lead to `normalize_to_error`
+                    // being invoked).
+                    false
+                } else {
+                    // If we're looking at a trait *impl*, the item is
+                    // specializable if the impl or the item are marked
+                    // `default`.
+                    node_item.item.defaultness.is_default()
+                        || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
+                };
+
+                match is_default {
+                    // Non-specializable items are always projectable
+                    false => true,
+
+                    // Only reveal a specializable default if we're past type-checking
+                    // and the obligation is monomorphic, otherwise passes such as
+                    // transmute checking and polymorphic MIR optimizations could
+                    // get a result which isn't correct for all monomorphizations.
+                    true if obligation.param_env.reveal == Reveal::All => {
+                        // NOTE(eddyb) inference variables can resolve to parameters, so
+                        // assume `poly_trait_ref` isn't monomorphic, if it contains any.
+                        let poly_trait_ref =
+                            selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
+                        !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
+                    }
+
+                    true => {
+                        debug!(
+                            "assemble_candidates_from_impls: not eligible due to default: \
+                             assoc_ty={} predicate={}",
+                            selcx.tcx().def_path_str(node_item.item.def_id),
+                            obligation.predicate,
+                        );
+                        false
+                    }
+                }
+            }
+            super::VtableParam(..) => {
+                // This case tell us nothing about the value of an
+                // associated type. Consider:
+                //
+                // ```
+                // trait SomeTrait { type Foo; }
+                // fn foo<T:SomeTrait>(...) { }
+                // ```
+                //
+                // If the user writes `<T as SomeTrait>::Foo`, then the `T
+                // : SomeTrait` binding does not help us decide what the
+                // type `Foo` is (at least, not more specifically than
+                // what we already knew).
+                //
+                // But wait, you say! What about an example like this:
+                //
+                // ```
+                // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
+                // ```
+                //
+                // Doesn't the `T : Sometrait<Foo=usize>` predicate help
+                // resolve `T::Foo`? And of course it does, but in fact
+                // that single predicate is desugared into two predicates
+                // in the compiler: a trait predicate (`T : SomeTrait`) and a
+                // projection. And the projection where clause is handled
+                // in `assemble_candidates_from_param_env`.
+                false
+            }
+            super::VtableAutoImpl(..) | super::VtableBuiltin(..) => {
+                // These traits have no associated types.
+                span_bug!(
+                    obligation.cause.span,
+                    "Cannot project an associated type from `{:?}`",
+                    vtable
+                );
+            }
+        };
+
+        if eligible {
+            if candidate_set.push_candidate(ProjectionTyCandidate::Select(vtable)) {
+                Ok(())
+            } else {
+                Err(())
+            }
+        } else {
+            Err(())
+        }
+    });
+}
+
+fn confirm_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate: ProjectionTyCandidate<'tcx>,
+) -> Progress<'tcx> {
+    debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
+
+    match candidate {
+        ProjectionTyCandidate::ParamEnv(poly_projection)
+        | ProjectionTyCandidate::TraitDef(poly_projection) => {
+            confirm_param_env_candidate(selcx, obligation, poly_projection)
+        }
+
+        ProjectionTyCandidate::Select(vtable) => {
+            confirm_select_candidate(selcx, obligation, obligation_trait_ref, vtable)
+        }
+    }
+}
+
+fn confirm_select_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    vtable: Selection<'tcx>,
+) -> Progress<'tcx> {
+    match vtable {
+        super::VtableImpl(data) => confirm_impl_candidate(selcx, obligation, data),
+        super::VtableGenerator(data) => confirm_generator_candidate(selcx, obligation, data),
+        super::VtableClosure(data) => confirm_closure_candidate(selcx, obligation, data),
+        super::VtableFnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
+        super::VtableObject(_) => confirm_object_candidate(selcx, obligation, obligation_trait_ref),
+        super::VtableAutoImpl(..)
+        | super::VtableParam(..)
+        | super::VtableBuiltin(..)
+        | super::VtableTraitAlias(..) =>
+        // we don't create Select candidates with this kind of resolution
+        {
+            span_bug!(
+                obligation.cause.span,
+                "Cannot project an associated type from `{:?}`",
+                vtable
+            )
+        }
+    }
+}
+
+fn confirm_object_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+) -> Progress<'tcx> {
+    let self_ty = obligation_trait_ref.self_ty();
+    let object_ty = selcx.infcx().shallow_resolve(self_ty);
+    debug!("confirm_object_candidate(object_ty={:?})", object_ty);
+    let data = match object_ty.kind {
+        ty::Dynamic(ref data, ..) => data,
+        _ => span_bug!(
+            obligation.cause.span,
+            "confirm_object_candidate called with non-object: {:?}",
+            object_ty
+        ),
+    };
+    let env_predicates = data
+        .projection_bounds()
+        .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate())
+        .collect();
+    let env_predicate = {
+        let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
+
+        // select only those projections that are actually projecting an
+        // item with the correct name
+        let env_predicates = env_predicates.filter_map(|p| match p {
+            ty::Predicate::Projection(data) => {
+                if data.projection_def_id() == obligation.predicate.item_def_id {
+                    Some(data)
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        });
+
+        // select those with a relevant trait-ref
+        let mut env_predicates = env_predicates.filter(|data| {
+            let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
+            let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
+            selcx.infcx().probe(|_| {
+                selcx
+                    .infcx()
+                    .at(&obligation.cause, obligation.param_env)
+                    .sup(obligation_poly_trait_ref, data_poly_trait_ref)
+                    .is_ok()
+            })
+        });
+
+        // select the first matching one; there really ought to be one or
+        // else the object type is not WF, since an object type should
+        // include all of its projections explicitly
+        match env_predicates.next() {
+            Some(env_predicate) => env_predicate,
+            None => {
+                debug!(
+                    "confirm_object_candidate: no env-predicate \
+                     found in object type `{:?}`; ill-formed",
+                    object_ty
+                );
+                return Progress::error(selcx.tcx());
+            }
+        }
+    };
+
+    confirm_param_env_candidate(selcx, obligation, env_predicate)
+}
+
+fn confirm_generator_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
+) -> Progress<'tcx> {
+    let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx());
+    let Normalized { value: gen_sig, obligations } = normalize_with_depth(
+        selcx,
+        obligation.param_env,
+        obligation.cause.clone(),
+        obligation.recursion_depth + 1,
+        &gen_sig,
+    );
+
+    debug!(
+        "confirm_generator_candidate: obligation={:?},gen_sig={:?},obligations={:?}",
+        obligation, gen_sig, obligations
+    );
+
+    let tcx = selcx.tcx();
+
+    let gen_def_id = tcx.lang_items().gen_trait().unwrap();
+
+    let predicate = super::util::generator_trait_ref_and_outputs(
+        tcx,
+        gen_def_id,
+        obligation.predicate.self_ty(),
+        gen_sig,
+    )
+    .map_bound(|(trait_ref, yield_ty, return_ty)| {
+        let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name;
+        let ty = if name == sym::Return {
+            return_ty
+        } else if name == sym::Yield {
+            yield_ty
+        } else {
+            bug!()
+        };
+
+        ty::ProjectionPredicate {
+            projection_ty: ty::ProjectionTy {
+                substs: trait_ref.substs,
+                item_def_id: obligation.predicate.item_def_id,
+            },
+            ty,
+        }
+    });
+
+    confirm_param_env_candidate(selcx, obligation, predicate)
+        .with_addl_obligations(vtable.nested)
+        .with_addl_obligations(obligations)
+}
+
+fn confirm_fn_pointer_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>,
+) -> Progress<'tcx> {
+    let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
+    let sig = fn_type.fn_sig(selcx.tcx());
+    let Normalized { value: sig, obligations } = normalize_with_depth(
+        selcx,
+        obligation.param_env,
+        obligation.cause.clone(),
+        obligation.recursion_depth + 1,
+        &sig,
+    );
+
+    confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
+        .with_addl_obligations(fn_pointer_vtable.nested)
+        .with_addl_obligations(obligations)
+}
+
+fn confirm_closure_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>,
+) -> Progress<'tcx> {
+    let tcx = selcx.tcx();
+    let infcx = selcx.infcx();
+    let closure_sig_ty = vtable.substs.as_closure().sig_ty(vtable.closure_def_id, tcx);
+    let closure_sig = infcx.shallow_resolve(closure_sig_ty).fn_sig(tcx);
+    let Normalized { value: closure_sig, obligations } = normalize_with_depth(
+        selcx,
+        obligation.param_env,
+        obligation.cause.clone(),
+        obligation.recursion_depth + 1,
+        &closure_sig,
+    );
+
+    debug!(
+        "confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}",
+        obligation, closure_sig, obligations
+    );
+
+    confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
+        .with_addl_obligations(vtable.nested)
+        .with_addl_obligations(obligations)
+}
+
+fn confirm_callable_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    fn_sig: ty::PolyFnSig<'tcx>,
+    flag: util::TupleArgumentsFlag,
+) -> Progress<'tcx> {
+    let tcx = selcx.tcx();
+
+    debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig);
+
+    // the `Output` associated type is declared on `FnOnce`
+    let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap();
+
+    let predicate = super::util::closure_trait_ref_and_return_type(
+        tcx,
+        fn_once_def_id,
+        obligation.predicate.self_ty(),
+        fn_sig,
+        flag,
+    )
+    .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
+        projection_ty: ty::ProjectionTy::from_ref_and_name(
+            tcx,
+            trait_ref,
+            Ident::with_dummy_span(rustc_hir::FN_OUTPUT_NAME),
+        ),
+        ty: ret_type,
+    });
+
+    confirm_param_env_candidate(selcx, obligation, predicate)
+}
+
+fn confirm_param_env_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
+) -> Progress<'tcx> {
+    let infcx = selcx.infcx();
+    let cause = &obligation.cause;
+    let param_env = obligation.param_env;
+
+    let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars(
+        cause.span,
+        LateBoundRegionConversionTime::HigherRankedType,
+        &poly_cache_entry,
+    );
+
+    let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx);
+    let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx);
+    match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) {
+        Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations },
+        Err(e) => {
+            let msg = format!(
+                "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
+                obligation, poly_cache_entry, e,
+            );
+            debug!("confirm_param_env_candidate: {}", msg);
+            infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg);
+            Progress { ty: infcx.tcx.types.err, obligations: vec![] }
+        }
+    }
+}
+
+fn confirm_impl_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>,
+) -> Progress<'tcx> {
+    let tcx = selcx.tcx();
+
+    let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
+    let assoc_item_id = obligation.predicate.item_def_id;
+    let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
+
+    let param_env = obligation.param_env;
+    let assoc_ty = match assoc_ty_def(selcx, impl_def_id, assoc_item_id) {
+        Ok(assoc_ty) => assoc_ty,
+        Err(ErrorReported) => return Progress { ty: tcx.types.err, obligations: nested },
+    };
+
+    if !assoc_ty.item.defaultness.has_value() {
+        // This means that the impl is missing a definition for the
+        // associated type. This error will be reported by the type
+        // checker method `check_impl_items_against_trait`, so here we
+        // just return Error.
+        debug!(
+            "confirm_impl_candidate: no associated type {:?} for {:?}",
+            assoc_ty.item.ident, obligation.predicate
+        );
+        return Progress { ty: tcx.types.err, obligations: nested };
+    }
+    let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
+    let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
+    let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
+        let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
+        tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
+    } else {
+        tcx.type_of(assoc_ty.item.def_id)
+    };
+    if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
+        tcx.sess
+            .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts");
+        Progress { ty: tcx.types.err, obligations: nested }
+    } else {
+        Progress { ty: ty.subst(tcx, substs), obligations: nested }
+    }
+}
+
+/// Locate the definition of an associated type in the specialization hierarchy,
+/// starting from the given impl.
+///
+/// Based on the "projection mode", this lookup may in fact only examine the
+/// topmost impl. See the comments for `Reveal` for more details.
+fn assoc_ty_def(
+    selcx: &SelectionContext<'_, '_>,
+    impl_def_id: DefId,
+    assoc_ty_def_id: DefId,
+) -> Result<specialization_graph::NodeItem<ty::AssocItem>, ErrorReported> {
+    let tcx = selcx.tcx();
+    let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
+    let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
+    let trait_def = tcx.trait_def(trait_def_id);
+
+    // This function may be called while we are still building the
+    // specialization graph that is queried below (via TraitDef::ancestors()),
+    // so, in order to avoid unnecessary infinite recursion, we manually look
+    // for the associated item at the given impl.
+    // If there is no such item in that impl, this function will fail with a
+    // cycle error if the specialization graph is currently being built.
+    let impl_node = specialization_graph::Node::Impl(impl_def_id);
+    for item in impl_node.items(tcx) {
+        if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
+            && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
+        {
+            return Ok(specialization_graph::NodeItem {
+                node: specialization_graph::Node::Impl(impl_def_id),
+                item: *item,
+            });
+        }
+    }
+
+    let ancestors = trait_def.ancestors(tcx, impl_def_id)?;
+    if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) {
+        Ok(assoc_item)
+    } else {
+        // This is saying that neither the trait nor
+        // the impl contain a definition for this
+        // associated type.  Normally this situation
+        // could only arise through a compiler bug --
+        // if the user wrote a bad item name, it
+        // should have failed in astconv.
+        bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id))
+    }
+}
+
+crate trait ProjectionCacheKeyExt<'tcx>: Sized {
+    fn from_poly_projection_predicate(
+        selcx: &mut SelectionContext<'cx, 'tcx>,
+        predicate: &ty::PolyProjectionPredicate<'tcx>,
+    ) -> Option<Self>;
+}
+
+impl<'tcx> ProjectionCacheKeyExt<'tcx> for ProjectionCacheKey<'tcx> {
+    fn from_poly_projection_predicate(
+        selcx: &mut SelectionContext<'cx, 'tcx>,
+        predicate: &ty::PolyProjectionPredicate<'tcx>,
+    ) -> Option<Self> {
+        let infcx = selcx.infcx();
+        // We don't do cross-snapshot caching of obligations with escaping regions,
+        // so there's no cache key to use
+        predicate.no_bound_vars().map(|predicate| {
+            ProjectionCacheKey::new(
+                // We don't attempt to match up with a specific type-variable state
+                // from a specific call to `opt_normalize_projection_type` - if
+                // there's no precise match, the original cache entry is "stranded"
+                // anyway.
+                infcx.resolve_vars_if_possible(&predicate.projection_ty),
+            )
+        })
+    }
+}
diff --git a/src/librustc_infer/traits/query/dropck_outlives.rs b/src/librustc_trait_selection/traits/query/dropck_outlives.rs
index a1d7a2836e4..40a21b5a6ed 100644
--- a/src/librustc_infer/traits/query/dropck_outlives.rs
+++ b/src/librustc_trait_selection/traits/query/dropck_outlives.rs
@@ -7,7 +7,11 @@ use rustc::ty::{self, Ty, TyCtxt};
 
 pub use rustc::traits::query::{DropckOutlivesResult, DtorckConstraint};
 
-impl<'cx, 'tcx> At<'cx, 'tcx> {
+pub trait AtExt<'tcx> {
+    fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx>>>;
+}
+
+impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
     /// Given a type `ty` of some value being dropped, computes a set
     /// of "kinds" (types, regions) that must be outlive the execution
     /// of the destructor. These basically correspond to data that the
@@ -25,7 +29,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
     ///
     /// [#1238]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
     /// [#1327]: https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md
-    pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx>>> {
+    fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx>>> {
         debug!("dropck_outlives(ty={:?}, param_env={:?})", ty, self.param_env,);
 
         // Quick check: there are a number of cases that we know do not require
diff --git a/src/librustc_infer/traits/query/evaluate_obligation.rs b/src/librustc_trait_selection/traits/query/evaluate_obligation.rs
index b9ce3ccff27..0569f6217da 100644
--- a/src/librustc_infer/traits/query/evaluate_obligation.rs
+++ b/src/librustc_trait_selection/traits/query/evaluate_obligation.rs
@@ -4,10 +4,35 @@ use crate::traits::{
     EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode,
 };
 
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
+pub trait InferCtxtExt<'tcx> {
+    fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool;
+
+    fn predicate_must_hold_considering_regions(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool;
+
+    fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool;
+
+    fn evaluate_obligation(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError>;
+
+    // Helper function that canonicalizes and runs the query. If an
+    // overflow results, we re-run it in the local context so we can
+    // report a nice error.
+    /*crate*/
+    fn evaluate_obligation_no_overflow(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> EvaluationResult;
+}
+
+impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
     /// Evaluates whether the predicate can be satisfied (by any means)
     /// in the given `ParamEnv`.
-    pub fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
+    fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
         self.evaluate_obligation_no_overflow(obligation).may_apply()
     }
 
@@ -17,7 +42,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     ///
     /// This version may conservatively fail when outlives obligations
     /// are required.
-    pub fn predicate_must_hold_considering_regions(
+    fn predicate_must_hold_considering_regions(
         &self,
         obligation: &PredicateObligation<'tcx>,
     ) -> bool {
@@ -29,15 +54,12 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// not entirely accurate if inference variables are involved.
     ///
     /// This version ignores all outlives constraints.
-    pub fn predicate_must_hold_modulo_regions(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
+    fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool {
         self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions()
     }
 
     /// Evaluate a given predicate, capturing overflow and propagating it back.
-    pub fn evaluate_obligation(
+    fn evaluate_obligation(
         &self,
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
@@ -53,7 +75,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     // Helper function that canonicalizes and runs the query. If an
     // overflow results, we re-run it in the local context so we can
     // report a nice error.
-    crate fn evaluate_obligation_no_overflow(
+    fn evaluate_obligation_no_overflow(
         &self,
         obligation: &PredicateObligation<'tcx>,
     ) -> EvaluationResult {
diff --git a/src/librustc_infer/traits/query/method_autoderef.rs b/src/librustc_trait_selection/traits/query/method_autoderef.rs
index 80748c5ef38..80748c5ef38 100644
--- a/src/librustc_infer/traits/query/method_autoderef.rs
+++ b/src/librustc_trait_selection/traits/query/method_autoderef.rs
diff --git a/src/librustc_infer/traits/query/mod.rs b/src/librustc_trait_selection/traits/query/mod.rs
index 77b5ec669a0..77b5ec669a0 100644
--- a/src/librustc_infer/traits/query/mod.rs
+++ b/src/librustc_trait_selection/traits/query/mod.rs
diff --git a/src/librustc_infer/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs
index 4577e3d2e1c..adec2ddb253 100644
--- a/src/librustc_infer/traits/query/normalize.rs
+++ b/src/librustc_trait_selection/traits/query/normalize.rs
@@ -5,17 +5,24 @@
 use crate::infer::at::At;
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::{InferCtxt, InferOk};
-use crate::traits::project::Normalized;
+use crate::traits::error_reporting::InferCtxtExt;
 use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
 use rustc::ty::fold::{TypeFoldable, TypeFolder};
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc_infer::traits::Normalized;
 
 use super::NoSolution;
 
 pub use rustc::traits::query::NormalizationResult;
 
-impl<'cx, 'tcx> At<'cx, 'tcx> {
+pub trait AtExt<'tcx> {
+    fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
+    where
+        T: TypeFoldable<'tcx>;
+}
+
+impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
     /// Normalize `value` in the context of the inference context,
     /// yielding a resulting type, or an error if `value` cannot be
     /// normalized. If you don't care about regions, you should prefer
@@ -29,7 +36,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
     /// normalizing, but for now should be used only when we actually
     /// know that normalization will succeed, since error reporting
     /// and other details are still "under development".
-    pub fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
+    fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
     where
         T: TypeFoldable<'tcx>,
     {
diff --git a/src/librustc_infer/traits/query/outlives_bounds.rs b/src/librustc_trait_selection/traits/query/outlives_bounds.rs
index eb32ebf5c4d..05c96dd520a 100644
--- a/src/librustc_infer/traits/query/outlives_bounds.rs
+++ b/src/librustc_trait_selection/traits/query/outlives_bounds.rs
@@ -1,14 +1,25 @@
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::InferCtxt;
 use crate::traits::query::NoSolution;
-use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
+use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine};
 use rustc::ty::{self, Ty};
 use rustc_hir as hir;
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::source_map::Span;
 
 pub use rustc::traits::query::OutlivesBound;
 
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
+pub trait InferCtxtExt<'tcx> {
+    fn implied_outlives_bounds(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        body_id: hir::HirId,
+        ty: Ty<'tcx>,
+        span: Span,
+    ) -> Vec<OutlivesBound<'tcx>>;
+}
+
+impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
     /// Implied bounds are region relationships that we deduce
     /// automatically. The idea is that (e.g.) a caller must check that a
     /// function's argument types are well-formed immediately before
@@ -30,7 +41,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// - `ty`, the type that we are supposed to assume is WF.
     /// - `span`, a span to use when normalizing, hopefully not important,
     ///   might be useful if a `bug!` occurs.
-    pub fn implied_outlives_bounds(
+    fn implied_outlives_bounds(
         &self,
         param_env: ty::ParamEnv<'tcx>,
         body_id: hir::HirId,
@@ -82,22 +93,3 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         result.value
     }
 }
-
-pub fn explicit_outlives_bounds<'tcx>(
-    param_env: ty::ParamEnv<'tcx>,
-) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
-    debug!("explicit_outlives_bounds()");
-    param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate {
-        ty::Predicate::Projection(..)
-        | ty::Predicate::Trait(..)
-        | ty::Predicate::Subtype(..)
-        | ty::Predicate::WellFormed(..)
-        | ty::Predicate::ObjectSafe(..)
-        | ty::Predicate::ClosureKind(..)
-        | ty::Predicate::TypeOutlives(..)
-        | ty::Predicate::ConstEvaluatable(..) => None,
-        ty::Predicate::RegionOutlives(ref data) => data
-            .no_bound_vars()
-            .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
-    })
-}
diff --git a/src/librustc_infer/traits/query/type_op/ascribe_user_type.rs b/src/librustc_trait_selection/traits/query/type_op/ascribe_user_type.rs
index b14b79f0907..b14b79f0907 100644
--- a/src/librustc_infer/traits/query/type_op/ascribe_user_type.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/ascribe_user_type.rs
diff --git a/src/librustc_infer/traits/query/type_op/custom.rs b/src/librustc_trait_selection/traits/query/type_op/custom.rs
index c1c9030b888..915e8ae4a7a 100644
--- a/src/librustc_infer/traits/query/type_op/custom.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/custom.rs
@@ -4,7 +4,9 @@ use std::fmt;
 
 use crate::infer::canonical::query_response;
 use crate::infer::canonical::QueryRegionConstraints;
-use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt};
+use crate::traits::engine::TraitEngineExt as _;
+use crate::traits::{ObligationCause, TraitEngine};
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::source_map::DUMMY_SP;
 use std::rc::Rc;
 
diff --git a/src/librustc_infer/traits/query/type_op/eq.rs b/src/librustc_trait_selection/traits/query/type_op/eq.rs
index 3b6fbc7d8dd..3b6fbc7d8dd 100644
--- a/src/librustc_infer/traits/query/type_op/eq.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/eq.rs
diff --git a/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc_trait_selection/traits/query/type_op/implied_outlives_bounds.rs
index 3dad546872e..3dad546872e 100644
--- a/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/implied_outlives_bounds.rs
diff --git a/src/librustc_infer/traits/query/type_op/mod.rs b/src/librustc_trait_selection/traits/query/type_op/mod.rs
index eb4c0a029e1..1644746c16e 100644
--- a/src/librustc_infer/traits/query/type_op/mod.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/mod.rs
@@ -44,7 +44,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
 /// first canonicalize the key and then invoke the query on the tcx,
 /// which produces the resulting query region constraints.
 ///
-/// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+/// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
 pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
     type QueryResponse: TypeFoldable<'tcx>;
 
diff --git a/src/librustc_infer/traits/query/type_op/normalize.rs b/src/librustc_trait_selection/traits/query/type_op/normalize.rs
index d2eec53bf80..d2eec53bf80 100644
--- a/src/librustc_infer/traits/query/type_op/normalize.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/normalize.rs
diff --git a/src/librustc_infer/traits/query/type_op/outlives.rs b/src/librustc_trait_selection/traits/query/type_op/outlives.rs
index b94948cffd6..b94948cffd6 100644
--- a/src/librustc_infer/traits/query/type_op/outlives.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/outlives.rs
diff --git a/src/librustc_infer/traits/query/type_op/prove_predicate.rs b/src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs
index 8c68f7db9e5..8c68f7db9e5 100644
--- a/src/librustc_infer/traits/query/type_op/prove_predicate.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/prove_predicate.rs
diff --git a/src/librustc_infer/traits/query/type_op/subtype.rs b/src/librustc_trait_selection/traits/query/type_op/subtype.rs
index 053411b0cac..053411b0cac 100644
--- a/src/librustc_infer/traits/query/type_op/subtype.rs
+++ b/src/librustc_trait_selection/traits/query/type_op/subtype.rs
diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_trait_selection/traits/select.rs
index c0d8f3cfd4f..ab3214d8d2d 100644
--- a/src/librustc_infer/traits/select.rs
+++ b/src/librustc_trait_selection/traits/select.rs
@@ -1,17 +1,15 @@
 // ignore-tidy-filelength
 
-//! Candidate selection. See the [rustc guide] for more information on how this works.
+//! Candidate selection. See the [rustc dev guide] for more information on how this works.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html#selection
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
 
 use self::EvaluationResult::*;
 use self::SelectionCandidate::*;
 
 use super::coherence::{self, Conflict};
 use super::project;
-use super::project::{
-    normalize_with_depth, normalize_with_depth_to, Normalized, ProjectionCacheKey,
-};
+use super::project::{normalize_with_depth, normalize_with_depth_to};
 use super::util;
 use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
 use super::wf;
@@ -21,6 +19,7 @@ use super::SelectionResult;
 use super::TraitNotObjectSafe;
 use super::TraitQueryMode;
 use super::{BuiltinDerivedObligation, ImplDerivedObligation, ObligationCauseCode};
+use super::{Normalized, ProjectionCacheKey};
 use super::{ObjectCastObligation, Obligation};
 use super::{ObligationCause, PredicateObligation, TraitObligation};
 use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented};
@@ -34,6 +33,8 @@ use super::{
 };
 
 use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
+use crate::traits::error_reporting::InferCtxtExt;
+use crate::traits::project::ProjectionCacheKeyExt;
 use rustc::dep_graph::{DepKind, DepNodeIndex};
 use rustc::middle::lang_items;
 use rustc::ty::fast_reject;
@@ -95,47 +96,6 @@ pub struct SelectionContext<'cx, 'tcx> {
     query_mode: TraitQueryMode,
 }
 
-#[derive(Clone, Debug)]
-pub enum IntercrateAmbiguityCause {
-    DownstreamCrate { trait_desc: String, self_desc: Option<String> },
-    UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> },
-    ReservationImpl { message: String },
-}
-
-impl IntercrateAmbiguityCause {
-    /// Emits notes when the overlap is caused by complex intercrate ambiguities.
-    /// See #23980 for details.
-    pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
-        err.note(&self.intercrate_ambiguity_hint());
-    }
-
-    pub fn intercrate_ambiguity_hint(&self) -> String {
-        match self {
-            &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
-                    format!(" for type `{}`", ty)
-                } else {
-                    String::new()
-                };
-                format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
-            }
-            &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
-                    format!(" for type `{}`", ty)
-                } else {
-                    String::new()
-                };
-                format!(
-                    "upstream crates may add a new impl of trait `{}`{} \
-                     in future versions",
-                    trait_desc, self_desc
-                )
-            }
-            &IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(),
-        }
-    }
-}
-
 // A stack that walks back up the stack frame.
 struct TraitObligationStack<'prev, 'tcx> {
     obligation: &'prev TraitObligation<'tcx>,
@@ -931,10 +891,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     //
     // The selection process begins by examining all in-scope impls,
     // caller obligations, and so forth and assembling a list of
-    // candidates. See the [rustc guide] for more details.
+    // candidates. See the [rustc dev guide] for more details.
     //
-    // [rustc guide]:
-    // https://rust-lang.github.io/rustc-guide/traits/resolution.html#candidate-assembly
+    // [rustc dev guide]:
+    // https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
 
     fn candidate_from_obligation<'o>(
         &mut self,
@@ -2447,10 +2407,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     //
     // Confirmation unifies the output type parameters of the trait
     // with the values found in the obligation, possibly yielding a
-    // type error.  See the [rustc guide] for more details.
+    // type error.  See the [rustc dev guide] for more details.
     //
-    // [rustc guide]:
-    // https://rust-lang.github.io/rustc-guide/traits/resolution.html#confirmation
+    // [rustc dev guide]:
+    // https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
 
     fn confirm_candidate(
         &mut self,
@@ -3506,9 +3466,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     }
 }
 
-impl<'tcx> TraitObligation<'tcx> {
+trait TraitObligationExt<'tcx> {
+    fn derived_cause(
+        &self,
+        variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
+    ) -> ObligationCause<'tcx>;
+}
+
+impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> {
     #[allow(unused_comparisons)]
-    pub fn derived_cause(
+    fn derived_cause(
         &self,
         variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
     ) -> ObligationCause<'tcx> {
diff --git a/src/librustc_infer/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs
index ee1c737c208..b763851b86e 100644
--- a/src/librustc_infer/traits/specialize/mod.rs
+++ b/src/librustc_trait_selection/traits/specialize/mod.rs
@@ -4,10 +4,10 @@
 //! At the moment, this implementation support only the simple "chain" rule:
 //! If any two impls overlap, one must be a strict subset of the other.
 //!
-//! See the [rustc guide] for a bit more detail on how specialization
+//! See the [rustc dev guide] for a bit more detail on how specialization
 //! fits together with the rest of the trait machinery.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
 
 pub mod specialization_graph;
 use specialization_graph::GraphExt;
@@ -130,24 +130,27 @@ pub fn find_associated_item<'tcx>(
     let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
     let trait_def = tcx.trait_def(trait_def_id);
 
-    let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id);
-    match ancestors.leaf_def(tcx, item.ident, item.kind) {
-        Some(node_item) => {
-            let substs = tcx.infer_ctxt().enter(|infcx| {
-                let param_env = param_env.with_reveal_all();
-                let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
-                let substs = translate_substs(
-                    &infcx,
-                    param_env,
-                    impl_data.impl_def_id,
-                    substs,
-                    node_item.node,
-                );
-                infcx.tcx.erase_regions(&substs)
-            });
-            (node_item.item.def_id, substs)
+    if let Ok(ancestors) = trait_def.ancestors(tcx, impl_data.impl_def_id) {
+        match ancestors.leaf_def(tcx, item.ident, item.kind) {
+            Some(node_item) => {
+                let substs = tcx.infer_ctxt().enter(|infcx| {
+                    let param_env = param_env.with_reveal_all();
+                    let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
+                    let substs = translate_substs(
+                        &infcx,
+                        param_env,
+                        impl_data.impl_def_id,
+                        substs,
+                        node_item.node,
+                    );
+                    infcx.tcx.erase_regions(&substs)
+                });
+                (node_item.item.def_id, substs)
+            }
+            None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id),
         }
-        None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id),
+    } else {
+        (item.def_id, substs)
     }
 }
 
@@ -161,7 +164,9 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
 
     // The feature gate should prevent introducing new specializations, but not
     // taking advantage of upstream ones.
-    if !tcx.features().specialization && (impl1_def_id.is_local() || impl2_def_id.is_local()) {
+    let features = tcx.features();
+    let specialization_enabled = features.specialization || features.min_specialization;
+    if !specialization_enabled && (impl1_def_id.is_local() || impl2_def_id.is_local()) {
         return false;
     }
 
@@ -380,6 +385,7 @@ pub(super) fn specialization_graph_provider(
 
                 match used_to_be_allowed {
                     None => {
+                        sg.has_errored = true;
                         let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
                         decorate(LintDiagnosticBuilder::new(err));
                     }
@@ -413,12 +419,7 @@ pub(super) fn specialization_graph_provider(
 fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
     use std::fmt::Write;
 
-    let trait_ref = if let Some(tr) = tcx.impl_trait_ref(impl_def_id) {
-        tr
-    } else {
-        return None;
-    };
-
+    let trait_ref = tcx.impl_trait_ref(impl_def_id)?;
     let mut w = "impl".to_owned();
 
     let substs = InternalSubsts::identity_for_item(tcx, impl_def_id);
diff --git a/src/librustc_infer/traits/specialize/specialization_graph.rs b/src/librustc_trait_selection/traits/specialize/specialization_graph.rs
index 17d4a22b9dd..17d4a22b9dd 100644
--- a/src/librustc_infer/traits/specialize/specialization_graph.rs
+++ b/src/librustc_trait_selection/traits/specialize/specialization_graph.rs
diff --git a/src/librustc_infer/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs
index 60682f58129..60682f58129 100644
--- a/src/librustc_infer/traits/structural_match.rs
+++ b/src/librustc_trait_selection/traits/structural_match.rs
diff --git a/src/librustc_trait_selection/traits/util.rs b/src/librustc_trait_selection/traits/util.rs
new file mode 100644
index 00000000000..cd4595e76cc
--- /dev/null
+++ b/src/librustc_trait_selection/traits/util.rs
@@ -0,0 +1,675 @@
+use rustc_errors::DiagnosticBuilder;
+use rustc_span::Span;
+use smallvec::smallvec;
+use smallvec::SmallVec;
+
+use rustc::ty::outlives::Component;
+use rustc::ty::subst::{GenericArg, Subst, SubstsRef};
+use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+
+use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
+
+fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+    match *pred {
+        ty::Predicate::Trait(ref data, constness) => {
+            ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness)
+        }
+
+        ty::Predicate::RegionOutlives(ref data) => {
+            ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data))
+        }
+
+        ty::Predicate::TypeOutlives(ref data) => {
+            ty::Predicate::TypeOutlives(tcx.anonymize_late_bound_regions(data))
+        }
+
+        ty::Predicate::Projection(ref data) => {
+            ty::Predicate::Projection(tcx.anonymize_late_bound_regions(data))
+        }
+
+        ty::Predicate::WellFormed(data) => ty::Predicate::WellFormed(data),
+
+        ty::Predicate::ObjectSafe(data) => ty::Predicate::ObjectSafe(data),
+
+        ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind)
+        }
+
+        ty::Predicate::Subtype(ref data) => {
+            ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data))
+        }
+
+        ty::Predicate::ConstEvaluatable(def_id, substs) => {
+            ty::Predicate::ConstEvaluatable(def_id, substs)
+        }
+    }
+}
+
+struct PredicateSet<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    set: FxHashSet<ty::Predicate<'tcx>>,
+}
+
+impl PredicateSet<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>) -> Self {
+        Self { tcx, set: Default::default() }
+    }
+
+    fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
+        // We have to be careful here because we want
+        //
+        //    for<'a> Foo<&'a int>
+        //
+        // and
+        //
+        //    for<'b> Foo<&'b int>
+        //
+        // to be considered equivalent. So normalize all late-bound
+        // regions before we throw things into the underlying set.
+        self.set.insert(anonymize_predicate(self.tcx, pred))
+    }
+}
+
+impl<T: AsRef<ty::Predicate<'tcx>>> Extend<T> for PredicateSet<'tcx> {
+    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
+        for pred in iter {
+            self.insert(pred.as_ref());
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// `Elaboration` iterator
+///////////////////////////////////////////////////////////////////////////
+
+/// "Elaboration" is the process of identifying all the predicates that
+/// are implied by a source predicate. Currently, this basically means
+/// walking the "supertraits" and other similar assumptions. For example,
+/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
+/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
+/// `T: Foo`, then we know that `T: 'static`.
+pub struct Elaborator<'tcx> {
+    stack: Vec<ty::Predicate<'tcx>>,
+    visited: PredicateSet<'tcx>,
+}
+
+pub fn elaborate_trait_ref<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> Elaborator<'tcx> {
+    elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
+}
+
+pub fn elaborate_trait_refs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+) -> Elaborator<'tcx> {
+    let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
+    elaborate_predicates(tcx, predicates)
+}
+
+pub fn elaborate_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mut predicates: Vec<ty::Predicate<'tcx>>,
+) -> Elaborator<'tcx> {
+    let mut visited = PredicateSet::new(tcx);
+    predicates.retain(|pred| visited.insert(pred));
+    Elaborator { stack: predicates, visited }
+}
+
+impl Elaborator<'tcx> {
+    pub fn filter_to_traits(self) -> FilterToTraits<Self> {
+        FilterToTraits::new(self)
+    }
+
+    fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
+        let tcx = self.visited.tcx;
+        match *predicate {
+            ty::Predicate::Trait(ref data, _) => {
+                // Get predicates declared on the trait.
+                let predicates = tcx.super_predicates_of(data.def_id());
+
+                let predicates = predicates
+                    .predicates
+                    .iter()
+                    .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref()));
+                debug!("super_predicates: data={:?} predicates={:?}", data, predicates.clone());
+
+                // Only keep those bounds that we haven't already seen.
+                // This is necessary to prevent infinite recursion in some
+                // cases. One common case is when people define
+                // `trait Sized: Sized { }` rather than `trait Sized { }`.
+                let visited = &mut self.visited;
+                let predicates = predicates.filter(|pred| visited.insert(pred));
+
+                self.stack.extend(predicates);
+            }
+            ty::Predicate::WellFormed(..) => {
+                // Currently, we do not elaborate WF predicates,
+                // although we easily could.
+            }
+            ty::Predicate::ObjectSafe(..) => {
+                // Currently, we do not elaborate object-safe
+                // predicates.
+            }
+            ty::Predicate::Subtype(..) => {
+                // Currently, we do not "elaborate" predicates like `X <: Y`,
+                // though conceivably we might.
+            }
+            ty::Predicate::Projection(..) => {
+                // Nothing to elaborate in a projection predicate.
+            }
+            ty::Predicate::ClosureKind(..) => {
+                // Nothing to elaborate when waiting for a closure's kind to be inferred.
+            }
+            ty::Predicate::ConstEvaluatable(..) => {
+                // Currently, we do not elaborate const-evaluatable
+                // predicates.
+            }
+            ty::Predicate::RegionOutlives(..) => {
+                // Nothing to elaborate from `'a: 'b`.
+            }
+            ty::Predicate::TypeOutlives(ref data) => {
+                // We know that `T: 'a` for some type `T`. We can
+                // often elaborate this. For example, if we know that
+                // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
+                // we know `&'a U: 'b`, then we know that `'a: 'b` and
+                // `U: 'b`.
+                //
+                // We can basically ignore bound regions here. So for
+                // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
+                // `'a: 'b`.
+
+                // Ignore `for<'a> T: 'a` -- we might in the future
+                // consider this as evidence that `T: 'static`, but
+                // I'm a bit wary of such constructions and so for now
+                // I want to be conservative. --nmatsakis
+                let ty_max = data.skip_binder().0;
+                let r_min = data.skip_binder().1;
+                if r_min.is_late_bound() {
+                    return;
+                }
+
+                let visited = &mut self.visited;
+                let mut components = smallvec![];
+                tcx.push_outlives_components(ty_max, &mut components);
+                self.stack.extend(
+                    components
+                        .into_iter()
+                        .filter_map(|component| match component {
+                            Component::Region(r) => {
+                                if r.is_late_bound() {
+                                    None
+                                } else {
+                                    Some(ty::Predicate::RegionOutlives(ty::Binder::dummy(
+                                        ty::OutlivesPredicate(r, r_min),
+                                    )))
+                                }
+                            }
+
+                            Component::Param(p) => {
+                                let ty = tcx.mk_ty_param(p.index, p.name);
+                                Some(ty::Predicate::TypeOutlives(ty::Binder::dummy(
+                                    ty::OutlivesPredicate(ty, r_min),
+                                )))
+                            }
+
+                            Component::UnresolvedInferenceVariable(_) => None,
+
+                            Component::Projection(_) | Component::EscapingProjection(_) => {
+                                // We can probably do more here. This
+                                // corresponds to a case like `<T as
+                                // Foo<'a>>::U: 'b`.
+                                None
+                            }
+                        })
+                        .filter(|p| visited.insert(p)),
+                );
+            }
+        }
+    }
+}
+
+impl Iterator for Elaborator<'tcx> {
+    type Item = ty::Predicate<'tcx>;
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.stack.len(), None)
+    }
+
+    fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
+        // Extract next item from top-most stack frame, if any.
+        if let Some(pred) = self.stack.pop() {
+            self.elaborate(&pred);
+            Some(pred)
+        } else {
+            None
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Supertrait iterator
+///////////////////////////////////////////////////////////////////////////
+
+pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
+
+pub fn supertraits<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> Supertraits<'tcx> {
+    elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
+}
+
+pub fn transitive_bounds<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+) -> Supertraits<'tcx> {
+    elaborate_trait_refs(tcx, bounds).filter_to_traits()
+}
+
+///////////////////////////////////////////////////////////////////////////
+// `TraitAliasExpander` iterator
+///////////////////////////////////////////////////////////////////////////
+
+/// "Trait alias expansion" is the process of expanding a sequence of trait
+/// references into another sequence by transitively following all trait
+/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias
+/// `trait Foo = Bar + Sync;`, and another trait alias
+/// `trait Bar = Read + Write`, then the bounds would expand to
+/// `Read + Write + Sync + Send`.
+/// Expansion is done via a DFS (depth-first search), and the `visited` field
+/// is used to avoid cycles.
+pub struct TraitAliasExpander<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    stack: Vec<TraitAliasExpansionInfo<'tcx>>,
+}
+
+/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
+#[derive(Debug, Clone)]
+pub struct TraitAliasExpansionInfo<'tcx> {
+    pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>,
+}
+
+impl<'tcx> TraitAliasExpansionInfo<'tcx> {
+    fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
+        Self { path: smallvec![(trait_ref, span)] }
+    }
+
+    /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
+    /// trait aliases.
+    pub fn label_with_exp_info(
+        &self,
+        diag: &mut DiagnosticBuilder<'_>,
+        top_label: &str,
+        use_desc: &str,
+    ) {
+        diag.span_label(self.top().1, top_label);
+        if self.path.len() > 1 {
+            for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
+                diag.span_label(*sp, format!("referenced here ({})", use_desc));
+            }
+        }
+        diag.span_label(
+            self.bottom().1,
+            format!("trait alias used in trait object type ({})", use_desc),
+        );
+    }
+
+    pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> {
+        &self.top().0
+    }
+
+    pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
+        self.path.last().unwrap()
+    }
+
+    pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
+        self.path.first().unwrap()
+    }
+
+    fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
+        let mut path = self.path.clone();
+        path.push((trait_ref, span));
+
+        Self { path }
+    }
+}
+
+pub fn expand_trait_aliases<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_refs: impl IntoIterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
+) -> TraitAliasExpander<'tcx> {
+    let items: Vec<_> = trait_refs
+        .into_iter()
+        .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span))
+        .collect();
+    TraitAliasExpander { tcx, stack: items }
+}
+
+impl<'tcx> TraitAliasExpander<'tcx> {
+    /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item`
+    /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`.
+    /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
+    /// trait alias.
+    /// The return value indicates whether `item` should be yielded to the user.
+    fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
+        let tcx = self.tcx;
+        let trait_ref = item.trait_ref();
+        let pred = trait_ref.without_const().to_predicate();
+
+        debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
+
+        // Don't recurse if this bound is not a trait alias.
+        let is_alias = tcx.is_trait_alias(trait_ref.def_id());
+        if !is_alias {
+            return true;
+        }
+
+        // Don't recurse if this trait alias is already on the stack for the DFS search.
+        let anon_pred = anonymize_predicate(tcx, &pred);
+        if item.path.iter().rev().skip(1).any(|(tr, _)| {
+            anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred
+        }) {
+            return false;
+        }
+
+        // Get components of trait alias.
+        let predicates = tcx.super_predicates_of(trait_ref.def_id());
+
+        let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
+            pred.subst_supertrait(tcx, &trait_ref)
+                .to_opt_poly_trait_ref()
+                .map(|trait_ref| item.clone_and_push(trait_ref, *span))
+        });
+        debug!("expand_trait_aliases: items={:?}", items.clone());
+
+        self.stack.extend(items);
+
+        false
+    }
+}
+
+impl<'tcx> Iterator for TraitAliasExpander<'tcx> {
+    type Item = TraitAliasExpansionInfo<'tcx>;
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.stack.len(), None)
+    }
+
+    fn next(&mut self) -> Option<TraitAliasExpansionInfo<'tcx>> {
+        while let Some(item) = self.stack.pop() {
+            if self.expand(&item) {
+                return Some(item);
+            }
+        }
+        None
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Iterator over def-IDs of supertraits
+///////////////////////////////////////////////////////////////////////////
+
+pub struct SupertraitDefIds<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    stack: Vec<DefId>,
+    visited: FxHashSet<DefId>,
+}
+
+pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> {
+    SupertraitDefIds {
+        tcx,
+        stack: vec![trait_def_id],
+        visited: Some(trait_def_id).into_iter().collect(),
+    }
+}
+
+impl Iterator for SupertraitDefIds<'tcx> {
+    type Item = DefId;
+
+    fn next(&mut self) -> Option<DefId> {
+        let def_id = self.stack.pop()?;
+        let predicates = self.tcx.super_predicates_of(def_id);
+        let visited = &mut self.visited;
+        self.stack.extend(
+            predicates
+                .predicates
+                .iter()
+                .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref())
+                .map(|trait_ref| trait_ref.def_id())
+                .filter(|&super_def_id| visited.insert(super_def_id)),
+        );
+        Some(def_id)
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Other
+///////////////////////////////////////////////////////////////////////////
+
+/// A filter around an iterator of predicates that makes it yield up
+/// just trait references.
+pub struct FilterToTraits<I> {
+    base_iterator: I,
+}
+
+impl<I> FilterToTraits<I> {
+    fn new(base: I) -> FilterToTraits<I> {
+        FilterToTraits { base_iterator: base }
+    }
+}
+
+impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
+    type Item = ty::PolyTraitRef<'tcx>;
+
+    fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
+        while let Some(pred) = self.base_iterator.next() {
+            if let ty::Predicate::Trait(data, _) = pred {
+                return Some(data.to_poly_trait_ref());
+            }
+        }
+        None
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (_, upper) = self.base_iterator.size_hint();
+        (0, upper)
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Other
+///////////////////////////////////////////////////////////////////////////
+
+/// Instantiate all bound parameters of the impl with the given substs,
+/// returning the resulting trait ref and all obligations that arise.
+/// The obligations are closed under normalization.
+pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
+    selcx: &mut SelectionContext<'a, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    impl_def_id: DefId,
+    impl_substs: SubstsRef<'tcx>,
+) -> (ty::TraitRef<'tcx>, Vec<PredicateObligation<'tcx>>) {
+    let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
+    let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs);
+    let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
+        super::normalize(selcx, param_env, ObligationCause::dummy(), &impl_trait_ref);
+
+    let predicates = selcx.tcx().predicates_of(impl_def_id);
+    let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
+    let Normalized { value: predicates, obligations: normalization_obligations2 } =
+        super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates);
+    let impl_obligations =
+        predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates);
+
+    let impl_obligations: Vec<_> = impl_obligations
+        .into_iter()
+        .chain(normalization_obligations1)
+        .chain(normalization_obligations2)
+        .collect();
+
+    (impl_trait_ref, impl_obligations)
+}
+
+/// See [`super::obligations_for_generics`].
+pub fn predicates_for_generics<'tcx>(
+    cause: ObligationCause<'tcx>,
+    recursion_depth: usize,
+    param_env: ty::ParamEnv<'tcx>,
+    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
+) -> Vec<PredicateObligation<'tcx>> {
+    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
+
+    generic_bounds
+        .predicates
+        .iter()
+        .map(|&predicate| Obligation {
+            cause: cause.clone(),
+            recursion_depth,
+            param_env,
+            predicate,
+        })
+        .collect()
+}
+
+pub fn predicate_for_trait_ref<'tcx>(
+    cause: ObligationCause<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
+    recursion_depth: usize,
+) -> PredicateObligation<'tcx> {
+    Obligation {
+        cause,
+        param_env,
+        recursion_depth,
+        predicate: trait_ref.without_const().to_predicate(),
+    }
+}
+
+pub fn predicate_for_trait_def(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    trait_def_id: DefId,
+    recursion_depth: usize,
+    self_ty: Ty<'tcx>,
+    params: &[GenericArg<'tcx>],
+) -> PredicateObligation<'tcx> {
+    let trait_ref =
+        ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) };
+    predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
+}
+
+/// Casts a trait reference into a reference to one of its super
+/// traits; returns `None` if `target_trait_def_id` is not a
+/// supertrait.
+pub fn upcast_choices(
+    tcx: TyCtxt<'tcx>,
+    source_trait_ref: ty::PolyTraitRef<'tcx>,
+    target_trait_def_id: DefId,
+) -> Vec<ty::PolyTraitRef<'tcx>> {
+    if source_trait_ref.def_id() == target_trait_def_id {
+        return vec![source_trait_ref]; // Shortcut the most common case.
+    }
+
+    supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
+}
+
+/// Given a trait `trait_ref`, returns the number of vtable entries
+/// that come from `trait_ref`, excluding its supertraits. Used in
+/// computing the vtable base for an upcast trait of a trait object.
+pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
+    let mut entries = 0;
+    // Count number of methods and add them to the total offset.
+    // Skip over associated types and constants.
+    for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
+        if trait_item.kind == ty::AssocKind::Method {
+            entries += 1;
+        }
+    }
+    entries
+}
+
+/// Given an upcast trait object described by `object`, returns the
+/// index of the method `method_def_id` (which should be part of
+/// `object.upcast_trait_ref`) within the vtable for `object`.
+pub fn get_vtable_index_of_object_method<N>(
+    tcx: TyCtxt<'tcx>,
+    object: &super::VtableObjectData<'tcx, N>,
+    method_def_id: DefId,
+) -> usize {
+    // Count number of methods preceding the one we are selecting and
+    // add them to the total offset.
+    // Skip over associated types and constants.
+    let mut entries = object.vtable_base;
+    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
+        if trait_item.def_id == method_def_id {
+            // The item with the ID we were given really ought to be a method.
+            assert_eq!(trait_item.kind, ty::AssocKind::Method);
+            return entries;
+        }
+        if trait_item.kind == ty::AssocKind::Method {
+            entries += 1;
+        }
+    }
+
+    bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
+}
+
+pub fn closure_trait_ref_and_return_type(
+    tcx: TyCtxt<'tcx>,
+    fn_trait_def_id: DefId,
+    self_ty: Ty<'tcx>,
+    sig: ty::PolyFnSig<'tcx>,
+    tuple_arguments: TupleArgumentsFlag,
+) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> {
+    let arguments_tuple = match tuple_arguments {
+        TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
+        TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
+    };
+    let trait_ref = ty::TraitRef {
+        def_id: fn_trait_def_id,
+        substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
+    };
+    ty::Binder::bind((trait_ref, sig.skip_binder().output()))
+}
+
+pub fn generator_trait_ref_and_outputs(
+    tcx: TyCtxt<'tcx>,
+    fn_trait_def_id: DefId,
+    self_ty: Ty<'tcx>,
+    sig: ty::PolyGenSig<'tcx>,
+) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
+    let trait_ref = ty::TraitRef {
+        def_id: fn_trait_def_id,
+        substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]),
+    };
+    ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
+}
+
+pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool {
+    match tcx.hir().as_local_hir_id(node_item_def_id) {
+        Some(hir_id) => {
+            let item = tcx.hir().expect_item(hir_id);
+            if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
+                defaultness.is_default()
+            } else {
+                false
+            }
+        }
+        None => tcx.impl_defaultness(node_item_def_id).is_default(),
+    }
+}
+
+pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
+    assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id())
+}
+
+pub enum TupleArgumentsFlag {
+    Yes,
+    No,
+}
diff --git a/src/librustc_infer/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs
index 980a3f04781..b69c5bdce2a 100644
--- a/src/librustc_infer/traits/wf.rs
+++ b/src/librustc_trait_selection/traits/wf.rs
@@ -1,5 +1,5 @@
-use crate::infer::opaque_types::required_region_bounds;
 use crate::infer::InferCtxt;
+use crate::opaque_types::required_region_bounds;
 use crate::traits::{self, AssocTypeBoundData};
 use rustc::middle::lang_items;
 use rustc::ty::subst::SubstsRef;
diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml
index 0dc3ad29833..5e33efb1cf9 100644
--- a/src/librustc_traits/Cargo.toml
+++ b/src/librustc_traits/Cargo.toml
@@ -19,3 +19,4 @@ rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_infer = { path = "../librustc_infer" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 2f854c045e5..b13a7a3acb1 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -5,11 +5,17 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::query::dropck_outlives::trivial_dropck_outlives;
-use rustc_infer::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint};
-use rustc_infer::traits::query::{CanonicalTyGoal, NoSolution};
-use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
+use rustc_trait_selection::traits::query::dropck_outlives::{
+    DropckOutlivesResult, DtorckConstraint,
+};
+use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
+use rustc_trait_selection::traits::{
+    Normalized, ObligationCause, TraitEngine, TraitEngineExt as _,
+};
 
 crate fn provide(p: &mut Providers<'_>) {
     *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p };
diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs
index 4cf5b66b3cb..87895d8e384 100644
--- a/src/librustc_traits/evaluate_obligation.rs
+++ b/src/librustc_traits/evaluate_obligation.rs
@@ -1,11 +1,11 @@
 use rustc::ty::query::Providers;
 use rustc::ty::{ParamEnvAnd, TyCtxt};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::query::CanonicalPredicateGoal;
-use rustc_infer::traits::{
+use rustc_span::source_map::DUMMY_SP;
+use rustc_trait_selection::traits::query::CanonicalPredicateGoal;
+use rustc_trait_selection::traits::{
     EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode,
 };
-use rustc_span::source_map::DUMMY_SP;
 
 crate fn provide(p: &mut Providers<'_>) {
     *p = Providers { evaluate_obligation, ..*p };
diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs
index 1b6b8735651..4505a1e59d9 100644
--- a/src/librustc_traits/implied_outlives_bounds.rs
+++ b/src/librustc_traits/implied_outlives_bounds.rs
@@ -7,12 +7,14 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_hir as hir;
 use rustc_infer::infer::canonical::{self, Canonical};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::query::outlives_bounds::OutlivesBound;
-use rustc_infer::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
-use rustc_infer::traits::wf;
-use rustc_infer::traits::FulfillmentContext;
-use rustc_infer::traits::{TraitEngine, TraitEngineExt};
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::source_map::DUMMY_SP;
+use rustc_trait_selection::infer::InferCtxtBuilderExt;
+use rustc_trait_selection::traits::query::outlives_bounds::OutlivesBound;
+use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
+use rustc_trait_selection::traits::wf;
+use rustc_trait_selection::traits::FulfillmentContext;
+use rustc_trait_selection::traits::TraitEngine;
 use smallvec::{smallvec, SmallVec};
 
 crate fn provide(p: &mut Providers<'_>) {
diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs
index 0e26e9461f4..69d0bd09296 100644
--- a/src/librustc_traits/lowering/environment.rs
+++ b/src/librustc_traits/lowering/environment.rs
@@ -185,12 +185,12 @@ crate fn environment(tcx: TyCtxt<'_>, def_id: DefId) -> Environment<'_> {
 
     let node_kind = match node {
         Node::TraitItem(item) => match item.kind {
-            TraitItemKind::Method(..) => NodeKind::Fn,
+            TraitItemKind::Fn(..) => NodeKind::Fn,
             _ => NodeKind::Other,
         },
 
         Node::ImplItem(item) => match item.kind {
-            ImplItemKind::Method(..) => NodeKind::Fn,
+            ImplItemKind::Fn(..) => NodeKind::Fn,
             _ => NodeKind::Other,
         },
 
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index 97b81c224d5..3a0c36a84ae 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -108,13 +108,13 @@ impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> {
     }
 }
 
-/// Used for implied bounds related rules (see rustc guide).
+/// Used for implied bounds related rules (see rustc dev guide).
 trait IntoFromEnvGoal {
     /// Transforms an existing goal into a `FromEnv` goal.
     fn into_from_env_goal(self) -> Self;
 }
 
-/// Used for well-formedness related rules (see rustc guide).
+/// Used for well-formedness related rules (see rustc dev guide).
 trait IntoWellFormedGoal {
     /// Transforms an existing goal into a `WellFormed` goal.
     fn into_well_formed_goal(self) -> Self;
@@ -178,7 +178,7 @@ crate fn program_clauses_for(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
 fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
     // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
 
-    // Rule Implemented-From-Env (see rustc guide)
+    // Rule Implemented-From-Env (see rustc dev guide)
     //
     // ```
     // forall<Self, P1..Pn> {
@@ -282,7 +282,7 @@ fn program_clauses_for_impl(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
         return List::empty();
     }
 
-    // Rule Implemented-From-Impl (see rustc guide)
+    // Rule Implemented-From-Impl (see rustc dev guide)
     //
     // `impl<P0..Pn> Trait<A1..An> for A0 where WC { .. }`
     //
@@ -501,7 +501,7 @@ pub fn program_clauses_for_associated_type_def(tcx: TyCtxt<'_>, item_id: DefId)
 }
 
 pub fn program_clauses_for_associated_type_value(tcx: TyCtxt<'_>, item_id: DefId) -> Clauses<'_> {
-    // Rule Normalize-From-Impl (see rustc guide)
+    // Rule Normalize-From-Impl (see rustc dev guide)
     //
     // ```
     // impl<P0..Pn> Trait<A1..An> for A0 {
@@ -603,8 +603,8 @@ impl ClauseDumper<'tcx> {
 impl Visitor<'tcx> for ClauseDumper<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs
index 4e5f20d80b0..c2fb237a05b 100644
--- a/src/librustc_traits/normalize_erasing_regions.rs
+++ b/src/librustc_traits/normalize_erasing_regions.rs
@@ -2,7 +2,8 @@ use rustc::traits::query::NoSolution;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::{Normalized, ObligationCause};
+use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::{Normalized, ObligationCause};
 use std::sync::atomic::Ordering;
 
 crate fn provide(p: &mut Providers<'_>) {
diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs
index b5678956347..57abff769de 100644
--- a/src/librustc_traits/normalize_projection_ty.rs
+++ b/src/librustc_traits/normalize_projection_ty.rs
@@ -3,11 +3,13 @@ use rustc::ty::{ParamEnvAnd, TyCtxt};
 use rustc_hir as hir;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::query::{
+use rustc_infer::traits::TraitEngineExt as _;
+use rustc_span::DUMMY_SP;
+use rustc_trait_selection::infer::InferCtxtBuilderExt;
+use rustc_trait_selection::traits::query::{
     normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution,
 };
-use rustc_infer::traits::{self, ObligationCause, SelectionContext, TraitEngineExt};
-use rustc_span::DUMMY_SP;
+use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext};
 use std::sync::atomic::Ordering;
 
 crate fn provide(p: &mut Providers<'_>) {
diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs
index 41181338061..e174c040e0d 100644
--- a/src/librustc_traits/type_op.rs
+++ b/src/librustc_traits/type_op.rs
@@ -8,14 +8,18 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::query::type_op::ascribe_user_type::AscribeUserType;
-use rustc_infer::traits::query::type_op::eq::Eq;
-use rustc_infer::traits::query::type_op::normalize::Normalize;
-use rustc_infer::traits::query::type_op::prove_predicate::ProvePredicate;
-use rustc_infer::traits::query::type_op::subtype::Subtype;
-use rustc_infer::traits::query::{Fallible, NoSolution};
-use rustc_infer::traits::{Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt};
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::DUMMY_SP;
+use rustc_trait_selection::infer::InferCtxtBuilderExt;
+use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::query::type_op::ascribe_user_type::AscribeUserType;
+use rustc_trait_selection::traits::query::type_op::eq::Eq;
+use rustc_trait_selection::traits::query::type_op::normalize::Normalize;
+use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
+use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
+use rustc_trait_selection::traits::query::{Fallible, NoSolution};
+use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine};
 use std::fmt;
 
 crate fn provide(p: &mut Providers<'_>) {
diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml
index 6e64df3492b..cf0b4b82eea 100644
--- a/src/librustc_ty/Cargo.toml
+++ b/src/librustc_ty/Cargo.toml
@@ -15,4 +15,6 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_infer = { path = "../librustc_infer" }
 rustc_span = { path = "../librustc_span" }
+rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
diff --git a/src/librustc_ty/common_traits.rs b/src/librustc_ty/common_traits.rs
index e0ce6ad23a6..311ba383f30 100644
--- a/src/librustc_ty/common_traits.rs
+++ b/src/librustc_ty/common_traits.rs
@@ -3,8 +3,8 @@
 use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits;
 use rustc_span::DUMMY_SP;
+use rustc_trait_selection::traits;
 
 fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
     is_item_raw(tcx, query, lang_items::CopyTraitLangItem)
diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs
index 8b1ba57e819..a5abe7b6413 100644
--- a/src/librustc_ty/instance.rs
+++ b/src/librustc_ty/instance.rs
@@ -1,8 +1,9 @@
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Instance, TyCtxt, TypeFoldable};
 use rustc_hir::def_id::DefId;
-use rustc_infer::traits;
+use rustc_span::sym;
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits;
 
 use log::debug;
 
@@ -31,21 +32,26 @@ pub fn resolve_instance<'tcx>(
                 debug!(" => intrinsic");
                 ty::InstanceDef::Intrinsic(def_id)
             }
-            _ => {
-                if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
-                    let ty = substs.type_at(0);
-                    if ty.needs_drop(tcx, param_env.with_reveal_all()) {
-                        debug!(" => nontrivial drop glue");
-                        ty::InstanceDef::DropGlue(def_id, Some(ty))
-                    } else {
-                        debug!(" => trivial drop glue");
-                        ty::InstanceDef::DropGlue(def_id, None)
+            ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
+                let ty = substs.type_at(0);
+
+                if ty.needs_drop(tcx, param_env) {
+                    // `DropGlue` requires a monomorphic aka concrete type.
+                    if ty.needs_subst() {
+                        return None;
                     }
+
+                    debug!(" => nontrivial drop glue");
+                    ty::InstanceDef::DropGlue(def_id, Some(ty))
                 } else {
-                    debug!(" => free item");
-                    ty::InstanceDef::Item(def_id)
+                    debug!(" => trivial drop glue");
+                    ty::InstanceDef::DropGlue(def_id, None)
                 }
             }
+            _ => {
+                debug!(" => free item");
+                ty::InstanceDef::Item(def_id)
+            }
         };
         Some(Instance { def, substs })
     };
@@ -113,20 +119,44 @@ fn resolve_associated_item<'tcx>(
                 trait_closure_kind,
             ))
         }
-        traits::VtableFnPointer(ref data) => Some(Instance {
-            def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
-            substs: rcvr_substs,
-        }),
+        traits::VtableFnPointer(ref data) => {
+            // `FnPtrShim` requires a monomorphic aka concrete type.
+            if data.fn_ty.needs_subst() {
+                return None;
+            }
+
+            Some(Instance {
+                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
+                substs: rcvr_substs,
+            })
+        }
         traits::VtableObject(ref data) => {
             let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
             Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
         }
         traits::VtableBuiltin(..) => {
-            if tcx.lang_items().clone_trait().is_some() {
-                Some(Instance {
-                    def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
-                    substs: rcvr_substs,
-                })
+            if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {
+                // FIXME(eddyb) use lang items for methods instead of names.
+                let name = tcx.item_name(def_id);
+                if name == sym::clone {
+                    let self_ty = trait_ref.self_ty();
+
+                    // `CloneShim` requires a monomorphic aka concrete type.
+                    if self_ty.needs_subst() {
+                        return None;
+                    }
+
+                    Some(Instance {
+                        def: ty::InstanceDef::CloneShim(def_id, self_ty),
+                        substs: rcvr_substs,
+                    })
+                } else {
+                    assert_eq!(name, sym::clone_from);
+
+                    // Use the default `fn clone_from` from `trait Clone`.
+                    let substs = tcx.erase_regions(&rcvr_substs);
+                    Some(ty::Instance::new(def_id, substs))
+                }
             } else {
                 None
             }
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
index 6bc29d0493e..4b522997537 100644
--- a/src/librustc_ty/ty.rs
+++ b/src/librustc_ty/ty.rs
@@ -1,13 +1,13 @@
 use rustc::hir::map as hir_map;
-use rustc::session::CrateDisambiguator;
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc_infer::traits;
+use rustc_session::CrateDisambiguator;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
 
 fn sized_constraint_for_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -210,7 +210,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
     }
 }
 
-fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::AssociatedItems {
+fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AssociatedItems {
     let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
     tcx.arena.alloc(ty::AssociatedItems::new(items))
 }
@@ -273,8 +273,7 @@ fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
 }
 
 fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.hir().crate_hash
+    tcx.index_hir(crate_num).crate_hash
 }
 
 fn instance_def_size_estimate<'tcx>(
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
index 51a9b259c8f..e61a36f844f 100644
--- a/src/librustc_typeck/Cargo.toml
+++ b/src/librustc_typeck/Cargo.toml
@@ -19,8 +19,10 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
+rustc_session = { path = "../librustc_session" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_ast = { path = "../librustc_ast" }
 rustc_span = { path = "../librustc_span" }
 rustc_index = { path = "../librustc_index" }
 rustc_infer = { path = "../librustc_infer" }
+rustc_trait_selection = { path = "../librustc_trait_selection" }
diff --git a/src/librustc_typeck/README.md b/src/librustc_typeck/README.md
index fdcbd935524..b61dbd8c964 100644
--- a/src/librustc_typeck/README.md
+++ b/src/librustc_typeck/README.md
@@ -1,5 +1,5 @@
 For high-level intro to how type checking works in rustc, see the
-[type checking] chapter of the [rustc guide].
+[type checking] chapter of the [rustc dev guide].
 
-[type checking]: https://rust-lang.github.io/rustc-guide/type-checking.html
-[rustc guide]: https://rust-lang.github.io/rustc-guide/
+[type checking]: https://rustc-dev-guide.rust-lang.org/type-checking.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index c3cf0cdc61d..9a8d161572b 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -6,13 +6,10 @@
 // ignore-tidy-filelength
 
 use crate::collect::PlaceholderHirTyCollector;
-use crate::lint;
 use crate::middle::lang_items::SizedTraitLangItem;
 use crate::middle::resolve_lifetime as rl;
 use crate::require_c_abi_if_c_variadic;
 use crate::util::common::ErrorReported;
-use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
-use rustc::session::{parse::feature_err, Session};
 use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
 use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
@@ -26,15 +23,18 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::print;
 use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs};
-use rustc_infer::traits;
-use rustc_infer::traits::astconv_object_safety_violations;
-use rustc_infer::traits::error_reporting::report_object_safety_error;
-use rustc_infer::traits::wf::object_region_bounds;
+use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS};
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use smallvec::SmallVec;
+use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::astconv_object_safety_violations;
+use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
+use rustc_trait_selection::traits::wf::object_region_bounds;
 
+use smallvec::SmallVec;
 use std::collections::BTreeSet;
 use std::iter;
 use std::slice;
@@ -340,7 +340,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     let mut multispan = MultiSpan::from_span(span);
                     multispan.push_span_label(span_late, note.to_string());
                     tcx.struct_span_lint_hir(
-                        lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
+                        LATE_BOUND_LIFETIME_ARGUMENTS,
                         args.args[0].id(),
                         multispan,
                         |lint| lint.build(msg).emit(),
@@ -1441,12 +1441,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let (assoc_ident, def_scope) =
             tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
 
-        // We have already adjusted the item name above, so compare with `ident.modern()` instead
+        // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
         // of calling `filter_by_name_and_kind`.
         let assoc_ty = tcx
             .associated_items(candidate.def_id())
             .filter_by_name_unhygienic(assoc_ident.name)
-            .find(|i| i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident)
+            .find(|i| {
+                i.kind == ty::AssocKind::Type && i.ident.normalize_to_macros_2_0() == assoc_ident
+            })
             .expect("missing associated type");
 
         if !assoc_ty.vis.is_accessible_from(def_scope, tcx) {
@@ -2298,12 +2300,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let (assoc_ident, def_scope) =
             tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
 
-        // We have already adjusted the item name above, so compare with `ident.modern()` instead
+        // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
         // of calling `filter_by_name_and_kind`.
         let item = tcx
             .associated_items(trait_did)
             .in_definition_order()
-            .find(|i| i.kind.namespace() == Namespace::TypeNS && i.ident.modern() == assoc_ident)
+            .find(|i| {
+                i.kind.namespace() == Namespace::TypeNS
+                    && i.ident.normalize_to_macros_2_0() == assoc_ident
+            })
             .expect("missing associated type");
 
         let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
@@ -2588,7 +2593,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
 
             // Case 4. Reference to a method or associated const.
-            DefKind::Method | DefKind::AssocConst => {
+            DefKind::AssocFn | DefKind::AssocConst => {
                 if segments.len() >= 2 {
                     let generics = tcx.generics_of(def_id);
                     path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 2c71fec6809..20737b44e7c 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -4,9 +4,9 @@ use rustc::ty::Ty;
 use rustc_hir as hir;
 use rustc_hir::ExprKind;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::ObligationCauseCode;
-use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
 use rustc_span::Span;
+use rustc_trait_selection::traits::ObligationCauseCode;
+use rustc_trait_selection::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn check_match(
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 67bfb090253..2315b42aec5 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -1,17 +1,17 @@
 use super::method::MethodCallee;
 use super::{FnCtxt, Needs, PlaceOp};
 
-use rustc::session::DiagnosticMessageId;
 use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
 use rustc::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
 use rustc::ty::{ToPredicate, TypeFoldable};
+use rustc_ast::ast::Ident;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_infer::infer::{InferCtxt, InferOk};
-use rustc_infer::traits::{self, TraitEngine};
-
-use rustc_ast::ast::Ident;
+use rustc_session::DiagnosticMessageId;
 use rustc_span::Span;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::{self, TraitEngine};
 
 use std::iter;
 
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index ff100c261f1..2875d38a996 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -31,11 +31,9 @@
 use super::FnCtxt;
 
 use crate::hir::def_id::DefId;
-use crate::lint;
 use crate::type_error_struct;
 use crate::util::common::ErrorReported;
 use rustc::middle::lang_items;
-use rustc::session::Session;
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::cast::{CastKind, CastTy};
 use rustc::ty::error::TypeError;
@@ -44,9 +42,11 @@ use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable};
 use rustc_ast::ast;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_infer::traits;
-use rustc_infer::traits::error_reporting::report_object_safety_error;
+use rustc_session::lint;
+use rustc_session::Session;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
 
 /// Reifies a cast check to be checked once we have full type information for
 /// a function context.
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 8689db1b1eb..49b7a997311 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -12,10 +12,11 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_infer::infer::{InferOk, InferResult};
-use rustc_infer::traits::error_reporting::ArgKind;
-use rustc_infer::traits::Obligation;
 use rustc_span::source_map::Span;
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits::error_reporting::ArgKind;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::Obligation;
 use std::cmp;
 use std::iter;
 
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 3720b74d92e..b0d74651847 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -52,7 +52,6 @@
 
 use crate::astconv::AstConv;
 use crate::check::{FnCtxt, Needs};
-use rustc::session::parse::feature_err;
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
 };
@@ -66,10 +65,13 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{Coercion, InferOk, InferResult};
-use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
+
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
 
@@ -111,7 +113,7 @@ fn identity(_: Ty<'_>) -> Vec<Adjustment<'_>> {
     vec![]
 }
 
-fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> {
+fn simple(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> {
     move |target| vec![Adjustment { kind, target }]
 }
 
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 8b54b534375..a2832d92d4a 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -1,4 +1,3 @@
-use rustc::hir::map::Map;
 use rustc::ty::error::{ExpectedFound, TypeError};
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::util::ExplicitSelf;
@@ -10,8 +9,9 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
-use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 use rustc_span::Span;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 
 use super::{potentially_plural_count, FnCtxt, Inherited};
 
@@ -402,7 +402,7 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
     let tcx = infcx.tcx;
     let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id).unwrap();
     let (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
-        ImplItemKind::Method(ref impl_m_sig, _) => {
+        ImplItemKind::Fn(ref impl_m_sig, _) => {
             (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter())
         }
         _ => bug!("{:?} is not a method", impl_m),
@@ -412,8 +412,8 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
         TypeError::Mutability => {
             if let Some(trait_m_hir_id) = tcx.hir().as_local_hir_id(trait_m.def_id) {
                 let trait_m_iter = match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
-                    TraitItemKind::Method(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(),
-                    _ => bug!("{:?} is not a TraitItemKind::Method", trait_m),
+                    TraitItemKind::Fn(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(),
+                    _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
                 };
 
                 impl_m_iter
@@ -440,10 +440,10 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
             if let Some(trait_m_hir_id) = tcx.hir().as_local_hir_id(trait_m.def_id) {
                 let (trait_m_output, trait_m_iter) =
                     match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
-                        TraitItemKind::Method(ref trait_m_sig, _) => {
+                        TraitItemKind::Fn(ref trait_m_sig, _) => {
                             (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter())
                         }
-                        _ => bug!("{:?} is not a TraitItemKind::Method", trait_m),
+                        _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
                     };
 
                 let impl_iter = impl_sig.inputs().iter();
@@ -708,7 +708,7 @@ fn compare_number_of_method_arguments<'tcx>(
         let trait_m_hir_id = tcx.hir().as_local_hir_id(trait_m.def_id);
         let trait_span = if let Some(trait_id) = trait_m_hir_id {
             match tcx.hir().expect_trait_item(trait_id).kind {
-                TraitItemKind::Method(ref trait_m_sig, _) => {
+                TraitItemKind::Fn(ref trait_m_sig, _) => {
                     let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 };
                     if let Some(arg) = trait_m_sig.decl.inputs.get(pos) {
                         Some(if pos == 0 {
@@ -731,7 +731,7 @@ fn compare_number_of_method_arguments<'tcx>(
         };
         let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id).unwrap();
         let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
-            ImplItemKind::Method(ref impl_m_sig, _) => {
+            ImplItemKind::Fn(ref impl_m_sig, _) => {
                 let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 };
                 if let Some(arg) = impl_m_sig.decl.inputs.get(pos) {
                     if pos == 0 {
@@ -872,7 +872,7 @@ fn compare_synthetic_generics<'tcx>(
                         let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id)?;
                         let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
                         let input_tys = match impl_m.kind {
-                            hir::ImplItemKind::Method(ref sig, _) => sig.decl.inputs,
+                            hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs,
                             _ => unreachable!(),
                         };
                         struct Visitor(Option<Span>, hir::def_id::DefId);
@@ -889,10 +889,10 @@ fn compare_synthetic_generics<'tcx>(
                                     }
                                 }
                             }
-                            type Map = Map<'v>;
+                            type Map = intravisit::ErasedMap<'v>;
                             fn nested_visit_map(
                                 &mut self,
-                            ) -> intravisit::NestedVisitorMap<'_, Self::Map>
+                            ) -> intravisit::NestedVisitorMap<Self::Map>
                             {
                                 intravisit::NestedVisitorMap::None
                             }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 6df9d054195..0556c80e4f7 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -1,6 +1,8 @@
 use crate::check::FnCtxt;
 use rustc_infer::infer::InferOk;
-use rustc_infer::traits::{self, ObligationCause};
+use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
+use rustc_trait_selection::traits::{self, ObligationCause};
 
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::{self, AssocItem, Ty};
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index ead7536f8c6..e48ebbbb235 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -9,9 +9,12 @@ use rustc::ty::subst::{Subst, SubstsRef};
 use rustc::ty::{self, Predicate, Ty, TyCtxt};
 use rustc_errors::struct_span_err;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{InferOk, SuppressRegionErrors, TyCtxtInferExt};
-use rustc_infer::traits::{ObligationCause, TraitEngine, TraitEngineExt};
+use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt};
+use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::Span;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::query::dropck_outlives::AtExt;
+use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt};
 
 /// This function confirms that the `Drop` implementation identified by
 /// `drop_impl_did` is not any more specialized than the type it is
@@ -136,7 +139,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
             drop_impl_did,
             &region_scope_tree,
             &outlives_env,
-            SuppressRegionErrors::default(),
+            RegionckMode::default(),
         );
         Ok(())
     })
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 859a219c95a..617c54a738e 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -34,10 +34,10 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{ExprKind, QPath};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::{self, ObligationCauseCode};
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_trait_selection::traits::{self, ObligationCauseCode};
 
 use std::fmt::Display;
 
@@ -1203,7 +1203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .fields
             .iter()
             .enumerate()
-            .map(|(i, field)| (field.ident.modern(), (i, field)))
+            .map(|(i, field)| (field.ident.normalize_to_macros_2_0(), (i, field)))
             .collect::<FxHashMap<_, _>>();
 
         let mut seen_fields = FxHashMap::default();
@@ -1469,7 +1469,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let (ident, def_scope) =
                         self.tcx.adjust_ident_and_get_scope(field, base_def.did, self.body_id);
                     let fields = &base_def.non_enum_variant().fields;
-                    if let Some(index) = fields.iter().position(|f| f.ident.modern() == ident) {
+                    if let Some(index) =
+                        fields.iter().position(|f| f.ident.normalize_to_macros_2_0() == ident)
+                    {
                         let field = &fields[index];
                         let field_ty = self.field_ty(expr.span, field, substs);
                         // Save the index of all fields regardless of their visibility in case
@@ -1629,7 +1631,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     fn point_at_param_definition(&self, err: &mut DiagnosticBuilder<'_>, param: ty::ParamTy) {
-        let generics = self.tcx.generics_of(self.body_id.owner_def_id());
+        let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
         let generic_param = generics.type_param(&param, self.tcx);
         if let ty::GenericParamDefKind::Type { synthetic: Some(..), .. } = generic_param.kind {
             return;
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index 50692e0f104..cdf68256a7a 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -4,7 +4,6 @@
 //! types computed here.
 
 use super::FnCtxt;
-use rustc::hir::map::Map;
 use rustc::middle::region::{self, YieldData};
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -209,9 +208,9 @@ pub fn resolve_interior<'a, 'tcx>(
 // librustc/middle/region.rs since `expr_count` is compared against the results
 // there.
 impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -237,7 +236,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
                         // ZST in a temporary, so skip its type, just in case it
                         // can significantly complicate the generator type.
                         Res::Def(DefKind::Fn, _)
-                        | Res::Def(DefKind::Method, _)
+                        | Res::Def(DefKind::AssocFn, _)
                         | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
                             // NOTE(eddyb) this assumes a path expression has
                             // no nested expressions to keep track of.
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index d2a358c3e09..dd5e5726e83 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -147,11 +147,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             ),
             "rustc_peek" => (1, vec![param(0)], param(0)),
             "caller_location" => (0, vec![], tcx.caller_location_ty()),
-            "panic_if_uninhabited" | "panic_if_zero_invalid" | "panic_if_any_invalid" => {
+            "assert_inhabited" | "assert_zero_valid" | "assert_uninit_valid" => {
                 (1, Vec::new(), tcx.mk_unit())
             }
-            "init" => (1, Vec::new(), param(0)),
-            "uninit" => (1, Vec::new(), param(0)),
             "forget" => (1, vec![param(0)], tcx.mk_unit()),
             "transmute" => (2, vec![param(0)], param(1)),
             "move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
@@ -299,14 +297,25 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
 
             "try" => {
                 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
-                let fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
+                let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
                     iter::once(mut_u8),
                     tcx.mk_unit(),
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust,
                 ));
-                (0, vec![tcx.mk_fn_ptr(fn_ty), mut_u8, mut_u8], tcx.types.i32)
+                let catch_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
+                    [mut_u8, mut_u8].iter().cloned(),
+                    tcx.mk_unit(),
+                    false,
+                    hir::Unsafety::Normal,
+                    Abi::Rust,
+                ));
+                (
+                    0,
+                    vec![tcx.mk_fn_ptr(try_fn_ty), mut_u8, tcx.mk_fn_ptr(catch_fn_ty)],
+                    tcx.types.i32,
+                )
             }
 
             "va_start" | "va_end" => match mk_va_list_ty(hir::Mutability::Mut) {
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 108affe5a86..48c72567b5c 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -11,8 +11,8 @@ use rustc::ty::subst::{Subst, SubstsRef};
 use rustc::ty::{self, GenericParamDefKind, Ty};
 use rustc_hir as hir;
 use rustc_infer::infer::{self, InferOk};
-use rustc_infer::traits;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
 
 use std::ops::Deref;
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 542a1ac4536..3cf7b65e30f 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -1,6 +1,6 @@
-//! Method lookup: the secret sauce of Rust. See the [rustc guide] for more information.
+//! Method lookup: the secret sauce of Rust. See the [rustc dev guide] for more information.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/method-lookup.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/method-lookup.html
 
 mod confirm;
 pub mod probe;
@@ -22,8 +22,9 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{self, InferOk};
-use rustc_infer::traits;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 
 use self::probe::{IsSuggestion, ProbeScope};
 
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index d35761a6a21..45b1c7d6ea7 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -8,9 +8,7 @@ use crate::check::FnCtxt;
 use crate::hir::def::DefKind;
 use crate::hir::def_id::DefId;
 
-use rustc::lint;
 use rustc::middle::stability;
-use rustc::session::config::nightly_options;
 use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc::ty::GenericParamDefKind;
 use rustc::ty::{
@@ -28,11 +26,16 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
-use rustc_infer::traits::query::method_autoderef::MethodAutoderefBadTy;
-use rustc_infer::traits::query::method_autoderef::{CandidateStep, MethodAutoderefStepsResult};
-use rustc_infer::traits::query::CanonicalTyGoal;
-use rustc_infer::traits::{self, ObligationCause};
+use rustc_session::config::nightly_options;
+use rustc_session::lint;
 use rustc_span::{symbol::Symbol, Span, DUMMY_SP};
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
+use rustc_trait_selection::traits::query::method_autoderef::{
+    CandidateStep, MethodAutoderefStepsResult,
+};
+use rustc_trait_selection::traits::query::CanonicalTyGoal;
+use rustc_trait_selection::traits::{self, ObligationCause};
 use std::cmp::max;
 use std::iter;
 use std::mem;
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 084601fbde1..2f0eb5e0670 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -4,7 +4,6 @@
 use crate::check::FnCtxt;
 use crate::middle::lang_items::FnOnceTraitLangItem;
 use rustc::hir::map as hir_map;
-use rustc::hir::map::Map;
 use rustc::ty::print::with_crate_prefix;
 use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_ast::ast;
@@ -17,9 +16,10 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::intravisit;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::Obligation;
 use rustc_span::symbol::kw;
 use rustc_span::{source_map, FileName, Span};
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::Obligation;
 
 use std::cmp::Ordering;
 
@@ -427,7 +427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         });
 
                     if let Some((field, field_ty)) = field_receiver {
-                        let scope = self.tcx.parent_module(self.body_id);
+                        let scope = self.tcx.parent_module(self.body_id).to_def_id();
                         let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
 
                         if is_accessible {
@@ -828,7 +828,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         candidates: Vec<DefId>,
     ) {
         let module_did = self.tcx.parent_module(self.body_id);
-        let module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap();
+        let module_id = self.tcx.hir().as_local_hir_id(module_did.to_def_id()).unwrap();
         let krate = self.tcx.hir().krate();
         let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
         if let Some(span) = span {
@@ -933,15 +933,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             if let ty::AssocKind::Method = item.kind {
                                 let id = self.tcx.hir().as_local_hir_id(item.def_id);
                                 if let Some(hir::Node::TraitItem(hir::TraitItem {
-                                    kind: hir::TraitItemKind::Method(fn_sig, method),
+                                    kind: hir::TraitItemKind::Fn(fn_sig, method),
                                     ..
                                 })) = id.map(|id| self.tcx.hir().get(id))
                                 {
                                     let self_first_arg = match method {
-                                        hir::TraitMethod::Required([ident, ..]) => {
+                                        hir::TraitFn::Required([ident, ..]) => {
                                             ident.name == kw::SelfLower
                                         }
-                                        hir::TraitMethod::Provided(body_id) => {
+                                        hir::TraitFn::Provided(body_id) => {
                                             match &self.tcx.hir().body(*body_id).params[..] {
                                                 [hir::Param {
                                                     pat:
@@ -1346,9 +1346,9 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
         }
     }
 
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
         intravisit::NestedVisitorMap::None
     }
 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index b34c6ddab39..368f64e4d41 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -90,10 +90,8 @@ pub mod writeback;
 use crate::astconv::{AstConv, GenericArgCountMismatch, PathSeg};
 use crate::middle::lang_items;
 use rustc::hir::map::blocks::FnLikeNode;
-use rustc::hir::map::Map;
 use rustc::middle::region;
 use rustc::mir::interpret::ConstValue;
-use rustc::session::parse::feature_err;
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
 };
@@ -121,17 +119,26 @@ use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, Q
 use rustc_index::vec::Idx;
 use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
-use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_infer::infer::{self, InferCtxt, InferOk, InferResult, TyCtxtInferExt};
-use rustc_infer::traits::error_reporting::recursive_type_with_infinite_size_error;
-use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
+use rustc_session::config::{self, EntryFnType};
+use rustc_session::lint;
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{original_sp, DUMMY_SP};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{self, BytePos, MultiSpan, Span};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::opaque_types::{InferCtxtExt as _, OpaqueTypeDecl};
+use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
+use rustc_trait_selection::traits::{
+    self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt,
+};
 
 use std::cell::{Cell, Ref, RefCell, RefMut};
 use std::cmp;
@@ -141,10 +148,7 @@ use std::mem::replace;
 use std::ops::{self, Deref};
 use std::slice;
 
-use crate::lint;
 use crate::require_c_abi_if_c_variadic;
-use crate::session::config::EntryFnType;
-use crate::session::Session;
 use crate::util::common::{indenter, ErrorReported};
 use crate::TypeAndSubsts;
 
@@ -634,9 +638,8 @@ pub struct InheritedBuilder<'tcx> {
 
 impl Inherited<'_, 'tcx> {
     pub fn build(tcx: TyCtxt<'tcx>, def_id: DefId) -> InheritedBuilder<'tcx> {
-        let hir_id_root = if def_id.is_local() {
-            let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-            DefId::local(hir_id.owner)
+        let hir_id_root = if let Some(def_id) = def_id.as_local() {
+            tcx.hir().local_def_id_to_hir_id(def_id).owner.to_def_id()
         } else {
             def_id
         };
@@ -811,14 +814,14 @@ fn primary_body_of(
         },
         Node::TraitItem(item) => match item.kind {
             hir::TraitItemKind::Const(ref ty, Some(body)) => Some((body, Some(ty), None, None)),
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                 Some((body, None, Some(&sig.header), Some(&sig.decl)))
             }
             _ => None,
         },
         Node::ImplItem(item) => match item.kind {
             hir::ImplItemKind::Const(ref ty, body) => Some((body, Some(ty), None, None)),
-            hir::ImplItemKind::Method(ref sig, body) => {
+            hir::ImplItemKind::Fn(ref sig, body) => {
                 Some((body, None, Some(&sig.header), Some(&sig.decl)))
             }
             _ => None,
@@ -1124,7 +1127,7 @@ fn typeck_tables_of_with_fallback<'tcx>(
 
     // Consistency check our TypeckTables instance can hold all ItemLocalIds
     // it will need to hold.
-    assert_eq!(tables.local_id_root, Some(DefId::local(id.owner)));
+    assert_eq!(tables.local_id_root, Some(id.owner.to_def_id()));
 
     tables
 }
@@ -1172,9 +1175,9 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -1733,7 +1736,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
 
             for item in items.iter() {
                 let item = tcx.hir().trait_item(item.id);
-                if let hir::TraitItemKind::Method(sig, _) = &item.kind {
+                if let hir::TraitItemKind::Fn(sig, _) = &item.kind {
                     let abi = sig.header.abi;
                     fn_maybe_err(tcx, item.ident.span, abi);
                 }
@@ -1891,13 +1894,16 @@ fn check_specialization_validity<'tcx>(
 ) {
     let kind = match impl_item.kind {
         hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
-        hir::ImplItemKind::Method(..) => ty::AssocKind::Method,
+        hir::ImplItemKind::Fn(..) => ty::AssocKind::Method,
         hir::ImplItemKind::OpaqueTy(..) => ty::AssocKind::OpaqueTy,
         hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type,
     };
 
-    let mut ancestor_impls = trait_def
-        .ancestors(tcx, impl_id)
+    let ancestors = match trait_def.ancestors(tcx, impl_id) {
+        Ok(ancestors) => ancestors,
+        Err(_) => return,
+    };
+    let mut ancestor_impls = ancestors
         .skip(1)
         .filter_map(|parent| {
             if parent.is_from_trait() {
@@ -2014,7 +2020,7 @@ fn check_impl_items_against_trait<'tcx>(
                         err.emit()
                     }
                 }
-                hir::ImplItemKind::Method(..) => {
+                hir::ImplItemKind::Fn(..) => {
                     let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
                     if ty_trait_item.kind == ty::AssocKind::Method {
                         compare_impl_method(
@@ -2078,16 +2084,17 @@ fn check_impl_items_against_trait<'tcx>(
 
     // Check for missing items from trait
     let mut missing_items = Vec::new();
-    for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
-        let is_implemented = trait_def
-            .ancestors(tcx, impl_id)
-            .leaf_def(tcx, trait_item.ident, trait_item.kind)
-            .map(|node_item| !node_item.node.is_from_trait())
-            .unwrap_or(false);
-
-        if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
-            if !trait_item.defaultness.has_value() {
-                missing_items.push(*trait_item);
+    if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) {
+        for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
+            let is_implemented = ancestors
+                .leaf_def(tcx, trait_item.ident, trait_item.kind)
+                .map(|node_item| !node_item.node.is_from_trait())
+                .unwrap_or(false);
+
+            if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
+                if !trait_item.defaultness.has_value() {
+                    missing_items.push(*trait_item);
+                }
             }
         }
     }
@@ -2976,7 +2983,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) {
         debug!("write_method_call(hir_id={:?}, method={:?})", hir_id, method);
-        self.write_resolution(hir_id, Ok((DefKind::Method, method.def_id)));
+        self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
         self.write_substs(hir_id, method.substs);
 
         // When the method is confirmed, the `method.substs` includes
@@ -4733,9 +4740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let node = self.tcx.hir().get(self.tcx.hir().get_parent_item(id));
         match node {
             Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
-            | Node::ImplItem(&hir::ImplItem {
-                kind: hir::ImplItemKind::Method(_, body_id), ..
-            }) => {
+            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
                 let body = self.tcx.hir().body(body_id);
                 if let ExprKind::Block(block, _) = &body.value.kind {
                     return Some(block.span);
@@ -4769,12 +4774,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Node::TraitItem(&hir::TraitItem {
                 ident,
-                kind: hir::TraitItemKind::Method(ref sig, ..),
+                kind: hir::TraitItemKind::Fn(ref sig, ..),
                 ..
             }) => Some((&sig.decl, ident, true)),
             Node::ImplItem(&hir::ImplItem {
                 ident,
-                kind: hir::ImplItemKind::Method(ref sig, ..),
+                kind: hir::ImplItemKind::Fn(ref sig, ..),
                 ..
             }) => Some((&sig.decl, ident, false)),
             _ => None,
@@ -4859,11 +4864,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             match hir.get_if_local(def_id) {
                 Some(Node::Item(hir::Item { kind: ItemKind::Fn(.., body_id), .. }))
                 | Some(Node::ImplItem(hir::ImplItem {
-                    kind: hir::ImplItemKind::Method(_, body_id),
+                    kind: hir::ImplItemKind::Fn(_, body_id),
                     ..
                 }))
                 | Some(Node::TraitItem(hir::TraitItem {
-                    kind: hir::TraitItemKind::Method(.., hir::TraitMethod::Provided(body_id)),
+                    kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Provided(body_id)),
                     ..
                 })) => {
                     let body = hir.body(*body_id);
@@ -4934,7 +4939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .join(", ")
                 }
                 Some(Node::TraitItem(hir::TraitItem {
-                    kind: hir::TraitItemKind::Method(.., hir::TraitMethod::Required(idents)),
+                    kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Required(idents)),
                     ..
                 })) => {
                     sugg_call = idents
@@ -5364,7 +5369,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     is_alias_variant_ctor = true;
                 }
             }
-            Res::Def(DefKind::Method, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
+            Res::Def(DefKind::AssocFn, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
                 let container = tcx.associated_item(def_id).container;
                 debug!("instantiate_value_path: def_id={:?} container={:?}", def_id, container);
                 match container {
@@ -5783,7 +5788,7 @@ fn fatally_break_rust(sess: &Session) {
     handler.note_without_error(&format!(
         "rustc {} running on {}",
         option_env!("CFG_VERSION").unwrap_or("unknown_version"),
-        crate::session::config::host_triple(),
+        config::host_triple(),
     ));
 }
 
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index bf3511a2614..f589805e1e2 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -10,6 +10,7 @@ use rustc_errors::{self, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Checks a `a <op>= b`
@@ -860,7 +861,7 @@ enum Op {
 }
 
 /// Dereferences a single level of immutable referencing.
-fn deref_ty_if_possible<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
+fn deref_ty_if_possible(ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.kind {
         ty::Ref(_, ty, hir::Mutability::Not) => ty,
         _ => ty,
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 84854dff851..0f3884de84e 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -11,9 +11,9 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::{HirId, Pat, PatKind};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::{ObligationCause, Pattern};
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{Span, Spanned};
+use rustc_trait_selection::traits::{ObligationCause, Pattern};
 
 use std::cmp;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -707,7 +707,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.set_tainted_by_errors();
                 return tcx.types.err;
             }
-            Res::Def(DefKind::Method, _)
+            Res::Def(DefKind::AssocFn, _)
             | Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _)
             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
                 report_unexpected_variant_res(tcx, res, pat.span, qpath);
@@ -716,7 +716,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
             | Res::SelfCtor(..)
             | Res::Def(DefKind::Const, _)
-            | Res::Def(DefKind::AssocConst, _) => {} // OK
+            | Res::Def(DefKind::AssocConst, _)
+            | Res::Def(DefKind::ConstParam, _) => {} // OK
             _ => bug!("unexpected pattern resolution: {:?}", res),
         }
 
@@ -793,7 +794,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             );
             let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
             match (res, &pat.kind) {
-                (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {
+                (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::AssocFn, _), _) => {
                     err.span_label(pat.span, "`fn` calls are not allowed in patterns");
                     err.help(
                         "for more information, visit \
@@ -830,7 +831,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 on_error();
                 return tcx.types.err;
             }
-            Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => {
+            Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocFn, _) => {
                 report_unexpected_res(res);
                 return tcx.types.err;
             }
@@ -1022,7 +1023,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .fields
             .iter()
             .enumerate()
-            .map(|(i, field)| (field.ident.modern(), (i, field)))
+            .map(|(i, field)| (field.ident.normalize_to_macros_2_0(), (i, field)))
             .collect::<FxHashMap<_, _>>();
 
         // Keep track of which fields have already appeared in the pattern.
@@ -1063,7 +1064,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut unmentioned_fields = variant
             .fields
             .iter()
-            .map(|field| field.ident.modern())
+            .map(|field| field.ident.normalize_to_macros_2_0())
             .filter(|ident| !used_fields.contains_key(&ident))
             .collect::<Vec<_>>();
 
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index c0e33637fd0..57a89614eb1 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -76,7 +76,6 @@ use crate::check::dropck;
 use crate::check::FnCtxt;
 use crate::mem_categorization as mc;
 use crate::middle::region;
-use rustc::hir::map::Map;
 use rustc::ty::adjustment;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
 use rustc::ty::{self, Ty};
@@ -85,8 +84,10 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::PatKind;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{self, RegionObligation, SuppressRegionErrors};
+use rustc_infer::infer::{self, RegionObligation, RegionckMode};
 use rustc_span::Span;
+use rustc_trait_selection::infer::OutlivesEnvironmentExt;
+use rustc_trait_selection::opaque_types::InferCtxtExt;
 use std::mem;
 use std::ops::Deref;
 
@@ -122,10 +123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             rcx.visit_body(body);
             rcx.visit_region_obligations(id);
         }
-        rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
-
-        assert!(self.tables.borrow().free_region_map.is_empty());
-        self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
+        rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
     }
 
     /// Region checking during the WF phase for items. `wf_tys` are the
@@ -143,7 +141,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
         rcx.outlives_environment.save_implied_bounds(item_id);
         rcx.visit_region_obligations(item_id);
-        rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default());
+        rcx.resolve_regions_and_report_errors(RegionckMode::default());
     }
 
     /// Region check a function body. Not invoked on closures, but
@@ -166,13 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id));
         }
 
-        rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
-
-        // In this mode, we also copy the free-region-map into the
-        // tables of the enclosing fcx. In the other regionck modes
-        // (e.g., `regionck_item`), we don't have an enclosing tables.
-        assert!(self.tables.borrow().free_region_map.is_empty());
-        self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
+        rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
     }
 }
 
@@ -353,7 +345,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
         self.select_all_obligations_or_error();
     }
 
-    fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) {
+    fn resolve_regions_and_report_errors(&self, mode: RegionckMode) {
         self.infcx.process_registered_region_obligations(
             self.outlives_environment.region_bound_pairs_map(),
             self.implicit_region_bound,
@@ -364,7 +356,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
             self.subject_def_id,
             &self.region_scope_tree,
             &self.outlives_environment,
-            suppress,
+            mode,
         );
     }
 
@@ -415,9 +407,9 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
     // hierarchy, and in particular the relationships between free
     // regions, until regionck, as described in #3238.
 
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index b5ed6335dc0..1b5f151870c 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -35,7 +35,6 @@ use super::FnCtxt;
 use crate::expr_use_visitor as euv;
 use crate::mem_categorization as mc;
 use crate::mem_categorization::PlaceBase;
-use rustc::hir::map::Map;
 use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
 use rustc_ast::ast;
 use rustc_data_structures::fx::FxIndexMap;
@@ -60,9 +59,9 @@ struct InferBorrowKindVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -119,7 +118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             for (&var_hir_id, _) in upvars.iter() {
                 let upvar_id = ty::UpvarId {
                     var_path: ty::UpvarPath { hir_id: var_hir_id },
-                    closure_expr_id: LocalDefId::from_def_id(closure_def_id),
+                    closure_expr_id: closure_def_id.expect_local(),
                 };
                 debug!("seed upvar_id {:?}", upvar_id);
                 // Adding the upvar Id to the list of Upvars, which will be added
@@ -229,7 +228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let upvar_ty = self.node_ty(var_hir_id);
                     let upvar_id = ty::UpvarId {
                         var_path: ty::UpvarPath { hir_id: var_hir_id },
-                        closure_expr_id: LocalDefId::from_def_id(closure_def_id),
+                        closure_expr_id: closure_def_id.expect_local(),
                     };
                     let capture = self.tables.borrow().upvar_capture(upvar_id);
 
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index e8e34a4e8f0..3255d7b435c 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -2,23 +2,24 @@ use crate::check::{FnCtxt, Inherited};
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
 use rustc::middle::lang_items;
-use rustc::session::parse::feature_err;
 use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::ty::trait_def::TraitSpecializationKind;
 use rustc::ty::{
     self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
 };
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 use rustc_hir::ItemKind;
-use rustc_infer::infer::opaque_types::may_define_opaque_type;
-use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-
-use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ParItemLikeVisitor;
+use rustc_trait_selection::opaque_types::may_define_opaque_type;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
 
 /// Helper type of a temporary returned by `.for_item(...)`.
 /// This is necessary because we can't write the following bound:
@@ -173,7 +174,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) {
     let trait_item = tcx.hir().expect_trait_item(hir_id);
 
     let method_sig = match trait_item.kind {
-        hir::TraitItemKind::Method(ref sig, _) => Some(sig),
+        hir::TraitItemKind::Fn(ref sig, _) => Some(sig),
         _ => None,
     };
     check_object_unsafe_self_trait_by_name(tcx, &trait_item);
@@ -207,7 +208,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
         {
             trait_should_be_self.push(ty.span)
         }
-        hir::TraitItemKind::Method(sig, _) => {
+        hir::TraitItemKind::Fn(sig, _) => {
             for ty in sig.decl.inputs {
                 if could_be_self(trait_def_id, ty) {
                     trait_should_be_self.push(ty.span);
@@ -247,7 +248,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {
     let impl_item = tcx.hir().expect_impl_item(hir_id);
 
     let method_sig = match impl_item.kind {
-        hir::ImplItemKind::Method(ref sig, _) => Some(sig),
+        hir::ImplItemKind::Fn(ref sig, _) => Some(sig),
         _ => None,
     };
 
@@ -411,7 +412,9 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     let trait_def_id = tcx.hir().local_def_id(item.hir_id);
 
     let trait_def = tcx.trait_def(trait_def_id);
-    if trait_def.is_marker {
+    if trait_def.is_marker
+        || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
+    {
         for associated_def_id in &*tcx.associated_item_def_ids(trait_def_id) {
             struct_span_err!(
                 tcx.sess,
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 380e256c9fc..fd92284effb 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -4,18 +4,18 @@
 
 use crate::check::FnCtxt;
 
-use rustc::hir::map::Map;
 use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc::ty::fold::{TypeFoldable, TypeFolder};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, DefIdSet, DefIndex};
+use rustc_hir::def_id::DefIdSet;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_trait_selection::opaque_types::InferCtxtExt;
 
 use std::mem;
 
@@ -61,7 +61,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.visit_fru_field_types();
         wbcx.visit_opaque_types(body.value.span);
         wbcx.visit_coercion_casts();
-        wbcx.visit_free_region_map();
         wbcx.visit_user_provided_tys();
         wbcx.visit_user_provided_sigs();
         wbcx.visit_generator_interior_types();
@@ -108,11 +107,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         body: &'tcx hir::Body<'tcx>,
         rustc_dump_user_substs: bool,
     ) -> WritebackCx<'cx, 'tcx> {
-        let owner = body.id().hir_id;
+        let owner = body.id().hir_id.owner;
 
         WritebackCx {
             fcx,
-            tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))),
+            tables: ty::TypeckTables::empty(Some(owner.to_def_id())),
             body,
             rustc_dump_user_substs,
         }
@@ -124,7 +123,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
     fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
         debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
-        assert!(!ty.needs_infer() && !ty.has_placeholders());
+        assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
         self.tables.node_types_mut().insert(hir_id, ty);
     }
 
@@ -243,9 +242,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 // traffic in node-ids or update tables in the type context etc.
 
 impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
-    type Map = Map<'tcx>;
+    type Map = intravisit::ErasedMap<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 
@@ -326,9 +325,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             let new_upvar_capture = match *upvar_capture {
                 ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
                 ty::UpvarCapture::ByRef(ref upvar_borrow) => {
-                    let r = upvar_borrow.region;
-                    let r = self.resolve(&r, &upvar_id.var_path.hir_id);
-                    ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: upvar_borrow.kind, region: r })
+                    ty::UpvarCapture::ByRef(ty::UpvarBorrow {
+                        kind: upvar_borrow.kind,
+                        region: self.tcx().lifetimes.re_erased,
+                    })
                 }
             };
             debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture);
@@ -342,7 +342,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         let common_local_id_root = fcx_tables.local_id_root.unwrap();
 
         for (&id, &origin) in fcx_tables.closure_kind_origins().iter() {
-            let hir_id = hir::HirId { owner: common_local_id_root.index, local_id: id };
+            let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id: id };
             self.tables.closure_kind_origins_mut().insert(hir_id, origin);
         }
     }
@@ -357,11 +357,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
-    fn visit_free_region_map(&mut self) {
-        self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone();
-        debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value()));
-    }
-
     fn visit_user_provided_tys(&mut self) {
         let fcx_tables = self.fcx.tables.borrow();
         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
@@ -369,7 +364,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
         let mut errors_buffer = Vec::new();
         for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() {
-            let hir_id = hir::HirId { owner: common_local_id_root.index, local_id };
+            let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id };
 
             if cfg!(debug_assertions) && c_ty.has_local_value() {
                 span_bug!(hir_id.to_span(self.fcx.tcx), "writeback: `{:?}` is a local value", c_ty);
@@ -426,8 +421,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     fn visit_opaque_types(&mut self, span: Span) {
         for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
             let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap();
-            let instantiated_ty =
-                self.tcx().erase_regions(&self.resolve(&opaque_defn.concrete_ty, &hir_id));
+            let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id);
 
             debug_assert!(!instantiated_ty.has_escaping_bound_vars());
 
@@ -563,7 +557,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         let common_local_id_root = fcx_tables.local_id_root.unwrap();
 
         for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() {
-            let hir_id = hir::HirId { owner: common_local_id_root.index, local_id };
+            let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id };
             let fn_sig = self.resolve(fn_sig, &hir_id);
             self.tables.liberated_fn_sigs_mut().insert(hir_id, fn_sig.clone());
         }
@@ -575,7 +569,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         let common_local_id_root = fcx_tables.local_id_root.unwrap();
 
         for (&local_id, ftys) in fcx_tables.fru_field_types().iter() {
-            let hir_id = hir::HirId { owner: common_local_id_root.index, local_id };
+            let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id };
             let ftys = self.resolve(ftys, &hir_id);
             self.tables.fru_field_types_mut().insert(hir_id, ftys);
         }
@@ -603,23 +597,14 @@ impl Locatable for Span {
     }
 }
 
-impl Locatable for DefIndex {
-    fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
-        let hir_id = tcx.hir().def_index_to_hir_id(*self);
-        tcx.hir().span(hir_id)
-    }
-}
-
 impl Locatable for hir::HirId {
     fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.hir().span(*self)
     }
 }
 
-///////////////////////////////////////////////////////////////////////////
-// The Resolver. This is the type folding engine that detects
-// unresolved types and so forth.
-
+/// The Resolver. This is the type folding engine that detects
+/// unresolved types and so forth.
 struct Resolver<'cx, 'tcx> {
     tcx: TyCtxt<'tcx>,
     infcx: &'cx InferCtxt<'cx, 'tcx>,
@@ -652,7 +637,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match self.infcx.fully_resolve(&t) {
-            Ok(t) => t,
+            Ok(t) => self.infcx.tcx.erase_regions(&t),
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 self.report_error(t);
@@ -661,15 +646,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
         }
     }
 
-    // FIXME This should be carefully checked
-    // We could use `self.report_error` but it doesn't accept a ty::Region, right now.
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        self.infcx.fully_resolve(&r).unwrap_or(self.tcx.lifetimes.re_static)
+        debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
+        self.tcx.lifetimes.re_erased
     }
 
     fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         match self.infcx.fully_resolve(&ct) {
-            Ok(ct) => ct,
+            Ok(ct) => self.infcx.tcx.erase_regions(&ct),
             Err(_) => {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
                 // FIXME: we'd like to use `self.report_error`, but it doesn't yet
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index 3517e09133c..d0414af5b21 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -1,4 +1,3 @@
-use crate::lint;
 use rustc::ty::TyCtxt;
 use rustc_ast::ast;
 use rustc_data_structures::fx::FxHashMap;
@@ -7,6 +6,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::print::visibility_qualified;
+use rustc_session::lint;
 use rustc_span::Span;
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index aa39a191b3d..e24d9bebf65 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -12,10 +12,11 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::ItemKind;
 use rustc_infer::infer;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{SuppressRegionErrors, TyCtxtInferExt};
-use rustc_infer::traits::misc::{can_type_implement_copy, CopyImplementationError};
-use rustc_infer::traits::predicate_for_trait_def;
-use rustc_infer::traits::{self, ObligationCause, TraitEngine};
+use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
+use rustc_trait_selection::traits::predicate_for_trait_def;
+use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt};
 
 pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
     let lang_items = tcx.lang_items();
@@ -306,7 +307,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) {
                             impl_did,
                             &region_scope_tree,
                             &outlives_env,
-                            SuppressRegionErrors::default(),
+                            RegionckMode::default(),
                         );
                     }
                 }
@@ -322,7 +323,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) {
     }
 }
 
-pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
+pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
     debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
     let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap();
 
@@ -567,7 +568,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
             impl_did,
             &region_scope_tree,
             &outlives_env,
-            SuppressRegionErrors::default(),
+            RegionckMode::default(),
         );
 
         CoerceUnsizedInfo { custom_kind: kind }
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index 778eee3586b..7513759c76b 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -3,7 +3,7 @@ use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_infer::traits::{self, SkipLeakCheck};
+use rustc_trait_selection::traits::{self, SkipLeakCheck};
 
 pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
     assert_eq!(crate_num, LOCAL_CRATE);
@@ -26,7 +26,8 @@ impl InherentOverlapChecker<'tcx> {
             let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).any(|item2| {
                 // Symbols and namespace match, compare hygienically.
                 item1.kind.namespace() == item2.kind.namespace()
-                    && item1.ident.modern() == item2.ident.modern()
+                    && item1.ident.normalize_to_macros_2_0()
+                        == item2.ident.normalize_to_macros_2_0()
             });
 
             if collision {
@@ -50,11 +51,12 @@ impl InherentOverlapChecker<'tcx> {
             let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).find(|item2| {
                 // Symbols and namespace match, compare hygienically.
                 item1.kind.namespace() == item2.kind.namespace()
-                    && item1.ident.modern() == item2.ident.modern()
+                    && item1.ident.normalize_to_macros_2_0()
+                        == item2.ident.normalize_to_macros_2_0()
             });
 
             if let Some(item2) = collision {
-                let name = item1.ident.modern();
+                let name = item1.ident.normalize_to_macros_2_0();
                 let mut err = struct_span_err!(
                     self.tcx.sess,
                     self.tcx.span_of_impl(item1.def_id).unwrap(),
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index d24ee5f156b..27b2c19499c 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -9,8 +9,8 @@ use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_infer::traits;
 use rustc_span::Span;
+use rustc_trait_selection::traits;
 
 mod builtin;
 mod inherent_impls;
@@ -76,6 +76,22 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt<'_>, impl_def_id: DefId, tra
         return;
     }
 
+    if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable =
+        tcx.trait_def(trait_def_id).specialization_kind
+    {
+        if !tcx.features().specialization && !tcx.features().min_specialization {
+            let span = impl_header_span(tcx, impl_def_id);
+            tcx.sess
+                .struct_span_err(
+                    span,
+                    "implementing `rustc_specialization_trait` traits is unstable",
+                )
+                .help("add `#![feature(min_specialization)]` to the crate attributes to enable")
+                .emit();
+            return;
+        }
+    }
+
     let trait_name = if did == li.fn_trait() {
         "Fn"
     } else if did == li.fn_mut_trait() {
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 0a574493573..fc77aad8688 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -6,7 +6,7 @@ use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits;
+use rustc_trait_selection::traits;
 
 pub fn check(tcx: TyCtxt<'_>) {
     let mut orphan = OrphanChecker { tcx };
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index a6044217403..3b25f67aacc 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -69,11 +69,11 @@ impl UnsafetyChecker<'tcx> {
                     .emit();
                 }
 
-                (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
+                (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
                     // Reported in AST validation
                     self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
                 }
-                (_, _, Unsafety::Normal, hir::ImplPolarity::Negative)
+                (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
                 | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
                 | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
                 | (Unsafety::Normal, None, Unsafety::Normal, _) => {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 08028a580d9..7145b948f2f 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -17,14 +17,12 @@
 use crate::astconv::{AstConv, Bounds, SizedByDefault};
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::constrained_generic_params as cgp;
-use crate::lint;
 use crate::middle::lang_items;
 use crate::middle::resolve_lifetime as rl;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::hir::map::Map;
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::mir::mono::Linkage;
-use rustc::session::parse::feature_err;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::util::Discr;
@@ -42,6 +40,8 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{GenericParamKind, Node, Unsafety};
+use rustc_session::lint;
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi;
@@ -105,9 +105,9 @@ pub struct ItemCtxt<'tcx> {
 crate struct PlaceholderHirTyCollector(crate Vec<Span>);
 
 impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
-    type Map = Map<'v>;
+    type Map = intravisit::ErasedMap<'v>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
     fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
@@ -201,8 +201,8 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
 impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
     type Map = Map<'tcx>;
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -715,7 +715,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
     tcx.generics_of(def_id);
 
     match trait_item.kind {
-        hir::TraitItemKind::Method(..) => {
+        hir::TraitItemKind::Fn(..) => {
             tcx.type_of(def_id);
             tcx.fn_sig(def_id);
         }
@@ -745,7 +745,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
     tcx.predicates_of(def_id);
     let impl_item = tcx.hir().expect_impl_item(impl_item_id);
     match impl_item.kind {
-        hir::ImplItemKind::Method(..) => {
+        hir::ImplItemKind::Fn(..) => {
             tcx.fn_sig(def_id);
         }
         hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => {
@@ -828,7 +828,7 @@ fn convert_variant(
         .iter()
         .map(|f| {
             let fid = tcx.hir().local_def_id(f.hir_id);
-            let dup_span = seen_fields.get(&f.ident.modern()).cloned();
+            let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned();
             if let Some(prev_span) = dup_span {
                 struct_span_err!(
                     tcx.sess,
@@ -841,7 +841,7 @@ fn convert_variant(
                 .span_label(prev_span, format!("`{}` first declared here", f.ident))
                 .emit();
             } else {
-                seen_fields.insert(f.ident.modern(), f.span);
+                seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
             }
 
             ty::FieldDef {
@@ -1032,8 +1032,23 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef {
     }
 
     let is_marker = tcx.has_attr(def_id, sym::marker);
+    let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
+        ty::trait_def::TraitSpecializationKind::Marker
+    } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
+        ty::trait_def::TraitSpecializationKind::AlwaysApplicable
+    } else {
+        ty::trait_def::TraitSpecializationKind::None
+    };
     let def_path_hash = tcx.def_path_hash(def_id);
-    let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, def_path_hash);
+    let def = ty::TraitDef::new(
+        def_id,
+        unsafety,
+        paren_sugar,
+        is_auto,
+        is_marker,
+        spec_kind,
+        def_path_hash,
+    );
     tcx.arena.alloc(def)
 }
 
@@ -1045,9 +1060,9 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
     }
 
     impl Visitor<'tcx> for LateBoundRegionsDetector<'tcx> {
-        type Map = Map<'tcx>;
+        type Map = intravisit::ErasedMap<'tcx>;
 
-        fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
             NestedVisitorMap::None
         }
 
@@ -1121,13 +1136,13 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
 
     match node {
         Node::TraitItem(item) => match item.kind {
-            hir::TraitItemKind::Method(ref sig, _) => {
+            hir::TraitItemKind::Fn(ref sig, _) => {
                 has_late_bound_regions(tcx, &item.generics, &sig.decl)
             }
             _ => None,
         },
         Node::ImplItem(item) => match item.kind {
-            hir::ImplItemKind::Method(ref sig, _) => {
+            hir::ImplItemKind::Fn(ref sig, _) => {
                 has_late_bound_regions(tcx, &item.generics, &sig.decl)
             }
             _ => None,
@@ -1437,12 +1452,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
 
     match tcx.hir().get(hir_id) {
         TraitItem(hir::TraitItem {
-            kind: TraitItemKind::Method(sig, TraitMethod::Provided(_)),
+            kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
             ident,
             generics,
             ..
         })
-        | ImplItem(hir::ImplItem { kind: ImplItemKind::Method(sig, _), ident, generics, .. })
+        | ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. })
         | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => {
             match get_infer_ret_ty(&sig.decl.output) {
                 Some(ty) => {
@@ -1474,7 +1489,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
         }
 
         TraitItem(hir::TraitItem {
-            kind: TraitItemKind::Method(FnSig { header, decl }, _),
+            kind: TraitItemKind::Fn(FnSig { header, decl }, _),
             ident,
             generics,
             ..
@@ -1548,7 +1563,7 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
     let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
     let item = tcx.hir().expect_item(hir_id);
     match &item.kind {
-        hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative, .. } => {
+        hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => {
             if is_rustc_reservation {
                 tcx.sess.span_err(item.span, "reservation impls can't be negative");
             }
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index ec87112b7a8..41c205bc11b 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -1,5 +1,4 @@
 use rustc::hir::map::Map;
-use rustc::session::parse::feature_err;
 use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc::ty::util::IntTypeExt;
 use rustc::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
@@ -11,9 +10,10 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::Node;
-use rustc_infer::traits;
+use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::traits;
 
 use super::ItemCtxt;
 use super::{bad_placeholder_type, is_suggestable_infer_ty};
@@ -27,7 +27,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
     match tcx.hir().get(hir_id) {
         Node::TraitItem(item) => match item.kind {
-            TraitItemKind::Method(..) => {
+            TraitItemKind::Fn(..) => {
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
@@ -47,7 +47,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
         },
 
         Node::ImplItem(item) => match item.kind {
-            ImplItemKind::Method(..) => {
+            ImplItemKind::Fn(..) => {
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
                 tcx.mk_fn_def(def_id, substs)
             }
@@ -529,8 +529,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
         type Map = Map<'tcx>;
 
-        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
-            intravisit::NestedVisitorMap::All(&self.tcx.hir())
+        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+            intravisit::NestedVisitorMap::All(self.tcx.hir())
         }
         fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
             if let hir::ExprKind::Closure(..) = ex.kind {
diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs
index 9b187d461cd..b16aa6ff3b2 100644
--- a/src/librustc_typeck/constrained_generic_params.rs
+++ b/src/librustc_typeck/constrained_generic_params.rs
@@ -36,7 +36,7 @@ pub fn parameters_for_impl<'tcx>(
     vec.into_iter().collect()
 }
 
-/// If `include_projections` is false, returns the list of parameters that are
+/// If `include_nonconstraining` is false, returns the list of parameters that are
 /// constrained by `t` - i.e., the value of each parameter in the list is
 /// uniquely determined by `t` (see RFC 447). If it is true, return the list
 /// of parameters whose values are needed in order to constrain `ty` - these
@@ -79,10 +79,18 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
     }
 
     fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
-        if let ty::ConstKind::Param(data) = c.val {
-            self.parameters.push(Parameter::from(data));
+        match c.val {
+            ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => {
+                // Constant expressions are not injective
+                return c.ty.visit_with(self);
+            }
+            ty::ConstKind::Param(data) => {
+                self.parameters.push(Parameter::from(data));
+            }
+            _ => {}
         }
-        false
+
+        c.super_visit_with(self)
     }
 }
 
diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs
index 6666b169994..a45d8ce6823 100644
--- a/src/librustc_typeck/expr_use_visitor.rs
+++ b/src/librustc_typeck/expr_use_visitor.rs
@@ -519,7 +519,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
             for &var_id in upvars.keys() {
                 let upvar_id = ty::UpvarId {
                     var_path: ty::UpvarPath { hir_id: var_id },
-                    closure_expr_id: closure_def_id.to_local(),
+                    closure_expr_id: closure_def_id.expect_local(),
                 };
                 let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
                 let captured_place = return_if_err!(self.cat_captured_var(
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index 0a765a1f9c9..42cb4fcf85d 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -9,6 +9,8 @@
 //! fixed, but for the moment it's easier to do these checks early.
 
 use crate::constrained_generic_params as cgp;
+use min_specialization::check_min_specialization;
+
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -16,9 +18,11 @@ use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_span::Span;
+
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 
-use rustc_span::Span;
+mod min_specialization;
 
 /// Checks that all the type/lifetime parameters on an impl also
 /// appear in the trait ref or self type (or are constrained by a
@@ -60,7 +64,9 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) {
 }
 
 fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: DefId) {
-    tcx.hir().visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx });
+    let min_specialization = tcx.features().min_specialization;
+    tcx.hir()
+        .visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx, min_specialization });
 }
 
 pub fn provide(providers: &mut Providers<'_>) {
@@ -69,6 +75,7 @@ pub fn provide(providers: &mut Providers<'_>) {
 
 struct ImplWfCheck<'tcx> {
     tcx: TyCtxt<'tcx>,
+    min_specialization: bool,
 }
 
 impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
@@ -77,6 +84,9 @@ impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
             let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
             enforce_impl_params_are_constrained(self.tcx, impl_def_id, items);
             enforce_impl_items_are_distinct(self.tcx, items);
+            if self.min_specialization {
+                check_min_specialization(self.tcx, impl_def_id, item.span);
+            }
         }
     }
 
@@ -227,7 +237,7 @@ fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplI
             hir::ImplItemKind::TyAlias(_) => &mut seen_type_items,
             _ => &mut seen_value_items,
         };
-        match seen_items.entry(impl_item.ident.modern()) {
+        match seen_items.entry(impl_item.ident.normalize_to_macros_2_0()) {
             Occupied(entry) => {
                 let mut err = struct_span_err!(
                     tcx.sess,
diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs
new file mode 100644
index 00000000000..cae88376118
--- /dev/null
+++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs
@@ -0,0 +1,409 @@
+//! # Minimal Specialization
+//!
+//! This module contains the checks for sound specialization used when the
+//! `min_specialization` feature is enabled. This requires that the impl is
+//! *always applicable*.
+//!
+//! If `impl1` specializes `impl2` then `impl1` is always applicable if we know
+//! that all the bounds of `impl2` are satisfied, and all of the bounds of
+//! `impl1` are satisfied for some choice of lifetimes then we know that
+//! `impl1` applies for any choice of lifetimes.
+//!
+//! ## Basic approach
+//!
+//! To enforce this requirement on specializations we take the following
+//! approach:
+//!
+//! 1. Match up the substs for `impl2` so that the implemented trait and
+//!    self-type match those for `impl1`.
+//! 2. Check for any direct use of `'static` in the substs of `impl2`.
+//! 3. Check that all of the generic parameters of `impl1` occur at most once
+//!    in the *unconstrained* substs for `impl2`. A parameter is constrained if
+//!    its value is completely determined by an associated type projection
+//!    predicate.
+//! 4. Check that all predicates on `impl1` either exist on `impl2` (after
+//!    matching substs), or are well-formed predicates for the trait's type
+//!    arguments.
+//!
+//! ## Example
+//!
+//! Suppose we have the following always applicable impl:
+//!
+//! ```rust
+//! impl<T> SpecExtend<T> for std::vec::IntoIter<T> { /* specialized impl */ }
+//! impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ }
+//! ```
+//!
+//! We get that the subst for `impl2` are `[T, std::vec::IntoIter<T>]`. `T` is
+//! constrained to be `<I as Iterator>::Item`, so we check only
+//! `std::vec::IntoIter<T>` for repeated parameters, which it doesn't have. The
+//! predicates of `impl1` are only `T: Sized`, which is also a predicate of
+//! `impl2`. So this specialization is sound.
+//!
+//! ## Extensions
+//!
+//! Unfortunately not all specializations in the standard library are allowed
+//! by this. So there are two extensions to these rules that allow specializing
+//! on some traits: that is, using them as bounds on the specializing impl,
+//! even when they don't occur in the base impl.
+//!
+//! ### rustc_specialization_trait
+//!
+//! If a trait is always applicable, then it's sound to specialize on it. We
+//! check trait is always applicable in the same way as impls, except that step
+//! 4 is now "all predicates on `impl1` are always applicable". We require that
+//! `specialization` or `min_specialization` is enabled to implement these
+//! traits.
+//!
+//! ### rustc_unsafe_specialization_marker
+//!
+//! There are also some specialization on traits with no methods, including the
+//! stable `FusedIterator` trait. We allow marking marker traits with an
+//! unstable attribute that means we ignore them in point 3 of the checks
+//! above. This is unsound, in the sense that the specialized impl may be used
+//! when it doesn't apply, but we allow it in the short term since it can't
+//! cause use after frees with purely safe code in the same way as specializing
+//! on traits with methods can.
+
+use crate::constrained_generic_params as cgp;
+
+use rustc::middle::region::ScopeTree;
+use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
+use rustc::ty::trait_def::TraitSpecializationKind;
+use rustc::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
+use rustc_infer::traits::specialization_graph::Node;
+use rustc_span::Span;
+use rustc_trait_selection::traits::{self, translate_substs, wf};
+
+pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: DefId, span: Span) {
+    if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
+        tcx.infer_ctxt().enter(|infcx| {
+            check_always_applicable(&infcx, impl_def_id, node, span);
+        });
+    }
+}
+
+fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option<Node> {
+    let trait_ref = tcx.impl_trait_ref(impl1_def_id)?;
+    let trait_def = tcx.trait_def(trait_ref.def_id);
+
+    let impl2_node = trait_def.ancestors(tcx, impl1_def_id).ok()?.nth(1)?;
+
+    let always_applicable_trait =
+        matches!(trait_def.specialization_kind, TraitSpecializationKind::AlwaysApplicable);
+    if impl2_node.is_from_trait() && !always_applicable_trait {
+        // Implementing a normal trait isn't a specialization.
+        return None;
+    }
+    Some(impl2_node)
+}
+
+/// Check that `impl1` is a sound specialization
+fn check_always_applicable(
+    infcx: &InferCtxt<'_, '_>,
+    impl1_def_id: DefId,
+    impl2_node: Node,
+    span: Span,
+) {
+    if let Some((impl1_substs, impl2_substs)) =
+        get_impl_substs(infcx, impl1_def_id, impl2_node, span)
+    {
+        let impl2_def_id = impl2_node.def_id();
+        debug!(
+            "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)",
+            impl1_def_id, impl2_def_id, impl2_substs
+        );
+
+        let tcx = infcx.tcx;
+
+        let parent_substs = if impl2_node.is_from_trait() {
+            impl2_substs.to_vec()
+        } else {
+            unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs)
+        };
+
+        check_static_lifetimes(tcx, &parent_substs, span);
+        check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
+
+        check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
+    }
+}
+
+/// Given a specializing impl `impl1`, and the base impl `impl2`, returns two
+/// substitutions `(S1, S2)` that equate their trait references. The returned
+/// types are expressed in terms of the generics of `impl1`.
+///
+/// Example
+///
+/// impl<A, B> Foo<A> for B { /* impl2 */ }
+/// impl<C> Foo<Vec<C>> for C { /* impl1 */ }
+///
+/// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
+fn get_impl_substs<'tcx>(
+    infcx: &InferCtxt<'_, 'tcx>,
+    impl1_def_id: DefId,
+    impl2_node: Node,
+    span: Span,
+) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> {
+    let tcx = infcx.tcx;
+    let param_env = tcx.param_env(impl1_def_id);
+
+    let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
+    let impl2_substs = translate_substs(infcx, param_env, impl1_def_id, impl1_substs, impl2_node);
+
+    // Conservatively use an empty `ParamEnv`.
+    let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
+    infcx.resolve_regions_and_report_errors(
+        impl1_def_id,
+        &ScopeTree::default(),
+        &outlives_env,
+        RegionckMode::default(),
+    );
+    let impl2_substs = match infcx.fully_resolve(&impl2_substs) {
+        Ok(s) => s,
+        Err(_) => {
+            tcx.sess.struct_span_err(span, "could not resolve substs on overridden impl").emit();
+            return None;
+        }
+    };
+    Some((impl1_substs, impl2_substs))
+}
+
+/// Returns a list of all of the unconstrained subst of the given impl.
+///
+/// For example given the impl:
+///
+/// impl<'a, T, I> ... where &'a I: IntoIterator<Item=&'a T>
+///
+/// This would return the substs corresponding to `['a, I]`, because knowing
+/// `'a` and `I` determines the value of `T`.
+fn unconstrained_parent_impl_substs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_def_id: DefId,
+    impl_substs: SubstsRef<'tcx>,
+) -> Vec<GenericArg<'tcx>> {
+    let impl_generic_predicates = tcx.predicates_of(impl_def_id);
+    let mut unconstrained_parameters = FxHashSet::default();
+    let mut constrained_params = FxHashSet::default();
+    let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
+
+    // Unfortunately the functions in `constrained_generic_parameters` don't do
+    // what we want here. We want only a list of constrained parameters while
+    // the functions in `cgp` add the constrained parameters to a list of
+    // unconstrained parameters.
+    for (predicate, _) in impl_generic_predicates.predicates.iter() {
+        if let ty::Predicate::Projection(proj) = predicate {
+            let projection_ty = proj.skip_binder().projection_ty;
+            let projected_ty = proj.skip_binder().ty;
+
+            let unbound_trait_ref = projection_ty.trait_ref(tcx);
+            if Some(unbound_trait_ref) == impl_trait_ref {
+                continue;
+            }
+
+            unconstrained_parameters.extend(cgp::parameters_for(&projection_ty, true));
+
+            for param in cgp::parameters_for(&projected_ty, false) {
+                if !unconstrained_parameters.contains(&param) {
+                    constrained_params.insert(param.0);
+                }
+            }
+
+            unconstrained_parameters.extend(cgp::parameters_for(&projected_ty, true));
+        }
+    }
+
+    impl_substs
+        .iter()
+        .enumerate()
+        .filter(|&(idx, _)| !constrained_params.contains(&(idx as u32)))
+        .map(|(_, arg)| *arg)
+        .collect()
+}
+
+/// Check that parameters of the derived impl don't occur more than once in the
+/// equated substs of the base impl.
+///
+/// For example forbid the following:
+///
+/// impl<A> Tr for A { }
+/// impl<B> Tr for (B, B) { }
+///
+/// Note that only consider the unconstrained parameters of the base impl:
+///
+/// impl<S, I: IntoIterator<Item = S>> Tr<S> for I { }
+/// impl<T> Tr<T> for Vec<T> { }
+///
+/// The substs for the parent impl here are `[T, Vec<T>]`, which repeats `T`,
+/// but `S` is constrained in the parent impl, so `parent_substs` is only
+/// `[Vec<T>]`. This means we allow this impl.
+fn check_duplicate_params<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl1_substs: SubstsRef<'tcx>,
+    parent_substs: &Vec<GenericArg<'tcx>>,
+    span: Span,
+) {
+    let mut base_params = cgp::parameters_for(parent_substs, true);
+    base_params.sort_by_key(|param| param.0);
+    if let (_, [duplicate, ..]) = base_params.partition_dedup() {
+        let param = impl1_substs[duplicate.0 as usize];
+        tcx.sess
+            .struct_span_err(span, &format!("specializing impl repeats parameter `{}`", param))
+            .emit();
+    }
+}
+
+/// Check that `'static` lifetimes are not introduced by the specializing impl.
+///
+/// For example forbid the following:
+///
+/// impl<A> Tr for A { }
+/// impl Tr for &'static i32 { }
+fn check_static_lifetimes<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    parent_substs: &Vec<GenericArg<'tcx>>,
+    span: Span,
+) {
+    if tcx.any_free_region_meets(parent_substs, |r| *r == ty::ReStatic) {
+        tcx.sess.struct_span_err(span, &format!("cannot specialize on `'static` lifetime")).emit();
+    }
+}
+
+/// Check whether predicates on the specializing impl (`impl1`) are allowed.
+///
+/// Each predicate `P` must be:
+///
+/// * global (not reference any parameters)
+/// * `T: Tr` predicate where `Tr` is an always-applicable trait
+/// * on the base `impl impl2`
+///     * Currently this check is done using syntactic equality, which is
+///       conservative but generally sufficient.
+/// * a well-formed predicate of a type argument of the trait being implemented,
+///   including the `Self`-type.
+fn check_predicates<'tcx>(
+    infcx: &InferCtxt<'_, 'tcx>,
+    impl1_def_id: DefId,
+    impl1_substs: SubstsRef<'tcx>,
+    impl2_node: Node,
+    impl2_substs: SubstsRef<'tcx>,
+    span: Span,
+) {
+    let tcx = infcx.tcx;
+    let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
+    let mut impl2_predicates = if impl2_node.is_from_trait() {
+        // Always applicable traits have to be always applicable without any
+        // assumptions.
+        InstantiatedPredicates::empty()
+    } else {
+        tcx.predicates_of(impl2_node.def_id()).instantiate(tcx, impl2_substs)
+    };
+    debug!(
+        "check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)",
+        impl1_predicates, impl2_predicates,
+    );
+
+    // Since impls of always applicable traits don't get to assume anything, we
+    // can also assume their supertraits apply.
+    //
+    // For example, we allow:
+    //
+    // #[rustc_specialization_trait]
+    // trait AlwaysApplicable: Debug { }
+    //
+    // impl<T> Tr for T { }
+    // impl<T: AlwaysApplicable> Tr for T { }
+    //
+    // Specializing on `AlwaysApplicable` allows also specializing on `Debug`
+    // which is sound because we forbid impls like the following
+    //
+    // impl<D: Debug> AlwaysApplicable for D { }
+    let always_applicable_traits: Vec<_> = impl1_predicates
+        .predicates
+        .iter()
+        .filter(|predicate| {
+            matches!(
+                trait_predicate_kind(tcx, predicate),
+                Some(TraitSpecializationKind::AlwaysApplicable)
+            )
+        })
+        .copied()
+        .collect();
+
+    // Include the well-formed predicates of the type parameters of the impl.
+    for ty in tcx.impl_trait_ref(impl1_def_id).unwrap().substs.types() {
+        if let Some(obligations) = wf::obligations(
+            infcx,
+            tcx.param_env(impl1_def_id),
+            tcx.hir().as_local_hir_id(impl1_def_id).unwrap(),
+            ty,
+            span,
+        ) {
+            impl2_predicates
+                .predicates
+                .extend(obligations.into_iter().map(|obligation| obligation.predicate))
+        }
+    }
+    impl2_predicates.predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits));
+
+    for predicate in impl1_predicates.predicates {
+        if !impl2_predicates.predicates.contains(&predicate) {
+            check_specialization_on(tcx, &predicate, span)
+        }
+    }
+}
+
+fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: &ty::Predicate<'tcx>, span: Span) {
+    debug!("can_specialize_on(predicate = {:?})", predicate);
+    match predicate {
+        // Global predicates are either always true or always false, so we
+        // are fine to specialize on.
+        _ if predicate.is_global() => (),
+        // We allow specializing on explicitly marked traits with no associated
+        // items.
+        ty::Predicate::Trait(pred, hir::Constness::NotConst) => {
+            if !matches!(
+                trait_predicate_kind(tcx, predicate),
+                Some(TraitSpecializationKind::Marker)
+            ) {
+                tcx.sess
+                    .struct_span_err(
+                        span,
+                        &format!(
+                            "cannot specialize on trait `{}`",
+                            tcx.def_path_str(pred.def_id()),
+                        ),
+                    )
+                    .emit()
+            }
+        }
+        _ => tcx
+            .sess
+            .struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate))
+            .emit(),
+    }
+}
+
+fn trait_predicate_kind<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    predicate: &ty::Predicate<'tcx>,
+) -> Option<TraitSpecializationKind> {
+    match predicate {
+        ty::Predicate::Trait(pred, hir::Constness::NotConst) => {
+            Some(tcx.trait_def(pred.def_id()).specialization_kind)
+        }
+        ty::Predicate::Trait(_, hir::Constness::Const)
+        | ty::Predicate::RegionOutlives(_)
+        | ty::Predicate::TypeOutlives(_)
+        | ty::Predicate::Projection(_)
+        | ty::Predicate::WellFormed(_)
+        | ty::Predicate::Subtype(_)
+        | ty::Predicate::ObjectSafe(_)
+        | ty::Predicate::ClosureKind(..)
+        | ty::Predicate::ConstEvaluatable(..) => None,
+    }
+}
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index c5f339d6b76..e487e0d265c 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -64,6 +64,7 @@ This API is completely unstable and subject to change.
 #![feature(nll)]
 #![feature(try_blocks)]
 #![feature(never_type)]
+#![feature(slice_partition_dedup)]
 #![recursion_limit = "256"]
 
 #[macro_use]
@@ -87,10 +88,7 @@ mod outlives;
 mod structured_errors;
 mod variance;
 
-use rustc::lint;
 use rustc::middle;
-use rustc::session;
-use rustc::session::config::EntryFnType;
 use rustc::ty::query::Providers;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -101,9 +99,14 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::Node;
 use rustc_infer::infer::{InferOk, TyCtxtInferExt};
-use rustc_infer::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
+use rustc_infer::traits::TraitEngineExt as _;
+use rustc_session::config::EntryFnType;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::{
+    ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _,
+};
 
 use std::iter;
 
diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs
index a4569a14756..7d8bf71cf97 100644
--- a/src/librustc_typeck/mem_categorization.rs
+++ b/src/librustc_typeck/mem_categorization.rs
@@ -59,6 +59,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::PatKind;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
 
 #[derive(Clone, Debug)]
 pub enum PlaceBase {
@@ -425,7 +426,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
             | Res::Def(DefKind::ConstParam, _)
             | Res::Def(DefKind::AssocConst, _)
             | Res::Def(DefKind::Fn, _)
-            | Res::Def(DefKind::Method, _)
+            | Res::Def(DefKind::AssocFn, _)
             | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, span, expr_ty)),
 
             Res::Def(DefKind::Static, _) => Ok(Place {
@@ -469,7 +470,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
 
         let upvar_id = ty::UpvarId {
             var_path: ty::UpvarPath { hir_id: var_id },
-            closure_expr_id: closure_expr_def_id.to_local(),
+            closure_expr_id: closure_expr_def_id.expect_local(),
         };
         let var_ty = self.node_ty(var_id)?;
 
diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs
index 99b7b2001a9..a4f8472ae28 100644
--- a/src/librustc_typeck/structured_errors.rs
+++ b/src/librustc_typeck/structured_errors.rs
@@ -1,6 +1,6 @@
-use rustc::session::Session;
 use rustc::ty::{Ty, TypeFoldable};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_session::Session;
 use rustc_span::Span;
 
 pub trait StructuredDiagnostic<'tcx> {
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 6f5caea250b..54f84272ae8 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -105,13 +105,13 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
     }
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
-        if let hir::TraitItemKind::Method(..) = trait_item.kind {
+        if let hir::TraitItemKind::Fn(..) = trait_item.kind {
             self.visit_node_helper(trait_item.hir_id);
         }
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
-        if let hir::ImplItemKind::Method(..) = impl_item.kind {
+        if let hir::ImplItemKind::Fn(..) = impl_item.kind {
             self.visit_node_helper(impl_item.hir_id);
         }
     }
diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs
index ddde11b3844..3cbb42bb5f3 100644
--- a/src/librustc_typeck/variance/mod.rs
+++ b/src/librustc_typeck/variance/mod.rs
@@ -1,7 +1,7 @@
-//! Module for inferring the variance of type and lifetime parameters. See the [rustc guide]
+//! Module for inferring the variance of type and lifetime parameters. See the [rustc dev guide]
 //! chapter for more info.
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/variance.html
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/variance.html
 
 use hir::Node;
 use rustc::ty::query::Providers;
@@ -54,13 +54,13 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
         },
 
         Node::TraitItem(item) => match item.kind {
-            hir::TraitItemKind::Method(..) => {}
+            hir::TraitItemKind::Fn(..) => {}
 
             _ => unsupported(),
         },
 
         Node::ImplItem(item) => match item.kind {
-            hir::ImplItemKind::Method(..) => {}
+            hir::ImplItemKind::Fn(..) => {}
 
             _ => unsupported(),
         },
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index dd593a6abb4..7e6ec96b379 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -77,8 +77,8 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
 
     // See the following for a discussion on dep-graph management.
     //
-    // - https://rust-lang.github.io/rustc-guide/query.html
-    // - https://rust-lang.github.io/rustc-guide/variance.html
+    // - https://rustc-dev-guide.rust-lang.org/query.html
+    // - https://rustc-dev-guide.rust-lang.org/variance.html
     tcx.hir().krate().visit_all_item_likes(&mut terms_cx);
 
     terms_cx
@@ -164,13 +164,13 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
     }
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
-        if let hir::TraitItemKind::Method(..) = trait_item.kind {
+        if let hir::TraitItemKind::Fn(..) = trait_item.kind {
             self.add_inferreds_for_item(trait_item.hir_id);
         }
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
-        if let hir::ImplItemKind::Method(..) = impl_item.kind {
+        if let hir::ImplItemKind::Fn(..) = impl_item.kind {
             self.add_inferreds_for_item(impl_item.hir_id);
         }
     }
diff --git a/src/librustdoc/README.md b/src/librustdoc/README.md
index e4f7bc30e3f..5a5f547068d 100644
--- a/src/librustdoc/README.md
+++ b/src/librustdoc/README.md
@@ -1,3 +1,3 @@
-For more information about how `librustdoc` works, see the [rustc guide].
+For more information about how `librustdoc` works, see the [rustc dev guide].
 
-[rustc guide]: https://rust-lang.github.io/rustc-guide/rustdoc.html
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustdoc.html
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 407b50382fa..c85b21a5500 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -1,7 +1,7 @@
 use rustc::ty::{self, Region, RegionVid, TypeFoldable};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_infer::traits::auto_trait::{self, AutoTraitResult};
+use rustc_trait_selection::traits::auto_trait::{self, AutoTraitResult};
 
 use std::fmt::Debug;
 
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 4a1e2570d06..e66f8697717 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -1,3 +1,4 @@
+use crate::rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc::ty::subst::Subst;
 use rustc::ty::{ToPredicate, WithConstness};
 use rustc_hir as hir;
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 7cb870ae702..153f7af9f97 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -12,7 +12,6 @@ use rustc_hir::Mutability;
 use rustc_metadata::creader::LoadedMacro;
 use rustc_mir::const_eval::is_min_const_fn;
 use rustc_span::hygiene::MacroKind;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
 
 use crate::clean::{self, GetDefId, ToSource, TypeKind};
@@ -42,11 +41,7 @@ pub fn try_inline(
     attrs: Option<Attrs<'_>>,
     visited: &mut FxHashSet<DefId>,
 ) -> Option<Vec<clean::Item>> {
-    let did = if let Some(did) = res.opt_def_id() {
-        did
-    } else {
-        return None;
-    };
+    let did = res.opt_def_id()?;
     if did.is_local() {
         return None;
     }
@@ -579,7 +574,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
                     name: ref _name,
                 },
             ref bounds,
-        } => !(*s == "Self" && did == trait_did) && !bounds.is_empty(),
+        } => !(bounds.is_empty() || *s == "Self" && did == trait_did),
         _ => true,
     });
     g
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b28f1899925..e69d4ddc2d0 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -141,6 +141,7 @@ impl Clean<ExternalCrate> for CrateNum {
             cx.tcx
                 .hir()
                 .krate()
+                .item
                 .module
                 .item_ids
                 .iter()
@@ -194,6 +195,7 @@ impl Clean<ExternalCrate> for CrateNum {
             cx.tcx
                 .hir()
                 .krate()
+                .item
                 .module
                 .item_ids
                 .iter()
@@ -1076,16 +1078,36 @@ impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
     }
 }
 
+impl Clean<TypeKind> for hir::def::DefKind {
+    fn clean(&self, _: &DocContext<'_>) -> TypeKind {
+        match *self {
+            hir::def::DefKind::Mod => TypeKind::Module,
+            hir::def::DefKind::Struct => TypeKind::Struct,
+            hir::def::DefKind::Union => TypeKind::Union,
+            hir::def::DefKind::Enum => TypeKind::Enum,
+            hir::def::DefKind::Trait => TypeKind::Trait,
+            hir::def::DefKind::TyAlias => TypeKind::Typedef,
+            hir::def::DefKind::ForeignTy => TypeKind::Foreign,
+            hir::def::DefKind::TraitAlias => TypeKind::TraitAlias,
+            hir::def::DefKind::Fn => TypeKind::Function,
+            hir::def::DefKind::Const => TypeKind::Const,
+            hir::def::DefKind::Static => TypeKind::Static,
+            hir::def::DefKind::Macro(_) => TypeKind::Macro,
+            _ => TypeKind::Foreign,
+        }
+    }
+}
+
 impl Clean<Item> for hir::TraitItem<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let inner = match self.kind {
             hir::TraitItemKind::Const(ref ty, default) => {
                 AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e)))
             }
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                 MethodItem((sig, &self.generics, body, None).clean(cx))
             }
-            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
+            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => {
                 let (generics, decl) = enter_impl_trait(cx, || {
                     (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
                 });
@@ -1116,7 +1138,7 @@ impl Clean<Item> for hir::ImplItem<'_> {
             hir::ImplItemKind::Const(ref ty, expr) => {
                 AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr)))
             }
-            hir::ImplItemKind::Method(ref sig, body) => {
+            hir::ImplItemKind::Fn(ref sig, body) => {
                 MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
             }
             hir::ImplItemKind::TyAlias(ref ty) => {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index b1aa094204a..73f2c399e56 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -836,8 +836,8 @@ pub struct Method {
     pub decl: FnDecl,
     pub header: hir::FnHeader,
     pub defaultness: Option<hir::Defaultness>,
-    pub all_types: Vec<Type>,
-    pub ret_types: Vec<Type>,
+    pub all_types: Vec<(Type, TypeKind)>,
+    pub ret_types: Vec<(Type, TypeKind)>,
 }
 
 #[derive(Clone, Debug)]
@@ -845,8 +845,8 @@ pub struct TyMethod {
     pub header: hir::FnHeader,
     pub decl: FnDecl,
     pub generics: Generics,
-    pub all_types: Vec<Type>,
-    pub ret_types: Vec<Type>,
+    pub all_types: Vec<(Type, TypeKind)>,
+    pub ret_types: Vec<(Type, TypeKind)>,
 }
 
 #[derive(Clone, Debug)]
@@ -854,8 +854,8 @@ pub struct Function {
     pub decl: FnDecl,
     pub generics: Generics,
     pub header: hir::FnHeader,
-    pub all_types: Vec<Type>,
-    pub ret_types: Vec<Type>,
+    pub all_types: Vec<(Type, TypeKind)>,
+    pub ret_types: Vec<(Type, TypeKind)>,
 }
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -1042,7 +1042,7 @@ pub enum PrimitiveType {
     Never,
 }
 
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
 pub enum TypeKind {
     Enum,
     Function,
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 21e3d24cc96..b54af499187 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -184,7 +184,7 @@ pub fn get_real_types(
     arg: &Type,
     cx: &DocContext<'_>,
     recurse: i32,
-) -> FxHashSet<Type> {
+) -> FxHashSet<(Type, TypeKind)> {
     let arg_s = arg.print().to_string();
     let mut res = FxHashSet::default();
     if recurse >= 10 {
@@ -209,7 +209,11 @@ pub fn get_real_types(
                                 if !adds.is_empty() {
                                     res.extend(adds);
                                 } else if !ty.is_full_generic() {
-                                    res.insert(ty);
+                                    if let Some(did) = ty.def_id() {
+                                        if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                                            res.insert((ty, kind));
+                                        }
+                                    }
                                 }
                             }
                         }
@@ -225,13 +229,21 @@ pub fn get_real_types(
                     if !adds.is_empty() {
                         res.extend(adds);
                     } else if !ty.is_full_generic() {
-                        res.insert(ty.clone());
+                        if let Some(did) = ty.def_id() {
+                            if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                                res.insert((ty.clone(), kind));
+                            }
+                        }
                     }
                 }
             }
         }
     } else {
-        res.insert(arg.clone());
+        if let Some(did) = arg.def_id() {
+            if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                res.insert((arg.clone(), kind));
+            }
+        }
         if let Some(gens) = arg.generics() {
             for gen in gens.iter() {
                 if gen.is_full_generic() {
@@ -239,8 +251,10 @@ pub fn get_real_types(
                     if !adds.is_empty() {
                         res.extend(adds);
                     }
-                } else {
-                    res.insert(gen.clone());
+                } else if let Some(did) = gen.def_id() {
+                    if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                        res.insert((gen.clone(), kind));
+                    }
                 }
             }
         }
@@ -256,7 +270,7 @@ pub fn get_all_types(
     generics: &Generics,
     decl: &FnDecl,
     cx: &DocContext<'_>,
-) -> (Vec<Type>, Vec<Type>) {
+) -> (Vec<(Type, TypeKind)>, Vec<(Type, TypeKind)>) {
     let mut all_types = FxHashSet::default();
     for arg in decl.inputs.values.iter() {
         if arg.type_.is_self_type() {
@@ -266,7 +280,11 @@ pub fn get_all_types(
         if !args.is_empty() {
             all_types.extend(args);
         } else {
-            all_types.insert(arg.type_.clone());
+            if let Some(did) = arg.type_.def_id() {
+                if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                    all_types.insert((arg.type_.clone(), kind));
+                }
+            }
         }
     }
 
@@ -274,7 +292,11 @@ pub fn get_all_types(
         FnRetTy::Return(ref return_type) => {
             let mut ret = get_real_types(generics, &return_type, cx, 0);
             if ret.is_empty() {
-                ret.insert(return_type.clone());
+                if let Some(did) = return_type.def_id() {
+                    if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                        ret.insert((return_type.clone(), kind));
+                    }
+                }
             }
             ret.into_iter().collect()
         }
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 33b3e800374..179c5bfacf3 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -1,17 +1,17 @@
 use std::collections::BTreeMap;
+use std::convert::TryFrom;
 use std::ffi::OsStr;
 use std::fmt;
 use std::path::PathBuf;
 
-use rustc::lint::Level;
-use rustc::session;
-use rustc::session::config::{
+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,
     nightly_options,
 };
-use rustc::session::config::{parse_crate_types_from_list, parse_externs, CrateType};
-use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
-use rustc::session::search_paths::SearchPath;
+use rustc_session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
+use rustc_session::lint::Level;
+use rustc_session::search_paths::SearchPath;
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_target::spec::TargetTriple;
 
@@ -24,6 +24,33 @@ use crate::opts;
 use crate::passes::{self, Condition, DefaultPassOption};
 use crate::theme;
 
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum OutputFormat {
+    Json,
+    Html,
+}
+
+impl OutputFormat {
+    pub fn is_json(&self) -> bool {
+        match self {
+            OutputFormat::Json => true,
+            _ => false,
+        }
+    }
+}
+
+impl TryFrom<&str> for OutputFormat {
+    type Error = String;
+
+    fn try_from(value: &str) -> Result<Self, Self::Error> {
+        match value {
+            "json" => Ok(OutputFormat::Json),
+            "html" => Ok(OutputFormat::Html),
+            _ => Err(format!("unknown output format `{}`", value)),
+        }
+    }
+}
+
 /// Configuration options for rustdoc.
 #[derive(Clone)]
 pub struct Options {
@@ -115,6 +142,8 @@ pub struct Options {
     pub crate_version: Option<String>,
     /// Collected options specific to outputting final pages.
     pub render_options: RenderOptions,
+    /// Output format rendering (used only for "show-coverage" option for the moment)
+    pub output_format: Option<OutputFormat>,
 }
 
 impl fmt::Debug for Options {
@@ -269,9 +298,9 @@ impl Options {
             return Err(0);
         }
 
-        let color = session::config::parse_color(&matches);
-        let (json_rendered, _artifacts) = session::config::parse_json(&matches);
-        let error_format = session::config::parse_error_format(&matches, color, json_rendered);
+        let color = config::parse_color(&matches);
+        let (json_rendered, _artifacts) = config::parse_json(&matches);
+        let error_format = config::parse_error_format(&matches, color, json_rendered);
 
         let codegen_options = build_codegen_options(matches, error_format);
         let debugging_options = build_debugging_options(matches, error_format);
@@ -425,14 +454,6 @@ impl Options {
             }
         }
 
-        match matches.opt_str("w").as_ref().map(|s| &**s) {
-            Some("html") | None => {}
-            Some(s) => {
-                diag.struct_err(&format!("unknown output format: {}", s)).emit();
-                return Err(1);
-            }
-        }
-
         let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s));
         if let Some(ref index_page) = index_page {
             if !index_page.is_file() {
@@ -469,6 +490,29 @@ 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 {
+                        diag.struct_err("json output format isn't supported for doc generation")
+                            .emit();
+                        return Err(1);
+                    } else if !o.is_json() && show_coverage {
+                        diag.struct_err(
+                            "html output format isn't supported for the --show-coverage option",
+                        )
+                        .emit();
+                        return Err(1);
+                    }
+                    Some(o)
+                }
+                Err(e) => {
+                    diag.struct_err(&e).emit();
+                    return Err(1);
+                }
+            },
+            None => None,
+        };
         let crate_name = matches.opt_str("crate-name");
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
         let playground_url = matches.opt_str("playground-url");
@@ -553,6 +597,7 @@ impl Options {
                 generate_search_filter,
                 generate_redirect_pages,
             },
+            output_format,
         })
     }
 
@@ -568,6 +613,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") {
+                continue;
+            }
             let mut err =
                 diag.struct_warn(&format!("the '{}' flag is considered deprecated", flag));
             err.warn(
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 8bc34e949f1..f0b9ad2852f 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -1,23 +1,22 @@
 use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
-use rustc::session::config::ErrorOutputType;
-use rustc::session::DiagnosticOutput;
-use rustc::session::{self, config};
 use rustc::ty::{Ty, TyCtxt};
+use rustc_ast::ast::CRATE_NODE_ID;
+use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_driver::abort_on_err;
+use rustc_errors::emitter::{Emitter, EmitterWriter};
+use rustc_errors::json::JsonEmitter;
 use rustc_feature::UnstableFeatures;
 use rustc_hir::def::Namespace::TypeNS;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use rustc_hir::HirId;
 use rustc_interface::interface;
 use rustc_resolve as resolve;
+use rustc_session::config::ErrorOutputType;
 use rustc_session::lint;
-
-use rustc_ast::ast::CRATE_NODE_ID;
-use rustc_attr as attr;
-use rustc_errors::emitter::{Emitter, EmitterWriter};
-use rustc_errors::json::JsonEmitter;
+use rustc_session::DiagnosticOutput;
+use rustc_session::{config, Session};
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
@@ -34,8 +33,8 @@ use crate::html::render::RenderInfo;
 
 use crate::passes::{self, Condition::*, ConditionalPass};
 
-pub use rustc::session::config::{CodegenOptions, DebuggingOptions, Input, Options};
-pub use rustc::session::search_paths::SearchPath;
+pub use rustc_session::config::{CodegenOptions, DebuggingOptions, Input, Options};
+pub use rustc_session::search_paths::SearchPath;
 
 pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
 
@@ -68,7 +67,7 @@ pub struct DocContext<'tcx> {
 }
 
 impl<'tcx> DocContext<'tcx> {
-    pub fn sess(&self) -> &session::Session {
+    pub fn sess(&self) -> &Session {
         &self.tcx.sess
     }
 
@@ -228,6 +227,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
         mut manual_passes,
         display_warnings,
         render_options,
+        output_format,
         ..
     } = options;
 
@@ -385,6 +385,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
 
                 let mut renderinfo = RenderInfo::default();
                 renderinfo.access_levels = access_levels;
+                renderinfo.output_format = output_format;
 
                 let mut ctxt = DocContext {
                     tcx,
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 42529a6682e..e13bf270440 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -844,11 +844,7 @@ pub fn plain_summary_line(md: &str) -> String {
         type Item = String;
 
         fn next(&mut self) -> Option<String> {
-            let next_event = self.inner.next();
-            if next_event.is_none() {
-                return None;
-            }
-            let next_event = next_event.unwrap();
+            let next_event = self.inner.next()?;
             let (ret, is_in) = match next_event {
                 Event::Start(Tag::Paragraph) => (None, 1),
                 Event::Start(Tag::Heading(_)) => (None, 1),
@@ -870,7 +866,7 @@ pub fn plain_summary_line(md: &str) -> String {
     }
     let mut s = String::with_capacity(md.len() * 3 / 2);
     let p = ParserWrapper { inner: Parser::new(md), is_in: 0, is_first: true };
-    p.into_iter().filter(|t| !t.is_empty()).for_each(|i| s.push_str(&i));
+    p.filter(|t| !t.is_empty()).for_each(|i| s.push_str(&i));
     s
 }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index d3015b403fc..eb7a367acf4 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -44,7 +44,6 @@ use std::sync::Arc;
 
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability;
-use rustc_ast::ast;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -59,8 +58,8 @@ use rustc_span::symbol::{sym, Symbol};
 use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
 
-use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy};
-use crate::config::RenderOptions;
+use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind};
+use crate::config::{OutputFormat, RenderOptions};
 use crate::docfs::{DocFS, ErrorStorage, PathError};
 use crate::doctree;
 use crate::html::escape::Escape;
@@ -270,6 +269,7 @@ pub struct RenderInfo {
     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
@@ -302,19 +302,25 @@ impl Serialize for IndexItem {
 
 /// A type used for the search index.
 #[derive(Debug)]
-struct Type {
+struct RenderType {
+    ty: Option<DefId>,
+    idx: Option<usize>,
     name: Option<String>,
-    generics: Option<Vec<String>>,
+    generics: Option<Vec<Generic>>,
 }
 
-impl Serialize for Type {
+impl Serialize for RenderType {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
         S: Serializer,
     {
         if let Some(name) = &self.name {
             let mut seq = serializer.serialize_seq(None)?;
-            seq.serialize_element(&name)?;
+            if let Some(id) = self.idx {
+                seq.serialize_element(&id)?;
+            } else {
+                seq.serialize_element(&name)?;
+            }
             if let Some(generics) = &self.generics {
                 seq.serialize_element(&generics)?;
             }
@@ -325,11 +331,32 @@ impl Serialize for Type {
     }
 }
 
+/// A type used for the search index.
+#[derive(Debug)]
+struct Generic {
+    name: String,
+    defid: Option<DefId>,
+    idx: Option<usize>,
+}
+
+impl Serialize for Generic {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        if let Some(id) = self.idx {
+            serializer.serialize_some(&id)
+        } else {
+            serializer.serialize_some(&self.name)
+        }
+    }
+}
+
 /// Full type of functions/methods in the search index.
 #[derive(Debug)]
 struct IndexItemFunctionType {
-    inputs: Vec<Type>,
-    output: Option<Vec<Type>>,
+    inputs: Vec<TypeWithKind>,
+    output: Option<Vec<TypeWithKind>>,
 }
 
 impl Serialize for IndexItemFunctionType {
@@ -340,8 +367,8 @@ impl Serialize for IndexItemFunctionType {
         // If we couldn't figure out a type, just write `null`.
         let mut iter = self.inputs.iter();
         if match self.output {
-            Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()),
-            None => iter.any(|ref i| i.name.is_none()),
+            Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()),
+            None => iter.any(|ref i| i.ty.name.is_none()),
         } {
             serializer.serialize_none()
         } else {
@@ -359,6 +386,31 @@ impl Serialize for IndexItemFunctionType {
     }
 }
 
+#[derive(Debug)]
+pub struct TypeWithKind {
+    ty: RenderType,
+    kind: TypeKind,
+}
+
+impl From<(RenderType, TypeKind)> for TypeWithKind {
+    fn from(x: (RenderType, TypeKind)) -> TypeWithKind {
+        TypeWithKind { ty: x.0, kind: x.1 }
+    }
+}
+
+impl Serialize for TypeWithKind {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        let mut seq = serializer.serialize_seq(None)?;
+        seq.serialize_element(&self.ty.name)?;
+        let x: ItemType = self.kind.into();
+        seq.serialize_element(&x)?;
+        seq.end()
+    }
+}
+
 thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
 thread_local!(pub static CURRENT_DEPTH: Cell<usize> = Cell::new(0));
 
@@ -1542,7 +1594,7 @@ impl Context {
         }
 
         if self.shared.sort_modules_alphabetically {
-            for (_, items) in &mut map {
+            for items in map.values_mut() {
                 items.sort();
             }
         }
@@ -3125,25 +3177,6 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
-    let path = pprust::path_to_string(&attr.path);
-
-    if attr.is_word() {
-        Some(path)
-    } else if let Some(v) = attr.value_str() {
-        Some(format!("{} = {:?}", path, v))
-    } else if let Some(values) = attr.meta_item_list() {
-        let display: Vec<_> = values
-            .iter()
-            .filter_map(|attr| attr.meta_item().and_then(|mi| render_attribute(mi)))
-            .collect();
-
-        if !display.is_empty() { Some(format!("{}({})", path, display.join(", "))) } else { None }
-    } else {
-        None
-    }
-}
-
 const ATTRIBUTE_WHITELIST: &[Symbol] = &[
     sym::export_name,
     sym::lang,
@@ -3169,9 +3202,8 @@ fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) {
         if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty()) {
             continue;
         }
-        if let Some(s) = render_attribute(&attr.meta().unwrap()) {
-            attrs.push_str(&format!("#[{}]\n", s));
-        }
+
+        attrs.push_str(&pprust::attribute_to_string(&attr));
     }
     if !attrs.is_empty() {
         write!(
@@ -3395,10 +3427,8 @@ fn render_assoc_items(
         let deref_impl =
             traits.iter().find(|t| t.inner_impl().trait_.def_id() == c.deref_trait_did);
         if let Some(impl_) = deref_impl {
-            let has_deref_mut = traits
-                .iter()
-                .find(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did)
-                .is_some();
+            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);
         }
 
@@ -3739,7 +3769,7 @@ fn render_impl(
     ) {
         for trait_item in &t.items {
             let n = trait_item.name.clone();
-            if i.items.iter().find(|m| m.name == n).is_some() {
+            if i.items.iter().any(|m| m.name == n) {
                 continue;
             }
             let did = i.trait_.as_ref().unwrap().def_id().unwrap();
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index a0a35e4ce4b..ed0de2b3119 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -12,7 +12,7 @@ use std::path::{Path, PathBuf};
 use serde::Serialize;
 
 use super::{plain_summary_line, shorten, Impl, IndexItem, IndexItemFunctionType, ItemType};
-use super::{RenderInfo, Type};
+use super::{Generic, RenderInfo, RenderType, TypeWithKind};
 
 /// Indicates where an external crate can be found.
 pub enum ExternalLocation {
@@ -139,6 +139,7 @@ impl Cache {
             deref_trait_did,
             deref_mut_trait_did,
             owned_box_did,
+            ..
         } = renderinfo;
 
         let external_paths =
@@ -587,17 +588,20 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     let mut lastpathid = 0usize;
 
     for item in search_index {
-        item.parent_idx = item.parent.map(|defid| {
+        item.parent_idx = item.parent.and_then(|defid| {
             if defid_to_pathid.contains_key(&defid) {
-                *defid_to_pathid.get(&defid).expect("no pathid")
+                defid_to_pathid.get(&defid).map(|x| *x)
             } else {
                 let pathid = lastpathid;
                 defid_to_pathid.insert(defid, pathid);
                 lastpathid += 1;
 
-                let &(ref fqp, short) = paths.get(&defid).unwrap();
-                crate_paths.push((short, fqp.last().unwrap().clone()));
-                pathid
+                if let Some(&(ref fqp, short)) = paths.get(&defid) {
+                    crate_paths.push((short, fqp.last().unwrap().clone()));
+                    Some(pathid)
+                } else {
+                    None
+                }
             }
         });
 
@@ -646,20 +650,25 @@ fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
         _ => return None,
     };
 
-    let inputs =
-        all_types.iter().map(|arg| get_index_type(&arg)).filter(|a| a.name.is_some()).collect();
+    let inputs = all_types
+        .iter()
+        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
+        .filter(|a| a.ty.name.is_some())
+        .collect();
     let output = ret_types
         .iter()
-        .map(|arg| get_index_type(&arg))
-        .filter(|a| a.name.is_some())
+        .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
+        .filter(|a| a.ty.name.is_some())
         .collect::<Vec<_>>();
     let output = if output.is_empty() { None } else { Some(output) };
 
     Some(IndexItemFunctionType { inputs, output })
 }
 
-fn get_index_type(clean_type: &clean::Type) -> Type {
-    let t = Type {
+fn get_index_type(clean_type: &clean::Type) -> RenderType {
+    let t = RenderType {
+        ty: clean_type.def_id(),
+        idx: None,
         name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()),
         generics: get_generics(clean_type),
     };
@@ -684,12 +693,17 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
     }
 }
 
-fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> {
+fn get_generics(clean_type: &clean::Type) -> Option<Vec<Generic>> {
     clean_type.generics().and_then(|types| {
         let r = types
             .iter()
-            .filter_map(|t| get_index_type_name(t, false))
-            .map(|s| s.to_ascii_lowercase())
+            .filter_map(|t| {
+                if let Some(name) = get_index_type_name(t, false) {
+                    Some(Generic { name: name.to_ascii_lowercase(), defid: t.def_id(), idx: None })
+                } else {
+                    None
+                }
+            })
             .collect::<Vec<_>>();
         if r.is_empty() { None } else { Some(r) }
     })
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index a799aed6985..3f12fb893a4 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -523,13 +523,14 @@ function getSearchElement() {
     }
 
     function initSearch(rawSearchIndex) {
-        var currentResults, index, searchIndex;
         var MAX_LEV_DISTANCE = 3;
         var MAX_RESULTS = 200;
         var GENERICS_DATA = 1;
         var NAME = 0;
         var INPUTS_DATA = 0;
         var OUTPUT_DATA = 1;
+        var NO_TYPE_FILTER = -1;
+        var currentResults, index, searchIndex;
         var params = getQueryStringParams();
 
         // Populate search bar with query string search term when provided,
@@ -556,7 +557,7 @@ function getSearchElement() {
                         return i;
                     }
                 }
-                return -1;
+                return NO_TYPE_FILTER;
             }
 
             var valLower = query.query.toLowerCase(),
@@ -719,6 +720,13 @@ function getSearchElement() {
                 };
             }
 
+            function getObjectFromId(id) {
+                if (typeof id === "number") {
+                    return searchIndex[id];
+                }
+                return {'name': id};
+            }
+
             function checkGenerics(obj, val) {
                 // The names match, but we need to be sure that all generics kinda
                 // match as well.
@@ -735,8 +743,10 @@ function getSearchElement() {
                         for (var y = 0; y < vlength; ++y) {
                             var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1};
                             var elength = elems.length;
+                            var firstGeneric = getObjectFromId(val.generics[y]).name;
                             for (var x = 0; x < elength; ++x) {
-                                var tmp_lev = levenshtein(elems[x], val.generics[y]);
+                                var tmp_lev = levenshtein(getObjectFromId(elems[x]).name,
+                                                          firstGeneric);
                                 if (tmp_lev < lev.lev) {
                                     lev.lev = tmp_lev;
                                     lev.pos = x;
@@ -771,8 +781,9 @@ function getSearchElement() {
 
                                 for (var y = 0; allFound === true && y < val.generics.length; ++y) {
                                     allFound = false;
+                                    var firstGeneric = getObjectFromId(val.generics[y]).name;
                                     for (x = 0; allFound === false && x < elems.length; ++x) {
-                                        allFound = elems[x] === val.generics[y];
+                                        allFound = getObjectFromId(elems[x]).name === firstGeneric;
                                     }
                                     if (allFound === true) {
                                         elems.splice(x - 1, 1);
@@ -829,16 +840,22 @@ function getSearchElement() {
                 return lev_distance + 1;
             }
 
-            function findArg(obj, val, literalSearch) {
+            function findArg(obj, val, literalSearch, typeFilter) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
 
-                if (obj && obj.type && obj.type[INPUTS_DATA] &&
-                      obj.type[INPUTS_DATA].length > 0) {
+                if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
                     var length = obj.type[INPUTS_DATA].length;
                     for (var i = 0; i < length; i++) {
-                        var tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch);
-                        if (literalSearch === true && tmp === true) {
-                            return true;
+                        var tmp = obj.type[INPUTS_DATA][i];
+                        if (typePassesFilter(typeFilter, tmp[1]) === false) {
+                            continue;
+                        }
+                        tmp = checkType(tmp, val, literalSearch);
+                        if (literalSearch === true) {
+                            if (tmp === true) {
+                                return true;
+                            }
+                            continue;
                         }
                         lev_distance = Math.min(tmp, lev_distance);
                         if (lev_distance === 0) {
@@ -849,20 +866,20 @@ function getSearchElement() {
                 return literalSearch === true ? false : lev_distance;
             }
 
-            function checkReturned(obj, val, literalSearch) {
+            function checkReturned(obj, val, literalSearch, typeFilter) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
 
                 if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
                     var ret = obj.type[OUTPUT_DATA];
-                    if (!obj.type[OUTPUT_DATA].length) {
+                    if (typeof ret[0] === "string") {
                         ret = [ret];
                     }
                     for (var x = 0; x < ret.length; ++x) {
-                        var r = ret[x];
-                        if (typeof r === "string") {
-                            r = [r];
+                        var tmp = ret[x];
+                        if (typePassesFilter(typeFilter, tmp[1]) === false) {
+                            continue;
                         }
-                        var tmp = checkType(r, val, literalSearch);
+                        tmp = checkType(tmp, val, literalSearch);
                         if (literalSearch === true) {
                             if (tmp === true) {
                                 return true;
@@ -917,7 +934,7 @@ function getSearchElement() {
 
             function typePassesFilter(filter, type) {
                 // No filter
-                if (filter < 0) return true;
+                if (filter <= NO_TYPE_FILTER) return true;
 
                 // Exact match
                 if (filter === type) return true;
@@ -926,11 +943,13 @@ function getSearchElement() {
                 var name = itemTypes[type];
                 switch (itemTypes[filter]) {
                     case "constant":
-                        return (name == "associatedconstant");
+                        return name === "associatedconstant";
                     case "fn":
-                        return (name == "method" || name == "tymethod");
+                        return name === "method" || name === "tymethod";
                     case "type":
-                        return (name == "primitive" || name == "keyword");
+                        return name === "primitive" || name === "associatedtype";
+                    case "trait":
+                        return name === "traitalias";
                 }
 
                 // No match
@@ -959,42 +978,33 @@ function getSearchElement() {
                     if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
                         continue;
                     }
-                    in_args = findArg(searchIndex[i], val, true);
-                    returned = checkReturned(searchIndex[i], val, true);
+                    in_args = findArg(searchIndex[i], val, true, typeFilter);
+                    returned = checkReturned(searchIndex[i], val, true, typeFilter);
                     ty = searchIndex[i];
                     fullId = generateId(ty);
 
-                    if (searchWords[i] === val.name) {
-                        // filter type: ... queries
-                        if (typePassesFilter(typeFilter, searchIndex[i].ty) &&
-                            results[fullId] === undefined)
-                        {
-                            results[fullId] = {id: i, index: -1};
-                        }
-                    } else if ((in_args === true || returned === true) &&
-                               typePassesFilter(typeFilter, searchIndex[i].ty)) {
-                        if (in_args === true || returned === true) {
-                            if (in_args === true) {
-                                results_in_args[fullId] = {
-                                    id: i,
-                                    index: -1,
-                                    dontValidate: true,
-                                };
-                            }
-                            if (returned === true) {
-                                results_returned[fullId] = {
-                                    id: i,
-                                    index: -1,
-                                    dontValidate: true,
-                                };
-                            }
-                        } else {
-                            results[fullId] = {
-                                id: i,
-                                index: -1,
-                                dontValidate: true,
-                            };
-                        }
+                    if (searchWords[i] === val.name
+                        && typePassesFilter(typeFilter, searchIndex[i].ty)
+                        && results[fullId] === undefined) {
+                        results[fullId] = {
+                            id: i,
+                            index: -1,
+                            dontValidate: true,
+                        };
+                    }
+                    if (in_args === true && results_in_args[fullId] === undefined) {
+                        results_in_args[fullId] = {
+                            id: i,
+                            index: -1,
+                            dontValidate: true,
+                        };
+                    }
+                    if (returned === true && results_returned[fullId] === undefined) {
+                        results_returned[fullId] = {
+                            id: i,
+                            index: -1,
+                            dontValidate: true,
+                        };
                     }
                 }
                 query.inputs = [val];
@@ -1025,7 +1035,7 @@ function getSearchElement() {
 
                     // allow searching for void (no output) functions as well
                     var typeOutput = type.length > OUTPUT_DATA ? type[OUTPUT_DATA].name : "";
-                    returned = checkReturned(ty, output, true);
+                    returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
                     if (output.name === "*" || returned === true) {
                         in_args = false;
                         var is_module = false;
@@ -1126,16 +1136,8 @@ function getSearchElement() {
                             lev += 1;
                         }
                     }
-                    if ((in_args = findArg(ty, valGenerics)) <= MAX_LEV_DISTANCE) {
-                        if (typePassesFilter(typeFilter, ty.ty) === false) {
-                            in_args = MAX_LEV_DISTANCE + 1;
-                        }
-                    }
-                    if ((returned = checkReturned(ty, valGenerics)) <= MAX_LEV_DISTANCE) {
-                        if (typePassesFilter(typeFilter, ty.ty) === false) {
-                            returned = MAX_LEV_DISTANCE + 1;
-                        }
-                    }
+                    in_args = findArg(ty, valGenerics, false, typeFilter);
+                    returned = checkReturned(ty, valGenerics, false, typeFilter);
 
                     lev += lev_add;
                     if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index f05db6c2185..8887bca3c59 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -1032,7 +1032,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
 
 .information {
 	position: absolute;
-	left: -20px;
+	left: -25px;
 	margin-top: 7px;
 	z-index: 1;
 }
@@ -1047,12 +1047,13 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
 	width: 120px;
 	display: none;
 	text-align: center;
-	padding: 5px 3px;
+	padding: 5px 3px 3px 3px;
 	border-radius: 6px;
 	margin-left: 5px;
 	top: -5px;
 	left: 105%;
 	z-index: 10;
+	font-size: 16px;
 }
 
 .tooltip:hover .tooltiptext {
@@ -1063,14 +1064,20 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
 	content: " ";
 	position: absolute;
 	top: 50%;
-	left: 11px;
+	left: 16px;
 	margin-top: -5px;
 	border-width: 5px;
 	border-style: solid;
 }
 
+.tooltip.compile_fail, .tooltip.ignore {
+	font-weight: bold;
+	font-size: 20px;
+}
+
 .tooltip .tooltiptext {
 	border: 1px solid;
+	font-weight: normal;
 }
 
 pre.rust {
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index e7041d54c6b..ff32a0fa09e 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -254,7 +254,7 @@ a.test-arrow:hover{
 }
 
 pre.compile_fail {
-	border-left: 2px solid rgba(255,0,0,.6);
+	border-left: 2px solid rgba(255,0,0,.8);
 }
 
 pre.compile_fail:hover, .information:hover + pre.compile_fail {
@@ -270,7 +270,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip.compile_fail {
-	color: rgba(255,0,0,.6);
+	color: rgba(255,0,0,.8);
 }
 
 .information > .compile_fail:hover {
@@ -282,7 +282,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .information > .ignore:hover {
-	color: rgba(255,142,0,1);
+	color: #ff9200;
 }
 
 .search-failed a {
@@ -290,8 +290,9 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip .tooltiptext {
-	background-color: black;
+	background-color: #000;
 	color: #fff;
+	border-color: #000;
 }
 
 .tooltip .tooltiptext::after {
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index a1efef6701f..2b2819f7126 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -248,7 +248,7 @@ a.test-arrow:hover{
 }
 
 pre.compile_fail {
-	border-left: 2px solid rgba(255,0,0,.4);
+	border-left: 2px solid rgba(255,0,0,.5);
 }
 
 pre.compile_fail:hover, .information:hover + pre.compile_fail {
@@ -256,7 +256,7 @@ pre.compile_fail:hover, .information:hover + pre.compile_fail {
 }
 
 pre.ignore {
-	border-left: 2px solid rgba(255,142,0,.4);
+	border-left: 2px solid rgba(255,142,0,.6);
 }
 
 pre.ignore:hover, .information:hover + pre.ignore {
@@ -264,7 +264,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip.compile_fail {
-	color: rgba(255,0,0,.3);
+	color: rgba(255,0,0,.5);
 }
 
 .information > .compile_fail:hover {
@@ -272,11 +272,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip.ignore {
-	color: rgba(255,142,0,.3);
+	color: rgba(255,142,0,.6);
 }
 
 .information > .ignore:hover {
-	color: rgba(255,142,0,1);
+	color: #ff9200;
 }
 
 .search-failed a {
@@ -284,7 +284,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
 }
 
 .tooltip .tooltiptext {
-	background-color: black;
+	background-color: #000;
 	color: #fff;
 }
 
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 9fc1d76185f..6790f3bd5d0 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -8,106 +8,106 @@
 //! directly written to a `Write` handle.
 
 /// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
-pub static RUSTDOC_CSS: &'static str = include_str!("static/rustdoc.css");
+pub static RUSTDOC_CSS: &str = include_str!("static/rustdoc.css");
 
 /// The file contents of `settings.css`, responsible for the items on the settings page.
-pub static SETTINGS_CSS: &'static str = include_str!("static/settings.css");
+pub static SETTINGS_CSS: &str = include_str!("static/settings.css");
 
 /// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
-pub static NOSCRIPT_CSS: &'static str = include_str!("static/noscript.css");
+pub static NOSCRIPT_CSS: &str = include_str!("static/noscript.css");
 
 /// The file contents of `normalize.css`, included to even out standard elements between browser
 /// implementations.
-pub static NORMALIZE_CSS: &'static str = include_str!("static/normalize.css");
+pub static NORMALIZE_CSS: &str = include_str!("static/normalize.css");
 
 /// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
 /// including search behavior and docblock folding, among others.
-pub static MAIN_JS: &'static str = include_str!("static/main.js");
+pub static MAIN_JS: &str = include_str!("static/main.js");
 
 /// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
 /// page.
-pub static SETTINGS_JS: &'static str = include_str!("static/settings.js");
+pub static SETTINGS_JS: &str = include_str!("static/settings.js");
 
 /// The file contents of `storage.js`, which contains functionality related to browser Local
 /// Storage, used to store documentation settings.
-pub static STORAGE_JS: &'static str = include_str!("static/storage.js");
+pub static STORAGE_JS: &str = include_str!("static/storage.js");
 
 /// The file contents of `brush.svg`, the icon used for the theme-switch button.
-pub static BRUSH_SVG: &'static [u8] = include_bytes!("static/brush.svg");
+pub static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg");
 
 /// The file contents of `wheel.svg`, the icon used for the settings button.
-pub static WHEEL_SVG: &'static [u8] = include_bytes!("static/wheel.svg");
+pub static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg");
 
 /// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
-pub static DOWN_ARROW_SVG: &'static [u8] = include_bytes!("static/down-arrow.svg");
+pub static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg");
 
 /// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
 /// output.
-pub static COPYRIGHT: &'static [u8] = include_bytes!("static/COPYRIGHT.txt");
+pub static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt");
 
 /// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0.
-pub static LICENSE_APACHE: &'static [u8] = include_bytes!("static/LICENSE-APACHE.txt");
+pub static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt");
 
 /// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
-pub static LICENSE_MIT: &'static [u8] = include_bytes!("static/LICENSE-MIT.txt");
+pub static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt");
 
 /// The contents of `rust-logo.png`, the default icon of the documentation.
-pub static RUST_LOGO: &'static [u8] = include_bytes!("static/rust-logo.png");
+pub static RUST_LOGO: &[u8] = include_bytes!("static/rust-logo.png");
 /// The contents of `favicon.ico`, the default favicon of the documentation.
-pub static RUST_FAVICON: &'static [u8] = include_bytes!("static/favicon.ico");
+pub static RUST_FAVICON: &[u8] = include_bytes!("static/favicon.ico");
 
 /// The built-in themes given to every documentation site.
 pub mod themes {
     /// The "light" theme, selected by default when no setting is available. Used as the basis for
     /// the `--check-theme` functionality.
-    pub static LIGHT: &'static str = include_str!("static/themes/light.css");
+    pub static LIGHT: &str = include_str!("static/themes/light.css");
 
     /// The "dark" theme.
-    pub static DARK: &'static str = include_str!("static/themes/dark.css");
+    pub static DARK: &str = include_str!("static/themes/dark.css");
 }
 
 /// Files related to the Fira Sans font.
 pub mod fira_sans {
     /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font.
-    pub static REGULAR: &'static [u8] = include_bytes!("static/FiraSans-Regular.woff");
+    pub static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff");
 
     /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font.
-    pub static MEDIUM: &'static [u8] = include_bytes!("static/FiraSans-Medium.woff");
+    pub static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff");
 
     /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
-    pub static LICENSE: &'static [u8] = include_bytes!("static/FiraSans-LICENSE.txt");
+    pub static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt");
 }
 
 /// Files related to the Source Serif Pro font.
 pub mod source_serif_pro {
     /// The file `SourceSerifPro-Regular.ttf.woff`, the Regular variant of the Source Serif Pro
     /// font.
-    pub static REGULAR: &'static [u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff");
+    pub static REGULAR: &[u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff");
 
     /// The file `SourceSerifPro-Bold.ttf.woff`, the Bold variant of the Source Serif Pro font.
-    pub static BOLD: &'static [u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff");
+    pub static BOLD: &[u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff");
 
     /// The file `SourceSerifPro-It.ttf.woff`, the Italic variant of the Source Serif Pro font.
-    pub static ITALIC: &'static [u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff");
+    pub static ITALIC: &[u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff");
 
     /// The file `SourceSerifPro-LICENSE.txt`, the license text for the Source Serif Pro font.
-    pub static LICENSE: &'static [u8] = include_bytes!("static/SourceSerifPro-LICENSE.md");
+    pub static LICENSE: &[u8] = include_bytes!("static/SourceSerifPro-LICENSE.md");
 }
 
 /// Files related to the Source Code Pro font.
 pub mod source_code_pro {
     /// The file `SourceCodePro-Regular.woff`, the Regular variant of the Source Code Pro font.
-    pub static REGULAR: &'static [u8] = include_bytes!("static/SourceCodePro-Regular.woff");
+    pub static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.woff");
 
     /// The file `SourceCodePro-Semibold.woff`, the Semibold variant of the Source Code Pro font.
-    pub static SEMIBOLD: &'static [u8] = include_bytes!("static/SourceCodePro-Semibold.woff");
+    pub static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.woff");
 
     /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
-    pub static LICENSE: &'static [u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
+    pub static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
 }
 
 /// Files related to the sidebar in rustdoc sources.
 pub mod sidebar {
     /// File script to handle sidebar.
-    pub static SOURCE_SCRIPT: &'static str = include_str!("static/source-script.js");
+    pub static SOURCE_SCRIPT: &str = include_str!("static/source-script.js");
 }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 4ea14ab9077..3c1f0509bba 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -38,6 +38,7 @@ extern crate rustc_resolve;
 extern crate rustc_session;
 extern crate rustc_span as rustc_span;
 extern crate rustc_target;
+extern crate rustc_trait_selection;
 extern crate rustc_typeck;
 extern crate test as testing;
 #[macro_use]
@@ -48,8 +49,8 @@ use std::env;
 use std::panic;
 use std::process;
 
-use rustc::session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup};
-use rustc::session::{early_error, early_warn};
+use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup};
+use rustc_session::{early_error, early_warn};
 
 #[macro_use]
 mod externalfiles;
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index d4a7f3313a4..f48224512ba 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -1,4 +1,5 @@
 use crate::clean;
+use crate::config::OutputFormat;
 use crate::core::DocContext;
 use crate::fold::{self, DocFolder};
 use crate::passes::Pass;
@@ -6,6 +7,8 @@ use crate::passes::Pass;
 use rustc_ast::attr;
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
+use serde::Serialize;
+use serde_json;
 
 use std::collections::BTreeMap;
 use std::ops;
@@ -16,16 +19,16 @@ pub const CALCULATE_DOC_COVERAGE: Pass = Pass {
     description: "counts the number of items with and without documentation",
 };
 
-fn calculate_doc_coverage(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
-    let mut calc = CoverageCalculator::default();
+fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate {
+    let mut calc = CoverageCalculator::new();
     let krate = calc.fold_crate(krate);
 
-    calc.print_results();
+    calc.print_results(ctx.renderinfo.borrow().output_format);
 
     krate
 }
 
-#[derive(Default, Copy, Clone)]
+#[derive(Default, Copy, Clone, Serialize)]
 struct ItemCount {
     total: u64,
     with_docs: u64,
@@ -64,13 +67,41 @@ impl ops::AddAssign for ItemCount {
     }
 }
 
-#[derive(Default)]
 struct CoverageCalculator {
     items: BTreeMap<FileName, ItemCount>,
 }
 
+fn limit_filename_len(filename: String) -> String {
+    let nb_chars = filename.chars().count();
+    if nb_chars > 35 {
+        "...".to_string()
+            + &filename[filename.char_indices().nth(nb_chars - 32).map(|x| x.0).unwrap_or(0)..]
+    } else {
+        filename
+    }
+}
+
 impl CoverageCalculator {
-    fn print_results(&self) {
+    fn new() -> CoverageCalculator {
+        CoverageCalculator { items: Default::default() }
+    }
+
+    fn to_json(&self) -> String {
+        serde_json::to_string(
+            &self
+                .items
+                .iter()
+                .map(|(k, v)| (k.to_string(), v))
+                .collect::<BTreeMap<String, &ItemCount>>(),
+        )
+        .expect("failed to convert JSON data to string")
+    }
+
+    fn print_results(&self, output_format: Option<OutputFormat>) {
+        if output_format.map(|o| o.is_json()).unwrap_or_else(|| false) {
+            println!("{}", self.to_json());
+            return;
+        }
         let mut total = ItemCount::default();
 
         fn print_table_line() {
@@ -93,15 +124,7 @@ impl CoverageCalculator {
 
         for (file, &count) in &self.items {
             if let Some(percentage) = count.percentage() {
-                let mut name = file.to_string();
-                // if a filename is too long, shorten it so we don't blow out the table
-                // FIXME(misdreavus): this needs to count graphemes, and probably also track
-                // double-wide characters...
-                if name.len() > 35 {
-                    name = "...".to_string() + &name[name.len() - 32..];
-                }
-
-                print_table_record(&name, count, percentage);
+                print_table_record(&limit_filename_len(file.to_string()), count, percentage);
 
                 total += count;
             }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 7aa90d66781..113c781e332 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1,4 +1,3 @@
-use rustc::lint;
 use rustc::ty;
 use rustc_ast::ast::{self, Ident};
 use rustc_errors::Applicability;
@@ -12,6 +11,7 @@ use rustc_hir::def::{
 };
 use rustc_hir::def_id::DefId;
 use rustc_resolve::ParentScope;
+use rustc_session::lint;
 use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
 
@@ -149,7 +149,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 // In case this is a trait item, skip the
                 // early return and try looking for the trait.
                 let value = match res {
-                    Res::Def(DefKind::Method, _) | Res::Def(DefKind::AssocConst, _) => true,
+                    Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::AssocConst, _) => true,
                     Res::Def(DefKind::AssocTy, _) => false,
                     Res::Def(DefKind::Variant, _) => {
                         return handle_variant(cx, res, extra_fragment);
@@ -348,7 +348,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
         let parent_node = self.cx.as_local_hir_id(item.def_id).and_then(|hir_id| {
             // FIXME: this fails hard for impls in non-module scope, but is necessary for the
             // current `resolve()` implementation.
-            match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id)).unwrap() {
+            match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id).to_def_id()).unwrap() {
                 id if id != hir_id => Some(id),
                 _ => None,
             }
@@ -813,7 +813,7 @@ fn ambiguity_error(
 
                     for (res, ns) in candidates {
                         let (action, mut suggestion) = match res {
-                            Res::Def(DefKind::Method, _) | Res::Def(DefKind::Fn, _) => {
+                            Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Fn, _) => {
                                 ("add parentheses", format!("{}()", path_str))
                             }
                             Res::Def(DefKind::Macro(..), _) => {
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 71cff637c12..38f371783e9 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -1,9 +1,9 @@
 //! Contains information about "passes", used to modify crate information during the documentation
 //! process.
 
-use rustc::lint;
 use rustc::middle::privacy::AccessLevels;
 use rustc_hir::def_id::{DefId, DefIdSet};
+use rustc_session::lint;
 use rustc_span::{InnerSpan, Span, DUMMY_SP};
 use std::mem;
 use std::ops::Range;
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index b63dbbf80d8..c5aa4677d56 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -1,5 +1,4 @@
 use rustc::hir::map::Map;
-use rustc::session::{self, config, DiagnosticOutput};
 use rustc::util::common::ErrorReported;
 use rustc_ast::ast;
 use rustc_ast::with_globals;
@@ -8,6 +7,7 @@ use rustc_feature::UnstableFeatures;
 use rustc_hir as hir;
 use rustc_hir::intravisit;
 use rustc_interface::interface;
+use rustc_session::{self, config, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
@@ -52,7 +52,7 @@ pub fn run(options: Options) -> i32 {
         cg: options.codegen_options.clone(),
         externs: options.externs.clone(),
         unstable_features: UnstableFeatures::from_environment(),
-        lint_cap: Some(::rustc::lint::Level::Allow),
+        lint_cap: Some(rustc_session::lint::Level::Allow),
         actually_rustdoc: true,
         debugging_opts: config::DebuggingOptions { ..config::basic_debugging_options() },
         edition: options.edition,
@@ -107,12 +107,12 @@ pub fn run(options: Options) -> i32 {
                 let mut hir_collector = HirCollector {
                     sess: compiler.session(),
                     collector: &mut collector,
-                    map: *tcx.hir(),
+                    map: tcx.hir(),
                     codes: ErrorCodes::from(
                         compiler.session().opts.unstable_features.is_nightly_build(),
                     ),
                 };
-                hir_collector.visit_testable("".to_string(), &krate.attrs, |this| {
+                hir_collector.visit_testable("".to_string(), &krate.item.attrs, |this| {
                     intravisit::walk_crate(this, krate);
                 });
             });
@@ -146,6 +146,7 @@ fn scrape_test_config(krate: &::rustc_hir::Crate) -> TestOptions {
         TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() };
 
     let test_attrs: Vec<_> = krate
+        .item
         .attrs
         .iter()
         .filter(|a| a.check_name(sym::doc))
@@ -449,7 +450,7 @@ pub fn make_test(
                         }
 
                         if !found_macro {
-                            if let ast::ItemKind::Mac(..) = item.kind {
+                            if let ast::ItemKind::MacCall(..) = item.kind {
                                 found_macro = true;
                             }
                         }
@@ -853,9 +854,9 @@ impl Tester for Collector {
 }
 
 struct HirCollector<'a, 'hir> {
-    sess: &'a session::Session,
+    sess: &'a Session,
     collector: &'a mut Collector,
-    map: &'a Map<'hir>,
+    map: Map<'hir>,
     codes: ErrorCodes,
 }
 
@@ -903,8 +904,8 @@ impl<'a, 'hir> HirCollector<'a, 'hir> {
 impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
     type Map = Map<'hir>;
 
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
-        intravisit::NestedVisitorMap::All(&self.map)
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::All(self.map)
     }
 
     fn visit_item(&mut self, item: &'hir hir::Item) {
@@ -955,7 +956,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
     }
 
     fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef) {
-        self.visit_testable(macro_def.name.to_string(), &macro_def.attrs, |_| ());
+        self.visit_testable(macro_def.ident.to_string(), &macro_def.attrs, |_| ());
     }
 }
 
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 8f2f88d08bf..feaf391c95a 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -64,11 +64,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
     pub fn visit(mut self, krate: &'tcx hir::Crate) -> Module<'tcx> {
         let mut module = self.visit_mod_contents(
-            krate.span,
-            krate.attrs,
+            krate.item.span,
+            krate.item.attrs,
             &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
-            &krate.module,
+            &krate.item.module,
             None,
         );
         // Attach the crate's exported macros to the top-level module:
@@ -620,8 +620,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         def: &'tcx hir::MacroDef,
         renamed: Option<ast::Name>,
     ) -> Macro<'tcx> {
-        debug!("visit_local_macro: {}", def.name);
-        let tts = def.body.trees().collect::<Vec<_>>();
+        debug!("visit_local_macro: {}", def.ident);
+        let tts = def.ast.body.inner_tokens().trees().collect::<Vec<_>>();
         // Extract the spans of all matchers. They represent the "interface" of the macro.
         let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect();
 
@@ -629,7 +629,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             hid: def.hir_id,
             def_id: self.cx.tcx.hir().local_def_id(def.hir_id),
             attrs: &def.attrs,
-            name: renamed.unwrap_or(def.name),
+            name: renamed.unwrap_or(def.ident.name),
             whence: def.span,
             matchers,
             imported_from: None,
diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs
index 97db0ff3791..34317c7a2ee 100644
--- a/src/libstd/backtrace.rs
+++ b/src/libstd/backtrace.rs
@@ -92,6 +92,7 @@
 // a backtrace or actually symbolizing it.
 
 use crate::env;
+use crate::ffi::c_void;
 use crate::fmt;
 use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
 use crate::sync::Mutex;
@@ -144,10 +145,16 @@ fn _assert_send_sync() {
 }
 
 struct BacktraceFrame {
-    frame: backtrace::Frame,
+    frame: RawFrame,
     symbols: Vec<BacktraceSymbol>,
 }
 
+enum RawFrame {
+    Actual(backtrace::Frame),
+    #[cfg(test)]
+    Fake,
+}
+
 struct BacktraceSymbol {
     name: Option<Vec<u8>>,
     filename: Option<BytesOrWide>,
@@ -162,8 +169,8 @@ enum BytesOrWide {
 impl fmt::Debug for Backtrace {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut capture = match &self.inner {
-            Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
-            Inner::Disabled => return fmt.write_str("disabled backtrace"),
+            Inner::Unsupported => return fmt.write_str("<unsupported>"),
+            Inner::Disabled => return fmt.write_str("<disabled>"),
             Inner::Captured(c) => c.lock().unwrap(),
         };
         capture.resolve();
@@ -193,11 +200,11 @@ impl fmt::Debug for BacktraceSymbol {
         if let Some(fn_name) = self.name.as_ref().map(|b| backtrace::SymbolName::new(b)) {
             write!(fmt, "fn: \"{:#}\"", fn_name)?;
         } else {
-            write!(fmt, "fn: \"<unknown>\"")?;
+            write!(fmt, "fn: <unknown>")?;
         }
 
         if let Some(fname) = self.filename.as_ref() {
-            write!(fmt, ", file: {:?}", fname)?;
+            write!(fmt, ", file: \"{:?}\"", fname)?;
         }
 
         if let Some(line) = self.lineno.as_ref() {
@@ -293,7 +300,10 @@ impl Backtrace {
         let mut actual_start = None;
         unsafe {
             backtrace::trace_unsynchronized(|frame| {
-                frames.push(BacktraceFrame { frame: frame.clone(), symbols: Vec::new() });
+                frames.push(BacktraceFrame {
+                    frame: RawFrame::Actual(frame.clone()),
+                    symbols: Vec::new(),
+                });
                 if frame.symbol_address() as usize == ip && actual_start.is_none() {
                     actual_start = Some(frames.len());
                 }
@@ -393,8 +403,13 @@ impl Capture {
         let _lock = lock();
         for frame in self.frames.iter_mut() {
             let symbols = &mut frame.symbols;
+            let frame = match &frame.frame {
+                RawFrame::Actual(frame) => frame,
+                #[cfg(test)]
+                RawFrame::Fake => unimplemented!(),
+            };
             unsafe {
-                backtrace::resolve_frame_unsynchronized(&frame.frame, |symbol| {
+                backtrace::resolve_frame_unsynchronized(frame, |symbol| {
                     symbols.push(BacktraceSymbol {
                         name: symbol.name().map(|m| m.as_bytes().to_vec()),
                         filename: symbol.filename_raw().map(|b| match b {
@@ -408,3 +423,65 @@ impl Capture {
         }
     }
 }
+
+impl RawFrame {
+    fn ip(&self) -> *mut c_void {
+        match self {
+            RawFrame::Actual(frame) => frame.ip(),
+            #[cfg(test)]
+            RawFrame::Fake => 1 as *mut c_void,
+        }
+    }
+}
+
+#[test]
+fn test_debug() {
+    let backtrace = Backtrace {
+        inner: Inner::Captured(Mutex::new(Capture {
+            actual_start: 1,
+            resolved: true,
+            frames: vec![
+                BacktraceFrame {
+                    frame: RawFrame::Fake,
+                    symbols: vec![BacktraceSymbol {
+                        name: Some(b"std::backtrace::Backtrace::create".to_vec()),
+                        filename: Some(BytesOrWide::Bytes(b"rust/backtrace.rs".to_vec())),
+                        lineno: Some(100),
+                    }],
+                },
+                BacktraceFrame {
+                    frame: RawFrame::Fake,
+                    symbols: vec![BacktraceSymbol {
+                        name: Some(b"__rust_maybe_catch_panic".to_vec()),
+                        filename: None,
+                        lineno: None,
+                    }],
+                },
+                BacktraceFrame {
+                    frame: RawFrame::Fake,
+                    symbols: vec![
+                        BacktraceSymbol {
+                            name: Some(b"std::rt::lang_start_internal".to_vec()),
+                            filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
+                            lineno: Some(300),
+                        },
+                        BacktraceSymbol {
+                            name: Some(b"std::rt::lang_start".to_vec()),
+                            filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
+                            lineno: Some(400),
+                        },
+                    ],
+                },
+            ],
+        })),
+    };
+
+    #[rustfmt::skip]
+    let expected = "Backtrace [\
+    \n    { fn: \"__rust_maybe_catch_panic\" },\
+    \n    { fn: \"std::rt::lang_start_internal\", file: \"rust/rt.rs\", line: 300 },\
+    \n    { fn: \"std::rt::lang_start\", file: \"rust/rt.rs\", line: 400 },\
+    \n]";
+
+    assert_eq!(format!("{:#?}", backtrace), expected);
+}
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 3f6501bc7b4..2a370f19296 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -552,6 +552,9 @@ impl Error for char::ParseCharError {
     }
 }
 
+#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
+impl Error for alloc::collections::TryReserveError {}
+
 // Copied from `any.rs`.
 impl dyn Error + 'static {
     /// Returns `true` if the boxed type is the same as `T`
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index 7b1beb1ecda..c1ca6771326 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -41,10 +41,7 @@ impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
         // Safe because we're !Unpin + !Drop mapping to a ?Unpin value
         let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
         let _guard = unsafe { set_task_context(cx) };
-        match gen.resume(
-            #[cfg(not(bootstrap))]
-            (),
-        ) {
+        match gen.resume(()) {
             GeneratorState::Yielded(()) => Poll::Pending,
             GeneratorState::Complete(x) => Poll::Ready(x),
         }
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 420d6ea589a..dc831432c17 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1050,6 +1050,7 @@ impl<'a> DerefMut for IoSliceMut<'a> {
 /// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
 /// Windows.
 #[stable(feature = "iovec", since = "1.36.0")]
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a>(sys::io::IoSlice<'a>);
 
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index d410faca30d..0fb0757792e 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -792,10 +792,14 @@ fn print_to<T>(
 {
     let result = local_s
         .try_with(|s| {
-            if let Ok(mut borrowed) = s.try_borrow_mut() {
-                if let Some(w) = borrowed.as_mut() {
-                    return w.write_fmt(args);
-                }
+            // Note that we completely remove a local sink to write to in case
+            // our printing recursively panics/prints, so the recursive
+            // panic/print goes to the global sink instead of our local sink.
+            let prev = s.borrow_mut().take();
+            if let Some(mut w) = prev {
+                let result = w.write_fmt(args);
+                *s.borrow_mut() = Some(w);
+                return result;
             }
             global_s().write_fmt(args)
         })
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index 3c69c1160d5..314424631fc 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -234,12 +234,55 @@ mod crate_keyword {}
 
 #[doc(keyword = "else")]
 //
-/// What to do when an [`if`] condition does not hold.
+/// What expression to evaluate when an [`if`] condition evaluates to [`false`].
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// `else` expressions are optional. When no else expressions are supplied it is assumed to evaluate
+/// to the unit type `()`.
+///
+/// The type that the `else` blocks evaluate to must be compatible with the type that the `if` block
+/// evaluates to.
+///
+/// As can be seen below, `else` must be followed by either: `if`, `if let`, or a block `{}` and it
+/// will return the value of that expression.
+///
+/// ```rust
+/// let result = if true == false {
+///     "oh no"
+/// } else if "something" == "other thing" {
+///     "oh dear"
+/// } else if let Some(200) = "blarg".parse::<i32>().ok() {
+///     "uh oh"
+/// } else {
+///     println!("Sneaky side effect.");
+///     "phew, nothing's broken"
+/// };
+/// ```
+///
+/// Here's another example but here we do not try and return an expression:
+///
+/// ```rust
+/// if true == false {
+///     println!("oh no");
+/// } else if "something" == "other thing" {
+///     println!("oh dear");
+/// } else if let Some(200) = "blarg".parse::<i32>().ok() {
+///     println!("uh oh");
+/// } else {
+///     println!("phew, nothing's broken");
+/// }
+/// ```
 ///
+/// The above is _still_ an expression but it will always evaluate to `()`.
+///
+/// There is possibly no limit to the number of `else` blocks that could follow an `if` expression
+/// however if you have several then a [`match`] expression might be preferable.
+///
+/// Read more about control flow in the [Rust Book].
+///
+/// [Rust Book]: ../book/ch03-05-control-flow.html#handling-multiple-conditions-with-else-if
+/// [`match`]: keyword.match.html
+/// [`false`]: keyword.false.html
 /// [`if`]: keyword.if.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
 mod else_keyword {}
 
 #[doc(keyword = "enum")]
@@ -637,10 +680,18 @@ mod impl_keyword {}
 //
 /// Iterate over a series of values with [`for`].
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// The expression immediately following `in` must implement the [`Iterator`] trait.
+///
+/// ## Literal Examples:
+///
+///    * `for _ **in** 1..3 {}` - Iterate over an exclusive range up to but excluding 3.
+///    * `for _ **in** 1..=3 {}` - Iterate over an inclusive range up to and includeing 3.
+///
+/// (Read more about [range patterns])
 ///
+/// [`Iterator`]: ../book/ch13-04-performance.html
+/// [`range patterns`]: ../reference/patterns.html?highlight=range#range-patterns
 /// [`for`]: keyword.for.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
 mod in_keyword {}
 
 #[doc(keyword = "let")]
@@ -925,9 +976,15 @@ mod mut_keyword {}
 //
 /// Make an item visible to others.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// The keyword `pub` makes any module, function, or data structure accessible from inside
+/// of external modules. The `pub` keyword may also be used in a `use` declaration to re-export
+/// an identifier from a namespace.
 ///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// For more information on the `pub` keyword, please see the visibility section
+/// of the [reference] and for some examples, see [Rust by Example].
+///
+/// [reference]:../reference/visibility-and-privacy.html?highlight=pub#visibility-and-privacy
+/// [Rust by Example]:../rust-by-example/mod/visibility.html
 mod pub_keyword {}
 
 #[doc(keyword = "ref")]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 231908ddda0..1f122b02b6a 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -240,6 +240,7 @@
 #![feature(atomic_mut_ptr)]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
+#![cfg_attr(not(bootstrap), feature(cfg_accessible))]
 #![feature(cfg_target_has_atomic)]
 #![feature(cfg_target_thread_local)]
 #![feature(char_error_internals)]
@@ -292,7 +293,8 @@
 #![feature(shrink_to)]
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
-#![feature(specialization)]
+#![cfg_attr(bootstrap, feature(specialization))]
+#![cfg_attr(not(bootstrap), feature(min_specialization))]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stdsimd)]
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 8b12aaaa7e2..10078bd4aee 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -14,7 +14,6 @@ use crate::fmt;
 use crate::intrinsics;
 use crate::mem::{self, ManuallyDrop};
 use crate::process;
-use crate::raw;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::stdio::panic_output;
 use crate::sys_common::backtrace::{self, RustBacktrace};
@@ -41,12 +40,7 @@ use realstd::io::set_panic;
 // hook up these functions, but it is not this day!
 #[allow(improper_ctypes)]
 extern "C" {
-    fn __rust_maybe_catch_panic(
-        f: fn(*mut u8),
-        data: *mut u8,
-        data_ptr: *mut usize,
-        vtable_ptr: *mut usize,
-    ) -> u32;
+    fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
 
     /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings.
     /// It cannot be `Box<dyn BoxMeUp>` because the other end of this call does not depend
@@ -247,54 +241,88 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
     union Data<F, R> {
         f: ManuallyDrop<F>,
         r: ManuallyDrop<R>,
+        p: ManuallyDrop<Box<dyn Any + Send>>,
     }
 
     // We do some sketchy operations with ownership here for the sake of
-    // performance. We can only  pass pointers down to
-    // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all
-    // the ownership tracking here manually using a union.
+    // performance. We can only pass pointers down to `do_call` (can't pass
+    // objects by value), so we do all the ownership tracking here manually
+    // using a union.
     //
     // We go through a transition where:
     //
-    // * First, we set the data to be the closure that we're going to call.
+    // * First, we set the data field `f` to be the argumentless closure that we're going to call.
     // * When we make the function call, the `do_call` function below, we take
-    //   ownership of the function pointer. At this point the `Data` union is
+    //   ownership of the function pointer. At this point the `data` union is
     //   entirely uninitialized.
     // * If the closure successfully returns, we write the return value into the
-    //   data's return slot. Note that `ptr::write` is used as it's overwriting
-    //   uninitialized data.
-    // * Finally, when we come back out of the `__rust_maybe_catch_panic` we're
+    //   data's return slot (field `r`).
+    // * If the closure panics (`do_catch` below), we write the panic payload into field `p`.
+    // * Finally, when we come back out of the `try` intrinsic we're
     //   in one of two states:
     //
     //      1. The closure didn't panic, in which case the return value was
-    //         filled in. We move it out of `data` and return it.
-    //      2. The closure panicked, in which case the return value wasn't
-    //         filled in. In this case the entire `data` union is invalid, so
-    //         there is no need to drop anything.
+    //         filled in. We move it out of `data.r` and return it.
+    //      2. The closure panicked, in which case the panic payload was
+    //         filled in. We move it out of `data.p` and return it.
     //
     // Once we stack all that together we should have the "most efficient'
     // method of calling a catch panic whilst juggling ownership.
-    let mut any_data = 0;
-    let mut any_vtable = 0;
     let mut data = Data { f: ManuallyDrop::new(f) };
 
-    let r = __rust_maybe_catch_panic(
-        do_call::<F, R>,
-        &mut data as *mut _ as *mut u8,
-        &mut any_data,
-        &mut any_vtable,
-    );
-
-    return if r == 0 {
+    let data_ptr = &mut data as *mut _ as *mut u8;
+    return if do_try(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
         Ok(ManuallyDrop::into_inner(data.r))
     } else {
-        update_panic_count(-1);
-        Err(mem::transmute(raw::TraitObject {
-            data: any_data as *mut _,
-            vtable: any_vtable as *mut _,
-        }))
+        Err(ManuallyDrop::into_inner(data.p))
     };
 
+    // Compatibility wrapper around the try intrinsic for bootstrap.
+    //
+    // We also need to mark it #[inline(never)] to work around a bug on MinGW
+    // targets: the unwinding implementation was relying on UB, but this only
+    // becomes a problem in practice if inlining is involved.
+    #[cfg(not(bootstrap))]
+    use intrinsics::r#try as do_try;
+    #[cfg(bootstrap)]
+    #[inline(never)]
+    unsafe fn do_try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32 {
+        use crate::mem::MaybeUninit;
+        #[cfg(target_env = "msvc")]
+        type TryPayload = [u64; 2];
+        #[cfg(not(target_env = "msvc"))]
+        type TryPayload = *mut u8;
+
+        let mut payload: MaybeUninit<TryPayload> = MaybeUninit::uninit();
+        let payload_ptr = payload.as_mut_ptr() as *mut u8;
+        let r = intrinsics::r#try(try_fn, data, payload_ptr);
+        if r != 0 {
+            #[cfg(target_env = "msvc")]
+            {
+                catch_fn(data, payload_ptr)
+            }
+            #[cfg(not(target_env = "msvc"))]
+            {
+                catch_fn(data, payload.assume_init())
+            }
+        }
+        r
+    }
+
+    // We consider unwinding to be rare, so mark this function as cold. However,
+    // do not mark it no-inline -- that decision is best to leave to the
+    // optimizer (in most cases this function is not inlined even as a normal,
+    // non-cold function, though, as of the writing of this comment).
+    #[cold]
+    unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send + 'static> {
+        let obj = Box::from_raw(__rust_panic_cleanup(payload));
+        update_panic_count(-1);
+        obj
+    }
+
+    // See comment on do_try above for why #[inline(never)] is needed on bootstrap.
+    #[cfg_attr(bootstrap, inline(never))]
+    #[cfg_attr(not(bootstrap), inline)]
     fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
         unsafe {
             let data = data as *mut Data<F, R>;
@@ -303,6 +331,19 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
             data.r = ManuallyDrop::new(f());
         }
     }
+
+    // We *do* want this part of the catch to be inlined: this allows the
+    // compiler to properly track accesses to the Data union and optimize it
+    // away most of the time.
+    #[inline]
+    fn do_catch<F: FnOnce() -> R, R>(data: *mut u8, payload: *mut u8) {
+        unsafe {
+            let data = data as *mut Data<F, R>;
+            let data = &mut (*data);
+            let obj = cleanup(payload);
+            data.p = ManuallyDrop::new(obj);
+        }
+    }
 }
 
 /// Determines whether the current thread is unwinding because of panic.
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index 7c0efe828c2..6712f5ba580 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -53,6 +53,15 @@ pub use core::prelude::v1::{
     PartialEq, PartialOrd, RustcDecodable, RustcEncodable,
 };
 
+#[cfg(not(bootstrap))]
+#[unstable(
+    feature = "cfg_accessible",
+    issue = "64797",
+    reason = "`cfg_accessible` is not fully implemented"
+)]
+#[doc(hidden)]
+pub use core::prelude::v1::cfg_accessible;
+
 // The file so far is equivalent to src/libcore/prelude/v1.rs,
 // and below to src/liballoc/prelude.rs.
 // Those files are duplicated rather than using glob imports
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index b99b4d8d9fd..1e6b6c430be 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -363,7 +363,7 @@ impl Once {
     /// assert!(handle.join().is_err());
     /// assert_eq!(INIT.is_completed(), false);
     /// ```
-    #[stable(feature = "once_is_completed", since = "1.44.0")]
+    #[stable(feature = "once_is_completed", since = "1.43.0")]
     #[inline]
     pub fn is_completed(&self) -> bool {
         // An `Acquire` load is enough because that makes all the initialization
diff --git a/src/libstd/sys/cloudabi/io.rs b/src/libstd/sys/cloudabi/io.rs
index 976e122463d..d5f475b4310 100644
--- a/src/libstd/sys/cloudabi/io.rs
+++ b/src/libstd/sys/cloudabi/io.rs
@@ -1,5 +1,6 @@
 use crate::mem;
 
+#[derive(Copy, Clone)]
 pub struct IoSlice<'a>(&'a [u8]);
 
 impl<'a> IoSlice<'a> {
diff --git a/src/libstd/sys/hermit/io.rs b/src/libstd/sys/hermit/io.rs
index 976e122463d..d5f475b4310 100644
--- a/src/libstd/sys/hermit/io.rs
+++ b/src/libstd/sys/hermit/io.rs
@@ -1,5 +1,6 @@
 use crate::mem;
 
+#[derive(Copy, Clone)]
 pub struct IoSlice<'a>(&'a [u8]);
 
 impl<'a> IoSlice<'a> {
diff --git a/src/libstd/sys/sgx/io.rs b/src/libstd/sys/sgx/io.rs
index 976e122463d..d5f475b4310 100644
--- a/src/libstd/sys/sgx/io.rs
+++ b/src/libstd/sys/sgx/io.rs
@@ -1,5 +1,6 @@
 use crate::mem;
 
+#[derive(Copy, Clone)]
 pub struct IoSlice<'a>(&'a [u8]);
 
 impl<'a> IoSlice<'a> {
diff --git a/src/libstd/sys/unix/io.rs b/src/libstd/sys/unix/io.rs
index b4a64e93c84..deb5ee76bd0 100644
--- a/src/libstd/sys/unix/io.rs
+++ b/src/libstd/sys/unix/io.rs
@@ -3,6 +3,7 @@ use crate::slice;
 
 use libc::{c_void, iovec};
 
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a> {
     vec: iovec,
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 9e8be550755..2626ca37cf8 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -45,8 +45,9 @@ mod imp {
     use libc::{mmap, munmap};
     use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
     use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
-    use libc::{MAP_ANON, MAP_PRIVATE, PROT_READ, PROT_WRITE, SIGSEGV};
+    use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
 
+    use crate::sys::unix::os::page_size;
     use crate::sys_common::thread_info;
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -137,12 +138,22 @@ mod imp {
     }
 
     unsafe fn get_stackp() -> *mut libc::c_void {
-        let stackp =
-            mmap(ptr::null_mut(), SIGSTKSZ, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+        let stackp = mmap(
+            ptr::null_mut(),
+            SIGSTKSZ + page_size(),
+            PROT_READ | PROT_WRITE,
+            MAP_PRIVATE | MAP_ANON,
+            -1,
+            0,
+        );
         if stackp == MAP_FAILED {
             panic!("failed to allocate an alternative stack");
         }
-        stackp
+        let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE);
+        if guard_result != 0 {
+            panic!("failed to set up alternative stack guard page");
+        }
+        stackp.add(page_size())
     }
 
     #[cfg(any(
@@ -190,7 +201,9 @@ mod imp {
                 ss_size: SIGSTKSZ,
             };
             sigaltstack(&stack, ptr::null_mut());
-            munmap(handler._data, SIGSTKSZ);
+            // We know from `get_stackp` that the alternate stack we installed is part of a mapping
+            // that started one page earlier, so walk back a page and unmap from there.
+            munmap(handler._data.sub(page_size()), SIGSTKSZ + page_size());
         }
     }
 }
diff --git a/src/libstd/sys/vxworks/io.rs b/src/libstd/sys/vxworks/io.rs
index f1a2c8446ff..0f68ebf8da9 100644
--- a/src/libstd/sys/vxworks/io.rs
+++ b/src/libstd/sys/vxworks/io.rs
@@ -3,6 +3,7 @@ use crate::slice;
 
 use libc::{c_void, iovec};
 
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a> {
     vec: iovec,
diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs
index ee20ea6dab8..0ad2e152855 100644
--- a/src/libstd/sys/wasi/io.rs
+++ b/src/libstd/sys/wasi/io.rs
@@ -1,6 +1,7 @@
 use crate::marker::PhantomData;
 use crate::slice;
 
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a> {
     vec: wasi::Ciovec,
diff --git a/src/libstd/sys/wasm/io.rs b/src/libstd/sys/wasm/io.rs
index 976e122463d..d5f475b4310 100644
--- a/src/libstd/sys/wasm/io.rs
+++ b/src/libstd/sys/wasm/io.rs
@@ -1,5 +1,6 @@
 use crate::mem;
 
+#[derive(Copy, Clone)]
 pub struct IoSlice<'a>(&'a [u8]);
 
 impl<'a> IoSlice<'a> {
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 4d377341be3..7f93ef87953 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -295,6 +295,7 @@ pub struct WSADATA {
     pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
 }
 
+#[derive(Copy, Clone)]
 #[repr(C)]
 pub struct WSABUF {
     pub len: ULONG,
@@ -1044,6 +1045,10 @@ compat_fn! {
                     _dwBufferSize: DWORD) -> BOOL {
         SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
     }
+    pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME)
+                                          -> () {
+        GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
+    }
     pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE,
                                      SRWLock: PSRWLOCK,
                                      dwMilliseconds: DWORD,
diff --git a/src/libstd/sys/windows/io.rs b/src/libstd/sys/windows/io.rs
index 9d8018fd5e8..5525d283252 100644
--- a/src/libstd/sys/windows/io.rs
+++ b/src/libstd/sys/windows/io.rs
@@ -2,6 +2,7 @@ use crate::marker::PhantomData;
 use crate::slice;
 use crate::sys::c;
 
+#[derive(Copy, Clone)]
 #[repr(transparent)]
 pub struct IoSlice<'a> {
     vec: c::WSABUF,
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
index 86667ca7ab2..900260169c7 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -74,7 +74,7 @@ impl SystemTime {
     pub fn now() -> SystemTime {
         unsafe {
             let mut t: SystemTime = mem::zeroed();
-            c::GetSystemTimeAsFileTime(&mut t.t);
+            c::GetSystemTimePreciseAsFileTime(&mut t.t);
             t
         }
     }
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 289ee07babf..2c7ba8f8ea1 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -70,7 +70,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
     let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| {
         output_filename(fmt, bows, print_fmt, cwd.as_ref())
     };
-    write!(fmt, "stack backtrace:\n")?;
+    writeln!(fmt, "stack backtrace:")?;
     let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path);
     bt_fmt.add_context()?;
     let mut idx = 0;
diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs
index 042641852b3..f3a2962098b 100644
--- a/src/libstd/sys_common/process.rs
+++ b/src/libstd/sys_common/process.rs
@@ -47,7 +47,7 @@ impl CommandEnv {
             }
         }
         for (key, maybe_val) in self.vars.iter() {
-            if let &Some(ref val) = maybe_val {
+            if let Some(ref val) = maybe_val {
                 env::set_var(key, val);
             } else {
                 env::remove_var(key);
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index 1d96cdfe460..498950e6821 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -599,24 +599,16 @@ impl Wtf8 {
 
     #[inline]
     fn final_lead_surrogate(&self) -> Option<u16> {
-        let len = self.len();
-        if len < 3 {
-            return None;
-        }
-        match &self.bytes[(len - 3)..] {
-            &[0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
+        match self.bytes {
+            [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
             _ => None,
         }
     }
 
     #[inline]
     fn initial_trail_surrogate(&self) -> Option<u16> {
-        let len = self.len();
-        if len < 3 {
-            return None;
-        }
-        match &self.bytes[..3] {
-            &[0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)),
+        match self.bytes {
+            [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)),
             _ => None,
         }
     }
diff --git a/src/libtest/console.rs b/src/libtest/console.rs
index 149c9202e6e..ff741e3bd53 100644
--- a/src/libtest/console.rs
+++ b/src/libtest/console.rs
@@ -169,7 +169,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
 
     if !quiet {
         if ntest != 0 || nbench != 0 {
-            writeln!(output, "")?;
+            writeln!(output)?;
         }
 
         writeln!(output, "{}, {}", plural(ntest, "test"), plural(nbench, "benchmark"))?;
diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs
index a64c0fc263d..1fb840520a6 100644
--- a/src/libtest/formatters/mod.rs
+++ b/src/libtest/formatters/mod.rs
@@ -36,5 +36,5 @@ pub(crate) fn write_stderr_delimiter(test_output: &mut Vec<u8>, test_name: &Test
         Some(_) => test_output.push(b'\n'),
         None => (),
     }
-    write!(test_output, "---- {} stderr ----\n", test_name).unwrap();
+    writeln!(test_output, "---- {} stderr ----", test_name).unwrap();
 }
diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs
index aab8d012fdf..077005371c0 100644
--- a/src/libtest/stats.rs
+++ b/src/libtest/stats.rs
@@ -204,7 +204,7 @@ impl Stats for [f64] {
     }
 
     fn median(&self) -> f64 {
-        self.percentile(50 as f64)
+        self.percentile(50_f64)
     }
 
     fn var(&self) -> f64 {
@@ -230,7 +230,7 @@ impl Stats for [f64] {
     }
 
     fn std_dev_pct(&self) -> f64 {
-        let hundred = 100 as f64;
+        let hundred = 100_f64;
         (self.std_dev() / self.mean()) * hundred
     }
 
@@ -244,7 +244,7 @@ impl Stats for [f64] {
     }
 
     fn median_abs_dev_pct(&self) -> f64 {
-        let hundred = 100 as f64;
+        let hundred = 100_f64;
         (self.median_abs_dev() / self.median()) * hundred
     }
 
@@ -257,11 +257,11 @@ impl Stats for [f64] {
     fn quartiles(&self) -> (f64, f64, f64) {
         let mut tmp = self.to_vec();
         local_sort(&mut tmp);
-        let first = 25f64;
+        let first = 25_f64;
         let a = percentile_of_sorted(&tmp, first);
-        let second = 50f64;
+        let second = 50_f64;
         let b = percentile_of_sorted(&tmp, second);
-        let third = 75f64;
+        let third = 75_f64;
         let c = percentile_of_sorted(&tmp, third);
         (a, b, c)
     }
@@ -281,7 +281,7 @@ fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 {
     }
     let zero: f64 = 0.0;
     assert!(zero <= pct);
-    let hundred = 100f64;
+    let hundred = 100_f64;
     assert!(pct <= hundred);
     if pct == hundred {
         return sorted_samples[sorted_samples.len() - 1];
@@ -307,7 +307,7 @@ pub fn winsorize(samples: &mut [f64], pct: f64) {
     let mut tmp = samples.to_vec();
     local_sort(&mut tmp);
     let lo = percentile_of_sorted(&tmp, pct);
-    let hundred = 100 as f64;
+    let hundred = 100_f64;
     let hi = percentile_of_sorted(&tmp, hundred - pct);
     for samp in samples {
         if *samp > hi {
diff --git a/src/libtest/types.rs b/src/libtest/types.rs
index 2619f99592a..5b75d2f367f 100644
--- a/src/libtest/types.rs
+++ b/src/libtest/types.rs
@@ -59,10 +59,10 @@ impl TestName {
     }
 
     pub fn with_padding(&self, padding: NamePadding) -> TestName {
-        let name = match self {
-            &TestName::StaticTestName(name) => Cow::Borrowed(name),
-            &TestName::DynTestName(ref name) => Cow::Owned(name.clone()),
-            &TestName::AlignedTestName(ref name, _) => name.clone(),
+        let name = match *self {
+            TestName::StaticTestName(name) => Cow::Borrowed(name),
+            TestName::DynTestName(ref name) => Cow::Owned(name.clone()),
+            TestName::AlignedTestName(ref name, _) => name.clone(),
         };
 
         TestName::AlignedTestName(name, padding)
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index a24808b3250..0628e5d2fc0 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -33,8 +33,13 @@ fn main() {
     } else if target.contains("dragonfly") {
         println!("cargo:rustc-link-lib=gcc_pic");
     } else if target.contains("pc-windows-gnu") {
-        println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
-        println!("cargo:rustc-link-lib=static-nobundle=pthread");
+        // This is handled in the target spec with late_link_args_[static|dynamic]
+
+        // cfg!(bootstrap) doesn't work in build scripts
+        if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) {
+            println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
+            println!("cargo:rustc-link-lib=static-nobundle=pthread");
+        }
     } else if target.contains("uwp-windows-gnu") {
         println!("cargo:rustc-link-lib=unwind");
     } else if target.contains("fuchsia") {
diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs
index f92ff9f071a..bd1946133e8 100644
--- a/src/rtstartup/rsbegin.rs
+++ b/src/rtstartup/rsbegin.rs
@@ -60,37 +60,36 @@ pub mod eh_frames {
     }
 
     // Unwind info registration/deregistration routines.
-    // See the docs of `unwind` module in libstd.
+    // See the docs of libpanic_unwind.
     extern "C" {
         fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8);
         fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8);
     }
 
-    unsafe fn init() {
+    unsafe extern "C" fn init() {
         // register unwind info on module startup
         rust_eh_register_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8);
     }
 
-    unsafe fn uninit() {
+    unsafe extern "C" fn uninit() {
         // unregister on shutdown
         rust_eh_unregister_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8);
     }
 
-    // MSVC-specific init/uninit routine registration
-    pub mod ms_init {
-        // .CRT$X?? sections are roughly analogous to ELF's .init_array and .fini_array,
-        // except that they exploit the fact that linker will sort them alphabitically,
-        // so e.g., sections with names between .CRT$XIA and .CRT$XIZ are guaranteed to be
-        // placed between those two, without requiring any ordering of objects on the linker
-        // command line.
-        // Note that ordering of same-named sections from different objects is not guaranteed.
-        // Since .CRT$XIA contains init array's header symbol, which must always come first,
-        // we place our initialization callback into .CRT$XIB.
+    // MinGW-specific init/uninit routine registration
+    pub mod mingw_init {
+        // MinGW's startup objects (crt0.o / dllcrt0.o) will invoke global constructors in the
+        // .ctors and .dtors sections on startup and exit. In the case of DLLs, this is done when
+        // the DLL is loaded and unloaded.
+        //
+        // The linker will sort the sections, which ensures that our callbacks are located at the
+        // end of the list. Since constructors are run in reverse order, this ensures that our
+        // callbacks are the first and last ones executed.
 
-        #[link_section = ".CRT$XIB"] // .CRT$XI? : C initialization callbacks
-        pub static P_INIT: unsafe fn() = super::init;
+        #[link_section = ".ctors.65535"] // .ctors.* : C initialization callbacks
+        pub static P_INIT: unsafe extern "C" fn() = super::init;
 
-        #[link_section = ".CRT$XTY"] // .CRT$XT? : C termination callbacks
-        pub static P_UNINIT: unsafe fn() = super::uninit;
+        #[link_section = ".dtors.65535"] // .dtors.* : C termination callbacks
+        pub static P_UNINIT: unsafe extern "C" fn() = super::uninit;
     }
 }
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index aeddd4cfb9f..25cfee3373d 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -112,20 +112,22 @@ extern "C" void LLVMRustPrintPassTimings() {
   TimerGroup::printAll(OS);
 }
 
-extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M,
-                                              const char *Name) {
-  return wrap(unwrap(M)->getNamedValue(Name));
+extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
+                                              size_t NameLen) {
+  return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
 }
 
 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
                                                     const char *Name,
+                                                    size_t NameLen,
                                                     LLVMTypeRef FunctionTy) {
-  return wrap(
-      unwrap(M)->getOrInsertFunction(Name, unwrap<FunctionType>(FunctionTy))
+  return wrap(unwrap(M)
+                  ->getOrInsertFunction(StringRef(Name, NameLen),
+                                        unwrap<FunctionType>(FunctionTy))
 #if LLVM_VERSION_GE(9, 0)
-      .getCallee()
+                  .getCallee()
 #endif
-      );
+  );
 }
 
 extern "C" LLVMValueRef
@@ -395,22 +397,26 @@ static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
   }
 }
 
-extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString,
-                                          char *Constraints,
-                                          LLVMBool HasSideEffects,
-                                          LLVMBool IsAlignStack,
-                                          LLVMRustAsmDialect Dialect) {
-  return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString, Constraints,
+extern "C" LLVMValueRef
+LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
+                  char *Constraints, size_t ConstraintsLen,
+                  LLVMBool HasSideEffects, LLVMBool IsAlignStack,
+                  LLVMRustAsmDialect Dialect) {
+  return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
+                             StringRef(AsmString, AsmStringLen),
+                             StringRef(Constraints, ConstraintsLen),
                              HasSideEffects, IsAlignStack, fromRust(Dialect)));
 }
 
-extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty,
-                                          char *Constraints) {
-  return InlineAsm::Verify(unwrap<FunctionType>(Ty), Constraints);
+extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
+                                        size_t ConstraintsLen) {
+  return InlineAsm::Verify(unwrap<FunctionType>(Ty),
+                           StringRef(Constraints, ConstraintsLen));
 }
 
-extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm) {
-  unwrap(M)->appendModuleInlineAsm(StringRef(Asm));
+extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
+                                              size_t AsmLen) {
+  unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
 }
 
 typedef DIBuilder *LLVMRustDIBuilderRef;
@@ -1282,12 +1288,11 @@ extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
 
 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
                                           LLVMValueRef *Args, unsigned NumArgs,
-                                          OperandBundleDef *Bundle,
-                                          const char *Name) {
+                                          OperandBundleDef *Bundle) {
   unsigned Len = Bundle ? 1 : 0;
   ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
   return wrap(unwrap(B)->CreateCall(
-      unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles, Name));
+      unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles));
 }
 
 extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
diff --git a/src/stage0.txt b/src/stage0.txt
index 55416b6729a..4d9a91e38b3 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2020-02-29
+date: 2020-03-12
 rustc: beta
 cargo: beta
 
diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md
index 3f47ca834cd..ea540bd0b18 100644
--- a/src/test/COMPILER_TESTS.md
+++ b/src/test/COMPILER_TESTS.md
@@ -1,4 +1,4 @@
 # Compiler Test Documentation
 
 Documentation for the compiler testing framework can be found in
-[the rustc guide](https://rust-lang.github.io/rustc-guide/tests/intro.html).
+[the rustc dev guide](https://rustc-dev-guide.rust-lang.org/tests/intro.html).
diff --git a/src/test/codegen/catch-unwind.rs b/src/test/codegen/catch-unwind.rs
new file mode 100644
index 00000000000..3c9bc35d1c8
--- /dev/null
+++ b/src/test/codegen/catch-unwind.rs
@@ -0,0 +1,19 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+extern "C" {
+    fn bar();
+}
+
+// CHECK-LABEL: @foo
+#[no_mangle]
+pub unsafe fn foo() -> i32 {
+    // CHECK: call void @bar
+    // CHECK: ret i32 0
+    std::panic::catch_unwind(|| {
+        bar();
+        0
+    })
+    .unwrap()
+}
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
index a89ecdfd3a9..e53e75b339b 100644
--- a/src/test/codegen/consts.rs
+++ b/src/test/codegen/consts.rs
@@ -10,11 +10,11 @@
 // CHECK: @STATIC = {{.*}}, align 4
 
 // This checks the constants from inline_enum_const
-// CHECK: @{{[0-9]+}} = {{.*}}, align 2
+// CHECK: @alloc5 = {{.*}}, align 2
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @2, i32 0, i32 0, i32 0), {{.*}},
+// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @alloc15, i32 0, i32 0, i32 0), {{.*}}
 
 #[derive(Copy, Clone)]
 // repr(i16) is required for the {low,high}_align_const test
diff --git a/src/test/codegen/debug-column-msvc.rs b/src/test/codegen/debug-column-msvc.rs
new file mode 100644
index 00000000000..aad8b372a8a
--- /dev/null
+++ b/src/test/codegen/debug-column-msvc.rs
@@ -0,0 +1,16 @@
+// Verify that no column information is emitted for MSVC targets
+//
+// only-msvc
+// compile-flags: -C debuginfo=2
+
+// CHECK-NOT: !DILexicalBlock({{.*}}column: {{.*}})
+// CHECK-NOT: !DILocation({{.*}}column: {{.*}})
+
+pub fn add(a: u32, b: u32) -> u32 {
+    a + b
+}
+
+fn main() {
+    let c = add(1, 2);
+    println!("{}", c);
+}
diff --git a/src/test/codegen/debug-column.rs b/src/test/codegen/debug-column.rs
new file mode 100644
index 00000000000..f348c48566d
--- /dev/null
+++ b/src/test/codegen/debug-column.rs
@@ -0,0 +1,24 @@
+// Verify that debuginfo column nubmers are 1-based byte offsets.
+//
+// ignore-windows
+// compile-flags: -C debuginfo=2
+
+fn main() {
+    unsafe {
+        // Column numbers are 1-based. Regression test for #65437.
+        // CHECK: call void @giraffe(), !dbg [[A:!.*]]
+        giraffe();
+
+        // Column numbers use byte offests. Regression test for #67360
+        // CHECK: call void @turtle(), !dbg [[B:!.*]]
+/* ż */ turtle();
+
+        // CHECK: [[A]] = !DILocation(line: 10, column: 9,
+        // CHECK: [[B]] = !DILocation(line: 14, column: 10,
+    }
+}
+
+extern {
+    fn giraffe();
+    fn turtle();
+}
diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs
index 52ffb97a5b2..4724dc3c3e5 100644
--- a/src/test/codegen/remap_path_prefix/main.rs
+++ b/src/test/codegen/remap_path_prefix/main.rs
@@ -12,7 +12,7 @@ mod aux_mod;
 include!("aux_mod.rs");
 
 // Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @0 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
+// CHECK: @alloc1 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
 pub static FILE_PATH: &'static str = file!();
 
 fn main() {
diff --git a/src/test/codegen/try-panic-abort.rs b/src/test/codegen/try-panic-abort.rs
new file mode 100644
index 00000000000..166d2bb9942
--- /dev/null
+++ b/src/test/codegen/try-panic-abort.rs
@@ -0,0 +1,20 @@
+// compile-flags: -C panic=abort -O
+
+#![crate_type = "lib"]
+#![feature(unwind_attributes, core_intrinsics)]
+
+extern "C" {
+    #[unwind(allow)]
+    fn bar(data: *mut u8);
+}
+extern "Rust" {
+    fn catch(data: *mut u8, exception: *mut u8);
+}
+
+// CHECK-LABEL: @foo
+#[no_mangle]
+pub unsafe fn foo() -> i32 {
+    // CHECK: call void @bar
+    // CHECK: ret i32 0
+    std::intrinsics::r#try(|x| bar(x), 0 as *mut u8, |x, y| catch(x, y))
+}
diff --git a/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs b/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs
index abe34a39caf..3e5cdad7ab9 100644
--- a/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs
+++ b/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs
@@ -11,5 +11,3 @@ use core::panic::PanicInfo;
 fn panic_impl(info: &PanicInfo) -> ! { loop {} }
 #[lang = "eh_personality"]
 fn eh_personality() {}
-#[lang = "eh_unwind_resume"]
-fn eh_unwind_resume() {}
diff --git a/src/test/incremental/change_symbol_export_status.rs b/src/test/incremental/change_symbol_export_status.rs
index f3de46d99dd..9b3b381d621 100644
--- a/src/test/incremental/change_symbol_export_status.rs
+++ b/src/test/incremental/change_symbol_export_status.rs
@@ -2,10 +2,8 @@
 // compile-flags: -Zquery-dep-graph
 
 #![feature(rustc_attrs)]
-#![allow(private_no_mangle_fns)]
-
-#![rustc_partition_codegened(module="change_symbol_export_status-mod1", cfg="rpass2")]
-#![rustc_partition_reused(module="change_symbol_export_status-mod2", cfg="rpass2")]
+#![rustc_partition_codegened(module = "change_symbol_export_status-mod1", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass2")]
 
 // This test case makes sure that a change in symbol visibility is detected by
 // our dependency tracking. We do this by changing a module's visibility to
diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs
index 50d3657d417..87f108abadd 100644
--- a/src/test/incremental/hashes/call_expressions.rs
+++ b/src/test/incremental/hashes/call_expressions.rs
@@ -25,7 +25,7 @@ pub fn change_callee_function() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_function() {
     callee2(1, 2)
@@ -40,7 +40,7 @@ pub fn change_argument_function() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_function() {
     callee1(1, 3)
@@ -55,10 +55,10 @@ mod change_callee_indirectly_function {
     #[cfg(not(cfail1))]
     use super::callee2 as callee;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 
 
     pub fn change_callee_indirectly_function() {
@@ -81,7 +81,7 @@ pub fn change_callee_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_method() {
     let s = Struct;
@@ -98,7 +98,7 @@ pub fn change_argument_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_method() {
     let s = Struct;
@@ -115,7 +115,7 @@ pub fn change_ufcs_callee_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_ufcs_callee_method() {
     let s = Struct;
@@ -132,7 +132,7 @@ pub fn change_argument_method_ufcs() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_method_ufcs() {
     let s = Struct;
@@ -149,10 +149,10 @@ pub fn change_to_ufcs() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
-// One might think this would be expanded in the HirBody/Mir, but it actually
-// results in slightly different Hir/Mir.
+// One might think this would be expanded in the hir_owner_items/Mir, but it actually
+// results in slightly different hir_owner/Mir.
 pub fn change_to_ufcs() {
     let s = Struct;
     Struct::method1(&s, 'x', true);
@@ -171,7 +171,7 @@ pub mod change_ufcs_callee_indirectly {
     #[cfg(not(cfail1))]
     use super::Struct2 as Struct;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
 
 
diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs
index 08693560d0b..8edece2c8d3 100644
--- a/src/test/incremental/hashes/closure_expressions.rs
+++ b/src/test/incremental/hashes/closure_expressions.rs
@@ -21,7 +21,7 @@ pub fn change_closure_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_closure_body() {
     let _ = || 3u32;
@@ -37,7 +37,7 @@ pub fn add_parameter() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_parameter() {
     let x = 0u32;
@@ -53,7 +53,7 @@ pub fn change_parameter_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_parameter_pattern() {
     let _ = |(x,): (u32,)| x;
@@ -68,7 +68,7 @@ pub fn add_move() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_move() {
     let _ = move || 1;
@@ -84,8 +84,8 @@ pub fn add_type_ascription_to_parameter() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
-#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner_items, typeck_tables_of")]
+#[rustc_clean(cfg = "cfail3")]
 pub fn add_type_ascription_to_parameter() {
     let closure = |x: u32| x + 1u32;
     let _: u32 = closure(1);
@@ -101,7 +101,7 @@ pub fn change_parameter_type() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_parameter_type() {
     let closure = |x: u16| (x as u64) + 1;
diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs
index 3d2eed89636..8f77bb24f87 100644
--- a/src/test/incremental/hashes/consts.rs
+++ b/src/test/incremental/hashes/consts.rs
@@ -19,7 +19,7 @@
 const CONST_VISIBILITY: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub const CONST_VISIBILITY: u8 = 0;
 
@@ -29,7 +29,7 @@ pub const CONST_VISIBILITY: u8 = 0;
 const CONST_CHANGE_TYPE_1: i32 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_TYPE_1: u32 = 0;
 
@@ -39,13 +39,13 @@ const CONST_CHANGE_TYPE_1: u32 = 0;
 const CONST_CHANGE_TYPE_2: Option<u32> = None;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_TYPE_2: Option<u64> = None;
 
 
 // Change value between simple literals
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_1: i16 = {
     #[cfg(cfail1)]
@@ -57,7 +57,7 @@ const CONST_CHANGE_VALUE_1: i16 = {
 
 
 // Change value between expressions
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_2: i16 = {
     #[cfg(cfail1)]
@@ -67,7 +67,7 @@ const CONST_CHANGE_VALUE_2: i16 = {
     { 1 + 2 }
 };
 
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_3: i16 = {
     #[cfg(cfail1)]
@@ -77,7 +77,7 @@ const CONST_CHANGE_VALUE_3: i16 = {
     { 2 * 3 }
 };
 
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 const CONST_CHANGE_VALUE_4: i16 = {
     #[cfg(cfail1)]
@@ -99,11 +99,11 @@ mod const_change_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
     #[rustc_clean(cfg="cfail3")]
     const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
     #[rustc_clean(cfg="cfail3")]
     const CONST_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
 }
diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs
index 575b2e92966..5ad6eeafc7f 100644
--- a/src/test/incremental/hashes/enum_constructors.rs
+++ b/src/test/incremental/hashes/enum_constructors.rs
@@ -34,7 +34,7 @@ pub fn change_field_value_struct_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
@@ -57,7 +57,7 @@ pub fn change_field_order_struct_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it
 // would if it were not all constants
@@ -96,7 +96,7 @@ pub fn change_constructor_path_struct_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_struct_like() {
     let _ = Enum2::Struct {
@@ -119,7 +119,7 @@ pub fn change_constructor_variant_struct_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct2 {
@@ -139,7 +139,7 @@ pub mod change_constructor_path_indirectly_struct_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,\
                 typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -161,7 +161,7 @@ pub mod change_constructor_variant_indirectly_struct_like {
     #[cfg(not(cfail1))]
     use super::Enum2::Struct2 as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Enum2 {
         Variant {
@@ -180,7 +180,7 @@ pub fn change_field_value_tuple_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 3)
@@ -197,7 +197,7 @@ pub fn change_constructor_path_tuple_like() {
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg="cfail2",
-    except="HirBody,optimized_mir,mir_built,typeck_tables_of"
+    except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of"
 )]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_tuple_like() {
@@ -215,7 +215,7 @@ pub fn change_constructor_variant_tuple_like() {
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg="cfail2",
-    except="HirBody,optimized_mir,mir_built,typeck_tables_of"
+    except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of"
 )]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_tuple_like() {
@@ -232,7 +232,7 @@ pub mod change_constructor_path_indirectly_tuple_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,\
                 typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -251,7 +251,7 @@ pub mod change_constructor_variant_indirectly_tuple_like {
     #[cfg(not(cfail1))]
     use super::Enum2::Tuple2 as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Enum2 {
         Variant(0, 1, 2)
@@ -278,7 +278,7 @@ pub fn change_constructor_path_c_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_c_like() {
     let _ = Clike2::B;
@@ -293,7 +293,7 @@ pub fn change_constructor_variant_c_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_c_like() {
     let _ = Clike::C;
@@ -309,7 +309,7 @@ pub mod change_constructor_path_indirectly_c_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,\
                 typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -328,7 +328,7 @@ pub mod change_constructor_variant_indirectly_c_like {
     #[cfg(not(cfail1))]
     use super::Clike::B as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Clike {
         Variant
diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs
index 7256c1aa153..7be15b4bb15 100644
--- a/src/test/incremental/hashes/enum_defs.rs
+++ b/src/test/incremental/hashes/enum_defs.rs
@@ -26,7 +26,7 @@
 enum EnumVisibility { A }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub enum EnumVisibility {
     A
@@ -42,7 +42,7 @@ enum EnumChangeNameCStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameCStyleVariant {
     Variant1,
@@ -59,7 +59,7 @@ enum EnumChangeNameTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameTupleStyleVariant {
     Variant1,
@@ -76,7 +76,7 @@ enum EnumChangeNameStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameStructStyleVariant {
     Variant1,
@@ -93,7 +93,7 @@ enum EnumChangeValueCStyleVariant0 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeValueCStyleVariant0 {
     Variant1,
@@ -109,7 +109,7 @@ enum EnumChangeValueCStyleVariant1 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeValueCStyleVariant1 {
     Variant1,
@@ -125,7 +125,7 @@ enum EnumAddCStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddCStyleVariant {
     Variant1,
@@ -142,7 +142,7 @@ enum EnumRemoveCStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumRemoveCStyleVariant {
     Variant1,
@@ -157,7 +157,7 @@ enum EnumAddTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddTupleStyleVariant {
     Variant1,
@@ -174,7 +174,7 @@ enum EnumRemoveTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumRemoveTupleStyleVariant {
     Variant1,
@@ -189,7 +189,7 @@ enum EnumAddStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddStructStyleVariant {
     Variant1,
@@ -206,7 +206,7 @@ enum EnumRemoveStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumRemoveStructStyleVariant {
     Variant1,
@@ -221,7 +221,7 @@ enum EnumChangeFieldTypeTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldTypeTupleStyleVariant {
     Variant1(u32,
@@ -238,7 +238,7 @@ enum EnumChangeFieldTypeStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldTypeStructStyleVariant {
     Variant1,
@@ -257,7 +257,7 @@ enum EnumChangeFieldNameStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldNameStructStyleVariant {
     Variant1 { a: u32, c: u32 },
@@ -272,7 +272,7 @@ enum EnumChangeOrderTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeOrderTupleStyleVariant {
     Variant1(
@@ -289,7 +289,7 @@ enum EnumChangeFieldOrderStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeFieldOrderStructStyleVariant {
     Variant1 { b: f32, a: u32 },
@@ -304,7 +304,7 @@ enum EnumAddFieldTupleStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddFieldTupleStyleVariant {
     Variant1(u32, u32, u32),
@@ -319,7 +319,7 @@ enum EnumAddFieldStructStyleVariant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddFieldStructStyleVariant {
     Variant1 { a: u32, b: u32, c: u32 },
@@ -335,7 +335,7 @@ enum EnumAddMustUse {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 #[must_use]
 enum EnumAddMustUse {
@@ -353,7 +353,7 @@ enum EnumAddReprC {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 #[repr(C)]
 enum EnumAddReprC {
@@ -531,7 +531,7 @@ enum EnumSwapUsageTypeParameters<A, B> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumSwapUsageTypeParameters<A, B> {
     Variant1 {
@@ -552,7 +552,7 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumSwapUsageLifetimeParameters<'a, 'b> {
     Variant1 {
@@ -577,7 +577,7 @@ mod change_field_type_indirectly_tuple_style {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     enum TupleStyle {
         Variant1(
@@ -595,7 +595,7 @@ mod change_field_type_indirectly_struct_style {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     enum StructStyle {
         Variant1 {
@@ -618,7 +618,7 @@ mod change_trait_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     enum Enum<T: Trait> {
         Variant1(T)
@@ -634,7 +634,7 @@ mod change_trait_bound_indirectly_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     enum Enum<T> where T: Trait {
         Variant1(T)
diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs
index ef275cabeaf..b546930ea8f 100644
--- a/src/test/incremental/hashes/exported_vs_not.rs
+++ b/src/test/incremental/hashes/exported_vs_not.rs
@@ -7,8 +7,8 @@
 #![crate_type="rlib"]
 
 // Case 1: The function body is not exported to metadata. If the body changes,
-//         the hash of the HirBody node should change, but not the hash of
-//         either the Hir or the Metadata node.
+//         the hash of the hir_owner_items node should change, but not the hash of
+//         either the hir_owner or the Metadata node.
 
 #[cfg(cfail1)]
 pub fn body_not_exported_to_metadata() -> u32 {
@@ -16,7 +16,7 @@ pub fn body_not_exported_to_metadata() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn body_not_exported_to_metadata() -> u32 {
     2
@@ -25,7 +25,7 @@ pub fn body_not_exported_to_metadata() -> u32 {
 
 
 // Case 2: The function body *is* exported to metadata because the function is
-//         marked as #[inline]. Only the hash of the Hir depnode should be
+//         marked as #[inline]. Only the hash of the hir_owner depnode should be
 //         unaffected by a change to the body.
 
 #[cfg(cfail1)]
@@ -35,7 +35,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_inline() -> u32 {
@@ -45,7 +45,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 {
 
 
 // Case 2: The function body *is* exported to metadata because the function is
-//         generic. Only the hash of the Hir depnode should be
+//         generic. Only the hash of the hir_owner depnode should be
 //         unaffected by a change to the body.
 
 #[cfg(cfail1)]
@@ -55,7 +55,7 @@ pub fn body_exported_to_metadata_because_of_generic() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_generic() -> u32 {
diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs
index 70820dfaea4..3e54dafd9ac 100644
--- a/src/test/incremental/hashes/for_loops.rs
+++ b/src/test/incremental/hashes/for_loops.rs
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_iteration_variable_name() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iteration_variable_name() {
     let mut _x = 0;
@@ -71,7 +71,7 @@ pub fn change_iteration_variable_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
@@ -94,7 +94,7 @@ pub fn change_iterable() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, promoted_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, promoted_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iterable() {
     let mut _x = 0;
@@ -116,7 +116,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -139,7 +139,7 @@ pub fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label() {
     let mut _x = 0;
@@ -162,7 +162,7 @@ pub fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
@@ -187,7 +187,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -212,7 +212,7 @@ pub fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
@@ -237,7 +237,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -262,7 +262,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index 9cc2d3bcf60..bfd53628466 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -9,198 +9,196 @@
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
-
 #![allow(warnings)]
 #![feature(linkage)]
 #![feature(rustc_attrs)]
 #![crate_type = "rlib"]
 
-
 // Add Parameter ---------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn add_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn add_parameter(p: i32) {}
 
-
 // Add Return Type -------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn add_return_type() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn add_return_type() -> () {}
 
-
 // Change Parameter Type -------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn type_of_parameter(p: i32) {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter(p: i64) {}
 
-
 // Change Parameter Type Reference ---------------------------------------------
 
 #[cfg(cfail1)]
 pub fn type_of_parameter_ref(p: &i32) {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter_ref(p: &mut i32) {}
 
-
 // Change Parameter Order ------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn order_of_parameters(p1: i32, p2: i64) {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn order_of_parameters(p2: i64, p1: i32) {}
 
-
 // Unsafe ----------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn make_unsafe() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub unsafe fn make_unsafe() {}
 
-
 // Extern ----------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn make_extern() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub extern "C" fn make_extern() {}
 
-
 // Type Parameter --------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn type_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, generics_of, type_of, predicates_of")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_parameter<T>() {}
 
-
 // Lifetime Parameter ----------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn lifetime_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, generics_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, generics_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn lifetime_parameter<'a>() {}
 
-
 // Trait Bound -----------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn trait_bound<T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn trait_bound<T: Eq>() {}
 
-
 // Builtin Bound ---------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn builtin_bound<T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn builtin_bound<T: Send>() {}
 
-
 // Lifetime Bound --------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn lifetime_bound<'a, T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, generics_of, type_of, predicates_of")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn lifetime_bound<'a, T: 'a>() {}
 
-
 // Second Trait Bound ----------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn second_trait_bound<T: Eq>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_trait_bound<T: Eq + Clone>() {}
 
-
 // Second Builtin Bound --------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn second_builtin_bound<T: Send>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_builtin_bound<T: Send + Sized>() {}
 
-
 // Second Lifetime Bound -------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, generics_of, type_of, predicates_of")]
+#[rustc_clean(
+    cfg = "cfail2",
+    except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of"
+)]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
 
-
 // Inline ----------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn inline() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 #[inline]
 pub fn inline() {}
 
-
 // Inline Never ----------------------------------------------------------------
 
 #[cfg(cfail1)]
@@ -208,36 +206,33 @@ pub fn inline() {}
 pub fn inline_never() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 #[inline(never)]
 pub fn inline_never() {}
 
-
 // No Mangle -------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn no_mangle() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 #[no_mangle]
 pub fn no_mangle() {}
 
-
 // Linkage ---------------------------------------------------------------------
 
 #[cfg(cfail1)]
 pub fn linkage() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")]
 #[rustc_clean(cfg = "cfail3")]
 #[linkage = "weak_odr"]
 pub fn linkage() {}
 
-
 // Return Impl Trait -----------------------------------------------------------
 
 #[cfg(cfail1)]
@@ -246,13 +241,12 @@ pub fn return_impl_trait() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn return_impl_trait() -> impl Clone {
     0
 }
 
-
 // Change Return Impl Trait ----------------------------------------------------
 
 #[cfg(cfail1)]
@@ -267,7 +261,6 @@ pub fn change_return_impl_trait() -> impl Copy {
     0u32
 }
 
-
 // Change Return Type Indirectly -----------------------------------------------
 
 pub struct ReferencedType1;
@@ -279,15 +272,16 @@ pub mod change_return_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as ReturnType;
 
-    #[rustc_clean(cfg = "cfail2",
-                  except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+    #[rustc_clean(
+        cfg = "cfail2",
+        except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+    )]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_return_type() -> ReturnType {
         ReturnType {}
     }
 }
 
-
 // Change Parameter Type Indirectly --------------------------------------------
 
 pub mod change_parameter_type_indirectly {
@@ -296,13 +290,14 @@ pub mod change_parameter_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as ParameterType;
 
-    #[rustc_clean(cfg = "cfail2",
-                  except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
+    #[rustc_clean(
+        cfg = "cfail2",
+        except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig"
+    )]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_parameter_type(p: ParameterType) {}
 }
 
-
 // Change Trait Bound Indirectly -----------------------------------------------
 
 pub trait ReferencedTrait1 {}
@@ -314,12 +309,11 @@ pub mod change_trait_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+    #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_trait_bound<T: Trait>(p: T) {}
 }
 
-
 // Change Trait Bound Indirectly In Where Clause -------------------------------
 
 pub mod change_trait_bound_indirectly_in_where_clause {
@@ -328,7 +322,7 @@ pub mod change_trait_bound_indirectly_in_where_clause {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")]
+    #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_trait_bound_where<T>(p: T)
     where
diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs
index 4b73f1371f8..93bdc0322bb 100644
--- a/src/test/incremental/hashes/if_expressions.rs
+++ b/src/test/incremental/hashes/if_expressions.rs
@@ -25,7 +25,7 @@ pub fn change_condition(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_condition(x: bool) -> u32 {
     if !x {
@@ -46,7 +46,7 @@ pub fn change_then_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_then_branch(x: bool) -> u32 {
     if x {
@@ -69,7 +69,7 @@ pub fn change_else_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_else_branch(x: bool) -> u32 {
     if x {
@@ -94,7 +94,7 @@ pub fn add_else_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_else_branch(x: bool) -> u32 {
     let mut ret = 1;
@@ -120,7 +120,7 @@ pub fn change_condition_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_condition_if_let(x: Option<u32>) -> u32 {
     if let Some(_) = x {
@@ -143,7 +143,7 @@ pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
@@ -166,7 +166,7 @@ pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
@@ -191,7 +191,7 @@ pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
     let mut ret = 1;
diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs
index 08cf19d7760..84c0298918e 100644
--- a/src/test/incremental/hashes/indexing_expressions.rs
+++ b/src/test/incremental/hashes/indexing_expressions.rs
@@ -20,10 +20,10 @@ fn change_simple_index(slice: &[u32]) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn change_simple_index(slice: &[u32]) -> u32 {
     slice[4]
 }
@@ -37,10 +37,10 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn change_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[2..5]
 }
@@ -54,10 +54,10 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn change_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -71,10 +71,10 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn add_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[3..4]
 }
@@ -88,10 +88,10 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn add_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -105,10 +105,10 @@ fn change_mutability(slice: &mut [u32]) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn change_mutability(slice: &mut [u32]) -> u32 {
     (&slice[3..5])[0]
 }
@@ -122,10 +122,10 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
     &slice[3..=7]
 }
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index 24d436f5f97..139c265164b 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -23,7 +23,7 @@ impl Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_clean(cfg="cfail3")]
@@ -44,7 +44,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
+        except="hir_owner_items,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_body() {
@@ -68,7 +68,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
+        except="hir_owner_items,optimized_mir,promoted_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     #[inline]
@@ -85,10 +85,10 @@ impl Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="associated_item,Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     fn method_privacy() { }
 }
@@ -100,7 +100,7 @@ impl Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of,promoted_mir")]
@@ -120,7 +120,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built"
+        except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_selfmutness(&mut self) { }
@@ -135,7 +135,7 @@ impl Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_clean(cfg="cfail2")]
@@ -160,7 +160,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built"
+        except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_method_parameter(&self, _: i32) { }
@@ -178,7 +178,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_parameter_name(&self, b: i64) { }
 }
@@ -197,7 +197,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,fn_sig,optimized_mir,mir_built,typeck_tables_of")]
+        except="hir_owner,hir_owner_items,fn_sig,optimized_mir,mir_built,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_return_type(&self) -> u8 { 0 }
 }
@@ -214,7 +214,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     #[inline]
     pub fn make_method_inline(&self) -> u8 { 0 }
@@ -232,7 +232,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
 }
@@ -251,7 +251,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built"
+        except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub unsafe fn make_method_unsafe(&self) { }
@@ -269,7 +269,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub extern fn make_method_extern(&self) { }
 }
@@ -286,7 +286,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub extern "system" fn change_method_calling_convention(&self) { }
 }
@@ -312,7 +312,7 @@ impl Foo {
     // if we lower generics before the body, then the `HirId` for
     // things in the body will be affected. So if you start to see
     // `typeck_tables_of` appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_parameter_to_method<'a>(&self) { }
 }
@@ -340,7 +340,7 @@ impl Foo {
     // appear dirty, that might be the cause. -nmatsakis
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,generics_of,predicates_of,type_of",
+        except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of",
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_type_parameter_to_method<T>(&self) { }
@@ -360,7 +360,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,generics_of,predicates_of,type_of,typeck_tables_of"
+        except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
@@ -387,7 +387,7 @@ impl Foo {
     // generics before the body, then the `HirId` for things in the
     // body will be affected. So if you start to see `typeck_tables_of`
     // appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of,predicates_of,\
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,generics_of,predicates_of,\
                                         type_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
@@ -414,7 +414,7 @@ impl Foo {
     // generics before the body, then the `HirId` for things in the
     // body will be affected. So if you start to see `typeck_tables_of`
     // appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_trait_bound_to_type_param_of_method<T: Clone>(&self) { }
 }
@@ -431,7 +431,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     #[no_mangle]
     pub fn add_no_mangle_to_method(&self) { }
@@ -448,7 +448,7 @@ impl Bar<u32> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,generics_of")]
 #[rustc_clean(cfg="cfail3")]
 impl<T> Bar<T> {
     #[rustc_clean(
@@ -468,7 +468,7 @@ impl Bar<u32> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl Bar<u64> {
     #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,mir_built,typeck_tables_of")]
@@ -485,7 +485,7 @@ impl<T> Bar<T> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl<T: 'static> Bar<T> {
     #[rustc_clean(cfg="cfail2")]
@@ -502,7 +502,7 @@ impl<T> Bar<T> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 impl<T: Clone> Bar<T> {
     #[rustc_clean(cfg="cfail2")]
diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs
index c50ee73d714..a77123110ae 100644
--- a/src/test/incremental/hashes/inline_asm.rs
+++ b/src/test/incremental/hashes/inline_asm.rs
@@ -33,7 +33,7 @@ pub fn change_template(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_template(a: i32) -> i32 {
@@ -69,7 +69,7 @@ pub fn change_output(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_output(a: i32) -> i32 {
@@ -105,7 +105,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input(_a: i32, _b: i32) -> i32 {
@@ -140,7 +140,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
@@ -175,7 +175,7 @@ pub fn change_clobber(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_clobber(_a: i32) -> i32 {
@@ -210,7 +210,7 @@ pub fn change_options(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_options(_a: i32) -> i32 {
diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs
index 68545b7daaa..2d9cf4203dc 100644
--- a/src/test/incremental/hashes/let_expressions.rs
+++ b/src/test/incremental/hashes/let_expressions.rs
@@ -22,7 +22,7 @@ pub fn change_name() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name() {
     let _y = 2u64;
@@ -38,7 +38,7 @@ pub fn add_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_type() {
     let _x: u32 = 2u32;
@@ -54,7 +54,7 @@ pub fn change_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_type() {
     let _x: u8 = 2;
@@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_reference_type() {
     let _x: &mut u64;
@@ -86,7 +86,7 @@ pub fn change_mutability_of_slot() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_slot() {
     let _x: u64 = 0;
@@ -102,7 +102,7 @@ pub fn change_simple_binding_to_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_simple_binding_to_pattern() {
     let (_a, _b) = (0u8, 'x');
@@ -118,7 +118,7 @@ pub fn change_name_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_in_pattern() {
     let (_a, _c) = (1u8, 'y');
@@ -134,7 +134,7 @@ pub fn add_ref_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_ref_in_pattern() {
     let (ref _a, _b) = (1u8, 'y');
@@ -150,7 +150,7 @@ pub fn add_amp_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_amp_in_pattern() {
     let (&_a, _b) = (&1u8, 'y');
@@ -166,7 +166,7 @@ pub fn change_mutability_of_binding_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_binding_in_pattern() {
     let (mut _a, _b) = (99u8, 'q');
@@ -182,7 +182,7 @@ pub fn add_initializer() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
+    except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_initializer() {
     let _x: i16 = 3i16;
@@ -198,7 +198,7 @@ pub fn change_initializer() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_initializer() {
     let _x = 5u16;
diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs
index a2222db4c59..7ce43559cff 100644
--- a/src/test/incremental/hashes/loop_expressions.rs
+++ b/src/test/incremental/hashes/loop_expressions.rs
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -47,7 +47,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label() {
     let mut _x = 0;
@@ -93,7 +93,7 @@ pub fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
@@ -118,7 +118,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -143,7 +143,7 @@ pub fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
@@ -168,7 +168,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -193,7 +193,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs
index 840b2222d90..30934c7c1d1 100644
--- a/src/test/incremental/hashes/match_expressions.rs
+++ b/src/test/incremental/hashes/match_expressions.rs
@@ -26,7 +26,7 @@ pub fn add_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_arm(x: u32) -> u32 {
     match x {
@@ -51,7 +51,7 @@ pub fn change_order_of_arms(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_order_of_arms(x: u32) -> u32 {
     match x {
@@ -75,7 +75,7 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_guard_clause(x: u32, y: bool) -> u32 {
     match x {
@@ -99,7 +99,7 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_guard_clause(x: u32, y: bool) -> u32 {
     match x {
@@ -123,7 +123,7 @@ pub fn add_at_binding(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_at_binding(x: u32) -> u32 {
     match x {
@@ -147,7 +147,7 @@ pub fn change_name_of_at_binding(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_of_at_binding(x: u32) -> u32 {
     match x {
@@ -170,7 +170,7 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_simple_name_to_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -193,7 +193,7 @@ pub fn change_name_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -216,7 +216,7 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -238,7 +238,7 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -260,7 +260,7 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
     match (&x, x & 1) {
@@ -283,7 +283,7 @@ pub fn change_rhs_of_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir")]
+    except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_rhs_of_arm(x: u32) -> u32 {
     match x {
@@ -307,7 +307,7 @@ pub fn add_alternative_to_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
+    except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_alternative_to_arm(x: u32) -> u32 {
     match x {
diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs
index 70b0a5ab78c..b46d1fac124 100644
--- a/src/test/incremental/hashes/panic_exprs.rs
+++ b/src/test/incremental/hashes/panic_exprs.rs
@@ -18,7 +18,7 @@
 
 
 // Indexing expression
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn indexing(slice: &[u8]) -> u8 {
     #[cfg(cfail1)]
@@ -33,7 +33,7 @@ pub fn indexing(slice: &[u8]) -> u8 {
 
 
 // Arithmetic overflow plus
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_plus(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -48,7 +48,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 {
 
 
 // Arithmetic overflow minus
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_minus(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -63,7 +63,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 {
 
 
 // Arithmetic overflow mult
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_mult(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -78,7 +78,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 {
 
 
 // Arithmetic overflow negation
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_negation(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -93,7 +93,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 {
 
 
 // Division by zero
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn division_by_zero(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -107,7 +107,7 @@ pub fn division_by_zero(val: i32) -> i32 {
 }
 
 // Division by zero
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn mod_by_zero(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -122,7 +122,7 @@ pub fn mod_by_zero(val: i32) -> i32 {
 
 
 // shift left
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_left(val: i32, shift: usize) -> i32 {
     #[cfg(cfail1)]
@@ -137,7 +137,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 {
 
 
 // shift right
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_right(val: i32, shift: usize) -> i32 {
     #[cfg(cfail1)]
diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs
index d70ebb08b71..536b7932473 100644
--- a/src/test/incremental/hashes/statics.rs
+++ b/src/test/incremental/hashes/statics.rs
@@ -21,7 +21,7 @@
 static STATIC_VISIBILITY: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub static STATIC_VISIBILITY: u8 = 0;
 
@@ -31,7 +31,7 @@ pub static STATIC_VISIBILITY: u8 = 0;
 static STATIC_MUTABILITY: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static mut STATIC_MUTABILITY: u8 = 0;
 
@@ -41,7 +41,7 @@ static mut STATIC_MUTABILITY: u8 = 0;
 static STATIC_LINKAGE: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 #[linkage="weak_odr"]
 static STATIC_LINKAGE: u8 = 0;
@@ -52,7 +52,7 @@ static STATIC_LINKAGE: u8 = 0;
 static STATIC_NO_MANGLE: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 #[no_mangle]
 static STATIC_NO_MANGLE: u8 = 0;
@@ -63,7 +63,7 @@ static STATIC_NO_MANGLE: u8 = 0;
 static STATIC_THREAD_LOCAL: u8 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 #[thread_local]
 static STATIC_THREAD_LOCAL: u8 = 0;
@@ -74,7 +74,7 @@ static STATIC_THREAD_LOCAL: u8 = 0;
 static STATIC_CHANGE_TYPE_1: i16 = 0;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_TYPE_1: u64 = 0;
 
@@ -84,13 +84,13 @@ static STATIC_CHANGE_TYPE_1: u64 = 0;
 static STATIC_CHANGE_TYPE_2: Option<i8> = None;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_TYPE_2: Option<u16> = None;
 
 
 // Change value between simple literals
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_1: i16 = {
     #[cfg(cfail1)]
@@ -102,7 +102,7 @@ static STATIC_CHANGE_VALUE_1: i16 = {
 
 
 // Change value between expressions
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_2: i16 = {
     #[cfg(cfail1)]
@@ -112,7 +112,7 @@ static STATIC_CHANGE_VALUE_2: i16 = {
     { 1 + 2 }
 };
 
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_3: i16 = {
     #[cfg(cfail1)]
@@ -122,7 +122,7 @@ static STATIC_CHANGE_VALUE_3: i16 = {
     { 2 * 3 }
 };
 
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 static STATIC_CHANGE_VALUE_4: i16 = {
     #[cfg(cfail1)]
@@ -144,11 +144,11 @@ mod static_change_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
     #[rustc_clean(cfg="cfail3")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")]
     #[rustc_clean(cfg="cfail3")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
 }
diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
index 7ae1798c7a2..89b18eefd06 100644
--- a/src/test/incremental/hashes/struct_constructors.rs
+++ b/src/test/incremental/hashes/struct_constructors.rs
@@ -31,7 +31,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
@@ -54,7 +54,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
@@ -82,7 +82,7 @@ pub fn add_field_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
@@ -117,7 +117,7 @@ pub fn change_field_label_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
@@ -152,7 +152,7 @@ pub fn change_constructor_path_regular_struct() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct2 {
@@ -173,7 +173,7 @@ pub mod change_constructor_path_indirectly_regular_struct {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of"
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
@@ -196,7 +196,7 @@ pub fn change_field_value_tuple_struct() -> TupleStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 3)
@@ -213,7 +213,7 @@ pub fn change_constructor_path_tuple_struct() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct2(0, 1, 2);
@@ -230,7 +230,7 @@ pub mod change_constructor_path_indirectly_tuple_struct {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of"
+        except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs
index e0c56964831..fa08b7ec1ed 100644
--- a/src/test/incremental/hashes/struct_defs.rs
+++ b/src/test/incremental/hashes/struct_defs.rs
@@ -24,13 +24,13 @@
 pub struct LayoutPacked;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -41,13 +41,13 @@ pub struct LayoutPacked;
 struct LayoutC;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -61,13 +61,13 @@ struct LayoutC;
 struct TupleStructFieldType(i32);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -84,13 +84,13 @@ struct TupleStructFieldType(
 struct TupleStructAddField(i32);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -106,13 +106,13 @@ struct TupleStructAddField(
 struct TupleStructFieldVisibility(char);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -125,13 +125,13 @@ struct TupleStructFieldVisibility(pub char);
 struct RecordStructFieldType { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -148,13 +148,13 @@ struct RecordStructFieldType {
 struct RecordStructFieldName { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -167,13 +167,13 @@ struct RecordStructFieldName { y: f32 }
 struct RecordStructAddField { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -188,13 +188,13 @@ struct RecordStructAddField {
 struct RecordStructFieldVisibility { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -209,13 +209,13 @@ struct RecordStructFieldVisibility {
 struct AddLifetimeParameter<'a>(&'a f32, &'a f64);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_dirty(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -228,13 +228,13 @@ struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64);
 struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -247,13 +247,13 @@ struct AddLifetimeParameterBound<'a, 'b: 'a>(
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -269,13 +269,13 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
 struct AddTypeParameter<T1>(T1, T1);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_dirty(label="type_of", cfg="cfail2")]
 #[rustc_dirty(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -293,13 +293,13 @@ struct AddTypeParameter<T1, T2>(
 struct AddTypeParameterBound<T>(T);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -312,13 +312,13 @@ struct AddTypeParameterBound<T: Send>(
 struct AddTypeParameterBoundWhereClause<T>(T);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -332,13 +332,13 @@ struct AddTypeParameterBoundWhereClause<T>(
 // fingerprint is stable (i.e., that there are no random influences like memory
 // addresses taken into account by the hashing algorithm).
 // Note: there is no #[cfg(...)], so this is ALWAYS compiled
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -351,13 +351,13 @@ pub struct EmptyStruct;
 struct Visibility;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
 #[rustc_clean(label="type_of", cfg="cfail2")]
 #[rustc_clean(label="generics_of", cfg="cfail2")]
 #[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(label="hir_owner_items", cfg="cfail3")]
 #[rustc_clean(label="type_of", cfg="cfail3")]
 #[rustc_clean(label="generics_of", cfg="cfail3")]
 #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -373,13 +373,13 @@ mod tuple_struct_change_field_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_clean(label="type_of", cfg="cfail2")]
     #[rustc_clean(label="generics_of", cfg="cfail2")]
     #[rustc_clean(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[rustc_clean(label="type_of", cfg="cfail3")]
     #[rustc_clean(label="generics_of", cfg="cfail3")]
     #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -396,13 +396,13 @@ mod record_struct_change_field_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_clean(label="type_of", cfg="cfail2")]
     #[rustc_clean(label="generics_of", cfg="cfail2")]
     #[rustc_clean(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[rustc_clean(label="type_of", cfg="cfail3")]
     #[rustc_clean(label="generics_of", cfg="cfail3")]
     #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -424,13 +424,13 @@ mod change_trait_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_clean(label="type_of", cfg="cfail2")]
     #[rustc_clean(label="generics_of", cfg="cfail2")]
     #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[rustc_clean(label="type_of", cfg="cfail3")]
     #[rustc_clean(label="generics_of", cfg="cfail3")]
     #[rustc_clean(label="predicates_of", cfg="cfail3")]
@@ -444,13 +444,13 @@ mod change_trait_bound_indirectly_in_where_clause {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_clean(label="type_of", cfg="cfail2")]
     #[rustc_clean(label="generics_of", cfg="cfail2")]
     #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[rustc_clean(label="type_of", cfg="cfail3")]
     #[rustc_clean(label="generics_of", cfg="cfail3")]
     #[rustc_clean(label="predicates_of", cfg="cfail3")]
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
index 3006cdccfbb..df41b73f92c 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -25,8 +25,8 @@
 trait TraitVisibility { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 pub trait TraitVisibility { }
 
 
@@ -36,8 +36,8 @@ pub trait TraitVisibility { }
 trait TraitUnsafety { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 unsafe trait TraitUnsafety { }
 
 
@@ -48,8 +48,8 @@ trait TraitAddMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 pub trait TraitAddMethod {
     fn method();
 }
@@ -63,8 +63,8 @@ trait TraitChangeMethodName {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodName {
     fn methodChanged();
 }
@@ -78,11 +78,11 @@ trait TraitAddReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddReturnType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method() -> u32;
 }
 
@@ -95,11 +95,11 @@ trait TraitChangeReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeReturnType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method() -> u64;
 }
 
@@ -112,11 +112,11 @@ trait TraitAddParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddParameterToMethod {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(a: u32);
 }
 
@@ -130,18 +130,18 @@ trait TraitChangeMethodParameterName {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodParameterName {
     // FIXME(#38501) This should preferably always be clean.
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(b: u32);
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     fn with_default(y: i32) {}
 }
 
@@ -154,11 +154,11 @@ trait TraitChangeMethodParameterType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodParameterType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(a: i64);
 }
 
@@ -171,11 +171,11 @@ trait TraitChangeMethodParameterTypeRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodParameterTypeRef {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(a: &mut i32);
 }
 
@@ -188,11 +188,11 @@ trait TraitChangeMethodParametersOrder {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeMethodParametersOrder {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(b: i64, a: i32);
 }
 
@@ -205,11 +205,11 @@ trait TraitAddMethodAutoImplementation {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddMethodAutoImplementation {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method() { }
 }
 
@@ -223,8 +223,8 @@ trait TraitChangeOrderOfMethods {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeOrderOfMethods {
     fn method1();
     fn method0();
@@ -239,11 +239,11 @@ trait TraitChangeModeSelfRefToMut {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeModeSelfRefToMut {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(&mut self);
 }
 
@@ -255,13 +255,13 @@ trait TraitChangeModeSelfOwnToMut: Sized {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeModeSelfOwnToMut: Sized {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     fn method(mut self) {}
 }
 
@@ -273,11 +273,11 @@ trait TraitChangeModeSelfOwnToRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeModeSelfOwnToRef {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method(&self);
 }
 
@@ -290,11 +290,11 @@ trait TraitAddUnsafeModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddUnsafeModifier {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     unsafe fn method();
 }
 
@@ -307,11 +307,11 @@ trait TraitAddExternModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddExternModifier {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     extern fn method();
 }
 
@@ -324,11 +324,11 @@ trait TraitChangeExternCToRustIntrinsic {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeExternCToRustIntrinsic {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     extern "stdcall" fn method();
 }
 
@@ -341,11 +341,11 @@ trait TraitAddTypeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTypeParameterToMethod {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T>();
 }
 
@@ -358,11 +358,11 @@ trait TraitAddLifetimeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeParameterToMethod {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<'a>();
 }
 
@@ -379,11 +379,11 @@ trait TraitAddTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitBoundToMethodTypeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T: ReferencedTrait0>();
 }
 
@@ -396,11 +396,11 @@ trait TraitAddBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T: Sized>();
 }
 
@@ -413,11 +413,11 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32);
 }
 
@@ -430,11 +430,11 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T: ReferencedTrait0 + ReferencedTrait1>();
 }
 
@@ -447,11 +447,11 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<T: Sized + Sync>();
 }
 
@@ -464,11 +464,11 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32);
 }
 
@@ -478,14 +478,14 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 #[cfg(cfail1)]
 trait TraitAddAssociatedType {
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method();
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddAssociatedType {
     type Associated;
 
@@ -506,11 +506,11 @@ trait TraitAddTraitBoundToAssociatedType {
 // Apparently the type bound contributes to the predicates of the trait, but
 // does not change the associated item itself.
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitBoundToAssociatedType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     type Associated: ReferencedTrait0;
 
     fn method();
@@ -527,11 +527,11 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     type Associated: 'a;
 
     fn method();
@@ -548,11 +548,11 @@ trait TraitAddDefaultToAssociatedType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddDefaultToAssociatedType {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     type Associated = ReferenceType0;
 
     fn method();
@@ -567,8 +567,8 @@ trait TraitAddAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddAssociatedConstant {
     const Value: u32;
 
@@ -586,15 +586,15 @@ trait TraitAddInitializerToAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddInitializerToAssociatedConstant {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     const Value: u32 = 1;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method();
 }
 
@@ -609,15 +609,15 @@ trait TraitChangeTypeOfAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitChangeTypeOfAssociatedConstant {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     const Value: f64;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method();
 }
 
@@ -628,8 +628,8 @@ trait TraitChangeTypeOfAssociatedConstant {
 trait TraitAddSuperTrait { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSuperTrait : ReferencedTrait0 { }
 
 
@@ -639,8 +639,8 @@ trait TraitAddSuperTrait : ReferencedTrait0 { }
 trait TraitAddBuiltiBound { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltiBound : Send { }
 
 
@@ -650,8 +650,8 @@ trait TraitAddBuiltiBound : Send { }
 trait TraitAddStaticLifetimeBound { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddStaticLifetimeBound : 'static { }
 
 
@@ -661,16 +661,16 @@ trait TraitAddStaticLifetimeBound : 'static { }
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { }
 
 #[cfg(cfail1)]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
 
 
@@ -680,16 +680,16 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { }
 
 #[cfg(cfail1)]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
 
 
@@ -699,16 +699,16 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { }
 
 #[cfg(cfail1)]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
 
 
@@ -718,8 +718,8 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
 trait TraitAddTypeParameterToTrait { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTypeParameterToTrait<T> { }
 
 
@@ -729,8 +729,8 @@ trait TraitAddTypeParameterToTrait<T> { }
 trait TraitAddLifetimeParameterToTrait { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeParameterToTrait<'a> { }
 
 
@@ -740,8 +740,8 @@ trait TraitAddLifetimeParameterToTrait<'a> { }
 trait TraitAddTraitBoundToTypeParameterOfTrait<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
 
@@ -751,8 +751,8 @@ trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
 
 
@@ -762,8 +762,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
 
 
@@ -773,8 +773,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
 
@@ -784,8 +784,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 trait TraitAddSecondTypeParameterToTrait<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondTypeParameterToTrait<T, S> { }
 
 
@@ -795,8 +795,8 @@ trait TraitAddSecondTypeParameterToTrait<T, S> { }
 trait TraitAddSecondLifetimeParameterToTrait<'a> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
 
 
@@ -806,8 +806,8 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + ReferencedTrait1> { }
 
 
@@ -817,8 +817,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + Refer
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
 
 
@@ -828,8 +828,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { }
 
 
@@ -839,8 +839,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c>
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send + Sync> { }
 
 
@@ -855,8 +855,8 @@ struct ReferenceType1 {}
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
 
@@ -866,8 +866,8 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
 
 
@@ -877,8 +877,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { }
 
 
@@ -888,8 +888,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
 
@@ -899,8 +899,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
     where T: ReferencedTrait0 + ReferencedTrait1 { }
 
@@ -911,8 +911,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { }
 
 
@@ -922,8 +922,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T:
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { }
 
 
@@ -933,8 +933,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { }
 
 
@@ -945,11 +945,11 @@ mod change_return_type_of_method_indirectly_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ReturnType;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeReturnType {
-        #[rustc_dirty(label="Hir", cfg="cfail2")]
-        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+        #[rustc_clean(label="hir_owner", cfg="cfail3")]
         fn method() -> ReturnType;
     }
 }
@@ -963,11 +963,11 @@ mod change_method_parameter_type_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ArgType;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeArgType {
-        #[rustc_dirty(label="Hir", cfg="cfail2")]
-        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+        #[rustc_clean(label="hir_owner", cfg="cfail3")]
         fn method(a: ArgType);
     }
 }
@@ -981,11 +981,11 @@ mod change_method_parameter_type_bound_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameter {
-        #[rustc_dirty(label="Hir", cfg="cfail2")]
-        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+        #[rustc_clean(label="hir_owner", cfg="cfail3")]
         fn method<T: Bound>(a: T);
     }
 }
@@ -1000,11 +1000,11 @@ mod change_method_parameter_type_bound_indirectly_by_use_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameterWhere {
-        #[rustc_dirty(label="Hir", cfg="cfail2")]
-        #[rustc_clean(label="Hir", cfg="cfail3")]
+        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+        #[rustc_clean(label="hir_owner", cfg="cfail3")]
         fn method<T>(a: T) where T: Bound;
     }
 }
@@ -1018,8 +1018,8 @@ mod change_method_type_parameter_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeTraitBound<T: Bound> {
         fn method(a: T);
     }
@@ -1035,8 +1035,8 @@ mod change_method_type_parameter_bound_indirectly_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     trait TraitChangeTraitBoundWhere<T> where T: Bound {
         fn method(a: T);
     }
diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs
index fa28b2ebedd..70e066870b6 100644
--- a/src/test/incremental/hashes/trait_impls.rs
+++ b/src/test/incremental/hashes/trait_impls.rs
@@ -30,18 +30,18 @@ impl ChangeMethodNameTrait for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 pub trait ChangeMethodNameTrait {
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name2();
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodNameTrait for Foo {
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name2() { }
 }
 
@@ -59,13 +59,13 @@ impl ChangeMethodBodyTrait for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodBodyTrait for Foo {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     fn method_name() {
         ()
     }
@@ -86,13 +86,13 @@ impl ChangeMethodBodyTraitInlined for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodBodyTraitInlined for Foo {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner_items", cfg="cfail3")]
     #[inline]
     fn method_name() {
         panic!()
@@ -117,11 +117,11 @@ pub trait ChangeMethodSelfnessTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodSelfnessTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name(&self) {
         ()
     }
@@ -145,11 +145,11 @@ pub trait RemoveMethodSelfnessTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl RemoveMethodSelfnessTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name() {}
 }
 
@@ -171,11 +171,11 @@ pub trait ChangeMethodSelfmutnessTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeMethodSelfmutnessTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name(&mut self) {}
 }
 
@@ -197,8 +197,8 @@ pub trait ChangeItemKindTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeItemKindTrait for Foo {
     type name = ();
 }
@@ -223,8 +223,8 @@ pub trait RemoveItemTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl RemoveItemTrait for Foo {
     type TypeName = ();
 }
@@ -248,8 +248,8 @@ pub trait AddItemTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl AddItemTrait for Foo {
     type TypeName = ();
     fn method_name() { }
@@ -268,17 +268,17 @@ impl ChangeHasValueTrait for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 pub trait ChangeHasValueTrait {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeHasValueTrait for Foo {
     fn method_name() { }
 }
@@ -295,11 +295,11 @@ impl AddDefaultTrait for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl AddDefaultTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     default fn method_name() { }
 }
 
@@ -321,11 +321,11 @@ pub trait AddArgumentTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl AddArgumentTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name(&self, _x: u32) { }
 }
 
@@ -347,11 +347,11 @@ pub trait ChangeArgumentTypeTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeArgumentTypeTrait for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn method_name(&self, _x: char) { }
 }
 
@@ -370,11 +370,11 @@ impl AddTypeParameterToImpl<u32> for Bar<u32> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl<T> AddTypeParameterToImpl<T> for Bar<T> {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn id(t: T) -> T { t }
 }
 
@@ -391,11 +391,11 @@ impl ChangeSelfTypeOfImpl for u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl ChangeSelfTypeOfImpl for u64 {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn id(self) -> Self { self }
 }
 
@@ -412,11 +412,11 @@ impl<T> AddLifetimeBoundToImplParameter for T {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl<T: 'static> AddLifetimeBoundToImplParameter for T {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn id(self) -> Self { self }
 }
 
@@ -433,11 +433,11 @@ impl<T> AddTraitBoundToImplParameter for T {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_dirty(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl<T: Clone> AddTraitBoundToImplParameter for T {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     fn id(self) -> Self { self }
 }
 
@@ -454,11 +454,11 @@ impl AddNoMangleToMethod for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl AddNoMangleToMethod for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     #[no_mangle]
     fn add_no_mangle_to_method(&self) { }
 }
@@ -475,11 +475,11 @@ impl MakeMethodInline for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(label="hir_owner", cfg="cfail2")]
+#[rustc_clean(label="hir_owner", cfg="cfail3")]
 impl MakeMethodInline for Foo {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail3")]
     #[inline]
     fn make_method_inline(&self) -> u8 { 0 }
 }
diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs
index 264e8f926ff..bbe1514ba9f 100644
--- a/src/test/incremental/hashes/type_defs.rs
+++ b/src/test/incremental/hashes/type_defs.rs
@@ -24,7 +24,7 @@
 type ChangePrimitiveType = i32;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangePrimitiveType = i64;
 
@@ -35,7 +35,7 @@ type ChangePrimitiveType = i64;
 type ChangeMutability = &'static i32;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeMutability = &'static mut i32;
 
@@ -46,7 +46,7 @@ type ChangeMutability = &'static mut i32;
 type ChangeLifetime<'a> = (&'static i32, &'a i32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeLifetime<'a> = (&'a i32, &'a i32);
 
@@ -60,7 +60,7 @@ struct Struct2;
 type ChangeTypeStruct = Struct1;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeTypeStruct = Struct2;
 
@@ -71,7 +71,7 @@ type ChangeTypeStruct = Struct2;
 type ChangeTypeTuple = (u32, u64);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeTypeTuple = (u32, i64);
 
@@ -91,7 +91,7 @@ enum Enum2 {
 type ChangeTypeEnum = Enum1;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeTypeEnum = Enum2;
 
@@ -102,7 +102,7 @@ type ChangeTypeEnum = Enum2;
 type AddTupleField = (i32, i64);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddTupleField = (i32, i64, i16);
 
@@ -113,7 +113,7 @@ type AddTupleField = (i32, i64, i16);
 type ChangeNestedTupleField = (i32, (i64, i16));
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type ChangeNestedTupleField = (i32, (i64, i8));
 
@@ -124,7 +124,7 @@ type ChangeNestedTupleField = (i32, (i64, i8));
 type AddTypeParam<T1> = (T1, T1);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddTypeParam<T1, T2> = (T1, T2);
 
@@ -135,7 +135,7 @@ type AddTypeParam<T1, T2> = (T1, T2);
 type AddTypeParamBound<T1> = (T1, u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddTypeParamBound<T1: Clone> = (T1, u32);
 
@@ -146,7 +146,7 @@ type AddTypeParamBound<T1: Clone> = (T1, u32);
 type AddTypeParamBoundWhereClause<T1> where T1: Clone = (T1, u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddTypeParamBoundWhereClause<T1> where T1: Clone+Copy = (T1, u32);
 
@@ -157,7 +157,7 @@ type AddTypeParamBoundWhereClause<T1> where T1: Clone+Copy = (T1, u32);
 type AddLifetimeParam<'a> = (&'a u32, &'a u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32);
 
@@ -168,7 +168,7 @@ type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32);
 type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32);
 
@@ -181,7 +181,7 @@ where 'b: 'a
     = (&'a u32, &'b u32, &'c u32);
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 type AddLifetimeParamBoundWhereClause<'a, 'b, 'c>
 where 'b: 'a,
@@ -200,7 +200,7 @@ mod change_trait_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     type ChangeTraitBoundIndirectly<T: Trait> = (T, u32);
 }
@@ -214,7 +214,7 @@ mod change_trait_bound_indirectly_in_where_clause {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")]
     #[rustc_clean(cfg="cfail3")]
     type ChangeTraitBoundIndirectly<T> where T : Trait = (T, u32);
 }
diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs
index 776a0273ca7..89aa0b1a58b 100644
--- a/src/test/incremental/hashes/unary_and_binary_exprs.rs
+++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs
@@ -21,7 +21,7 @@ pub fn const_negation() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn const_negation() -> i32 {
     -1
@@ -36,7 +36,7 @@ pub fn const_bitwise_not() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn const_bitwise_not() -> i32 {
     !99
@@ -51,7 +51,7 @@ pub fn var_negation(x: i32, y: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_negation(x: i32, y: i32) -> i32 {
     -y
@@ -66,7 +66,7 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
     !y
@@ -81,7 +81,7 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_deref(x: &i32, y: &i32) -> i32 {
     *y
@@ -96,7 +96,7 @@ pub fn first_const_add() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn first_const_add() -> i32 {
     2 + 3
@@ -111,7 +111,7 @@ pub fn second_const_add() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn second_const_add() -> i32 {
     1 + 3
@@ -126,7 +126,7 @@ pub fn first_var_add(a: i32, b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn first_var_add(a: i32, b: i32) -> i32 {
     b + 2
@@ -141,7 +141,7 @@ pub fn second_var_add(a: i32, b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn second_var_add(a: i32, b: i32) -> i32 {
     1 + b
@@ -156,7 +156,7 @@ pub fn plus_to_minus(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_minus(a: i32) -> i32 {
     1 - a
@@ -171,7 +171,7 @@ pub fn plus_to_mult(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_mult(a: i32) -> i32 {
     1 * a
@@ -186,7 +186,7 @@ pub fn plus_to_div(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_div(a: i32) -> i32 {
     1 / a
@@ -201,7 +201,7 @@ pub fn plus_to_mod(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_mod(a: i32) -> i32 {
     1 % a
@@ -216,7 +216,7 @@ pub fn and_to_or(a: bool, b: bool) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn and_to_or(a: bool, b: bool) -> bool {
     a || b
@@ -231,7 +231,7 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
     1 | a
@@ -246,7 +246,7 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
     1 ^ a
@@ -261,7 +261,7 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_lshift(a: i32) -> i32 {
     a << 1
@@ -276,7 +276,7 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_rshift(a: i32) -> i32 {
     a >> 1
@@ -291,7 +291,7 @@ pub fn eq_to_uneq(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_uneq(a: i32) -> bool {
     a != 1
@@ -306,7 +306,7 @@ pub fn eq_to_lt(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_lt(a: i32) -> bool {
     a < 1
@@ -321,7 +321,7 @@ pub fn eq_to_gt(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_gt(a: i32) -> bool {
     a > 1
@@ -336,7 +336,7 @@ pub fn eq_to_le(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_le(a: i32) -> bool {
     a <= 1
@@ -351,7 +351,7 @@ pub fn eq_to_ge(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_ge(a: i32) -> bool {
     a >= 1
@@ -368,7 +368,7 @@ pub fn type_cast(a: u8) -> u64 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn type_cast(a: u8) -> u64 {
     let b = a as u32;
@@ -385,7 +385,7 @@ pub fn value_cast(a: u32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn value_cast(a: u32) -> i32 {
     2 as i32
@@ -403,7 +403,7 @@ pub fn place() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn place() -> i32 {
     let mut x = 10;
@@ -423,7 +423,7 @@ pub fn rvalue() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn rvalue() -> i32 {
     let mut x = 10;
@@ -440,7 +440,7 @@ pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
+#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
     s[j]
diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs
index 615f1fe1fd0..908f60440fa 100644
--- a/src/test/incremental/hashes/while_let_loops.rs
+++ b/src/test/incremental/hashes/while_let_loops.rs
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_condition() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -93,7 +93,7 @@ pub fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label() {
     let mut _x = 0;
@@ -116,7 +116,7 @@ pub fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
@@ -141,7 +141,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -166,7 +166,7 @@ pub fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
@@ -191,7 +191,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -216,7 +216,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs
index a427ffb96e3..365ec5fa567 100644
--- a/src/test/incremental/hashes/while_loops.rs
+++ b/src/test/incremental/hashes/while_loops.rs
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_condition() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -93,7 +93,7 @@ pub fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label() {
     let mut _x = 0;
@@ -116,7 +116,7 @@ pub fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
@@ -141,7 +141,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -166,7 +166,7 @@ pub fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
@@ -191,7 +191,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -216,7 +216,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs
index 9dfd2ae2511..a9ec66346ac 100644
--- a/src/test/incremental/ich_method_call_trait_scope.rs
+++ b/src/test/incremental/ich_method_call_trait_scope.rs
@@ -26,15 +26,15 @@ mod mod3 {
     #[cfg(rpass2)]
     use Trait2;
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner_items", cfg="rpass2")]
     #[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
     fn bar() {
         ().method();
     }
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner_items", cfg="rpass2")]
     #[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
     fn baz() {
         22; // no method call, traits in scope don't matter
diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs
index b2b7e663151..a9232190eef 100644
--- a/src/test/incremental/ich_nested_items.rs
+++ b/src/test/incremental/ich_nested_items.rs
@@ -7,18 +7,21 @@
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
+#[rustc_clean(label = "hir_owner", cfg = "cfail2")]
+#[rustc_dirty(label = "hir_owner_items", cfg = "cfail2")]
 pub fn foo() {
     #[cfg(cfail1)]
-    pub fn baz() { } // order is different...
+    pub fn baz() {} // order is different...
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail2")]
-    pub fn bar() { } // but that doesn't matter.
+    // FIXME: Make "hir_owner" use `rustc_clean` here. Currently "hir_owner" includes a reference to
+    // the parent node, which is the statement holding this item. Changing the position of
+    // `bar` in `foo` will update that reference and make `hir_owner(bar)` dirty.
+    #[rustc_dirty(label = "hir_owner", cfg = "cfail2")]
+    #[rustc_clean(label = "hir_owner_items", cfg = "cfail2")]
+    pub fn bar() {} // but that doesn't matter.
 
     #[cfg(cfail2)]
-    pub fn baz() { } // order is different...
+    pub fn baz() {} // order is different...
 
-    pub fn bap() { } // neither does adding a new item
+    pub fn bap() {} // neither does adding a new item
 }
diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs
index 0e4ab6b78e2..c4674faabf5 100644
--- a/src/test/incremental/ich_resolve_results.rs
+++ b/src/test/incremental/ich_resolve_results.rs
@@ -28,18 +28,18 @@ mod mod3 {
     #[cfg(rpass3)]
     use mod2::Foo;
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
-    #[rustc_clean(label="Hir", cfg="rpass3")]
-    #[rustc_dirty(label="HirBody", cfg="rpass3")]
+    #[rustc_clean(label="hir_owner", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner_items", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner", cfg="rpass3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="rpass3")]
     fn in_expr() {
         Foo(0);
     }
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
-    #[rustc_clean(label="Hir", cfg="rpass3")]
-    #[rustc_dirty(label="HirBody", cfg="rpass3")]
+    #[rustc_clean(label="hir_owner", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner_items", cfg="rpass2")]
+    #[rustc_clean(label="hir_owner", cfg="rpass3")]
+    #[rustc_dirty(label="hir_owner_items", cfg="rpass3")]
     fn in_type() {
         test::<Foo>();
     }
diff --git a/src/test/incremental/inlined_hir_34991/main.rs b/src/test/incremental/inlined_hir_34991/main.rs
index 819b8434b08..bb76a0bb8fe 100644
--- a/src/test/incremental/inlined_hir_34991/main.rs
+++ b/src/test/incremental/inlined_hir_34991/main.rs
@@ -1,6 +1,6 @@
 // Regression test for #34991: an ICE occurred here because we inline
 // some of the vector routines and give them a local def-id `X`. This
-// got hashed after codegen (`Hir(X)`). When we load back up, we get an
+// got hashed after codegen (`hir_owner(X)`). When we load back up, we get an
 // error because the `X` is remapped to the original def-id (in
 // libstd), and we can't hash a HIR node from std.
 
diff --git a/src/test/incremental/issue-69596.rs b/src/test/incremental/issue-69596.rs
new file mode 100644
index 00000000000..dc587fdc44b
--- /dev/null
+++ b/src/test/incremental/issue-69596.rs
@@ -0,0 +1,21 @@
+// revisions: rpass1 rpass2
+
+#![allow(unused_imports)]
+
+#[macro_export]
+macro_rules! a_macro {
+    () => {};
+}
+
+#[cfg(rpass1)]
+use a_macro as same_name;
+
+mod same_name {}
+
+mod needed_mod {
+    fn _crash() {
+        use super::same_name;
+    }
+}
+
+fn main() {}
diff --git a/src/test/incremental/source_loc_macros.rs b/src/test/incremental/source_loc_macros.rs
index 51ea7d6d447..a360a66a64b 100644
--- a/src/test/incremental/source_loc_macros.rs
+++ b/src/test/incremental/source_loc_macros.rs
@@ -7,26 +7,26 @@
 
 #![feature(rustc_attrs)]
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_clean(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_clean(label="hir_owner_items", cfg="rpass2")]
 fn line_same() {
     let _ = line!();
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_clean(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_clean(label="hir_owner_items", cfg="rpass2")]
 fn col_same() {
     let _ = column!();
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_clean(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_clean(label="hir_owner_items", cfg="rpass2")]
 fn file_same() {
     let _ = file!();
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_dirty(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_dirty(label="hir_owner_items", cfg="rpass2")]
 fn line_different() {
     #[cfg(rpass1)]
     {
@@ -38,8 +38,8 @@ fn line_different() {
     }
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_dirty(label="HirBody", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_dirty(label="hir_owner_items", cfg="rpass2")]
 fn col_different() {
     #[cfg(rpass1)]
     {
diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub1.rs b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs
index 54fbe4465e3..2927ddec4e5 100644
--- a/src/test/incremental/span_hash_stable/auxiliary/sub1.rs
+++ b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs
@@ -1,4 +1,4 @@
-#[rustc_clean(label="Hir", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
 pub struct SomeType {
     pub x: u32,
     pub y: i64,
diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub2.rs b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs
index 34957616856..aa635077db8 100644
--- a/src/test/incremental/span_hash_stable/auxiliary/sub2.rs
+++ b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs
@@ -1,4 +1,4 @@
-#[rustc_clean(label="Hir", cfg="rpass2")]
+#[rustc_clean(label="hir_owner", cfg="rpass2")]
 pub struct SomeOtherType {
     pub a: i32,
     pub b: u64,
diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs
index e6fdc7cb3a0..b87d829132b 100644
--- a/src/test/incremental/spans_significant_w_debuginfo.rs
+++ b/src/test/incremental/spans_significant_w_debuginfo.rs
@@ -12,6 +12,6 @@
 pub fn main() {}
 
 #[cfg(rpass2)]
-#[rustc_dirty(label="Hir", cfg="rpass2")]
-#[rustc_dirty(label="HirBody", cfg="rpass2")]
+#[rustc_dirty(label="hir_owner", cfg="rpass2")]
+#[rustc_dirty(label="hir_owner_items", cfg="rpass2")]
 pub fn main() {}
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
index b88acd2af75..11a42262c16 100644
--- a/src/test/incremental/string_constant.rs
+++ b/src/test/incremental/string_constant.rs
@@ -18,7 +18,7 @@ pub mod x {
     }
 
     #[cfg(cfail2)]
-    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner_items", cfg="cfail2")]
     #[rustc_dirty(label="optimized_mir", cfg="cfail2")]
     pub fn x() {
         println!("{}", "2");
diff --git a/src/test/incremental/unchecked_dirty_clean.rs b/src/test/incremental/unchecked_dirty_clean.rs
index 66bdb670167..3bc8818aa6f 100644
--- a/src/test/incremental/unchecked_dirty_clean.rs
+++ b/src/test/incremental/unchecked_dirty_clean.rs
@@ -10,13 +10,13 @@
 
 fn main() {
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
     //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
     {
         // empty block
     }
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
     //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
     {
         // empty block
@@ -24,11 +24,11 @@ fn main() {
 }
 
 struct _Struct {
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
+    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
     //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
     _field1: i32,
 
-    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="hir_owner", cfg="cfail2")]
     //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
     _field2: i32,
 }
diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs
index f6f7d091091..c858a4c5ee7 100644
--- a/src/test/mir-opt/const-promotion-extern-static.rs
+++ b/src/test/mir-opt/const-promotion-extern-static.rs
@@ -4,9 +4,9 @@ extern "C" {
 
 static Y: i32 = 42;
 
-static mut BAR: *const &'static i32 = [&Y].as_ptr();
+static mut BAR: *const &i32 = [&Y].as_ptr();
 
-static mut FOO: *const &'static i32 = [unsafe { &X }].as_ptr();
+static mut FOO: *const &i32 = [unsafe { &X }].as_ptr();
 
 fn main() {}
 
@@ -14,12 +14,12 @@ fn main() {}
 // START rustc.FOO.PromoteTemps.before.mir
 // bb0: {
 // ...
-//     _5 = const Scalar(alloc1+0) : &i32;
+//     _5 = const {alloc1+0: &i32};
 //     _4 = &(*_5);
 //     _3 = [move _4];
 //     _2 = &_3;
-//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
-//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+//     _1 = move _2 as &[&i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
 // }
 // ...
 // bb2: {
@@ -31,12 +31,12 @@ fn main() {}
 // START rustc.BAR.PromoteTemps.before.mir
 // bb0: {
 // ...
-//     _5 = const Scalar(alloc0+0) : &i32;
+//     _5 = const {alloc0+0: &i32};
 //     _4 = &(*_5);
 //     _3 = [move _4];
 //     _2 = &_3;
-//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
-//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+//     _1 = move _2 as &[&i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
 // }
 // ...
 // bb2: {
@@ -50,8 +50,8 @@ fn main() {}
 // ...
 //     _6 = const BAR::promoted[0];
 //     _2 = &(*_6);
-//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
-//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+//     _1 = move _2 as &[&i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
 // }
 // ...
 // bb2: {
@@ -63,8 +63,8 @@ fn main() {}
 // ...
 //     _6 = const FOO::promoted[0];
 //     _2 = &(*_6);
-//     _1 = move _2 as &[&'static i32] (Pointer(Unsize));
-//     _0 = const core::slice::<impl [&'static i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
+//     _1 = move _2 as &[&i32] (Pointer(Unsize));
+//     _0 = const core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1];
 // }
 // ...
 // bb2: {
diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs
index 667d21fc14e..636aa1af653 100644
--- a/src/test/mir-opt/const_prop/discriminant.rs
+++ b/src/test/mir-opt/const_prop/discriminant.rs
@@ -31,7 +31,7 @@ fn main() {
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(0x01) : std::option::Option<bool>;
+//      _3 = const {transmute(0x01): std::option::Option<bool>};
 //      _4 = const 1isize;
 //      switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1];
 //  }
diff --git a/src/test/mir-opt/const_prop/issue-66971.rs b/src/test/mir-opt/const_prop/issue-66971.rs
index 30c75303b3e..f332bb89509 100644
--- a/src/test/mir-opt/const_prop/issue-66971.rs
+++ b/src/test/mir-opt/const_prop/issue-66971.rs
@@ -29,7 +29,7 @@ fn main() {
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(<ZST>) : ();
+//      _3 = const ();
 //      _2 = (move _3, const 0u8, const 0u8);
 //      ...
 //      _1 = const encode(move _2) -> bb1;
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 693ef783985..d307cebd715 100644
--- a/src/test/mir-opt/const_prop/read_immutable_static.rs
+++ b/src/test/mir-opt/const_prop/read_immutable_static.rs
@@ -10,10 +10,10 @@ fn main() {
 // START rustc.main.ConstProp.before.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(alloc0+0) : &u8;
+//      _3 = const {alloc0+0: &u8};
 //      _2 = (*_3);
 //      ...
-//      _5 = const Scalar(alloc0+0) : &u8;
+//      _5 = const {alloc0+0: &u8};
 //      _4 = (*_5);
 //      _1 = Add(move _2, move _4);
 //      ...
diff --git a/src/test/mir-opt/generator-tiny.rs b/src/test/mir-opt/generator-tiny.rs
new file mode 100644
index 00000000000..09e943bd962
--- /dev/null
+++ b/src/test/mir-opt/generator-tiny.rs
@@ -0,0 +1,34 @@
+//! Tests that generators that cannot return or unwind don't have unnecessary
+//! panic branches.
+
+// compile-flags: -Zno-landing-pads
+
+#![feature(generators, generator_trait)]
+
+struct HasDrop;
+
+impl Drop for HasDrop {
+    fn drop(&mut self) {}
+}
+
+fn callee() {}
+
+fn main() {
+    let _gen = |_x: u8| {
+        let _d = HasDrop;
+        loop {
+            yield;
+            callee();
+        }
+    };
+}
+
+// END RUST SOURCE
+
+// START rustc.main-{{closure}}.generator_resume.0.mir
+// bb0: {
+//     ...
+//     switchInt(move _11) -> [0u32: bb1, 3u32: bb5, otherwise: bb6];
+// }
+// ...
+// END rustc.main-{{closure}}.generator_resume.0.mir
diff --git a/src/test/mir-opt/no-drop-for-inactive-variant.rs b/src/test/mir-opt/no-drop-for-inactive-variant.rs
new file mode 100644
index 00000000000..74a606af28f
--- /dev/null
+++ b/src/test/mir-opt/no-drop-for-inactive-variant.rs
@@ -0,0 +1,43 @@
+// ignore-wasm32-bare compiled with panic=abort by default
+
+// Ensure that there are no drop terminators in `unwrap<T>` (except the one along the cleanup
+// path).
+
+fn unwrap<T>(opt: Option<T>) -> T {
+    match opt {
+        Some(x) => x,
+        None => panic!(),
+    }
+}
+
+fn main() {
+    let _ = unwrap(Some(1i32));
+}
+
+// END RUST SOURCE
+// START rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir
+// fn unwrap(_1: std::option::Option<T>) -> T {
+//     ...
+//     bb0: {
+//         ...
+//         switchInt(move _2) -> [0isize: bb2, 1isize: bb4, otherwise: bb3];
+//     }
+//     bb1 (cleanup): {
+//         resume;
+//     }
+//     bb2: {
+//         ...
+//         const std::rt::begin_panic::<&str>(const "explicit panic") -> bb5;
+//     }
+//     bb3: {
+//         unreachable;
+//     }
+//     bb4: {
+//         ...
+//         return;
+//     }
+//     bb5 (cleanup): {
+//         drop(_1) -> bb1;
+//     }
+// }
+// END rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir
diff --git a/src/test/mir-opt/remove_fake_borrows.rs b/src/test/mir-opt/remove_fake_borrows.rs
index 294fe247c38..ea106eaf595 100644
--- a/src/test/mir-opt/remove_fake_borrows.rs
+++ b/src/test/mir-opt/remove_fake_borrows.rs
@@ -26,16 +26,16 @@ fn main() {
 //     goto -> bb7;
 // }
 // bb2: {
-//     switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb1];
+//     switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1];
 // }
 // bb3: {
 //     goto -> bb4;
 // }
 // bb4: {
 //     _4 = &shallow _1;
-//     _5 = &shallow ((_1 as Some).0: &'<empty> &'<empty> i32);
-//     _6 = &shallow (*((_1 as Some).0: &'<empty> &'<empty> i32));
-//     _7 = &shallow (*(*((_1 as Some).0: &'<empty> &'<empty> i32)));
+//     _5 = &shallow ((_1 as Some).0: &&i32);
+//     _6 = &shallow (*((_1 as Some).0: &&i32));
+//     _7 = &shallow (*(*((_1 as Some).0: &&i32)));
 //     StorageLive(_8);
 //     _8 = _2;
 //     switchInt(move _8) -> [false: bb6, otherwise: bb5];
@@ -72,7 +72,7 @@ fn main() {
 //     goto -> bb7;
 // }
 // bb2: {
-//     switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb1];
+//     switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1];
 // }
 // bb3: {
 //     goto -> bb4;
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 6f03438ff72..e427fd55ad6 100644
--- a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs
+++ b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs
@@ -1,18 +1,18 @@
 // compile-flags: -C overflow-checks=no
 
-fn use_zst(_: ((), ())) { }
+fn use_zst(_: ((), ())) {}
 
 struct Temp {
-    x: u8
+    x: u8,
 }
 
-fn use_u8(_: u8) { }
+fn use_u8(_: u8) {}
 
 fn main() {
     let ((), ()) = ((), ());
     use_zst(((), ()));
 
-    use_u8((Temp { x : 40 }).x + 2);
+    use_u8((Temp { x: 40 }).x + 2);
 }
 
 // END RUST SOURCE
@@ -35,28 +35,28 @@ fn main() {
 // bb0: {
 //   StorageLive(_1);
 //   StorageLive(_2);
-//   _2 = const Scalar(<ZST>) : ();
+//   _2 = const ();
 //   StorageLive(_3);
-//   _3 = const Scalar(<ZST>) : ();
-//   _1 = const Scalar(<ZST>) : ((), ());
+//   _3 = const ();
+//   _1 = const {transmute(()): ((), ())};
 //   StorageDead(_3);
 //   StorageDead(_2);
 //   StorageDead(_1);
 //   StorageLive(_4);
 //   StorageLive(_6);
-//   _6 = const Scalar(<ZST>) : ();
+//   _6 = const ();
 //   StorageLive(_7);
-//   _7 = const Scalar(<ZST>) : ();
+//   _7 = const ();
 //   StorageDead(_7);
 //   StorageDead(_6);
-//   _4 = const use_zst(const Scalar(<ZST>) : ((), ())) -> bb1;
+//   _4 = const use_zst(const {transmute(()): ((), ())}) -> bb1;
 // }
 // bb1: {
 //   StorageDead(_4);
 //   StorageLive(_8);
 //   StorageLive(_10);
 //   StorageLive(_11);
-//   _11 = const Scalar(0x28) : Temp;
+//   _11 = const {transmute(0x28) : Temp};
 //   _10 = const 40u8;
 //   StorageDead(_10);
 //   _8 = const use_u8(const 42u8) -> bb2;
@@ -75,7 +75,7 @@ fn main() {
 // }
 // bb0: {
 //   StorageLive(_1);
-//   _1 = const use_zst(const Scalar(<ZST>) : ((), ())) -> bb1;
+//   _1 = const use_zst(const {transmute(()): ((), ())}) -> bb1;
 // }
 // bb1: {
 //   StorageDead(_1);
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 5dc15286bab..1c98766b968 100644
--- a/src/test/mir-opt/storage_live_dead_in_statics.rs
+++ b/src/test/mir-opt/storage_live_dead_in_statics.rs
@@ -35,12 +35,12 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.XXX.mir_map.0.mir
-//    let mut _0: &'static Foo;
-//    let _1: &'static Foo;
+//    let mut _0: &Foo;
+//    let _1: &Foo;
 //    let _2: Foo;
-//    let mut _3: &'static [(u32, u32)];
-//    let mut _4: &'static [(u32, u32); 42];
-//    let _5: &'static [(u32, u32); 42];
+//    let mut _3: &[(u32, u32)];
+//    let mut _4: &[(u32, u32); 42];
+//    let _5: &[(u32, u32); 42];
 //    let _6: [(u32, u32); 42];
 //    let mut _7: (u32, u32);
 //    let mut _8: (u32, u32);
@@ -178,7 +178,7 @@ fn main() {
 //        _6 = [move _7, move _8, move _9, move _10, move _11, move _12, move _13, move _14, move _15, move _16, move _17, move _18, move _19, move _20, move _21, move _22, move _23, move _24, move _25, move _26, move _27, move _28, move _29, move _30, move _31, move _32, move _33, move _34, move _35, move _36, move _37, move _38, move _39, move _40, move _41, move _42, move _43, move _44, move _45, move _46, move _47, move _48];
 //        _5 = &_6;
 //        _4 = &(*_5);
-//        _3 = move _4 as &'static [(u32, u32)] (Pointer(Unsize));
+//        _3 = move _4 as &[(u32, u32)] (Pointer(Unsize));
 //        _2 = Foo { tup: const "hi", data: move _3 };
 //        _1 = &_2;
 //        _0 = &(*_1);
diff --git a/src/test/pretty/attr-literals.rs b/src/test/pretty/attr-literals.rs
index 9db7e27b161..44d2c5db3e6 100644
--- a/src/test/pretty/attr-literals.rs
+++ b/src/test/pretty/attr-literals.rs
@@ -5,7 +5,7 @@
 #![feature(rustc_attrs)]
 
 fn main() {
-    #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name ("John"))]
+    #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name("John"))]
     #[rustc_dummy = 8]
     fn f() { }
 
diff --git a/src/test/pretty/delimited-token-groups.rs b/src/test/pretty/delimited-token-groups.rs
index 7bbb7dc911f..66de0fc6cf7 100644
--- a/src/test/pretty/delimited-token-groups.rs
+++ b/src/test/pretty/delimited-token-groups.rs
@@ -7,7 +7,7 @@ macro_rules! mac { ($ ($ tt : tt) *) => () }
 mac! {
     struct S { field1 : u8, field2 : u16, } impl Clone for S
     {
-        fn clone () -> S
+        fn clone() -> S
         {
             panic ! () ;
 
@@ -16,9 +16,8 @@ mac! {
 }
 
 mac! {
-    a
-    (aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa
-     aaaaaaaa aaaaaaaa) a
+    a(aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa
+      aaaaaaaa aaaaaaaa) a
     [aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa
      aaaaaaaa aaaaaaaa] a
     {
diff --git a/src/test/pretty/issue-12590-a.rs b/src/test/pretty/issue-12590-a.rs
index 1a9e85c42d8..ca1fef83cff 100644
--- a/src/test/pretty/issue-12590-a.rs
+++ b/src/test/pretty/issue-12590-a.rs
@@ -1,4 +1,5 @@
 // pp-exact
+// pretty-compare-only
 
 // The next line should not be expanded
 
diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
index 8aa4cdeb539..ee7586bae82 100644
--- a/src/test/pretty/issue-4264.pp
+++ b/src/test/pretty/issue-4264.pp
@@ -34,29 +34,29 @@ pub fn bar() ({
                            ((::alloc::fmt::format as
                                 for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((::core::fmt::Arguments::new_v1
                                                                                                                     as
-                                                                                                                    fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test"
-                                                                                                                                                                                                                                     as
-                                                                                                                                                                                                                                     &'static str)]
-                                                                                                                                                                                                                                   as
-                                                                                                                                                                                                                                   [&str; 1])
-                                                                                                                                                                                                                                 as
-                                                                                                                                                                                                                                 &[&str; 1]),
-                                                                                                                                                                                                                             (&(match (()
-                                                                                                                                                                                                                                          as
-                                                                                                                                                                                                                                          ())
-                                                                                                                                                                                                                                    {
-                                                                                                                                                                                                                                    ()
-                                                                                                                                                                                                                                    =>
-                                                                                                                                                                                                                                    ([]
-                                                                                                                                                                                                                                        as
-                                                                                                                                                                                                                                        [std::fmt::ArgumentV1<'_>; 0]),
-                                                                                                                                                                                                                                }
-                                                                                                                                                                                                                                   as
-                                                                                                                                                                                                                                   [std::fmt::ArgumentV1<'_>; 0])
-                                                                                                                                                                                                                                 as
-                                                                                                                                                                                                                                 &[std::fmt::ArgumentV1<'_>; 0]))
+                                                                                                                    fn(&[&str], &[std::fmt::ArgumentV1]) -> std::fmt::Arguments {std::fmt::Arguments::new_v1})((&([("test"
+                                                                                                                                                                                                                       as
+                                                                                                                                                                                                                       &str)]
+                                                                                                                                                                                                                     as
+                                                                                                                                                                                                                     [&str; 1])
+                                                                                                                                                                                                                   as
+                                                                                                                                                                                                                   &[&str; 1]),
+                                                                                                                                                                                                               (&(match (()
+                                                                                                                                                                                                                            as
+                                                                                                                                                                                                                            ())
+                                                                                                                                                                                                                      {
+                                                                                                                                                                                                                      ()
+                                                                                                                                                                                                                      =>
+                                                                                                                                                                                                                      ([]
+                                                                                                                                                                                                                          as
+                                                                                                                                                                                                                          [std::fmt::ArgumentV1; 0]),
+                                                                                                                                                                                                                  }
+                                                                                                                                                                                                                     as
+                                                                                                                                                                                                                     [std::fmt::ArgumentV1; 0])
+                                                                                                                                                                                                                   as
+                                                                                                                                                                                                                   &[std::fmt::ArgumentV1; 0]))
                                                                                                                    as
-                                                                                                                   std::fmt::Arguments<'_>))
+                                                                                                                   std::fmt::Arguments))
                                as std::string::String);
                        (res as std::string::String)
                    } as std::string::String);
diff --git a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs
index 643ca761aac..031a4825959 100644
--- a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs
+++ b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs
@@ -12,5 +12,5 @@ const C: C =
       #[cfg(debug_assertions)]
       field: 0,
 
-      #[cfg(not (debug_assertions))]
+      #[cfg(not(debug_assertions))]
       field: 1,};
diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index 07ef2424cc8..d975af52f5b 100644
--- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -7,14 +7,12 @@ extern crate rustc_data_structures;
 extern crate rustc_hir;
 extern crate rustc_target;
 extern crate rustc_driver;
+extern crate rustc_session;
 extern crate rustc_span;
 
 use std::any::Any;
 use std::sync::Arc;
 use std::path::Path;
-use rustc_span::symbol::Symbol;
-use rustc::session::Session;
-use rustc::session::config::OutputFilenames;
 use rustc::ty::TyCtxt;
 use rustc::ty::query::Providers;
 use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
@@ -23,6 +21,9 @@ use rustc::util::common::ErrorReported;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::sync::MetadataRef;
 use rustc_data_structures::owning_ref::OwningRef;
+use rustc_session::Session;
+use rustc_session::config::OutputFilenames;
+use rustc_span::symbol::Symbol;
 use rustc_target::spec::Target;
 
 pub struct NoLlvmMetadataLoader;
@@ -89,7 +90,7 @@ impl CodegenBackend for TheBackend {
         outputs: &OutputFilenames,
     ) -> Result<(), ErrorReported> {
         use std::io::Write;
-        use rustc::session::config::CrateType;
+        use rustc_session::config::CrateType;
         use rustc_codegen_utils::link::out_filename;
         let crate_name = codegen_results.downcast::<Symbol>()
             .expect("in link: codegen_results is not a Symbol");
diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs
index 12da64fc88f..af84faa7511 100644
--- a/src/test/run-make-fulldeps/issue-19371/foo.rs
+++ b/src/test/run-make-fulldeps/issue-19371/foo.rs
@@ -1,13 +1,12 @@
 #![feature(rustc_private)]
 
-extern crate rustc;
 extern crate rustc_interface;
 extern crate rustc_driver;
+extern crate rustc_session;
 extern crate rustc_span;
 
-use rustc::session::DiagnosticOutput;
-use rustc::session::config::{Input, Options,
-                             OutputType, OutputTypes};
+use rustc_session::DiagnosticOutput;
+use rustc_session::config::{Input, Options, OutputType, OutputTypes};
 use rustc_interface::interface;
 use rustc_span::source_map::FileName;
 
diff --git a/src/test/rustdoc-js-std/return-specific-literal.js b/src/test/rustdoc-js-std/return-specific-literal.js
new file mode 100644
index 00000000000..c7c347240b7
--- /dev/null
+++ b/src/test/rustdoc-js-std/return-specific-literal.js
@@ -0,0 +1,10 @@
+const QUERY = 'struct:"string"';
+
+const EXPECTED = {
+    'in_args': [
+        { 'path': 'std::string::String', 'name': 'ne' },
+    ],
+    'returned': [
+        { 'path': 'std::string::String', 'name': 'add' },
+    ],
+};
diff --git a/src/test/rustdoc-js-std/return-specific.js b/src/test/rustdoc-js-std/return-specific.js
new file mode 100644
index 00000000000..d9a910553b8
--- /dev/null
+++ b/src/test/rustdoc-js-std/return-specific.js
@@ -0,0 +1,10 @@
+const QUERY = 'struct:string';
+
+const EXPECTED = {
+    'in_args': [
+        { 'path': 'std::string::String', 'name': 'ne' },
+    ],
+    'returned': [
+        { 'path': 'std::string::String', 'name': 'add' },
+    ],
+};
diff --git a/src/test/rustdoc-ui/coverage/html.rs b/src/test/rustdoc-ui/coverage/html.rs
new file mode 100644
index 00000000000..181cb4c5061
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/html.rs
@@ -0,0 +1,4 @@
+// compile-flags:-Z unstable-options --output-format html --show-coverage
+
+/// Foo
+pub struct Xo;
diff --git a/src/test/rustdoc-ui/coverage/html.stderr b/src/test/rustdoc-ui/coverage/html.stderr
new file mode 100644
index 00000000000..adca375d4bc
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/html.stderr
@@ -0,0 +1,2 @@
+error: html output format isn't supported for the --show-coverage option
+
diff --git a/src/test/rustdoc-ui/coverage/json.rs b/src/test/rustdoc-ui/coverage/json.rs
new file mode 100644
index 00000000000..b1220b32e91
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/json.rs
@@ -0,0 +1,27 @@
+// build-pass
+// compile-flags:-Z unstable-options --output-format json --show-coverage
+
+pub mod foo {
+    /// Hello!
+    pub struct Foo;
+    /// Bar
+    pub enum Bar { A }
+}
+
+/// X
+pub struct X;
+
+/// Bar
+pub mod bar {
+    /// bar
+    pub struct Bar;
+    /// X
+    pub enum X { Y }
+}
+
+/// yolo
+pub enum Yolo { X }
+
+pub struct Xo<T: Clone> {
+    x: T,
+}
diff --git a/src/test/rustdoc-ui/coverage/json.stdout b/src/test/rustdoc-ui/coverage/json.stdout
new file mode 100644
index 00000000000..63b22a7d94b
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/json.stdout
@@ -0,0 +1 @@
+{"$DIR/json.rs":{"total":13,"with_docs":7}}
diff --git a/src/test/rustdoc-ui/issue-61732.rs b/src/test/rustdoc-ui/issue-61732.rs
index d4835c09224..4bd8efeaa3b 100644
--- a/src/test/rustdoc-ui/issue-61732.rs
+++ b/src/test/rustdoc-ui/issue-61732.rs
@@ -1,4 +1,4 @@
 // This previously triggered an ICE.
 
 pub(in crate::r#mod) fn main() {}
-//~^ ERROR expected module, found unresolved item
+//~^ ERROR failed to resolve: maybe a missing crate `r#mod`
diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr
index 6c8ba48864d..82134224911 100644
--- a/src/test/rustdoc-ui/issue-61732.stderr
+++ b/src/test/rustdoc-ui/issue-61732.stderr
@@ -1,11 +1,11 @@
-error[E0577]: expected module, found unresolved item `crate::r#mod`
-  --> $DIR/issue-61732.rs:3:8
+error[E0433]: failed to resolve: maybe a missing crate `r#mod`?
+  --> $DIR/issue-61732.rs:3:15
    |
 LL | pub(in crate::r#mod) fn main() {}
-   |        ^^^^^^^^^^^^ not a module
+   |               ^^^^^ maybe a missing crate `r#mod`?
 
 error: Compilation failed, aborting rustdoc
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0577`.
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs
index 6ecdad3ec00..e9cd3514a07 100644
--- a/src/test/rustdoc/attributes.rs
+++ b/src/test/rustdoc/attributes.rs
@@ -15,3 +15,7 @@ pub extern "C" fn g() {}
 pub enum Foo {
     Bar,
 }
+
+// @has foo/struct.Repr.html '//*[@class="docblock attributes top-attr"]' '#[repr(C, align(8))]'
+#[repr(C, align(8))]
+pub struct Repr;
diff --git a/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs b/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs
index 8917693d45e..837ed1f002f 100644
--- a/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs
+++ b/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs
@@ -2,16 +2,14 @@
 
 #![feature(rustc_private)]
 
-// We're testing linkage visibility; the compiler warns us, but we want to
-// do the runtime check that these functions aren't exported.
-#![allow(private_no_mangle_fns)]
-
 extern crate rustc_metadata;
 
 use rustc_metadata::dynamic_lib::DynamicLibrary;
 
 #[no_mangle]
-pub fn foo() { bar(); }
+pub fn foo() {
+    bar();
+}
 
 pub fn foo2<T>() {
     fn bar2() {
@@ -21,11 +19,11 @@ pub fn foo2<T>() {
 }
 
 #[no_mangle]
-fn bar() { }
+fn bar() {}
 
 #[allow(dead_code)]
 #[no_mangle]
-fn baz() { }
+fn baz() {}
 
 pub fn test() {
     let lib = DynamicLibrary::open(None).unwrap();
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
index 4936bdb1ece..52620b2464b 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
@@ -29,10 +29,10 @@ macro_rules! fake_lint_pass {
         impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct {
             fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
                 $(
-                    if !attr::contains_name(&krate.attrs, $attr) {
+                    if !attr::contains_name(&krate.item.attrs, $attr) {
                         cx.lint(CRATE_NOT_OKAY, |lint| {
                              let msg = format!("crate is not marked with #![{}]", $attr);
-                             lint.build(&msg).set_span(krate.span).emit()
+                             lint.build(&msg).set_span(krate.item.span).emit()
                         });
                     }
                 )*
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index 32b7ed9dfe2..6978d02c09d 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -27,10 +27,10 @@ declare_lint_pass!(Pass => [CRATE_NOT_OKAY]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
-        if !attr::contains_name(&krate.attrs, Symbol::intern("crate_okay")) {
+        if !attr::contains_name(&krate.item.attrs, Symbol::intern("crate_okay")) {
             cx.lint(CRATE_NOT_OKAY, |lint| {
                 lint.build("crate is not marked with #![crate_okay]")
-                    .set_span(krate.span)
+                    .set_span(krate.item.span)
                     .emit()
             });
         }
diff --git a/src/test/ui/asm/issue-69092.rs b/src/test/ui/asm/issue-69092.rs
new file mode 100644
index 00000000000..caa5c2e0b9f
--- /dev/null
+++ b/src/test/ui/asm/issue-69092.rs
@@ -0,0 +1,10 @@
+// build-fail
+// ignore-emscripten no asm! support
+// Regression test for #69092
+
+#![feature(asm)]
+
+fn main() {
+    unsafe { asm!(".ascii \"Xen\0\""); }
+    //~^ ERROR: <inline asm>:1:9: error: expected string in '.ascii' directive
+}
diff --git a/src/test/ui/asm/issue-69092.stderr b/src/test/ui/asm/issue-69092.stderr
new file mode 100644
index 00000000000..5661097cb8b
--- /dev/null
+++ b/src/test/ui/asm/issue-69092.stderr
@@ -0,0 +1,11 @@
+error: <inline asm>:1:9: error: expected string in '.ascii' directive
+        .ascii "Xen
+               ^
+
+  --> $DIR/issue-69092.rs:8:14
+   |
+LL |     unsafe { asm!(".ascii \"Xen\0\""); }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-item/associated-item-enum.stderr b/src/test/ui/associated-item/associated-item-enum.stderr
index 6f89530eac9..cadf55454a7 100644
--- a/src/test/ui/associated-item/associated-item-enum.stderr
+++ b/src/test/ui/associated-item/associated-item-enum.stderr
@@ -8,7 +8,7 @@ LL |     Enum::mispellable();
    |           ^^^^^^^^^^^
    |           |
    |           variant or associated item not found in `Enum`
-   |           help: there is a method with a similar name: `misspellable`
+   |           help: there is an associated function with a similar name: `misspellable`
 
 error[E0599]: no variant or associated item named `mispellable_trait` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:18:11
diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs
index 4a413381aa3..636fafc2bc4 100644
--- a/src/test/ui/async-await/async-fn-size-moved-locals.rs
+++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs
@@ -110,9 +110,9 @@ async fn mixed_sizes() {
 }
 
 fn main() {
-    assert_eq!(1028, std::mem::size_of_val(&single()));
-    assert_eq!(1032, std::mem::size_of_val(&single_with_noop()));
-    assert_eq!(3084, std::mem::size_of_val(&joined()));
-    assert_eq!(3084, std::mem::size_of_val(&joined_with_noop()));
-    assert_eq!(7188, std::mem::size_of_val(&mixed_sizes()));
+    assert_eq!(1025, std::mem::size_of_val(&single()));
+    assert_eq!(1026, std::mem::size_of_val(&single_with_noop()));
+    assert_eq!(3078, std::mem::size_of_val(&joined()));
+    assert_eq!(3079, std::mem::size_of_val(&joined_with_noop()));
+    assert_eq!(7181, std::mem::size_of_val(&mixed_sizes()));
 }
diff --git a/src/test/ui/async-await/async-fn-size-uninit-locals.rs b/src/test/ui/async-await/async-fn-size-uninit-locals.rs
index 0558084f4f8..d5d7b3fc3f0 100644
--- a/src/test/ui/async-await/async-fn-size-uninit-locals.rs
+++ b/src/test/ui/async-await/async-fn-size-uninit-locals.rs
@@ -95,9 +95,9 @@ async fn join_retval() -> Joiner {
 }
 
 fn main() {
-    assert_eq!(8, std::mem::size_of_val(&single()));
-    assert_eq!(12, std::mem::size_of_val(&single_with_noop()));
-    assert_eq!(3084, std::mem::size_of_val(&joined()));
-    assert_eq!(3084, std::mem::size_of_val(&joined_with_noop()));
-    assert_eq!(3080, std::mem::size_of_val(&join_retval()));
+    assert_eq!(2, std::mem::size_of_val(&single()));
+    assert_eq!(3, std::mem::size_of_val(&single_with_noop()));
+    assert_eq!(3078, std::mem::size_of_val(&joined()));
+    assert_eq!(3078, std::mem::size_of_val(&joined_with_noop()));
+    assert_eq!(3074, std::mem::size_of_val(&join_retval()));
 }
diff --git a/src/test/ui/async-await/async-fn-size.rs b/src/test/ui/async-await/async-fn-size.rs
index b313992db4e..0c1f3636446 100644
--- a/src/test/ui/async-await/async-fn-size.rs
+++ b/src/test/ui/async-await/async-fn-size.rs
@@ -86,13 +86,13 @@ async fn await3_level5() -> u8 {
 
 fn main() {
     assert_eq!(2, std::mem::size_of_val(&base()));
-    assert_eq!(8, std::mem::size_of_val(&await1_level1()));
-    assert_eq!(12, std::mem::size_of_val(&await2_level1()));
-    assert_eq!(12, std::mem::size_of_val(&await3_level1()));
-    assert_eq!(24, std::mem::size_of_val(&await3_level2()));
-    assert_eq!(36, std::mem::size_of_val(&await3_level3()));
-    assert_eq!(48, std::mem::size_of_val(&await3_level4()));
-    assert_eq!(60, std::mem::size_of_val(&await3_level5()));
+    assert_eq!(3, std::mem::size_of_val(&await1_level1()));
+    assert_eq!(4, std::mem::size_of_val(&await2_level1()));
+    assert_eq!(5, std::mem::size_of_val(&await3_level1()));
+    assert_eq!(8, std::mem::size_of_val(&await3_level2()));
+    assert_eq!(11, std::mem::size_of_val(&await3_level3()));
+    assert_eq!(14, std::mem::size_of_val(&await3_level4()));
+    assert_eq!(17, std::mem::size_of_val(&await3_level5()));
 
     assert_eq!(1,   wait(base()));
     assert_eq!(1,   wait(await1_level1()));
diff --git a/src/test/ui/async-await/expansion-in-attrs.rs b/src/test/ui/async-await/expansion-in-attrs.rs
new file mode 100644
index 00000000000..af77c3463b5
--- /dev/null
+++ b/src/test/ui/async-await/expansion-in-attrs.rs
@@ -0,0 +1,13 @@
+// check-pass
+// edition:2018
+
+macro_rules! with_doc {
+    ($doc: expr) => {
+        #[doc = $doc]
+        async fn f() {}
+    };
+}
+
+with_doc!(concat!(""));
+
+fn main() {}
diff --git a/src/test/ui/async-await/issues/issue-62097.nll.stderr b/src/test/ui/async-await/issues/issue-62097.nll.stderr
index f72c645bf8d..2a399540e52 100644
--- a/src/test/ui/async-await/issues/issue-62097.nll.stderr
+++ b/src/test/ui/async-await/issues/issue-62097.nll.stderr
@@ -16,13 +16,13 @@ help: to force the closure to take ownership of `self` (and any other referenced
 LL |         foo(move || self.bar()).await;
    |             ^^^^^^^
 
-error[E0521]: borrowed data escapes outside of method
+error[E0521]: borrowed data escapes outside of associated function
   --> $DIR/issue-62097.rs:13:9
    |
 LL |     pub async fn run_dummy_fn(&self) {
-   |                               ----- `self` is a reference that is only valid in the method body
+   |                               ----- `self` is a reference that is only valid in the associated function body
 LL |         foo(|| self.bar()).await;
-   |         ^^^^^^^^^^^^^^^^^^ `self` escapes the method body here
+   |         ^^^^^^^^^^^^^^^^^^ `self` escapes the associated function body here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
index 696f79ec40f..464459d2d61 100644
--- a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
+++ b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr
@@ -9,7 +9,7 @@ LL |       ) -> &dyn Foo
 LL | /     {
 LL | |         foo
 LL | |     }
-   | |_____^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
+   | |_____^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr
index 07559cd240b..4e59bb50767 100644
--- a/src/test/ui/async-await/no-const-async.stderr
+++ b/src/test/ui/async-await/no-const-async.stderr
@@ -1,8 +1,8 @@
 error: functions cannot be both `const` and `async`
-  --> $DIR/no-const-async.rs:4:1
+  --> $DIR/no-const-async.rs:4:5
    |
 LL | pub const async fn x() {}
-   | ^^^^-----^-----^^^^^^^^^^
+   | ----^^^^^-^^^^^----------
    |     |     |
    |     |     `async` because of this
    |     `const` because of this
diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr
index 50ca5cad4bc..dc7deb8a7c7 100644
--- a/src/test/ui/auto-ref-slice-plus-ref.stderr
+++ b/src/test/ui/auto-ref-slice-plus-ref.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{intege
   --> $DIR/auto-ref-slice-plus-ref.rs:7:7
    |
 LL |     a.test_mut();
-   |       ^^^^^^^^ help: there is a method with a similar name: `get_mut`
+   |       ^^^^^^^^ help: there is an associated function with a similar name: `get_mut`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `MyIter` defines an item `test_mut`, perhaps you need to implement it
diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-trait-validation.stderr
index 51422fab81f..4040e66c6af 100644
--- a/src/test/ui/auto-trait-validation.stderr
+++ b/src/test/ui/auto-trait-validation.stderr
@@ -1,20 +1,26 @@
 error[E0567]: auto traits cannot have generic parameters
-  --> $DIR/auto-trait-validation.rs:3:1
+  --> $DIR/auto-trait-validation.rs:3:19
    |
 LL | auto trait Generic<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -------^^^ help: remove the parameters
+   |            |
+   |            auto trait cannot have generic parameters
 
 error[E0568]: auto traits cannot have super traits
-  --> $DIR/auto-trait-validation.rs:5:1
+  --> $DIR/auto-trait-validation.rs:5:20
    |
 LL | auto trait Bound : Copy {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -----   ^^^^ help: remove the super traits
+   |            |
+   |            auto trait cannot have super traits
 
 error[E0380]: auto traits cannot have methods or associated items
-  --> $DIR/auto-trait-validation.rs:7:1
+  --> $DIR/auto-trait-validation.rs:7:25
    |
 LL | auto trait MyTrait { fn foo() {} }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -------      ^^^
+   |            |
+   |            auto trait cannot have items
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/binding/ambiguity-item.rs b/src/test/ui/binding/ambiguity-item.rs
new file mode 100644
index 00000000000..10613cc6164
--- /dev/null
+++ b/src/test/ui/binding/ambiguity-item.rs
@@ -0,0 +1,18 @@
+// Identifier pattern referring to an ambiguity item is an error (issue #46079).
+
+mod m {
+    pub fn f() {}
+}
+use m::*;
+
+mod n {
+    pub fn f() {}
+}
+use n::*; // OK, no conflict with `use m::*;`
+
+fn main() {
+    let v = f; //~ ERROR `f` is ambiguous
+    match v {
+        f => {} //~ ERROR `f` is ambiguous
+    }
+}
diff --git a/src/test/ui/binding/ambiguity-item.stderr b/src/test/ui/binding/ambiguity-item.stderr
new file mode 100644
index 00000000000..615193c0d02
--- /dev/null
+++ b/src/test/ui/binding/ambiguity-item.stderr
@@ -0,0 +1,41 @@
+error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/ambiguity-item.rs:14:13
+   |
+LL |     let v = f;
+   |             ^ ambiguous name
+   |
+note: `f` could refer to the function imported here
+  --> $DIR/ambiguity-item.rs:6:5
+   |
+LL | use m::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+note: `f` could also refer to the function imported here
+  --> $DIR/ambiguity-item.rs:11:5
+   |
+LL | use n::*; // OK, no conflict with `use m::*;`
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+
+error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
+  --> $DIR/ambiguity-item.rs:16:9
+   |
+LL |         f => {}
+   |         ^ ambiguous name
+   |
+note: `f` could refer to the function imported here
+  --> $DIR/ambiguity-item.rs:6:5
+   |
+LL | use m::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+note: `f` could also refer to the function imported here
+  --> $DIR/ambiguity-item.rs:11:5
+   |
+LL | use n::*; // OK, no conflict with `use m::*;`
+   |     ^^^^
+   = help: consider adding an explicit import of `f` to disambiguate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/binding/const-param.rs b/src/test/ui/binding/const-param.rs
new file mode 100644
index 00000000000..3c7f4d071f6
--- /dev/null
+++ b/src/test/ui/binding/const-param.rs
@@ -0,0 +1,12 @@
+// Identifier pattern referring to a const generic parameter is an error (issue #68853).
+
+#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
+
+fn check<const N: usize>() {
+    match 1 {
+        N => {} //~ ERROR const parameters cannot be referenced in patterns
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/binding/const-param.stderr b/src/test/ui/binding/const-param.stderr
new file mode 100644
index 00000000000..25b1c75c9a0
--- /dev/null
+++ b/src/test/ui/binding/const-param.stderr
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-param.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0158]: const parameters cannot be referenced in patterns
+  --> $DIR/const-param.rs:7:9
+   |
+LL |         N => {}
+   |         ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0158`.
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
index be551f6e889..5255e48bee1 100644
--- a/src/test/ui/block-result/issue-3563.stderr
+++ b/src/test/ui/block-result/issue-3563.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `b` found for reference `&Self` in the current sco
   --> $DIR/issue-3563.rs:3:17
    |
 LL |         || self.b()
-   |                 ^ help: there is a method with a similar name: `a`
+   |                 ^ help: there is an associated function with a similar name: `a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/coherence-negative-impls-safe.stderr b/src/test/ui/coherence/coherence-negative-impls-safe.stderr
index 4db66af6783..1bd37f39590 100644
--- a/src/test/ui/coherence/coherence-negative-impls-safe.stderr
+++ b/src/test/ui/coherence/coherence-negative-impls-safe.stderr
@@ -1,9 +1,10 @@
 error[E0198]: negative impls cannot be unsafe
-  --> $DIR/coherence-negative-impls-safe.rs:7:1
+  --> $DIR/coherence-negative-impls-safe.rs:7:13
    |
 LL | unsafe impl !Send for TestType {}
-   | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
+   | ------      -^^^^
+   | |           |
+   | |           negative because of this
    | unsafe because of this
 
 error: aborting due to previous error
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs
new file mode 100644
index 00000000000..c51c908a426
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs
@@ -0,0 +1,24 @@
+#![feature(cfg_accessible)]
+
+#[cfg_accessible] //~ ERROR malformed `cfg_accessible` attribute input
+struct S1;
+
+#[cfg_accessible = "value"] //~ ERROR malformed `cfg_accessible` attribute input
+struct S2;
+
+#[cfg_accessible()] //~ ERROR `cfg_accessible` path is not specified
+struct S3;
+
+#[cfg_accessible(std, core)] //~ ERROR multiple `cfg_accessible` paths are specified
+struct S4;
+
+#[cfg_accessible("std")] //~ ERROR `cfg_accessible` path cannot be a literal
+struct S5;
+
+#[cfg_accessible(std = "value")] //~ ERROR `cfg_accessible` path cannot accept arguments
+struct S6;
+
+#[cfg_accessible(std(value))] //~ ERROR `cfg_accessible` path cannot accept arguments
+struct S7;
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr
new file mode 100644
index 00000000000..86706c76635
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr
@@ -0,0 +1,44 @@
+error: malformed `cfg_accessible` attribute input
+  --> $DIR/cfg_accessible-input-validation.rs:3:1
+   |
+LL | #[cfg_accessible]
+   | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]`
+
+error: malformed `cfg_accessible` attribute input
+  --> $DIR/cfg_accessible-input-validation.rs:6:1
+   |
+LL | #[cfg_accessible = "value"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]`
+
+error: `cfg_accessible` path is not specified
+  --> $DIR/cfg_accessible-input-validation.rs:9:1
+   |
+LL | #[cfg_accessible()]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: multiple `cfg_accessible` paths are specified
+  --> $DIR/cfg_accessible-input-validation.rs:12:23
+   |
+LL | #[cfg_accessible(std, core)]
+   |                       ^^^^
+
+error: `cfg_accessible` path cannot be a literal
+  --> $DIR/cfg_accessible-input-validation.rs:15:18
+   |
+LL | #[cfg_accessible("std")]
+   |                  ^^^^^
+
+error: `cfg_accessible` path cannot accept arguments
+  --> $DIR/cfg_accessible-input-validation.rs:18:18
+   |
+LL | #[cfg_accessible(std = "value")]
+   |                  ^^^^^^^^^^^^^
+
+error: `cfg_accessible` path cannot accept arguments
+  --> $DIR/cfg_accessible-input-validation.rs:21:18
+   |
+LL | #[cfg_accessible(std(value))]
+   |                  ^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs b/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs
new file mode 100644
index 00000000000..8bc93fa3243
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs
@@ -0,0 +1,9 @@
+#![feature(cfg_accessible)]
+
+#[cfg_accessible(Z)] //~ ERROR cannot determine whether the path is accessible or not
+struct S;
+
+#[cfg_accessible(S)] //~ ERROR cannot determine whether the path is accessible or not
+struct Z;
+
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr b/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr
new file mode 100644
index 00000000000..9641441a819
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr
@@ -0,0 +1,14 @@
+error: cannot determine whether the path is accessible or not
+  --> $DIR/cfg_accessible-stuck.rs:6:1
+   |
+LL | #[cfg_accessible(S)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: cannot determine whether the path is accessible or not
+  --> $DIR/cfg_accessible-stuck.rs:3:1
+   |
+LL | #[cfg_accessible(Z)]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs b/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs
new file mode 100644
index 00000000000..e9247e67a2a
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs
@@ -0,0 +1,2 @@
+#[cfg_accessible(std)] //~ ERROR use of unstable library feature 'cfg_accessible'
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr b/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr
new file mode 100644
index 00000000000..2f55b9559c7
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr
@@ -0,0 +1,12 @@
+error[E0658]: use of unstable library feature 'cfg_accessible': `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible-unstable.rs:1:3
+   |
+LL | #[cfg_accessible(std)]
+   |   ^^^^^^^^^^^^^^
+   |
+   = note: see issue #64797 <https://github.com/rust-lang/rust/issues/64797> for more information
+   = help: add `#![feature(cfg_accessible)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/conditional-compilation/cfg_accessible.rs b/src/test/ui/conditional-compilation/cfg_accessible.rs
new file mode 100644
index 00000000000..07b0be5b1ae
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible.rs
@@ -0,0 +1,43 @@
+#![feature(cfg_accessible)]
+
+mod m {
+    pub struct ExistingPublic;
+    struct ExistingPrivate;
+}
+
+#[cfg_accessible(m::ExistingPublic)]
+struct ExistingPublic;
+
+// FIXME: Not implemented yet.
+#[cfg_accessible(m::ExistingPrivate)] //~ ERROR not sure whether the path is accessible or not
+struct ExistingPrivate;
+
+// FIXME: Not implemented yet.
+#[cfg_accessible(m::NonExistent)] //~ ERROR not sure whether the path is accessible or not
+struct ExistingPrivate;
+
+#[cfg_accessible(n::AccessibleExpanded)] // OK, `cfg_accessible` can wait and retry.
+struct AccessibleExpanded;
+
+macro_rules! generate_accessible_expanded {
+    () => {
+        mod n {
+            pub struct AccessibleExpanded;
+        }
+    };
+}
+
+generate_accessible_expanded!();
+
+struct S {
+    field: u8,
+}
+
+// FIXME: Not implemented yet.
+#[cfg_accessible(S::field)] //~ ERROR not sure whether the path is accessible or not
+struct Field;
+
+fn main() {
+    ExistingPublic;
+    AccessibleExpanded;
+}
diff --git a/src/test/ui/conditional-compilation/cfg_accessible.stderr b/src/test/ui/conditional-compilation/cfg_accessible.stderr
new file mode 100644
index 00000000000..167765cd66e
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg_accessible.stderr
@@ -0,0 +1,38 @@
+error: not sure whether the path is accessible or not
+  --> $DIR/cfg_accessible.rs:12:18
+   |
+LL | #[cfg_accessible(m::ExistingPrivate)]
+   |                  ^^^^^^^^^^^^^^^^^^
+   |
+note: `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible.rs:12:18
+   |
+LL | #[cfg_accessible(m::ExistingPrivate)]
+   |                  ^^^^^^^^^^^^^^^^^^
+
+error: not sure whether the path is accessible or not
+  --> $DIR/cfg_accessible.rs:16:18
+   |
+LL | #[cfg_accessible(m::NonExistent)]
+   |                  ^^^^^^^^^^^^^^
+   |
+note: `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible.rs:16:18
+   |
+LL | #[cfg_accessible(m::NonExistent)]
+   |                  ^^^^^^^^^^^^^^
+
+error: not sure whether the path is accessible or not
+  --> $DIR/cfg_accessible.rs:37:18
+   |
+LL | #[cfg_accessible(S::field)]
+   |                  ^^^^^^^^
+   |
+note: `cfg_accessible` is not fully implemented
+  --> $DIR/cfg_accessible.rs:37:18
+   |
+LL | #[cfg_accessible(S::field)]
+   |                  ^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr
index 43b76bf6497..0b78532c737 100644
--- a/src/test/ui/conflicting-repr-hints.stderr
+++ b/src/test/ui/conflicting-repr-hints.stderr
@@ -76,5 +76,5 @@ LL | | }
 
 error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0566, E0587.
+Some errors have detailed explanations: E0566, E0587, E0634.
 For more information about an error, try `rustc --explain E0566`.
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.stderr b/src/test/ui/const-generics/cannot-infer-const-args.stderr
index 8379cbd4908..c1d7022d56b 100644
--- a/src/test/ui/const-generics/cannot-infer-const-args.stderr
+++ b/src/test/ui/const-generics/cannot-infer-const-args.stderr
@@ -10,7 +10,7 @@ error[E0282]: type annotations needed
   --> $DIR/cannot-infer-const-args.rs:9:5
    |
 LL |     foo();
-   |     ^^^ cannot infer type for fn item `fn() -> usize {foo::<_: usize>}`
+   |     ^^^ cannot infer type for fn item `fn() -> usize {foo::<{_: usize}>}`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/const-generic-type_name.rs b/src/test/ui/const-generics/const-generic-type_name.rs
index 28586426b44..469843d6aae 100644
--- a/src/test/ui/const-generics/const-generic-type_name.rs
+++ b/src/test/ui/const-generics/const-generic-type_name.rs
@@ -7,5 +7,5 @@
 struct S<const N: usize>;
 
 fn main() {
-    assert_eq!(std::any::type_name::<S<3>>(), "const_generic_type_name::S<3usize>");
+    assert_eq!(std::any::type_name::<S<3>>(), "const_generic_type_name::S<3>");
 }
diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr
index 44eab8baa40..05d2dff8e98 100644
--- a/src/test/ui/const-generics/fn-const-param-infer.stderr
+++ b/src/test/ui/const-generics/fn-const-param-infer.stderr
@@ -10,12 +10,12 @@ error[E0308]: mismatched types
   --> $DIR/fn-const-param-infer.rs:16:31
    |
 LL |     let _: Checked<not_one> = Checked::<not_two>;
-   |            ----------------   ^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two`
+   |            ----------------   ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}`
    |            |
    |            expected due to this
    |
-   = note: expected struct `Checked<not_one>`
-              found struct `Checked<not_two>`
+   = note: expected struct `Checked<{not_one as fn(usize) -> bool}>`
+              found struct `Checked<{not_two as fn(usize) -> bool}>`
 
 error[E0308]: mismatched types
   --> $DIR/fn-const-param-infer.rs:20:24
@@ -36,12 +36,12 @@ error[E0308]: mismatched types
   --> $DIR/fn-const-param-infer.rs:25:40
    |
 LL |     let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
-   |            -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::<u32>`, found `generic::<u16>`
+   |            -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic::<u32> as fn(usize) -> bool}`, found `{generic::<u16> as fn(usize) -> bool}`
    |            |
    |            expected due to this
    |
-   = note: expected struct `Checked<generic::<u32>>`
-              found struct `Checked<generic::<u16>>`
+   = note: expected struct `Checked<{generic::<u32> as fn(usize) -> bool}>`
+              found struct `Checked<{generic::<u16> as fn(usize) -> bool}>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs
new file mode 100644
index 00000000000..74ed3d354fc
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62504.rs
@@ -0,0 +1,25 @@
+// Regression test for #62504
+
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+trait HasSize {
+    const SIZE: usize;
+}
+
+impl<const X: usize> HasSize for ArrayHolder<{ X }> {
+    const SIZE: usize = X;
+}
+
+struct ArrayHolder<const X: usize>([u32; X]);
+
+impl<const X: usize> ArrayHolder<{ X }> {
+    pub const fn new() -> Self {
+        ArrayHolder([0; Self::SIZE])
+        //~^ ERROR: array lengths can't depend on generic parameters
+    }
+}
+
+fn main() {
+    let mut array = ArrayHolder::new();
+}
diff --git a/src/test/ui/const-generics/issues/issue-62504.stderr b/src/test/ui/const-generics/issues/issue-62504.stderr
new file mode 100644
index 00000000000..c2a752ec171
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-62504.stderr
@@ -0,0 +1,8 @@
+error: array lengths can't depend on generic parameters
+  --> $DIR/issue-62504.rs:18:25
+   |
+LL |         ArrayHolder([0; Self::SIZE])
+   |                         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-67739.rs b/src/test/ui/const-generics/issues/issue-67739.rs
new file mode 100644
index 00000000000..79c5ac9dd18
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-67739.rs
@@ -0,0 +1,18 @@
+// Regression test for #67739
+
+#![allow(incomplete_features)]
+#![feature(const_generics)]
+
+use std::mem;
+
+pub trait Trait {
+    type Associated: Sized;
+
+    fn associated_size(&self) -> usize {
+        [0u8; mem::size_of::<Self::Associated>()];
+        //~^ ERROR: array lengths can't depend on generic parameters
+        0
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67739.stderr b/src/test/ui/const-generics/issues/issue-67739.stderr
new file mode 100644
index 00000000000..a31b556c086
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-67739.stderr
@@ -0,0 +1,8 @@
+error: array lengths can't depend on generic parameters
+  --> $DIR/issue-67739.rs:12:15
+   |
+LL |         [0u8; mem::size_of::<Self::Associated>()];
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs
index f69c37fbb8f..f0349f46962 100644
--- a/src/test/ui/const-generics/raw-ptr-const-param.rs
+++ b/src/test/ui/const-generics/raw-ptr-const-param.rs
@@ -4,6 +4,6 @@
 struct Const<const P: *const u32>;
 
 fn main() {
-    let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types
-    let _: Const<{10 as *const _}> = Const::<{10 as *const _}>;
+    let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; //~ mismatched types
+    let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>;
 }
diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr
index 9cd39b61dc9..d9794f60a19 100644
--- a/src/test/ui/const-generics/raw-ptr-const-param.stderr
+++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr
@@ -7,15 +7,15 @@ LL | #![feature(const_generics, const_compare_raw_pointers)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0308]: mismatched types
-  --> $DIR/raw-ptr-const-param.rs:7:38
+  --> $DIR/raw-ptr-const-param.rs:7:40
    |
-LL |     let _: Const<{15 as *const _}> = Const::<{10 as *const _}>;
-   |            -----------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{pointer}`, found `{pointer}`
+LL |     let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>;
+   |            -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}`
    |            |
    |            expected due to this
    |
-   = note: expected struct `Const<{pointer}>`
-              found struct `Const<{pointer}>`
+   = note: expected struct `Const<{0xf as *const u32}>`
+              found struct `Const<{0xa as *const u32}>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
index e0df787f80a..305f259eac2 100644
--- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
+++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
@@ -12,7 +12,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
    |
    = note: `#[deny(const_err)]` on by default
 
@@ -22,7 +22,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:34:45
@@ -30,7 +30,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:37:5
@@ -54,7 +54,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:46:45
@@ -62,7 +62,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:49:45
@@ -70,7 +70,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:52:5
@@ -94,7 +94,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
    |     ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                             |
-   |                                             a raw memory access tried to access part of a pointer value as raw bytes
+   |                                             unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:61:5
@@ -110,7 +110,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
    |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                               |
-   |                                               a raw memory access tried to access part of a pointer value as raw bytes
+   |                                               unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:67:47
@@ -118,7 +118,7 @@ error: any use of this value will cause an error
 LL |     const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
    |     ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                               |
-   |                                               a raw memory access tried to access part of a pointer value as raw bytes
+   |                                               unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:70:39
@@ -126,7 +126,7 @@ error: any use of this value will cause an error
 LL |     const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
    |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                       |
-   |                                       a raw memory access tried to access part of a pointer value as raw bytes
+   |                                       unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:73:41
@@ -134,7 +134,7 @@ error: any use of this value will cause an error
 LL |     const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:76:41
@@ -142,7 +142,7 @@ error: any use of this value will cause an error
 LL |     const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:79:5
@@ -158,7 +158,7 @@ error: any use of this value will cause an error
 LL |     const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:85:39
@@ -166,7 +166,7 @@ error: any use of this value will cause an error
 LL |     const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
    |     ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                       |
-   |                                       a raw memory access tried to access part of a pointer value as raw bytes
+   |                                       unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:88:41
@@ -174,7 +174,7 @@ error: any use of this value will cause an error
 LL |     const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:91:41
@@ -182,7 +182,7 @@ error: any use of this value will cause an error
 LL |     const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:94:5
@@ -198,7 +198,7 @@ error: any use of this value will cause an error
 LL |     const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:100:41
@@ -206,7 +206,7 @@ error: any use of this value will cause an error
 LL |     const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
    |     ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                         |
-   |                                         a raw memory access tried to access part of a pointer value as raw bytes
+   |                                         unable to turn pointer into raw bytes
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:103:5
@@ -222,7 +222,7 @@ error: any use of this value will cause an error
 LL |     const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:109:43
@@ -230,7 +230,7 @@ error: any use of this value will cause an error
 LL |     const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
    |     --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                           |
-   |                                           a raw memory access tried to access part of a pointer value as raw bytes
+   |                                           unable to turn pointer into raw bytes
 
 error: aborting due to 29 previous errors
 
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
index 9afcdf77610..6b86feb5921 100644
--- a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
+++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
@@ -17,8 +17,6 @@ const X: () = unimplemented!();
 
 #[lang = "eh_personality"]
 fn eh() {}
-#[lang = "eh_unwind_resume"]
-fn eh_unwind_resume() {}
 
 #[panic_handler]
 fn panic(_info: &PanicInfo) -> ! {
diff --git a/src/test/ui/consts/const-eval/const_prop_errors.rs b/src/test/ui/consts/const-eval/const_prop_errors.rs
index 48cfea82bd6..f9a36d37943 100644
--- a/src/test/ui/consts/const-eval/const_prop_errors.rs
+++ b/src/test/ui/consts/const-eval/const_prop_errors.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub trait Foo {
     fn foo(self) -> u32;
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
index 2cba833a748..cc40728e6b5 100644
--- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
@@ -30,7 +30,7 @@ error: any use of this value will cause an error
 LL | const Z2: i32 = unsafe { *(42 as *const i32) };
    | -------------------------^^^^^^^^^^^^^^^^^^^---
    |                          |
-   |                          a memory access tried to interpret some bytes as a pointer
+   |                          unable to turn bytes into a pointer
 
 error: any use of this value will cause an error
   --> $DIR/const_raw_ptr_ops.rs:17:26
@@ -38,7 +38,7 @@ error: any use of this value will cause an error
 LL | const Z3: i32 = unsafe { *(44 as *const i32) };
    | -------------------------^^^^^^^^^^^^^^^^^^^---
    |                          |
-   |                          a memory access tried to interpret some bytes as a pointer
+   |                          unable to turn bytes into a pointer
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/consts/const-eval/const_signed_pat.rs b/src/test/ui/consts/const-eval/const_signed_pat.rs
index d209e604486..c61239bb677 100644
--- a/src/test/ui/consts/const-eval/const_signed_pat.rs
+++ b/src/test/ui/consts/const-eval/const_signed_pat.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 fn main() {
     const MIN: i8 = -5;
diff --git a/src/test/ui/consts/const-eval/double_check.rs b/src/test/ui/consts/const-eval/double_check.rs
index ff2fff7fb79..f156d259abb 100644
--- a/src/test/ui/consts/const-eval/double_check.rs
+++ b/src/test/ui/consts/const-eval/double_check.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 enum Foo {
     A = 5,
diff --git a/src/test/ui/consts/const-eval/double_promotion.rs b/src/test/ui/consts/const-eval/double_promotion.rs
index a9a3f071bf8..48f4426d9cf 100644
--- a/src/test/ui/consts/const-eval/double_promotion.rs
+++ b/src/test/ui/consts/const-eval/double_promotion.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(const_fn, rustc_attrs)]
 
diff --git a/src/test/ui/consts/const-eval/duration_conversion.rs b/src/test/ui/consts/const-eval/duration_conversion.rs
index 029d4e5e373..87b12937dd4 100644
--- a/src/test/ui/consts/const-eval/duration_conversion.rs
+++ b/src/test/ui/consts/const-eval/duration_conversion.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 use std::time::Duration;
 
diff --git a/src/test/ui/consts/const-eval/extern_fat_pointer.rs b/src/test/ui/consts/const-eval/extern_fat_pointer.rs
index e2b3bc83c3f..f210d1a0a90 100644
--- a/src/test/ui/consts/const-eval/extern_fat_pointer.rs
+++ b/src/test/ui/consts/const-eval/extern_fat_pointer.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 #![feature(extern_types)]
 
diff --git a/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs b/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs
index ce0e11f29f4..4444cdfcda9 100644
--- a/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs
+++ b/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub trait Nullable {
     const NULL: Self;
diff --git a/src/test/ui/consts/const-eval/ice-packed.rs b/src/test/ui/consts/const-eval/ice-packed.rs
index 250bf954e9a..4758a5a9d56 100644
--- a/src/test/ui/consts/const-eval/ice-packed.rs
+++ b/src/test/ui/consts/const-eval/ice-packed.rs
@@ -1,4 +1,7 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// Regression test for #50356: Compiler panic when using repr(packed)
+// associated constant in a match arm
+
+// check-pass
 #[derive(Copy, Clone, PartialEq, Eq)]
 #[repr(packed)]
 pub struct Num(u64);
diff --git a/src/test/ui/consts/const-eval/issue-47971.rs b/src/test/ui/consts/const-eval/issue-47971.rs
index 9de150bd052..b98e76031d4 100644
--- a/src/test/ui/consts/const-eval/issue-47971.rs
+++ b/src/test/ui/consts/const-eval/issue-47971.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 struct S(pub &'static u32, pub u32);
 
diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr
index 48809e0ae64..798f130a4ba 100644
--- a/src/test/ui/consts/const-eval/issue-49296.stderr
+++ b/src/test/ui/consts/const-eval/issue-49296.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const X: u64 = *wat(42);
    | ---------------^^^^^^^^-
    |                |
-   |                dangling pointer was dereferenced
+   |                pointer to alloc2 was dereferenced after this allocation got freed
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/const-eval/issue-50706.rs b/src/test/ui/consts/const-eval/issue-50706.rs
index bf69bc28da4..a13c27f2e78 100644
--- a/src/test/ui/consts/const-eval/issue-50706.rs
+++ b/src/test/ui/consts/const-eval/issue-50706.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub struct Stats;
 
diff --git a/src/test/ui/consts/const-eval/issue-51300.rs b/src/test/ui/consts/const-eval/issue-51300.rs
index 4753bf0f7b1..8e68e8c9117 100644
--- a/src/test/ui/consts/const-eval/issue-51300.rs
+++ b/src/test/ui/consts/const-eval/issue-51300.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 // https://github.com/rust-lang/rust/issues/51300
 
 #[derive(PartialEq, Eq, Clone, Copy)]
diff --git a/src/test/ui/consts/const-eval/issue-53157.rs b/src/test/ui/consts/const-eval/issue-53157.rs
index ac0940b33e4..850338625bc 100644
--- a/src/test/ui/consts/const-eval/issue-53157.rs
+++ b/src/test/ui/consts/const-eval/issue-53157.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 macro_rules! m {
     () => {{
diff --git a/src/test/ui/consts/const-eval/issue-53401.rs b/src/test/ui/consts/const-eval/issue-53401.rs
index d300e0b5125..31c946c3cb7 100644
--- a/src/test/ui/consts/const-eval/issue-53401.rs
+++ b/src/test/ui/consts/const-eval/issue-53401.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub const STATIC_TRAIT: &dyn Test = &();
 
diff --git a/src/test/ui/consts/const-eval/issue-55541.rs b/src/test/ui/consts/const-eval/issue-55541.rs
index d04570c67ff..4c9e10d9cbe 100644
--- a/src/test/ui/consts/const-eval/issue-55541.rs
+++ b/src/test/ui/consts/const-eval/issue-55541.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 // Test that we can handle newtypes wrapping extern types
 
diff --git a/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs b/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs
index cea367528c9..910ca3c4bcb 100644
--- a/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs
+++ b/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 // if `X` were used instead of `x`, `X - 10` would result in a lint.
 // This file should never produce a lint, no matter how the const
diff --git a/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs b/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs
index ca75d65a39a..edda10e6e82 100644
--- a/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs
+++ b/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 pub fn main() {
     let y: &'static mut [u8; 0] = &mut [];
diff --git a/src/test/ui/consts/const-eval/pub_const_err.rs b/src/test/ui/consts/const-eval/pub_const_err.rs
index 4ff140fee7a..ad165d40a76 100644
--- a/src/test/ui/consts/const-eval/pub_const_err.rs
+++ b/src/test/ui/consts/const-eval/pub_const_err.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 #![warn(const_err)]
 
 #![crate_type = "lib"]
diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.rs b/src/test/ui/consts/const-eval/pub_const_err_bin.rs
index 7f1586336e7..078e4c896df 100644
--- a/src/test/ui/consts/const-eval/pub_const_err_bin.rs
+++ b/src/test/ui/consts/const-eval/pub_const_err_bin.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 #![warn(const_err)]
 
 pub const Z: u32 = 0 - 1;
diff --git a/src/test/ui/consts/const-eval/simple_with_undef.rs b/src/test/ui/consts/const-eval/simple_with_undef.rs
index 8a9f3fe974d..1a416dd460d 100644
--- a/src/test/ui/consts/const-eval/simple_with_undef.rs
+++ b/src/test/ui/consts/const-eval/simple_with_undef.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 const PARSE_BOOL: Option<&'static str> = None;
 static FOO: (Option<&str>, u32) = (PARSE_BOOL, 42);
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr
index edfc7ac837f..adad1b4f7fa 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr
@@ -13,7 +13,7 @@ LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
 LL | |     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
 LL | |     // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
 LL | |     let out_of_bounds_ptr = &ptr[255];
-   | |                             ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 8 which has size 1
+   | |                             ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc8 which has size 1
 LL | |     mem::transmute(out_of_bounds_ptr)
 LL | | } };
    | |____-
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
index 2d48309b727..0200bfe9f08 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
@@ -6,7 +6,7 @@
 use std::mem;
 
 // normalize-stderr-test "offset \d+" -> "offset N"
-// normalize-stderr-test "allocation \d+" -> "allocation N"
+// normalize-stderr-test "alloc\d+" -> "allocN"
 // normalize-stderr-test "size \d+" -> "size N"
 
 #[repr(C)]
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
index a562c64b124..80e60dbb58a 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:32:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
@@ -70,7 +70,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:62:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
@@ -86,7 +86,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:68:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
@@ -192,7 +192,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/ub-wide-ptr.rs:125:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
 
 error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr
index d0e35615dab..cede356a6b8 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr
@@ -4,7 +4,7 @@ warning: any use of this value will cause an error
 LL |     unsafe { std::mem::transmute(()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^
    |              |
-   |              entering unreachable code
+   |              transmuting to uninhabited type
    |              inside call to `foo` at $DIR/validate_uninhabited_zsts.rs:14:26
 ...
 LL | const FOO: [Empty; 3] = [foo(); 3];
diff --git a/src/test/ui/consts/const-eval/zst_operand_eval.rs b/src/test/ui/consts/const-eval/zst_operand_eval.rs
index 7edb6bd03da..5f7ddf7f758 100644
--- a/src/test/ui/consts/const-eval/zst_operand_eval.rs
+++ b/src/test/ui/consts/const-eval/zst_operand_eval.rs
@@ -1,4 +1,4 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 static ASSERT: () = [()][!(std::mem::size_of::<u32>() == 4) as usize];
 
diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr
index bf31e0b0732..cf70454b6bf 100644
--- a/src/test/ui/consts/const-int-unchecked.stderr
+++ b/src/test/ui/consts/const-int-unchecked.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                             |
-   |                             Overflowing shift by 8 in `unchecked_shl`
+   |                             overflowing shift by 8 in `unchecked_shl`
    |
    = note: `#[deny(const_err)]` on by default
 
@@ -14,7 +14,7 @@ error: any use of this value will cause an error
 LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 16 in `unchecked_shl`
+   |                               overflowing shift by 16 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:19:31
@@ -22,7 +22,7 @@ error: any use of this value will cause an error
 LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 32 in `unchecked_shl`
+   |                               overflowing shift by 32 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:21:31
@@ -30,7 +30,7 @@ error: any use of this value will cause an error
 LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 64 in `unchecked_shl`
+   |                               overflowing shift by 64 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:23:33
@@ -38,7 +38,7 @@ error: any use of this value will cause an error
 LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 128 in `unchecked_shl`
+   |                                 overflowing shift by 128 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:28:29
@@ -46,7 +46,7 @@ error: any use of this value will cause an error
 LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                             |
-   |                             Overflowing shift by 8 in `unchecked_shl`
+   |                             overflowing shift by 8 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:30:31
@@ -54,7 +54,7 @@ error: any use of this value will cause an error
 LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 16 in `unchecked_shl`
+   |                               overflowing shift by 16 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:32:31
@@ -62,7 +62,7 @@ error: any use of this value will cause an error
 LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 32 in `unchecked_shl`
+   |                               overflowing shift by 32 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:34:31
@@ -70,7 +70,7 @@ error: any use of this value will cause an error
 LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 64 in `unchecked_shl`
+   |                               overflowing shift by 64 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:36:33
@@ -78,7 +78,7 @@ error: any use of this value will cause an error
 LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 128 in `unchecked_shl`
+   |                                 overflowing shift by 128 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:41:33
@@ -86,7 +86,7 @@ error: any use of this value will cause an error
 LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 255 in `unchecked_shl`
+   |                                 overflowing shift by 255 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:43:35
@@ -94,7 +94,7 @@ error: any use of this value will cause an error
 LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 65535 in `unchecked_shl`
+   |                                   overflowing shift by 65535 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:45:35
@@ -102,7 +102,7 @@ error: any use of this value will cause an error
 LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 4294967295 in `unchecked_shl`
+   |                                   overflowing shift by 4294967295 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:47:35
@@ -110,7 +110,7 @@ error: any use of this value will cause an error
 LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 18446744073709551615 in `unchecked_shl`
+   |                                   overflowing shift by 18446744073709551615 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:49:37
@@ -118,7 +118,7 @@ error: any use of this value will cause an error
 LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
    | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                     |
-   |                                     Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
+   |                                     overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:55:40
@@ -126,7 +126,7 @@ error: any use of this value will cause an error
 LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
    | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                        |
-   |                                        Overflowing shift by 250 in `unchecked_shl`
+   |                                        overflowing shift by 250 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:57:42
@@ -134,7 +134,7 @@ error: any use of this value will cause an error
 LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 65523 in `unchecked_shl`
+   |                                          overflowing shift by 65523 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:59:42
@@ -142,7 +142,7 @@ error: any use of this value will cause an error
 LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 4294967271 in `unchecked_shl`
+   |                                          overflowing shift by 4294967271 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:61:42
@@ -150,7 +150,7 @@ error: any use of this value will cause an error
 LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 18446744073709551586 in `unchecked_shl`
+   |                                          overflowing shift by 18446744073709551586 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:63:44
@@ -158,7 +158,7 @@ error: any use of this value will cause an error
 LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
    | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                            |
-   |                                            Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
+   |                                            overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:70:29
@@ -166,7 +166,7 @@ error: any use of this value will cause an error
 LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                             |
-   |                             Overflowing shift by 8 in `unchecked_shr`
+   |                             overflowing shift by 8 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:72:31
@@ -174,7 +174,7 @@ error: any use of this value will cause an error
 LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 16 in `unchecked_shr`
+   |                               overflowing shift by 16 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:74:31
@@ -182,7 +182,7 @@ error: any use of this value will cause an error
 LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 32 in `unchecked_shr`
+   |                               overflowing shift by 32 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:76:31
@@ -190,7 +190,7 @@ error: any use of this value will cause an error
 LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 64 in `unchecked_shr`
+   |                               overflowing shift by 64 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:78:33
@@ -198,7 +198,7 @@ error: any use of this value will cause an error
 LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 128 in `unchecked_shr`
+   |                                 overflowing shift by 128 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:83:29
@@ -206,7 +206,7 @@ error: any use of this value will cause an error
 LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                             |
-   |                             Overflowing shift by 8 in `unchecked_shr`
+   |                             overflowing shift by 8 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:85:31
@@ -214,7 +214,7 @@ error: any use of this value will cause an error
 LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 16 in `unchecked_shr`
+   |                               overflowing shift by 16 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:87:31
@@ -222,7 +222,7 @@ error: any use of this value will cause an error
 LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 32 in `unchecked_shr`
+   |                               overflowing shift by 32 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:89:31
@@ -230,7 +230,7 @@ error: any use of this value will cause an error
 LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
    | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                               |
-   |                               Overflowing shift by 64 in `unchecked_shr`
+   |                               overflowing shift by 64 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:91:33
@@ -238,7 +238,7 @@ error: any use of this value will cause an error
 LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 128 in `unchecked_shr`
+   |                                 overflowing shift by 128 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:96:33
@@ -246,7 +246,7 @@ error: any use of this value will cause an error
 LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
    | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                 |
-   |                                 Overflowing shift by 255 in `unchecked_shr`
+   |                                 overflowing shift by 255 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:98:35
@@ -254,7 +254,7 @@ error: any use of this value will cause an error
 LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 65535 in `unchecked_shr`
+   |                                   overflowing shift by 65535 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:100:35
@@ -262,7 +262,7 @@ error: any use of this value will cause an error
 LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 4294967295 in `unchecked_shr`
+   |                                   overflowing shift by 4294967295 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:102:35
@@ -270,7 +270,7 @@ error: any use of this value will cause an error
 LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
    | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                   |
-   |                                   Overflowing shift by 18446744073709551615 in `unchecked_shr`
+   |                                   overflowing shift by 18446744073709551615 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:104:37
@@ -278,7 +278,7 @@ error: any use of this value will cause an error
 LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
    | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                     |
-   |                                     Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
+   |                                     overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:110:40
@@ -286,7 +286,7 @@ error: any use of this value will cause an error
 LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
    | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                        |
-   |                                        Overflowing shift by 250 in `unchecked_shr`
+   |                                        overflowing shift by 250 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:112:42
@@ -294,7 +294,7 @@ error: any use of this value will cause an error
 LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 65523 in `unchecked_shr`
+   |                                          overflowing shift by 65523 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:114:42
@@ -302,7 +302,7 @@ error: any use of this value will cause an error
 LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 4294967271 in `unchecked_shr`
+   |                                          overflowing shift by 4294967271 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:116:42
@@ -310,7 +310,7 @@ error: any use of this value will cause an error
 LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
    | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                          |
-   |                                          Overflowing shift by 18446744073709551586 in `unchecked_shr`
+   |                                          overflowing shift by 18446744073709551586 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:118:44
@@ -318,7 +318,7 @@ error: any use of this value will cause an error
 LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
    | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                                            |
-   |                                            Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
+   |                                            overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:123:25
@@ -326,7 +326,7 @@ error: any use of this value will cause an error
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_add`
+   |                         overflow executing `unchecked_add`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:126:25
@@ -334,7 +334,7 @@ error: any use of this value will cause an error
 LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_sub`
+   |                         overflow executing `unchecked_sub`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:129:25
@@ -342,7 +342,7 @@ error: any use of this value will cause an error
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_mul`
+   |                         overflow executing `unchecked_mul`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:132:25
@@ -358,7 +358,7 @@ error: any use of this value will cause an error
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::min_value(), -1) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_div`
+   |                         overflow executing `unchecked_div`
 
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:137:25
@@ -374,7 +374,7 @@ error: any use of this value will cause an error
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::min_value(), -1) };
    | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
-   |                         Overflow executing `unchecked_rem`
+   |                         overflow executing `unchecked_rem`
 
 error: aborting due to 47 previous errors
 
diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr
index bac9f555d27..0e213555052 100644
--- a/src/test/ui/consts/dangling-alloc-id-ice.stderr
+++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr
@@ -5,7 +5,7 @@ LL | / const FOO: &() = {
 LL | |     let y = ();
 LL | |     unsafe { Foo { y: &y }.long_live_the_unit }
 LL | | };
-   | |__^ type validation failed: encountered dangling pointer in final constant
+   | |__^ encountered dangling pointer in final constant
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/dangling_raw_ptr.stderr b/src/test/ui/consts/dangling_raw_ptr.stderr
index 4748be37dff..4d4c2876c45 100644
--- a/src/test/ui/consts/dangling_raw_ptr.stderr
+++ b/src/test/ui/consts/dangling_raw_ptr.stderr
@@ -5,7 +5,7 @@ LL | / const FOO: *const u32 = {
 LL | |     let x = 42;
 LL | |     &x
 LL | | };
-   | |__^ type validation failed: encountered dangling pointer in final constant
+   | |__^ encountered dangling pointer in final constant
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
index da00c49963e..c7e902132e9 100644
--- a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
+++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
@@ -16,7 +16,7 @@ error: any use of this value will cause an error
 LL |     my_fn();
    |     ^^^^^^^
    |     |
-   |     tried to call a function with ABI C using caller ABI Rust
+   |     calling a function with ABI C using caller ABI Rust
    |     inside call to `call_rust_fn` at $DIR/abi-mismatch.rs:13:17
 ...
 LL | const VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
index 86f27784701..8456e8ec687 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
@@ -11,7 +11,7 @@ LL | / const MUTATING_BEHIND_RAW: () = {
 LL | |     // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
 LL | |     unsafe {
 LL | |         *MUTABLE_BEHIND_RAW = 99
-   | |         ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc1 which is read-only
 LL | |     }
 LL | | };
    | |__-
diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr
index 24da983cf08..21753074007 100644
--- a/src/test/ui/consts/offset_from_ub.stderr
+++ b/src/test/ui/consts/offset_from_ub.stderr
@@ -26,7 +26,7 @@ error: any use of this value will cause an error
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
-   |           a memory access tried to interpret some bytes as a pointer
+   |           unable to turn bytes into a pointer
    |           inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:28:14
    | 
   ::: $DIR/offset_from_ub.rs:26:1
@@ -43,7 +43,7 @@ error: any use of this value will cause an error
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
-   |           exact_div: 1 cannot be divided by 2 without remainder
+   |           exact_div: 1isize cannot be divided by 2isize without remainder
    |           inside call to `std::ptr::const_ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:36:14
    | 
   ::: $DIR/offset_from_ub.rs:31:1
@@ -81,7 +81,7 @@ error: any use of this value will cause an error
 LL |           intrinsics::ptr_offset_from(self, origin)
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |           |
-   |           a memory access tried to interpret some bytes as a pointer
+   |           unable to turn bytes into a pointer
    |           inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:49:14
    | 
   ::: $DIR/offset_from_ub.rs:45:1
diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
index 296a55ef160..5a477714596 100644
--- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
+++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
@@ -21,7 +21,7 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    |                             ^^^^^^^^^^^^^^^^^^^
    |
    = note: source type: `usize` (word size)
-   = note: target type: `&'static [u8]` (2 * word size)
+   = note: target type: `&[u8]` (2 * word size)
 
 error: could not evaluate constant pattern
   --> $DIR/transmute-size-mismatch-before-typeck.rs:10:9
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index 613d7eee594..76e87a3749c 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -32,11 +32,11 @@ LL |     X() {}
 LL | }
    | - the item list ends here
 
-error: expected `[`, found `#`
+error: expected one of `!` or `[`, found `#`
   --> $DIR/issue-40006.rs:19:17
    |
 LL |     fn xxx() { ### }
-   |                 ^ expected `[`
+   |                 ^ expected one of `!` or `[`
 
 error: expected one of `!` or `::`, found `=`
   --> $DIR/issue-40006.rs:22:7
diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs
index 376c1a9cd66..9cb159603a8 100644
--- a/src/test/ui/directory_ownership/macro-expanded-mod.rs
+++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs
@@ -1,7 +1,9 @@
 // Test that macro-expanded non-inline modules behave correctly
 
 macro_rules! mod_decl {
-    ($i:ident) => { mod $i; } //~ ERROR Cannot declare a non-inline module inside a block
+    ($i:ident) => {
+        mod $i; //~ ERROR Cannot declare a non-inline module inside a block
+    };
 }
 
 mod macro_expanded_mod_helper {
diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr
index c7780c869d6..f90419247c9 100644
--- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr
+++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr
@@ -1,8 +1,8 @@
 error: Cannot declare a non-inline module inside a block unless it has a path attribute
-  --> $DIR/macro-expanded-mod.rs:4:25
+  --> $DIR/macro-expanded-mod.rs:5:9
    |
-LL |     ($i:ident) => { mod $i; }
-   |                         ^^
+LL |         mod $i;
+   |         ^^^^^^^
 ...
 LL |     mod_decl!(foo);
    |     --------------- in this macro invocation
diff --git a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr
index 46acc7e66d8..d034942ca5d 100644
--- a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr
+++ b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr
@@ -1,8 +1,8 @@
 error: Cannot declare a non-inline module inside a block unless it has a path attribute
-  --> $DIR/non-inline-mod-restriction.rs:4:9
+  --> $DIR/non-inline-mod-restriction.rs:4:5
    |
 LL |     mod foo;
-   |         ^^^
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/enum/enum-discrim-too-small2.stderr b/src/test/ui/enum/enum-discrim-too-small2.stderr
index 3aa88df29f1..fadf6ab86b4 100644
--- a/src/test/ui/enum/enum-discrim-too-small2.stderr
+++ b/src/test/ui/enum/enum-discrim-too-small2.stderr
@@ -9,24 +9,31 @@ note: the lint level is defined here
    |
 LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `223` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i16`
   --> $DIR/enum-discrim-too-small2.rs:15:12
    |
 LL |     Ci16 = 55555,
    |            ^^^^^
+   |
+   = note: the literal `55555` does not fit into the type `i16` whose range is `-32768..=32767`
 
 error: literal out of range for `i32`
   --> $DIR/enum-discrim-too-small2.rs:22:12
    |
 LL |     Ci32 = 3_000_000_000,
    |            ^^^^^^^^^^^^^
+   |
+   = note: the literal `3_000_000_000` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i64`
   --> $DIR/enum-discrim-too-small2.rs:29:12
    |
 LL |     Ci64 = 9223372036854775809,
    |            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr
index 5a5c6b40c5a..ad854837ae5 100644
--- a/src/test/ui/error-codes/E0121.stderr
+++ b/src/test/ui/error-codes/E0121.stderr
@@ -14,7 +14,7 @@ LL | static BAR: _ = "test";
    |             ^
    |             |
    |             not allowed in type signatures
-   |             help: replace `_` with the correct type: `&'static str`
+   |             help: replace `_` with the correct type: `&str`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0197.stderr b/src/test/ui/error-codes/E0197.stderr
index 51ed9c83bc9..35e1042649e 100644
--- a/src/test/ui/error-codes/E0197.stderr
+++ b/src/test/ui/error-codes/E0197.stderr
@@ -1,8 +1,8 @@
 error[E0197]: inherent impls cannot be unsafe
-  --> $DIR/E0197.rs:3:1
+  --> $DIR/E0197.rs:3:13
    |
 LL | unsafe impl Foo { }
-   | ------^^^^^^^^^^^^^
+   | ------      ^^^ inherent impl for this type
    | |
    | unsafe because of this
 
diff --git a/src/test/ui/error-codes/E0198.stderr b/src/test/ui/error-codes/E0198.stderr
index 90e8b4abd12..bb2efefb427 100644
--- a/src/test/ui/error-codes/E0198.stderr
+++ b/src/test/ui/error-codes/E0198.stderr
@@ -1,9 +1,10 @@
 error[E0198]: negative impls cannot be unsafe
-  --> $DIR/E0198.rs:5:1
+  --> $DIR/E0198.rs:5:13
    |
 LL | unsafe impl !Send for Foo { }
-   | ------^^^^^^^^^^^^^^^^^^^^^^^
-   | |
+   | ------      -^^^^
+   | |           |
+   | |           negative because of this
    | unsafe because of this
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0396-fixed.stderr b/src/test/ui/error-codes/E0396-fixed.stderr
index 7222f87da24..68505552562 100644
--- a/src/test/ui/error-codes/E0396-fixed.stderr
+++ b/src/test/ui/error-codes/E0396-fixed.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const VALUE: u8 = unsafe { *REG_ADDR };
    | ---------------------------^^^^^^^^^---
    |                            |
-   |                            a memory access tried to interpret some bytes as a pointer
+   |                            unable to turn bytes into a pointer
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/error-codes/E0583.stderr b/src/test/ui/error-codes/E0583.stderr
index ef7a48bc8a4..dbe70035595 100644
--- a/src/test/ui/error-codes/E0583.stderr
+++ b/src/test/ui/error-codes/E0583.stderr
@@ -1,10 +1,10 @@
 error[E0583]: file not found for module `module_that_doesnt_exist`
-  --> $DIR/E0583.rs:1:5
+  --> $DIR/E0583.rs:1:1
    |
 LL | mod module_that_doesnt_exist;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: name the file either module_that_doesnt_exist.rs or module_that_doesnt_exist/mod.rs inside the directory "$DIR"
+   = help: to create the module `module_that_doesnt_exist`, create file "$DIR/module_that_doesnt_exist.rs"
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0624.rs b/src/test/ui/error-codes/E0624.rs
index 45f72a565ca..4c68b70fb16 100644
--- a/src/test/ui/error-codes/E0624.rs
+++ b/src/test/ui/error-codes/E0624.rs
@@ -8,5 +8,5 @@ mod inner {
 
 fn main() {
     let foo = inner::Foo;
-    foo.method(); //~ ERROR method `method` is private [E0624]
+    foo.method(); //~ ERROR associated function `method` is private [E0624]
 }
diff --git a/src/test/ui/error-codes/E0624.stderr b/src/test/ui/error-codes/E0624.stderr
index 01ac24cfbbe..65256c8dd2d 100644
--- a/src/test/ui/error-codes/E0624.stderr
+++ b/src/test/ui/error-codes/E0624.stderr
@@ -1,4 +1,4 @@
-error[E0624]: method `method` is private
+error[E0624]: associated function `method` is private
   --> $DIR/E0624.rs:11:9
    |
 LL |     foo.method();
diff --git a/src/test/ui/explore-issue-38412.stderr b/src/test/ui/explore-issue-38412.stderr
index 4c80989951a..94a2cfe013d 100644
--- a/src/test/ui/explore-issue-38412.stderr
+++ b/src/test/ui/explore-issue-38412.stderr
@@ -79,19 +79,19 @@ LL |     r.unstable_undeclared();
    = note: see issue #38412 <https://github.com/rust-lang/rust/issues/38412> for more information
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
-error[E0624]: method `pub_crate` is private
+error[E0624]: associated function `pub_crate` is private
   --> $DIR/explore-issue-38412.rs:50:7
    |
 LL |     r.pub_crate();
    |       ^^^^^^^^^
 
-error[E0624]: method `pub_mod` is private
+error[E0624]: associated function `pub_mod` is private
   --> $DIR/explore-issue-38412.rs:51:7
    |
 LL |     r.pub_mod();
    |       ^^^^^^^
 
-error[E0624]: method `private` is private
+error[E0624]: associated function `private` is private
   --> $DIR/explore-issue-38412.rs:52:7
    |
 LL |     r.private();
@@ -115,19 +115,19 @@ LL |     t.unstable_undeclared();
    = note: see issue #38412 <https://github.com/rust-lang/rust/issues/38412> for more information
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
-error[E0624]: method `pub_crate` is private
+error[E0624]: associated function `pub_crate` is private
   --> $DIR/explore-issue-38412.rs:63:7
    |
 LL |     t.pub_crate();
    |       ^^^^^^^^^
 
-error[E0624]: method `pub_mod` is private
+error[E0624]: associated function `pub_mod` is private
   --> $DIR/explore-issue-38412.rs:64:7
    |
 LL |     t.pub_mod();
    |       ^^^^^^^
 
-error[E0624]: method `private` is private
+error[E0624]: associated function `private` is private
   --> $DIR/explore-issue-38412.rs:65:7
    |
 LL |     t.private();
diff --git a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr
index d29c373a33c..490d29ad8a3 100644
--- a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr
+++ b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr
@@ -8,10 +8,10 @@ LL | auto trait AutoDummyTrait {}
    = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable
 
 error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
-  --> $DIR/feature-gate-optin-builtin-traits.rs:9:1
+  --> $DIR/feature-gate-optin-builtin-traits.rs:9:6
    |
 LL | impl !AutoDummyTrait for DummyStruct {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |      ^^^^^^^^^^^^^^^
    |
    = note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
    = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable
diff --git a/src/test/ui/fn-in-pat.rs b/src/test/ui/fn-in-pat.rs
index b83252012b8..2d7c86b8666 100644
--- a/src/test/ui/fn-in-pat.rs
+++ b/src/test/ui/fn-in-pat.rs
@@ -8,7 +8,7 @@ fn hof<F>(_: F) where F: FnMut(()) {}
 
 fn ice() {
     hof(|c| match c {
-        A::new() => (), //~ ERROR expected tuple struct or tuple variant, found method
+        A::new() => (), //~ ERROR expected tuple struct or tuple variant, found associated function
         _ => ()
     })
 }
diff --git a/src/test/ui/fn-in-pat.stderr b/src/test/ui/fn-in-pat.stderr
index 5d6632f2fc2..2482d632695 100644
--- a/src/test/ui/fn-in-pat.stderr
+++ b/src/test/ui/fn-in-pat.stderr
@@ -1,4 +1,4 @@
-error[E0164]: expected tuple struct or tuple variant, found method `A::new`
+error[E0164]: expected tuple struct or tuple variant, found associated function `A::new`
   --> $DIR/fn-in-pat.rs:11:9
    |
 LL |         A::new() => (),
diff --git a/src/test/ui/generator/discriminant.rs b/src/test/ui/generator/discriminant.rs
new file mode 100644
index 00000000000..8a0f8a380ab
--- /dev/null
+++ b/src/test/ui/generator/discriminant.rs
@@ -0,0 +1,134 @@
+//! Tests that generator discriminant sizes and ranges are chosen optimally and that they are
+//! reflected in the output of `mem::discriminant`.
+
+// run-pass
+
+#![feature(generators, generator_trait, core_intrinsics)]
+
+use std::intrinsics::discriminant_value;
+use std::marker::Unpin;
+use std::mem::size_of_val;
+use std::{cmp, ops::*};
+
+macro_rules! yield25 {
+    ($e:expr) => {
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+        yield $e;
+    };
+}
+
+/// Yields 250 times.
+macro_rules! yield250 {
+    () => {
+        yield250!(())
+    };
+
+    ($e:expr) => {
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+        yield25!($e);
+    };
+}
+
+fn cycle(gen: impl Generator<()> + Unpin, expected_max_discr: u64) {
+    let mut gen = Box::pin(gen);
+    let mut max_discr = 0;
+    loop {
+        max_discr = cmp::max(max_discr, discriminant_value(gen.as_mut().get_mut()));
+        match gen.as_mut().resume(()) {
+            GeneratorState::Yielded(_) => {}
+            GeneratorState::Complete(_) => {
+                assert_eq!(max_discr, expected_max_discr);
+                return;
+            }
+        }
+    }
+}
+
+fn main() {
+    // Has only one invalid discr. value.
+    let gen_u8_tiny_niche = || {
+        || {
+            // 3 reserved variants
+
+            yield250!(); // 253 variants
+
+            yield; // 254
+            yield; // 255
+        }
+    };
+
+    // Uses all values in the u8 discriminant.
+    let gen_u8_full = || {
+        || {
+            // 3 reserved variants
+
+            yield250!(); // 253 variants
+
+            yield; // 254
+            yield; // 255
+            yield; // 256
+        }
+    };
+
+    // Barely needs a u16 discriminant.
+    let gen_u16 = || {
+        || {
+            // 3 reserved variants
+
+            yield250!(); // 253 variants
+
+            yield; // 254
+            yield; // 255
+            yield; // 256
+            yield; // 257
+        }
+    };
+
+    assert_eq!(size_of_val(&gen_u8_tiny_niche()), 1);
+    assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche
+    assert_eq!(size_of_val(&Some(Some(gen_u8_tiny_niche()))), 2); // cannot use niche anymore
+    assert_eq!(size_of_val(&gen_u8_full()), 1);
+    assert_eq!(size_of_val(&Some(gen_u8_full())), 2); // cannot use niche
+    assert_eq!(size_of_val(&gen_u16()), 2);
+    assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche
+
+    cycle(gen_u8_tiny_niche(), 254);
+    cycle(gen_u8_full(), 255);
+    cycle(gen_u16(), 256);
+}
diff --git a/src/test/ui/generator-yielding-or-returning-itself.rs b/src/test/ui/generator/generator-yielding-or-returning-itself.rs
index 30788e3c186..30788e3c186 100644
--- a/src/test/ui/generator-yielding-or-returning-itself.rs
+++ b/src/test/ui/generator/generator-yielding-or-returning-itself.rs
diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr
index fc8064d8225..fc8064d8225 100644
--- a/src/test/ui/generator-yielding-or-returning-itself.stderr
+++ b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr
diff --git a/src/test/ui/generator/issue-69039.rs b/src/test/ui/generator/issue-69039.rs
index 60004f3b0ae..ccc141860aa 100644
--- a/src/test/ui/generator/issue-69039.rs
+++ b/src/test/ui/generator/issue-69039.rs
@@ -4,11 +4,15 @@
 
 use std::ops::{Generator, GeneratorState};
 
+fn mkstr(my_name: String, my_mood: String) -> String {
+    format!("{} is {}", my_name.trim(), my_mood.trim())
+}
+
 fn my_scenario() -> impl Generator<String, Yield = &'static str, Return = String> {
     |_arg: String| {
         let my_name = yield "What is your name?";
         let my_mood = yield "How are you feeling?";
-        format!("{} is {}", my_name.trim(), my_mood.trim())
+        mkstr(my_name, my_mood)
     }
 }
 
diff --git a/src/test/ui/generator/resume-arg-size.rs b/src/test/ui/generator/resume-arg-size.rs
new file mode 100644
index 00000000000..4f08ac0702b
--- /dev/null
+++ b/src/test/ui/generator/resume-arg-size.rs
@@ -0,0 +1,28 @@
+#![feature(generators)]
+
+// run-pass
+
+use std::mem::size_of_val;
+
+fn main() {
+    // Generator taking a `Copy`able resume arg.
+    let gen_copy = |mut x: usize| {
+        loop {
+            drop(x);
+            x = yield;
+        }
+    };
+
+    // Generator taking a non-`Copy` resume arg.
+    let gen_move = |mut x: Box<usize>| {
+        loop {
+            drop(x);
+            x = yield;
+        }
+    };
+
+    // Neither of these generators have the resume arg live across the `yield`, so they should be
+    // 4 Bytes in size (only storing the discriminant)
+    assert_eq!(size_of_val(&gen_copy), 1);
+    assert_eq!(size_of_val(&gen_move), 1);
+}
diff --git a/src/test/ui/generator/size-moved-locals.rs b/src/test/ui/generator/size-moved-locals.rs
index 2864fbb2f3c..74c60d98154 100644
--- a/src/test/ui/generator/size-moved-locals.rs
+++ b/src/test/ui/generator/size-moved-locals.rs
@@ -58,7 +58,7 @@ fn overlap_move_points() -> impl Generator<Yield = (), Return = ()> {
     }
 }
 
-fn overlap_x_and_y() -> impl Generator<Yield = (), Return = ()>{
+fn overlap_x_and_y() -> impl Generator<Yield = (), Return = ()> {
     static || {
         let x = Foo([0; FOO_SIZE]);
         yield;
@@ -70,8 +70,8 @@ fn overlap_x_and_y() -> impl Generator<Yield = (), Return = ()>{
 }
 
 fn main() {
-    assert_eq!(1028, std::mem::size_of_val(&move_before_yield()));
-    assert_eq!(1032, std::mem::size_of_val(&move_before_yield_with_noop()));
-    assert_eq!(2056, std::mem::size_of_val(&overlap_move_points()));
-    assert_eq!(1032, std::mem::size_of_val(&overlap_x_and_y()));
+    assert_eq!(1025, std::mem::size_of_val(&move_before_yield()));
+    assert_eq!(1026, std::mem::size_of_val(&move_before_yield_with_noop()));
+    assert_eq!(2051, std::mem::size_of_val(&overlap_move_points()));
+    assert_eq!(1026, std::mem::size_of_val(&overlap_x_and_y()));
 }
diff --git a/src/test/ui/generator/too-many-parameters.stderr b/src/test/ui/generator/too-many-parameters.stderr
index a297ee43de9..22d40db3f26 100644
--- a/src/test/ui/generator/too-many-parameters.stderr
+++ b/src/test/ui/generator/too-many-parameters.stderr
@@ -6,3 +6,4 @@ LL |     |(), ()| {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0628`.
diff --git a/src/test/ui/generic-associated-types/empty_generics.rs b/src/test/ui/generic-associated-types/empty_generics.rs
index 522e23ca43d..6eb25a92f34 100644
--- a/src/test/ui/generic-associated-types/empty_generics.rs
+++ b/src/test/ui/generic-associated-types/empty_generics.rs
@@ -3,7 +3,7 @@
 
 trait Foo {
     type Bar<,>;
-    //~^ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
+    //~^ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
 }
 
 fn main() {}
diff --git a/src/test/ui/generic-associated-types/empty_generics.stderr b/src/test/ui/generic-associated-types/empty_generics.stderr
index bd5708d8140..1599d683ad6 100644
--- a/src/test/ui/generic-associated-types/empty_generics.stderr
+++ b/src/test/ui/generic-associated-types/empty_generics.stderr
@@ -1,10 +1,10 @@
-error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/empty_generics.rs:5:14
    |
 LL | trait Foo {
    |           - while parsing this item list starting here
 LL |     type Bar<,>;
-   |              ^ expected one of `>`, `const`, identifier, or lifetime
+   |              ^ expected one of `#`, `>`, `const`, identifier, or lifetime
 LL |
 LL | }
    | - the item list ends here
diff --git a/src/test/ui/hygiene/macro-metavars-legacy.rs b/src/test/ui/hygiene/macro-metavars-legacy.rs
new file mode 100644
index 00000000000..09070f0f561
--- /dev/null
+++ b/src/test/ui/hygiene/macro-metavars-legacy.rs
@@ -0,0 +1,29 @@
+// Ensure macro metavariables are compared with legacy hygiene
+
+#![feature(rustc_attrs)]
+
+// run-pass
+
+macro_rules! make_mac {
+    ( $($dollar:tt $arg:ident),+ ) => {
+        macro_rules! mac {
+            ( $($dollar $arg : ident),+ ) => {
+                $( $dollar $arg )-+
+            }
+        }
+    }
+}
+
+macro_rules! show_hygiene {
+    ( $dollar:tt $arg:ident ) => {
+        make_mac!($dollar $arg, $dollar arg);
+    }
+}
+
+show_hygiene!( $arg );
+
+fn main() {
+    let x = 5;
+    let y = 3;
+    assert_eq!(2, mac!(x, y));
+}
diff --git a/src/test/ui/hygiene/macro-metavars-transparent.rs b/src/test/ui/hygiene/macro-metavars-transparent.rs
new file mode 100644
index 00000000000..e475b5728a0
--- /dev/null
+++ b/src/test/ui/hygiene/macro-metavars-transparent.rs
@@ -0,0 +1,24 @@
+// Ensure macro metavariables are not compared without removing transparent
+// marks.
+
+#![feature(rustc_attrs)]
+
+// run-pass
+
+#[rustc_macro_transparency = "transparent"]
+macro_rules! k {
+    ($($s:tt)*) => {
+        macro_rules! m {
+            ($y:tt) => {
+                $($s)*
+            }
+        }
+    }
+}
+
+k!(1 + $y);
+
+fn main() {
+    let x = 2;
+    assert_eq!(3, m!(x));
+}
diff --git a/src/test/ui/if-attrs/else-attrs.rs b/src/test/ui/if-attrs/else-attrs.rs
index 4394b2100c1..85da7cf6bb8 100644
--- a/src/test/ui/if-attrs/else-attrs.rs
+++ b/src/test/ui/if-attrs/else-attrs.rs
@@ -8,7 +8,7 @@ fn if_else_parse_error() {
 #[cfg(FALSE)]
 fn else_attr_ifparse_error() {
     if true {
-    } else #[attr] if false { //~ ERROR expected
+    } else #[attr] if false { //~ ERROR outer attributes are not allowed
     } else {
     }
 }
diff --git a/src/test/ui/if-attrs/else-attrs.stderr b/src/test/ui/if-attrs/else-attrs.stderr
index af25b6abc0a..2733377054d 100644
--- a/src/test/ui/if-attrs/else-attrs.stderr
+++ b/src/test/ui/if-attrs/else-attrs.stderr
@@ -4,18 +4,17 @@ error: expected expression, found keyword `else`
 LL |     } #[attr] else if false {
    |               ^^^^ expected expression
 
-error: expected `{`, found `#`
+error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/else-attrs.rs:11:12
    |
-LL |     } else #[attr] if false {
-   |            ^ expected `{`
-   |
-help: try placing this code inside a block
-   |
-LL |     } else #[attr] { if false {
-LL |     } else {
-LL |     } }
-   |
+LL |       } else #[attr] if false {
+   |  _______----_^^^^^^^_-
+   | |       |    |
+   | |       |    help: remove the attributes
+   | |       the branch belongs to this `else`
+LL | |     } else {
+LL | |     }
+   | |_____- the attributes are attached to this branch
 
 error: expected expression, found keyword `else`
   --> $DIR/else-attrs.rs:20:15
diff --git a/src/test/ui/imports/issue-55884-2.stderr b/src/test/ui/imports/issue-55884-2.stderr
index f16d2adb365..490c08446b5 100644
--- a/src/test/ui/imports/issue-55884-2.stderr
+++ b/src/test/ui/imports/issue-55884-2.stderr
@@ -4,11 +4,26 @@ error[E0603]: struct import `ParseOptions` is private
 LL | pub use parser::ParseOptions;
    |                 ^^^^^^^^^^^^ this struct import is private
    |
-note: the struct import `ParseOptions` is defined here
+note: the struct import `ParseOptions` is defined here...
   --> $DIR/issue-55884-2.rs:9:9
    |
 LL |     use ParseOptions;
    |         ^^^^^^^^^^^^
+note: ...and refers to the struct import `ParseOptions` which is defined here...
+  --> $DIR/issue-55884-2.rs:12:9
+   |
+LL | pub use parser::ParseOptions;
+   |         ^^^^^^^^^^^^^^^^^^^^ consider importing it directly
+note: ...and refers to the struct import `ParseOptions` which is defined here...
+  --> $DIR/issue-55884-2.rs:6:13
+   |
+LL |     pub use options::*;
+   |             ^^^^^^^^^^ consider importing it directly
+note: ...and refers to the struct `ParseOptions` which is defined here
+  --> $DIR/issue-55884-2.rs:2:5
+   |
+LL |     pub struct ParseOptions {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/imports/reexports.stderr b/src/test/ui/imports/reexports.stderr
index 7b0d63574ec..d63fbc7ec67 100644
--- a/src/test/ui/imports/reexports.stderr
+++ b/src/test/ui/imports/reexports.stderr
@@ -16,11 +16,16 @@ error[E0603]: module import `foo` is private
 LL |     use b::a::foo::S;
    |               ^^^ this module import is private
    |
-note: the module import `foo` is defined here
+note: the module import `foo` is defined here...
   --> $DIR/reexports.rs:21:17
    |
 LL |         pub use super::foo; // This is OK since the value `foo` is visible enough.
    |                 ^^^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/reexports.rs:16:5
+   |
+LL |     mod foo {
+   |     ^^^^^^^
 
 error[E0603]: module import `foo` is private
   --> $DIR/reexports.rs:34:15
@@ -28,11 +33,16 @@ error[E0603]: module import `foo` is private
 LL |     use b::b::foo::S as T;
    |               ^^^ this module import is private
    |
-note: the module import `foo` is defined here
+note: the module import `foo` is defined here...
   --> $DIR/reexports.rs:26:17
    |
 LL |         pub use super::*; // This is also OK since the value `foo` is visible enough.
    |                 ^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/reexports.rs:16:5
+   |
+LL |     mod foo {
+   |     ^^^^^^^
 
 warning: glob import doesn't reexport anything because no candidate is public enough
   --> $DIR/reexports.rs:9:17
diff --git a/src/test/ui/init-large-type.rs b/src/test/ui/init-large-type.rs
index a304fc9356b..ce905572f2a 100644
--- a/src/test/ui/init-large-type.rs
+++ b/src/test/ui/init-large-type.rs
@@ -1,3 +1,4 @@
+// compile-flags: -O
 // run-pass
 
 #![allow(unused_must_use)]
@@ -10,17 +11,13 @@
 
 #![feature(intrinsics)]
 
-use std::thread;
-
-extern "rust-intrinsic" {
-    pub fn init<T>() -> T;
-}
+use std::{mem, thread};
 
 const SIZE: usize = 1024 * 1024;
 
 fn main() {
     // do the test in a new thread to avoid (spurious?) stack overflows
     thread::spawn(|| {
-        let _memory: [u8; SIZE] = unsafe { init() };
+        let _memory: [u8; SIZE] = unsafe { mem::zeroed() };
     }).join();
 }
diff --git a/src/test/ui/init-unsafe.rs b/src/test/ui/init-unsafe.rs
deleted file mode 100644
index 3d65cfc2340..00000000000
--- a/src/test/ui/init-unsafe.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![allow(deprecated)]
-#![feature(core_intrinsics)]
-
-use std::intrinsics::{init};
-
-// Test that the `init` intrinsic is really unsafe
-pub fn main() {
-    let stuff = init::<isize>(); //~ ERROR call to unsafe function is unsafe
-}
diff --git a/src/test/ui/init-unsafe.stderr b/src/test/ui/init-unsafe.stderr
deleted file mode 100644
index e1126316af3..00000000000
--- a/src/test/ui/init-unsafe.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
-  --> $DIR/init-unsafe.rs:8:17
-   |
-LL |     let stuff = init::<isize>();
-   |                 ^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/intrinsics/intrinsic-move-val.rs b/src/test/ui/intrinsics/intrinsic-move-val.rs
index 75b4ec365fe..b672f1ed26e 100644
--- a/src/test/ui/intrinsics/intrinsic-move-val.rs
+++ b/src/test/ui/intrinsics/intrinsic-move-val.rs
@@ -5,7 +5,6 @@
 
 mod rusti {
     extern "rust-intrinsic" {
-        pub fn init<T>() -> T;
         pub fn move_val_init<T>(dst: *mut T, src: T);
     }
 }
@@ -15,17 +14,17 @@ pub fn main() {
         // sanity check
         check_drops_state(0, None);
 
-        let mut x: Box<D> = box D(1);
-        assert_eq!(x.0, 1);
+        let mut x: Option<Box<D>> = Some(box D(1));
+        assert_eq!(x.as_ref().unwrap().0, 1);
 
         // A normal overwrite, to demonstrate `check_drops_state`.
-        x = box D(2);
+        x = Some(box D(2));
 
         // At this point, one destructor has run, because the
         // overwrite of `x` drops its initial value.
         check_drops_state(1, Some(1));
 
-        let mut y: Box<D> = rusti::init();
+        let mut y: Option<Box<D>> = std::mem::zeroed();
 
         // An initial binding does not overwrite anything.
         check_drops_state(1, Some(1));
@@ -51,9 +50,9 @@ pub fn main() {
         // during such a destructor call. We do so after the end of
         // this scope.
 
-        assert_eq!(y.0, 2);
-        y.0 = 3;
-        assert_eq!(y.0, 3);
+        assert_eq!(y.as_ref().unwrap().0, 2);
+        y.as_mut().unwrap().0 = 3;
+        assert_eq!(y.as_ref().unwrap().0, 3);
 
         check_drops_state(1, Some(1));
     }
diff --git a/src/test/ui/intrinsics/intrinsic-uninit.rs b/src/test/ui/intrinsics/intrinsic-uninit.rs
deleted file mode 100644
index 9555efb639b..00000000000
--- a/src/test/ui/intrinsics/intrinsic-uninit.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-#![feature(intrinsics)]
-
-mod rusti {
-    extern "rust-intrinsic" {
-        pub fn uninit<T>() -> T;
-    }
-}
-pub fn main() {
-    let _a : isize = unsafe {rusti::uninit()};
-}
diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr
index c95df5b4534..52296042eb4 100644
--- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr
+++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr
@@ -1,10 +1,10 @@
 error[E0583]: file not found for module `baz`
-  --> $DIR/auxiliary/foo/bar.rs:1:9
+  --> $DIR/auxiliary/foo/bar.rs:1:1
    |
 LL | pub mod baz;
-   |         ^^^
+   | ^^^^^^^^^^^^
    |
-   = help: name the file either bar/baz.rs or bar/baz/mod.rs inside the directory "$DIR/auxiliary/foo"
+   = help: to create the module `baz`, create file "$DIR/auxiliary/foo/bar/baz.rs"
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-16683.nll.stderr b/src/test/ui/issues/issue-16683.nll.stderr
index f76e7a4e44f..b82b0b552e2 100644
--- a/src/test/ui/issues/issue-16683.nll.stderr
+++ b/src/test/ui/issues/issue-16683.nll.stderr
@@ -1,10 +1,10 @@
-error[E0521]: borrowed data escapes outside of method
+error[E0521]: borrowed data escapes outside of associated function
   --> $DIR/issue-16683.rs:4:9
    |
 LL |     fn b(&self) {
-   |          ----- `self` is a reference that is only valid in the method body
+   |          ----- `self` is a reference that is only valid in the associated function body
 LL |         self.a();
-   |         ^^^^^^^^ `self` escapes the method body here
+   |         ^^^^^^^^ `self` escapes the associated function body here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17758.nll.stderr b/src/test/ui/issues/issue-17758.nll.stderr
index 92e21f4dc17..23557b4d956 100644
--- a/src/test/ui/issues/issue-17758.nll.stderr
+++ b/src/test/ui/issues/issue-17758.nll.stderr
@@ -1,10 +1,10 @@
-error[E0521]: borrowed data escapes outside of method
+error[E0521]: borrowed data escapes outside of associated function
   --> $DIR/issue-17758.rs:7:9
    |
 LL |     fn bar(&self) {
-   |            ----- `self` is a reference that is only valid in the method body
+   |            ----- `self` is a reference that is only valid in the associated function body
 LL |         self.foo();
-   |         ^^^^^^^^^^ `self` escapes the method body here
+   |         ^^^^^^^^^^ `self` escapes the associated function body here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20616-8.rs b/src/test/ui/issues/issue-20616-8.rs
index c9e8b61e50b..3ceb58d1252 100644
--- a/src/test/ui/issues/issue-20616-8.rs
+++ b/src/test/ui/issues/issue-20616-8.rs
@@ -29,7 +29,7 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 
 
 type Type_8<'a,,> = &'a ();
-//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+//~^ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
 
 
 //type Type_9<T,,> = Box<T>; // error: expected identifier, found `,`
diff --git a/src/test/ui/issues/issue-20616-8.stderr b/src/test/ui/issues/issue-20616-8.stderr
index 479469634c5..e9f37e50fff 100644
--- a/src/test/ui/issues/issue-20616-8.stderr
+++ b/src/test/ui/issues/issue-20616-8.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/issue-20616-8.rs:31:16
    |
 LL | type Type_8<'a,,> = &'a ();
-   |                ^ expected one of `>`, `const`, identifier, or lifetime
+   |                ^ expected one of `#`, `>`, `const`, identifier, or lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20616-9.rs b/src/test/ui/issues/issue-20616-9.rs
index 1c509f26fd6..7f84284481e 100644
--- a/src/test/ui/issues/issue-20616-9.rs
+++ b/src/test/ui/issues/issue-20616-9.rs
@@ -32,4 +32,4 @@ type Type_5_<'a> = Type_1_<'a, ()>;
 
 
 type Type_9<T,,> = Box<T>;
-//~^ error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+//~^ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
diff --git a/src/test/ui/issues/issue-20616-9.stderr b/src/test/ui/issues/issue-20616-9.stderr
index b7e3322b7aa..dc309d1bce1 100644
--- a/src/test/ui/issues/issue-20616-9.stderr
+++ b/src/test/ui/issues/issue-20616-9.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/issue-20616-9.rs:34:15
    |
 LL | type Type_9<T,,> = Box<T>;
-   |               ^ expected one of `>`, `const`, identifier, or lifetime
+   |               ^ expected one of `#`, `>`, `const`, identifier, or lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-21174.stderr b/src/test/ui/issues/issue-21174.stderr
index 5ac5a8665bc..09402c3d814 100644
--- a/src/test/ui/issues/issue-21174.stderr
+++ b/src/test/ui/issues/issue-21174.stderr
@@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     let new: T::B = unsafe { std::mem::transmute(value) };
    |                              ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `<T as Trait<'a>>::A` (size can vary because of <T as Trait>::A)
-   = note: target type: `<T as Trait<'a>>::B` (size can vary because of <T as Trait>::B)
+   = note: source type: `<T as Trait>::A` (this type does not have a fixed size)
+   = note: target type: `<T as Trait>::B` (this type does not have a fixed size)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-21202.rs b/src/test/ui/issues/issue-21202.rs
index 2c5f1394449..f62de7ce7db 100644
--- a/src/test/ui/issues/issue-21202.rs
+++ b/src/test/ui/issues/issue-21202.rs
@@ -8,7 +8,7 @@ mod B {
     use crate1::A::Foo;
     fn bar(f: Foo) {
         Foo::foo(&f);
-        //~^ ERROR: method `foo` is private
+        //~^ ERROR: associated function `foo` is private
     }
 }
 
diff --git a/src/test/ui/issues/issue-21202.stderr b/src/test/ui/issues/issue-21202.stderr
index d19e42d8d9c..18669add205 100644
--- a/src/test/ui/issues/issue-21202.stderr
+++ b/src/test/ui/issues/issue-21202.stderr
@@ -1,4 +1,4 @@
-error[E0624]: method `foo` is private
+error[E0624]: associated function `foo` is private
   --> $DIR/issue-21202.rs:10:9
    |
 LL |         Foo::foo(&f);
diff --git a/src/test/ui/issues/issue-23080-2.rs b/src/test/ui/issues/issue-23080-2.rs
index 319aa2a5cce..d20bb4bd907 100644
--- a/src/test/ui/issues/issue-23080-2.rs
+++ b/src/test/ui/issues/issue-23080-2.rs
@@ -3,8 +3,7 @@
 #![feature(optin_builtin_traits)]
 
 unsafe auto trait Trait {
-//~^ ERROR E0380
-    type Output;
+    type Output; //~ ERROR E0380
 }
 
 fn call_method<T: Trait>(x: T) {}
diff --git a/src/test/ui/issues/issue-23080-2.stderr b/src/test/ui/issues/issue-23080-2.stderr
index 1103de0d910..fcd1ecfa982 100644
--- a/src/test/ui/issues/issue-23080-2.stderr
+++ b/src/test/ui/issues/issue-23080-2.stderr
@@ -1,11 +1,10 @@
 error[E0380]: auto traits cannot have methods or associated items
-  --> $DIR/issue-23080-2.rs:5:1
+  --> $DIR/issue-23080-2.rs:6:10
    |
-LL | / unsafe auto trait Trait {
-LL | |
-LL | |     type Output;
-LL | | }
-   | |_^
+LL | unsafe auto trait Trait {
+   |                   ----- auto trait cannot have items
+LL |     type Output;
+   |          ^^^^^^
 
 error[E0275]: overflow evaluating the requirement `<() as Trait>::Output`
    |
diff --git a/src/test/ui/issues/issue-23080.rs b/src/test/ui/issues/issue-23080.rs
index fdfee698144..fa5c35316bc 100644
--- a/src/test/ui/issues/issue-23080.rs
+++ b/src/test/ui/issues/issue-23080.rs
@@ -1,8 +1,7 @@
 #![feature(optin_builtin_traits)]
 
 unsafe auto trait Trait {
-//~^ ERROR E0380
-    fn method(&self) {
+    fn method(&self) { //~ ERROR E0380
         println!("Hello");
     }
 }
diff --git a/src/test/ui/issues/issue-23080.stderr b/src/test/ui/issues/issue-23080.stderr
index 91c27217324..dbb9861b578 100644
--- a/src/test/ui/issues/issue-23080.stderr
+++ b/src/test/ui/issues/issue-23080.stderr
@@ -1,13 +1,10 @@
 error[E0380]: auto traits cannot have methods or associated items
-  --> $DIR/issue-23080.rs:3:1
+  --> $DIR/issue-23080.rs:4:8
    |
-LL | / unsafe auto trait Trait {
-LL | |
-LL | |     fn method(&self) {
-LL | |         println!("Hello");
-LL | |     }
-LL | | }
-   | |_^
+LL | unsafe auto trait Trait {
+   |                   ----- auto trait cannot have items
+LL |     fn method(&self) {
+   |        ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr
index 77bc8292094..e34ac45e69d 100644
--- a/src/test/ui/issues/issue-28344.stderr
+++ b/src/test/ui/issues/issue-28344.stderr
@@ -11,7 +11,7 @@ LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
    |                         ^^^^^
    |                         |
    |                         function or associated item not found in `dyn std::ops::BitXor<_>`
-   |                         help: there is a method with a similar name: `bitxor`
+   |                         help: there is an associated function with a similar name: `bitxor`
 
 error[E0191]: the value of the associated type `Output` (from trait `std::ops::BitXor`) must be specified
   --> $DIR/issue-28344.rs:8:13
@@ -26,7 +26,7 @@ LL |     let g = BitXor::bitor;
    |                     ^^^^^
    |                     |
    |                     function or associated item not found in `dyn std::ops::BitXor<_>`
-   |                     help: there is a method with a similar name: `bitxor`
+   |                     help: there is an associated function with a similar name: `bitxor`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-3763.rs b/src/test/ui/issues/issue-3763.rs
index 3494df37fe7..451321c5503 100644
--- a/src/test/ui/issues/issue-3763.rs
+++ b/src/test/ui/issues/issue-3763.rs
@@ -21,9 +21,9 @@ fn main() {
     let _woohoo = (Box::new(my_struct)).priv_field;
     //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
 
-    (&my_struct).happyfun();               //~ ERROR method `happyfun` is private
+    (&my_struct).happyfun();               //~ ERROR associated function `happyfun` is private
 
-    (Box::new(my_struct)).happyfun();          //~ ERROR method `happyfun` is private
+    (Box::new(my_struct)).happyfun();          //~ ERROR associated function `happyfun` is private
     let nope = my_struct.priv_field;
     //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
 }
diff --git a/src/test/ui/issues/issue-3763.stderr b/src/test/ui/issues/issue-3763.stderr
index 873f69d390e..d548477a88f 100644
--- a/src/test/ui/issues/issue-3763.stderr
+++ b/src/test/ui/issues/issue-3763.stderr
@@ -10,13 +10,13 @@ error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private
 LL |     let _woohoo = (Box::new(my_struct)).priv_field;
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0624]: method `happyfun` is private
+error[E0624]: associated function `happyfun` is private
   --> $DIR/issue-3763.rs:24:18
    |
 LL |     (&my_struct).happyfun();
    |                  ^^^^^^^^
 
-error[E0624]: method `happyfun` is private
+error[E0624]: associated function `happyfun` is private
   --> $DIR/issue-3763.rs:26:27
    |
 LL |     (Box::new(my_struct)).happyfun();
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
index 5db521536a8..b97131a1992 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for enum `std::option::Option<{in
   --> $DIR/option-as_deref.rs:2:29
    |
 LL |     let _result = &Some(42).as_deref();
-   |                             ^^^^^^^^ help: there is a method with a similar name: `as_ref`
+   |                             ^^^^^^^^ help: there is an associated function with a similar name: `as_ref`
    |
    = note: the method `as_deref` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::Deref`
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
index 2dfc6d53750..f33e9c7823e 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for enum `std::result::Result<{in
   --> $DIR/result-as_deref.rs:4:27
    |
 LL |     let _result = &Ok(42).as_deref();
-   |                           ^^^^^^^^ help: there is a method with a similar name: `as_ref`
+   |                           ^^^^^^^^ help: there is an associated function with a similar name: `as_ref`
    |
    = note: the method `as_deref` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::Deref`
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
index 1d65c57e5e9..68ebfab95c4 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_err` found for enum `std::result::Result
   --> $DIR/result-as_deref_err.rs:4:28
    |
 LL |     let _result = &Err(41).as_deref_err();
-   |                            ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
+   |                            ^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_mut`
    |
    = note: the method `as_deref_err` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::Deref`
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
index 2f4bf0c94b5..d2ba1049b76 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut` found for enum `std::result::Result
   --> $DIR/result-as_deref_mut.rs:4:31
    |
 LL |     let _result = &mut Ok(42).as_deref_mut();
-   |                               ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err`
+   |                               ^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_err`
    |
    = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::DerefMut`
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
index b76d36c804e..d724ae5c74b 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut_err` found for enum `std::result::Re
   --> $DIR/result-as_deref_mut_err.rs:4:32
    |
 LL |     let _result = &mut Err(41).as_deref_mut_err();
-   |                                ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
+   |                                ^^^^^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_mut`
    |
    = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied:
            `{integer}: std::ops::DerefMut`
diff --git a/src/test/ui/issues/issue-53498.rs b/src/test/ui/issues/issue-53498.rs
index c87d4236492..9e0437c46f4 100644
--- a/src/test/ui/issues/issue-53498.rs
+++ b/src/test/ui/issues/issue-53498.rs
@@ -13,5 +13,5 @@ pub mod test {
 }
 
 fn main() {
-    test::Foo::<test::B>::foo(); //~ ERROR method `foo` is private
+    test::Foo::<test::B>::foo(); //~ ERROR associated function `foo` is private
 }
diff --git a/src/test/ui/issues/issue-53498.stderr b/src/test/ui/issues/issue-53498.stderr
index 3fd48233dae..042848c27bb 100644
--- a/src/test/ui/issues/issue-53498.stderr
+++ b/src/test/ui/issues/issue-53498.stderr
@@ -1,4 +1,4 @@
-error[E0624]: method `foo` is private
+error[E0624]: associated function `foo` is private
   --> $DIR/issue-53498.rs:16:5
    |
 LL |     test::Foo::<test::B>::foo();
diff --git a/src/test/ui/issues/issue-55587.stderr b/src/test/ui/issues/issue-55587.stderr
index bb0d15a23d6..faf78cfe8d9 100644
--- a/src/test/ui/issues/issue-55587.stderr
+++ b/src/test/ui/issues/issue-55587.stderr
@@ -1,4 +1,4 @@
-error[E0164]: expected tuple struct or tuple variant, found method `Path::new`
+error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new`
   --> $DIR/issue-55587.rs:4:9
    |
 LL |     let Path::new();
diff --git a/src/test/ui/issues/issue-63364.stderr b/src/test/ui/issues/issue-63364.stderr
index 60ff318f35a..0375359aeab 100644
--- a/src/test/ui/issues/issue-63364.stderr
+++ b/src/test/ui/issues/issue-63364.stderr
@@ -5,6 +5,7 @@ LL |     for n in 100_000.. {
    |              ^^^^^^^
    |
    = note: `#[deny(overflowing_literals)]` on by default
+   = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-66473.rs b/src/test/ui/issues/issue-66473.rs
index cc298a28b97..9db4521bb42 100644
--- a/src/test/ui/issues/issue-66473.rs
+++ b/src/test/ui/issues/issue-66473.rs
Binary files differdiff --git a/src/test/ui/issues/issue-66473.stderr b/src/test/ui/issues/issue-66473.stderr
index dbeef44bad0..b370b125cfe 100644
--- a/src/test/ui/issues/issue-66473.stderr
+++ b/src/test/ui/issues/issue-66473.stderr
Binary files differdiff --git a/src/test/ui/json-bom-plus-crlf-multifile.stderr b/src/test/ui/json-bom-plus-crlf-multifile.stderr
index ab0feb3c451..026943669f8 100644
--- a/src/test/ui/json-bom-plus-crlf-multifile.stderr
+++ b/src/test/ui/json-bom-plus-crlf-multifile.stderr
@@ -1,10 +1,6 @@
-{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
-variable. It can occur for several cases, the most common of which is a
-mismatch in the expected type that the compiler inferred for a variable's
-initializing expression, and the actual type explicitly assigned to the
-variable.
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
-"}
-{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
+
+This error occurs when the compiler was unable to infer the concrete type of a
 variable. It can occur for several cases, the most common of which is a
 mismatch in the expected type that the compiler inferred for a variable's
 initializing expression, and the actual type explicitly assigned to the
 variable.
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
+"}
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
-"}
-{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
+
+This error occurs when the compiler was unable to infer the concrete type of a
 variable. It can occur for several cases, the most common of which is a
 mismatch in the expected type that the compiler inferred for a variable's
 initializing expression, and the actual type explicitly assigned to the
 variable.
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
+"}
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
-"}
-{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
+
+This error occurs when the compiler was unable to infer the concrete type of a
 variable. It can occur for several cases, the most common of which is a
 mismatch in the expected type that the compiler inferred for a variable's
 initializing expression, and the actual type explicitly assigned to the
 variable.
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
+"}
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
+
+This error occurs when the compiler was unable to infer the concrete type of a
+variable. It can occur for several cases, the most common of which is a
+mismatch in the expected type that the compiler inferred for a variable's
+initializing expression, and the actual type explicitly assigned to the
+variable.
 "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":"    let s : String = (","highlight_start":22,"highlight_end":23},{"text":"    );  // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types
 "}
 {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
diff --git a/src/test/ui/json-bom-plus-crlf.stderr b/src/test/ui/json-bom-plus-crlf.stderr
index 1dd898db3ad..735a46b8c87 100644
--- a/src/test/ui/json-bom-plus-crlf.stderr
+++ b/src/test/ui/json-bom-plus-crlf.stderr
@@ -1,10 +1,6 @@
-{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
-variable. It can occur for several cases, the most common of which is a
-mismatch in the expected type that the compiler inferred for a variable's
-initializing expression, and the actual type explicitly assigned to the
-variable.
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types
-"}
-{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
+
+This error occurs when the compiler was unable to infer the concrete type of a
 variable. It can occur for several cases, the most common of which is a
 mismatch in the expected type that the compiler inferred for a variable's
 initializing expression, and the actual type explicitly assigned to the
 variable.
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1;  // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types
+"}
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types
-"}
-{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
+
+This error occurs when the compiler was unable to infer the concrete type of a
 variable. It can occur for several cases, the most common of which is a
 mismatch in the expected type that the compiler inferred for a variable's
 initializing expression, and the actual type explicitly assigned to the
 variable.
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":"    let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types
+"}
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types
-"}
-{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a
+
+This error occurs when the compiler was unable to infer the concrete type of a
 variable. It can occur for several cases, the most common of which is a
 mismatch in the expected type that the compiler inferred for a variable's
 initializing expression, and the actual type explicitly assigned to the
 variable.
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1;  // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types
+"}
+{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0308
 let x: i32 = \"I am not a number!\";
@@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\";
 //      |
 //    type `i32` assigned to variable `x`
 ```
+
+This error occurs when the compiler was unable to infer the concrete type of a
+variable. It can occur for several cases, the most common of which is a
+mismatch in the expected type that the compiler inferred for a variable's
+initializing expression, and the actual type explicitly assigned to the
+variable.
 "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":"    let s : String = (","highlight_start":22,"highlight_end":23},{"text":"    );  // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":"    let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types
 "}
 {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
index b07de3e341c..a46ce67d40d 100644
--- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
@@ -1,3 +1,4 @@
 use extern::foo; //~ ERROR expected identifier, found keyword `extern`
+                 //~| ERROR unresolved import `r#extern`
 
 fn main() {}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
index 05802f2d367..edbb36452b6 100644
--- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
@@ -9,5 +9,12 @@ help: you can escape reserved keywords to use them as identifiers
 LL | use r#extern::foo;
    |     ^^^^^^^^
 
-error: aborting due to previous error
+error[E0432]: unresolved import `r#extern`
+  --> $DIR/keyword-extern-as-identifier-use.rs:1:5
+   |
+LL | use extern::foo;
+   |     ^^^^^^ maybe a missing crate `r#extern`?
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/label/label_break_value_illegal_uses.stderr b/src/test/ui/label/label_break_value_illegal_uses.stderr
index fd8850dd8da..a2c75882be0 100644
--- a/src/test/ui/label/label_break_value_illegal_uses.stderr
+++ b/src/test/ui/label/label_break_value_illegal_uses.stderr
@@ -2,7 +2,10 @@ error: expected `{`, found `'b`
   --> $DIR/label_break_value_illegal_uses.rs:6:12
    |
 LL |     unsafe 'b: {}
-   |            ^^ expected `{`
+   |            ^^----
+   |            |
+   |            expected `{`
+   |            help: try placing this code inside a block: `{ 'b: {} }`
 
 error: expected `{`, found `'b`
   --> $DIR/label_break_value_illegal_uses.rs:10:13
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr
index 291edc505cd..4c788211576 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr
@@ -7,7 +7,7 @@ LL |     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
    |            lifetime `'a` defined here
 LL | 
 LL |         if x > y { x } else { y }
-   |                    ^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
+   |                    ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr
index 15ee58574ec..11e7fa96d7e 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr
@@ -7,7 +7,7 @@ LL |   fn foo<'a>(&self, x: &'a i32) -> &i32 {
    |          lifetime `'a` defined here
 LL | 
 LL |     x
-   |     ^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+   |     ^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr
index a27a91e38f1..c41f08e691a 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr
@@ -7,7 +7,7 @@ LL |     fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
    |            lifetime `'a` defined here
 LL | 
 LL |         if true { x } else { self }
-   |                              ^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
+   |                              ^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
index 5f922d8560b..1a19e81f235 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
@@ -6,7 +6,7 @@ LL |   fn foo<'a>(&self, x: &i32) -> &i32 {
    |              |
    |              let's call the lifetime of this reference `'2`
 LL |     x
-   |     ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |     ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
index 91d7597c87f..87b13dc1591 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
@@ -6,7 +6,7 @@ LL |     fn foo<'a>(&self, x: &Foo) -> &Foo {
    |                |
    |                let's call the lifetime of this reference `'2`
 LL |         if true { x } else { self }
-   |                   ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                   ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/deny-overflowing-literals.stderr b/src/test/ui/lint/deny-overflowing-literals.stderr
index 7f59495023e..127dd4127c2 100644
--- a/src/test/ui/lint/deny-overflowing-literals.stderr
+++ b/src/test/ui/lint/deny-overflowing-literals.stderr
@@ -5,6 +5,7 @@ LL |     let x: u8 = 256;
    |                 ^^^
    |
    = note: `#[deny(overflowing_literals)]` on by default
+   = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
 
 error: range endpoint is out of range for `u8`
   --> $DIR/deny-overflowing-literals.rs:5:14
diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs
new file mode 100644
index 00000000000..49d489d9168
--- /dev/null
+++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs
@@ -0,0 +1,10 @@
+// build-fail
+// only-x86_64
+
+fn main() {
+    Bug::V([0; !0]); //~ ERROR is too big for the current
+}
+
+enum Bug {
+    V([u8; !0]),
+}
diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr
new file mode 100644
index 00000000000..d31ce9cfe0c
--- /dev/null
+++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr
@@ -0,0 +1,8 @@
+error: the type `[u8; 18446744073709551615]` is too big for the current architecture
+  --> $DIR/issue-69485-var-size-diffs-too-large.rs:5:12
+   |
+LL |     Bug::V([0; !0]);
+   |            ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-pre-expansion-extern-module.rs b/src/test/ui/lint/lint-pre-expansion-extern-module.rs
new file mode 100644
index 00000000000..30e2ed8b7a6
--- /dev/null
+++ b/src/test/ui/lint/lint-pre-expansion-extern-module.rs
@@ -0,0 +1,7 @@
+// check-pass
+// compile-flags: -W rust-2018-compatibility
+// error-pattern: `try` is a keyword in the 2018 edition
+
+fn main() {}
+
+mod lint_pre_expansion_extern_module_aux;
diff --git a/src/test/ui/lint/lint-pre-expansion-extern-module.stderr b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr
new file mode 100644
index 00000000000..c683a3fa670
--- /dev/null
+++ b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr
@@ -0,0 +1,10 @@
+warning: `try` is a keyword in the 2018 edition
+  --> $DIR/lint_pre_expansion_extern_module_aux.rs:3:8
+   |
+LL | pub fn try() {}
+   |        ^^^ help: you can use a raw identifier to stay compatible: `r#try`
+   |
+   = note: `-W keyword-idents` implied by `-W rust-2018-compatibility`
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
diff --git a/src/test/ui/lint/lint-range-endpoint-overflow.stderr b/src/test/ui/lint/lint-range-endpoint-overflow.stderr
index dff61e022eb..d2df7372741 100644
--- a/src/test/ui/lint/lint-range-endpoint-overflow.stderr
+++ b/src/test/ui/lint/lint-range-endpoint-overflow.stderr
@@ -15,18 +15,24 @@ error: literal out of range for `u8`
    |
 LL |     let range_c = 0..=256;
    |                       ^^^
+   |
+   = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `u8`
   --> $DIR/lint-range-endpoint-overflow.rs:7:19
    |
 LL |     let range_d = 256..5;
    |                   ^^^
+   |
+   = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `u8`
   --> $DIR/lint-range-endpoint-overflow.rs:8:22
    |
 LL |     let range_e = 0..257;
    |                      ^^^
+   |
+   = note: the literal `257` does not fit into the type `u8` whose range is `0..=255`
 
 error: range endpoint is out of range for `u8`
   --> $DIR/lint-range-endpoint-overflow.rs:9:20
diff --git a/src/test/ui/lint/lint-type-limits2.stderr b/src/test/ui/lint/lint-type-limits2.stderr
index bf510823b56..1e3c88dfc46 100644
--- a/src/test/ui/lint/lint-type-limits2.stderr
+++ b/src/test/ui/lint/lint-type-limits2.stderr
@@ -17,6 +17,7 @@ note: the lint level is defined here
    |
 LL | #![warn(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/lint-type-limits3.stderr b/src/test/ui/lint/lint-type-limits3.stderr
index 00441f99e60..150e9a2aa47 100644
--- a/src/test/ui/lint/lint-type-limits3.stderr
+++ b/src/test/ui/lint/lint-type-limits3.stderr
@@ -17,6 +17,7 @@ note: the lint level is defined here
    |
 LL | #![warn(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `200` does not fit into the type `i8` whose range is `-128..=127`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/lint-type-overflow.stderr b/src/test/ui/lint/lint-type-overflow.stderr
index ec15313158d..7715c0d3a4d 100644
--- a/src/test/ui/lint/lint-type-overflow.stderr
+++ b/src/test/ui/lint/lint-type-overflow.stderr
@@ -9,108 +9,143 @@ note: the lint level is defined here
    |
 LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `u8`
   --> $DIR/lint-type-overflow.rs:13:14
    |
 LL |     let x1 = 256_u8;
    |              ^^^^^^
+   |
+   = note: the literal `256_u8` does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:16:18
    |
 LL |     let x1: i8 = 128;
    |                  ^^^
+   |
+   = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:18:19
    |
 LL |     let x3: i8 = -129;
    |                   ^^^
+   |
+   = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:19:19
    |
 LL |     let x3: i8 = -(129);
    |                   ^^^^^
+   |
+   = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:20:20
    |
 LL |     let x3: i8 = -{129};
    |                    ^^^
+   |
+   = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:22:10
    |
 LL |     test(1000);
    |          ^^^^
+   |
+   = note: the literal `1000` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:24:13
    |
 LL |     let x = 128_i8;
    |             ^^^^^^
+   |
+   = note: the literal `128_i8` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
   --> $DIR/lint-type-overflow.rs:28:14
    |
 LL |     let x = -129_i8;
    |              ^^^^^^
+   |
+   = note: the literal `129_i8` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:32:18
    |
 LL |     let x: i32 = 2147483648;
    |                  ^^^^^^^^^^
+   |
+   = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:33:13
    |
 LL |     let x = 2147483648_i32;
    |             ^^^^^^^^^^^^^^
+   |
+   = note: the literal `2147483648_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:36:19
    |
 LL |     let x: i32 = -2147483649;
    |                   ^^^^^^^^^^
+   |
+   = note: the literal `2147483649` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:37:14
    |
 LL |     let x = -2147483649_i32;
    |              ^^^^^^^^^^^^^^
+   |
+   = note: the literal `2147483649_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i32`
   --> $DIR/lint-type-overflow.rs:38:13
    |
 LL |     let x = 2147483648;
    |             ^^^^^^^^^^
+   |
+   = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
 
 error: literal out of range for `i64`
   --> $DIR/lint-type-overflow.rs:40:13
    |
 LL |     let x = 9223372036854775808_i64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `9223372036854775808_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: literal out of range for `i64`
   --> $DIR/lint-type-overflow.rs:42:13
    |
 LL |     let x = 18446744073709551615_i64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `18446744073709551615_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: literal out of range for `i64`
   --> $DIR/lint-type-overflow.rs:43:19
    |
 LL |     let x: i64 = -9223372036854775809;
    |                   ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: literal out of range for `i64`
   --> $DIR/lint-type-overflow.rs:44:14
    |
 LL |     let x = -9223372036854775809_i64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `9223372036854775809_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
 
 error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/lint/lint-type-overflow2.stderr b/src/test/ui/lint/lint-type-overflow2.stderr
index dfc691ab910..61e33b7a260 100644
--- a/src/test/ui/lint/lint-type-overflow2.stderr
+++ b/src/test/ui/lint/lint-type-overflow2.stderr
@@ -9,30 +9,39 @@ note: the lint level is defined here
    |
 LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `f32`
   --> $DIR/lint-type-overflow2.rs:9:14
    |
 LL |     let x = -3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY`
 
 error: literal out of range for `f32`
   --> $DIR/lint-type-overflow2.rs:10:14
    |
 LL |     let x =  3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY`
 
 error: literal out of range for `f64`
   --> $DIR/lint-type-overflow2.rs:11:14
    |
 LL |     let x = -1.7976931348623159e+308_f64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY`
 
 error: literal out of range for `f64`
   --> $DIR/lint-type-overflow2.rs:12:14
    |
 LL |     let x =  1.7976931348623159e+308_f64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs b/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs
new file mode 100644
index 00000000000..71dec40ea44
--- /dev/null
+++ b/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs
@@ -0,0 +1,3 @@
+// ignore-test: not a test
+
+pub fn try() {}
diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr
index 2432eb78b87..a7a788b877a 100644
--- a/src/test/ui/lint/type-overflow.stderr
+++ b/src/test/ui/lint/type-overflow.stderr
@@ -9,6 +9,7 @@ note: the lint level is defined here
    |
 LL | #![warn(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
+   = note: the literal `255i8` does not fit into the type `i8` whose range is `-128..=127`
 
 warning: literal out of range for i8
   --> $DIR/type-overflow.rs:10:16
@@ -16,7 +17,7 @@ warning: literal out of range for i8
 LL |     let fail = 0b1000_0001i8;
    |                ^^^^^^^^^^^^^ help: consider using `u8` instead: `0b1000_0001u8`
    |
-   = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8`
+   = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into the type `i8` and will become `-127i8`
 
 warning: literal out of range for i64
   --> $DIR/type-overflow.rs:12:16
@@ -24,7 +25,7 @@ warning: literal out of range for i64
 LL |     let fail = 0x8000_0000_0000_0000i64;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x8000_0000_0000_0000u64`
    |
-   = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64`
+   = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into the type `i64` and will become `-9223372036854775808i64`
 
 warning: literal out of range for u32
   --> $DIR/type-overflow.rs:14:16
@@ -32,7 +33,7 @@ warning: literal out of range for u32
 LL |     let fail = 0x1_FFFF_FFFFu32;
    |                ^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x1_FFFF_FFFFu64`
    |
-   = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32`
+   = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into the type `u32` and will become `4294967295u32`
 
 warning: literal out of range for i128
   --> $DIR/type-overflow.rs:16:22
@@ -40,7 +41,7 @@ warning: literal out of range for i128
 LL |     let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into an `i128` and will become `-170141183460469231731687303715884105728i128`
+   = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i128` and will become `-170141183460469231731687303715884105728i128`
    = help: consider using `u128` instead
 
 warning: literal out of range for i32
@@ -49,7 +50,7 @@ warning: literal out of range for i32
 LL |     let fail = 0x8FFF_FFFF_FFFF_FFFE;
    |                ^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32`
+   = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32`
    = help: consider using `i128` instead
 
 warning: literal out of range for i8
@@ -58,5 +59,5 @@ warning: literal out of range for i8
 LL |     let fail = -0b1111_1111i8;
    |                 ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16`
    |
-   = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8`
+   = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into the type `i8` and will become `-1i8`
 
diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr
index 6d669184deb..bf0562713a4 100644
--- a/src/test/ui/lint/uninitialized-zeroed.stderr
+++ b/src/test/ui/lint/uninitialized-zeroed.stderr
@@ -1,4 +1,4 @@
-error: the type `&'static T` does not permit zero-initialization
+error: the type `&T` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:29:32
    |
 LL |         let _val: &'static T = mem::zeroed();
@@ -14,7 +14,7 @@ LL | #![deny(invalid_value)]
    |         ^^^^^^^^^^^^^
    = note: references must be non-null
 
-error: the type `&'static T` does not permit being left uninitialized
+error: the type `&T` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:30:32
    |
 LL |         let _val: &'static T = mem::uninitialized();
@@ -25,7 +25,7 @@ LL |         let _val: &'static T = mem::uninitialized();
    |
    = note: references must be non-null
 
-error: the type `Wrap<&'static T>` does not permit zero-initialization
+error: the type `Wrap<&T>` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:32:38
    |
 LL |         let _val: Wrap<&'static T> = mem::zeroed();
@@ -40,7 +40,7 @@ note: references must be non-null (in this struct field)
 LL | struct Wrap<T> { wrapped: T }
    |                  ^^^^^^^^^^
 
-error: the type `Wrap<&'static T>` does not permit being left uninitialized
+error: the type `Wrap<&T>` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:33:38
    |
 LL |         let _val: Wrap<&'static T> = mem::uninitialized();
@@ -121,7 +121,7 @@ LL |         let _val: Void = mem::uninitialized();
    |
    = note: enums with no variants have no valid value
 
-error: the type `&'static i32` does not permit zero-initialization
+error: the type `&i32` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:49:34
    |
 LL |         let _val: &'static i32 = mem::zeroed();
@@ -132,7 +132,7 @@ LL |         let _val: &'static i32 = mem::zeroed();
    |
    = note: references must be non-null
 
-error: the type `&'static i32` does not permit being left uninitialized
+error: the type `&i32` does not permit being left uninitialized
   --> $DIR/uninitialized-zeroed.rs:50:34
    |
 LL |         let _val: &'static i32 = mem::uninitialized();
@@ -366,7 +366,7 @@ LL |         let _val: NonBig = mem::uninitialized();
    |
    = note: `NonBig` must be initialized inside its custom valid range
 
-error: the type `&'static i32` does not permit zero-initialization
+error: the type `&i32` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:84:34
    |
 LL |         let _val: &'static i32 = mem::transmute(0usize);
@@ -377,7 +377,7 @@ LL |         let _val: &'static i32 = mem::transmute(0usize);
    |
    = note: references must be non-null
 
-error: the type `&'static [i32]` does not permit zero-initialization
+error: the type `&[i32]` does not permit zero-initialization
   --> $DIR/uninitialized-zeroed.rs:85:36
    |
 LL |         let _val: &'static [i32] = mem::transmute((0usize, 0usize));
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index 0dc0d247af5..7176f17bc3f 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -2,7 +2,7 @@
   "message": "cannot find type `Iter` in this scope",
   "code": {
     "code": "E0412",
-    "explanation": "The type name used is not in scope.
+    "explanation": "A used type name is not in scope.
 
 Erroneous code examples:
 
diff --git a/src/test/ui/macros/issue-58490.rs b/src/test/ui/macros/issue-58490.rs
new file mode 100644
index 00000000000..97e71c9a1ce
--- /dev/null
+++ b/src/test/ui/macros/issue-58490.rs
@@ -0,0 +1,26 @@
+// Regression test for #58490
+
+macro_rules! a {
+    ( @1 $i:item ) => {
+        a! { @2 $i }
+    };
+    ( @2 $i:item ) => {
+        $i
+    };
+}
+mod b {
+    a! {
+        @1
+        #[macro_export]
+        macro_rules! b { () => () }
+    }
+    #[macro_export]
+    macro_rules! b { () => () }
+    //~^ ERROR: the name `b` is defined multiple times
+}
+mod c {
+    #[allow(unused_imports)]
+    use crate::b;
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-58490.stderr b/src/test/ui/macros/issue-58490.stderr
new file mode 100644
index 00000000000..b1f0896f3b6
--- /dev/null
+++ b/src/test/ui/macros/issue-58490.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `b` is defined multiple times
+  --> $DIR/issue-58490.rs:18:5
+   |
+LL |         macro_rules! b { () => () }
+   |         -------------- previous definition of the macro `b` here
+...
+LL |     macro_rules! b { () => () }
+   |     ^^^^^^^^^^^^^^ `b` redefined here
+   |
+   = note: `b` must be defined only once in the macro namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/macros/macro-comma-behavior.core.stderr b/src/test/ui/macros/macro-comma-behavior.core.stderr
index dd0cac659fd..83a88ab3bd9 100644
--- a/src/test/ui/macros/macro-comma-behavior.core.stderr
+++ b/src/test/ui/macros/macro-comma-behavior.core.stderr
@@ -1,41 +1,41 @@
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:21:23
+  --> $DIR/macro-comma-behavior.rs:20:23
    |
 LL |     assert_eq!(1, 1, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:24:23
+  --> $DIR/macro-comma-behavior.rs:23:23
    |
 LL |     assert_ne!(1, 2, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:30:29
+  --> $DIR/macro-comma-behavior.rs:29:29
    |
 LL |     debug_assert_eq!(1, 1, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:33:29
+  --> $DIR/macro-comma-behavior.rs:32:29
    |
 LL |     debug_assert_ne!(1, 2, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:54:19
+  --> $DIR/macro-comma-behavior.rs:53:19
    |
 LL |     format_args!("{}",);
    |                   ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:72:21
+  --> $DIR/macro-comma-behavior.rs:71:21
    |
 LL |     unimplemented!("{}",);
    |                     ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:81:24
+  --> $DIR/macro-comma-behavior.rs:80:24
    |
 LL |             write!(f, "{}",)?;
    |                        ^^
diff --git a/src/test/ui/macros/macro-comma-behavior.rs b/src/test/ui/macros/macro-comma-behavior.rs
index 006319aa9f5..04714c65b5c 100644
--- a/src/test/ui/macros/macro-comma-behavior.rs
+++ b/src/test/ui/macros/macro-comma-behavior.rs
@@ -9,7 +9,6 @@
 #[cfg(std)] use std::fmt;
 #[cfg(core)] use core::fmt;
 #[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {}
-#[cfg(core)] #[lang = "eh_unwind_resume"] fn eh_unwind_resume() {}
 #[cfg(core)] #[lang = "panic_impl"] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} }
 
 // (see documentation of the similarly-named test in run-pass)
diff --git a/src/test/ui/macros/macro-comma-behavior.std.stderr b/src/test/ui/macros/macro-comma-behavior.std.stderr
index 4372d89fbf5..26445f2c5c5 100644
--- a/src/test/ui/macros/macro-comma-behavior.std.stderr
+++ b/src/test/ui/macros/macro-comma-behavior.std.stderr
@@ -1,59 +1,59 @@
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:21:23
+  --> $DIR/macro-comma-behavior.rs:20:23
    |
 LL |     assert_eq!(1, 1, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:24:23
+  --> $DIR/macro-comma-behavior.rs:23:23
    |
 LL |     assert_ne!(1, 2, "{}",);
    |                       ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:30:29
+  --> $DIR/macro-comma-behavior.rs:29:29
    |
 LL |     debug_assert_eq!(1, 1, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:33:29
+  --> $DIR/macro-comma-behavior.rs:32:29
    |
 LL |     debug_assert_ne!(1, 2, "{}",);
    |                             ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:38:18
+  --> $DIR/macro-comma-behavior.rs:37:18
    |
 LL |         eprint!("{}",);
    |                  ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:50:18
+  --> $DIR/macro-comma-behavior.rs:49:18
    |
 LL |         format!("{}",);
    |                  ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:54:19
+  --> $DIR/macro-comma-behavior.rs:53:19
    |
 LL |     format_args!("{}",);
    |                   ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:61:17
+  --> $DIR/macro-comma-behavior.rs:60:17
    |
 LL |         print!("{}",);
    |                 ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:72:21
+  --> $DIR/macro-comma-behavior.rs:71:21
    |
 LL |     unimplemented!("{}",);
    |                     ^^
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/macro-comma-behavior.rs:81:24
+  --> $DIR/macro-comma-behavior.rs:80:24
    |
 LL |             write!(f, "{}",)?;
    |                        ^^
diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr
index 202a9235adb..6217decd8ef 100644
--- a/src/test/ui/macros/trace-macro.stderr
+++ b/src/test/ui/macros/trace-macro.stderr
@@ -5,5 +5,5 @@ LL |     println!("Hello, World!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `println! { "Hello, World!" }`
-   = note: to `{ $crate :: io :: _print ($crate :: format_args_nl ! ("Hello, World!")) ; }`
+   = note: to `{ $crate :: io :: _print($crate :: format_args_nl ! ("Hello, World!")) ; }`
 
diff --git a/src/test/ui/match/match-fn-call.stderr b/src/test/ui/match/match-fn-call.stderr
index 2d7a0f16141..297aa4cd95d 100644
--- a/src/test/ui/match/match-fn-call.stderr
+++ b/src/test/ui/match/match-fn-call.stderr
@@ -1,4 +1,4 @@
-error[E0164]: expected tuple struct or tuple variant, found method `Path::new`
+error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new`
   --> $DIR/match-fn-call.rs:6:9
    |
 LL |         Path::new("foo") => println!("foo"),
@@ -6,7 +6,7 @@ LL |         Path::new("foo") => println!("foo"),
    |
    = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
-error[E0164]: expected tuple struct or tuple variant, found method `Path::new`
+error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new`
   --> $DIR/match-fn-call.rs:8:9
    |
 LL |         Path::new("bar") => println!("bar"),
diff --git a/src/test/ui/methods/method-path-in-pattern.rs b/src/test/ui/methods/method-path-in-pattern.rs
index f94be1734b7..40645309552 100644
--- a/src/test/ui/methods/method-path-in-pattern.rs
+++ b/src/test/ui/methods/method-path-in-pattern.rs
@@ -13,20 +13,20 @@ impl MyTrait for Foo {}
 fn main() {
     match 0u32 {
         Foo::bar => {}
-        //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar`
+        //~^ ERROR expected unit struct, unit variant or constant, found associated function
     }
     match 0u32 {
         <Foo>::bar => {}
-        //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar`
+        //~^ ERROR expected unit struct, unit variant or constant, found associated function
     }
     match 0u32 {
         <Foo>::trait_bar => {}
-        //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::trait_bar`
+        //~^ ERROR expected unit struct, unit variant or constant, found associated function
     }
     if let Foo::bar = 0u32 {}
-    //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar`
+    //~^ ERROR expected unit struct, unit variant or constant, found associated function
     if let <Foo>::bar = 0u32 {}
-    //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::bar`
+    //~^ ERROR expected unit struct, unit variant or constant, found associated function
     if let Foo::trait_bar = 0u32 {}
-    //~^ ERROR expected unit struct, unit variant or constant, found method `Foo::trait_bar`
+    //~^ ERROR expected unit struct, unit variant or constant, found associated function
 }
diff --git a/src/test/ui/methods/method-path-in-pattern.stderr b/src/test/ui/methods/method-path-in-pattern.stderr
index 6b0c5946ff8..1d1bdb6b052 100644
--- a/src/test/ui/methods/method-path-in-pattern.stderr
+++ b/src/test/ui/methods/method-path-in-pattern.stderr
@@ -1,34 +1,34 @@
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:15:9
    |
 LL |         Foo::bar => {}
    |         ^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:19:9
    |
 LL |         <Foo>::bar => {}
    |         ^^^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::trait_bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar`
   --> $DIR/method-path-in-pattern.rs:23:9
    |
 LL |         <Foo>::trait_bar => {}
    |         ^^^^^^^^^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:26:12
    |
 LL |     if let Foo::bar = 0u32 {}
    |            ^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar`
   --> $DIR/method-path-in-pattern.rs:28:12
    |
 LL |     if let <Foo>::bar = 0u32 {}
    |            ^^^^^^^^^^
 
-error[E0533]: expected unit struct, unit variant or constant, found method `Foo::trait_bar`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar`
   --> $DIR/method-path-in-pattern.rs:30:12
    |
 LL |     if let Foo::trait_bar = 0u32 {}
diff --git a/src/test/ui/methods/method-resolvable-path-in-pattern.rs b/src/test/ui/methods/method-resolvable-path-in-pattern.rs
index c05160792d3..2973800a4d4 100644
--- a/src/test/ui/methods/method-resolvable-path-in-pattern.rs
+++ b/src/test/ui/methods/method-resolvable-path-in-pattern.rs
@@ -9,6 +9,6 @@ impl MyTrait for Foo {}
 fn main() {
     match 0u32 {
         <Foo as MyTrait>::trait_bar => {}
-        //~^ ERROR expected unit struct, unit variant or constant, found method `MyTrait::trait_bar`
+        //~^ ERROR expected unit struct, unit variant or constant, found associated function
     }
 }
diff --git a/src/test/ui/methods/method-resolvable-path-in-pattern.stderr b/src/test/ui/methods/method-resolvable-path-in-pattern.stderr
index 4b25b694e13..7c454a9a777 100644
--- a/src/test/ui/methods/method-resolvable-path-in-pattern.stderr
+++ b/src/test/ui/methods/method-resolvable-path-in-pattern.stderr
@@ -1,4 +1,4 @@
-error[E0532]: expected unit struct, unit variant or constant, found method `MyTrait::trait_bar`
+error[E0532]: expected unit struct, unit variant or constant, found associated function `MyTrait::trait_bar`
   --> $DIR/method-resolvable-path-in-pattern.rs:11:9
    |
 LL |         <Foo as MyTrait>::trait_bar => {}
diff --git a/src/test/ui/mir/issue-60390.rs b/src/test/ui/mir/issue-60390.rs
new file mode 100644
index 00000000000..fd9d6b46dd4
--- /dev/null
+++ b/src/test/ui/mir/issue-60390.rs
@@ -0,0 +1,8 @@
+// check-pass
+// compile-flags: --emit=mir,link
+// Regression test for #60390, this ICE requires `--emit=mir` flag.
+
+fn main() {
+    enum Inner { Member(u32) };
+    Inner::Member(0);
+}
diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr
index 98b74e5f5cb..91b3fe15c4b 100644
--- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr
+++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr
@@ -1,10 +1,10 @@
 error[E0583]: file not found for module `missing`
-  --> $DIR/foo.rs:4:5
+  --> $DIR/foo.rs:4:1
    |
 LL | mod missing;
-   |     ^^^^^^^
+   | ^^^^^^^^^^^^
    |
-   = help: name the file either foo/missing.rs or foo/missing/mod.rs inside the directory "$DIR"
+   = help: to create the module `missing`, create file "$DIR/foo/missing.rs"
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr
index 457e8fcccbf..f519de46c76 100644
--- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr
+++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr
@@ -1,10 +1,10 @@
 error[E0583]: file not found for module `missing`
-  --> $DIR/foo_inline.rs:4:9
+  --> $DIR/foo_inline.rs:4:5
    |
 LL |     mod missing;
-   |         ^^^^^^^
+   |     ^^^^^^^^^^^^
    |
-   = help: name the file either missing.rs or missing/mod.rs inside the directory "$DIR/foo_inline/inline"
+   = help: to create the module `missing`, create file "$DIR/foo_inline/inline/missing.rs"
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/mod/mod_file_disambig.rs b/src/test/ui/mod/mod_file_disambig.rs
index ef203ef082b..7b182421d34 100644
--- a/src/test/ui/mod/mod_file_disambig.rs
+++ b/src/test/ui/mod/mod_file_disambig.rs
@@ -2,4 +2,5 @@ mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` fou
 
 fn main() {
     assert_eq!(mod_file_aux::bar(), 10);
+    //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux`
 }
diff --git a/src/test/ui/mod/mod_file_disambig.stderr b/src/test/ui/mod/mod_file_disambig.stderr
index 2b77d866fb3..490633a3fb0 100644
--- a/src/test/ui/mod/mod_file_disambig.stderr
+++ b/src/test/ui/mod/mod_file_disambig.stderr
@@ -1,11 +1,18 @@
 error[E0584]: file for module `mod_file_disambig_aux` found at both mod_file_disambig_aux.rs and mod_file_disambig_aux/mod.rs
-  --> $DIR/mod_file_disambig.rs:1:5
+  --> $DIR/mod_file_disambig.rs:1:1
    |
 LL | mod mod_file_disambig_aux;
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: delete or rename one of them to remove the ambiguity
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux`
+  --> $DIR/mod_file_disambig.rs:4:16
+   |
+LL |     assert_eq!(mod_file_aux::bar(), 10);
+   |                ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0584`.
+Some errors have detailed explanations: E0433, E0584.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/nll/outlives-suggestion-simple.rs b/src/test/ui/nll/outlives-suggestion-simple.rs
index ee5a80ae648..41e4d83aa92 100644
--- a/src/test/ui/nll/outlives-suggestion-simple.rs
+++ b/src/test/ui/nll/outlives-suggestion-simple.rs
@@ -70,7 +70,7 @@ pub struct Foo2<'a> {
 impl<'a> Foo2<'a> {
     // should not produce outlives suggestions to name 'self
     fn get_bar(&self) -> Bar2 {
-        Bar2::new(&self) //~ERROR borrowed data escapes outside of method
+        Bar2::new(&self) //~ERROR borrowed data escapes outside of associated function
     }
 }
 
diff --git a/src/test/ui/nll/outlives-suggestion-simple.stderr b/src/test/ui/nll/outlives-suggestion-simple.stderr
index cf55603cd71..6300ea66511 100644
--- a/src/test/ui/nll/outlives-suggestion-simple.stderr
+++ b/src/test/ui/nll/outlives-suggestion-simple.stderr
@@ -93,16 +93,16 @@ LL |         self.x
    |
    = help: consider adding the following bound: `'b: 'a`
 
-error[E0521]: borrowed data escapes outside of method
+error[E0521]: borrowed data escapes outside of associated function
   --> $DIR/outlives-suggestion-simple.rs:73:9
    |
 LL |     fn get_bar(&self) -> Bar2 {
    |                -----
    |                |
-   |                `self` declared here, outside of the method body
-   |                `self` is a reference that is only valid in the method body
+   |                `self` declared here, outside of the associated function body
+   |                `self` is a reference that is only valid in the associated function body
 LL |         Bar2::new(&self)
-   |         ^^^^^^^^^^^^^^^^ `self` escapes the method body here
+   |         ^^^^^^^^^^^^^^^^ `self` escapes the associated function body here
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/no-landing-pads.rs b/src/test/ui/no-landing-pads.rs
deleted file mode 100644
index d9d53210612..00000000000
--- a/src/test/ui/no-landing-pads.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-// compile-flags: -Z no-landing-pads -C codegen-units=1
-// ignore-emscripten no threads support
-
-use std::thread;
-
-static mut HIT: bool = false;
-
-struct A;
-
-impl Drop for A {
-    fn drop(&mut self) {
-        unsafe { HIT = true; }
-    }
-}
-
-fn main() {
-    thread::spawn(move|| -> () {
-        let _a = A;
-        panic!();
-    }).join().unwrap_err();
-    assert!(unsafe { !HIT });
-}
diff --git a/src/test/ui/no_owned_box_lang_item.rs b/src/test/ui/no_owned_box_lang_item.rs
index b76699c19ac..58e45ff73a5 100644
--- a/src/test/ui/no_owned_box_lang_item.rs
+++ b/src/test/ui/no_owned_box_lang_item.rs
@@ -12,5 +12,4 @@ fn main() {
 }
 
 #[lang = "eh_personality"] extern fn eh_personality() {}
-#[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {}
 #[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} }
diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
index abe34a39caf..3e5cdad7ab9 100644
--- a/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
+++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs
@@ -11,5 +11,3 @@ use core::panic::PanicInfo;
 fn panic_impl(info: &PanicInfo) -> ! { loop {} }
 #[lang = "eh_personality"]
 fn eh_personality() {}
-#[lang = "eh_unwind_resume"]
-fn eh_unwind_resume() {}
diff --git a/src/test/ui/panic-while-printing.rs b/src/test/ui/panic-while-printing.rs
new file mode 100644
index 00000000000..7e9fa16b084
--- /dev/null
+++ b/src/test/ui/panic-while-printing.rs
@@ -0,0 +1,24 @@
+// run-pass
+// ignore-emscripten no subprocess support
+
+#![feature(set_stdio)]
+
+use std::fmt;
+use std::fmt::{Display, Formatter};
+use std::io::set_panic;
+
+pub struct A;
+
+impl Display for A {
+    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
+        panic!();
+    }
+}
+
+fn main() {
+    set_panic(Some(Box::new(Vec::new())));
+    assert!(std::panic::catch_unwind(|| {
+        eprintln!("{}", A);
+    })
+    .is_err());
+}
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
index f3980a59648..09f494bdc2f 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
@@ -39,35 +39,35 @@ fn main() {}
 #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
 //~^ ERROR expected one of
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
 //~^ ERROR expected one of
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
-//~^ ERROR expected `{`, found `#`
+//~^ ERROR outer attributes are not allowed on `if`
 #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
 //~^ ERROR an inner attribute is not permitted in this context
 
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
index 4dcba27cb68..6dfe7aad6ea 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
@@ -136,14 +136,14 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: expected `{`, found `#`
+error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
-   |                                --   ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                --   ^^^^^^^ -- the attributes are attached to this branch
    |                                |    |
-   |                                |    expected `{`
-   |                                this `if` expression has a condition, but no block
+   |                                |    help: remove the attributes
+   |                                the branch belongs to this `if`
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:43:38
@@ -159,13 +159,14 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
    |                                        ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
-error: expected `{`, found `#`
+error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:47:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
-   |                                             ^       --- help: try placing this code inside a block: `{ {}; }`
-   |                                             |
-   |                                             expected `{`
+   |                                        ---- ^^^^^^^ -- the attributes are attached to this branch
+   |                                        |    |
+   |                                        |    help: remove the attributes
+   |                                        the branch belongs to this `else`
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:49:46
@@ -175,22 +176,23 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: expected `{`, found `#`
+error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
-   |                                             ^       -------- help: try placing this code inside a block: `{ if 0 {}; }`
-   |                                             |
-   |                                             expected `{`
+   |                                        ---- ^^^^^^^ ------- the attributes are attached to this branch
+   |                                        |    |
+   |                                        |    help: remove the attributes
+   |                                        the branch belongs to this `else`
 
-error: expected `{`, found `#`
+error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:53:50
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
-   |                                             --   ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                             --   ^^^^^^^ -- the attributes are attached to this branch
    |                                             |    |
-   |                                             |    expected `{`
-   |                                             this `if` expression has a condition, but no block
+   |                                             |    help: remove the attributes
+   |                                             the branch belongs to this `if`
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:55:51
@@ -200,14 +202,14 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: expected `{`, found `#`
+error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:57:45
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
-   |                                --           ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                --           ^^^^^^^ -- the attributes are attached to this branch
    |                                |            |
-   |                                |            expected `{`
-   |                                this `if` expression has a condition, but no block
+   |                                |            help: remove the attributes
+   |                                the branch belongs to this `if`
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:59:46
@@ -223,13 +225,14 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
    |                                                ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
-error: expected `{`, found `#`
+error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:63:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
-   |                                                     ^       --- help: try placing this code inside a block: `{ {}; }`
-   |                                                     |
-   |                                                     expected `{`
+   |                                                ---- ^^^^^^^ -- the attributes are attached to this branch
+   |                                                |    |
+   |                                                |    help: remove the attributes
+   |                                                the branch belongs to this `else`
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:65:54
@@ -239,22 +242,23 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
-error: expected `{`, found `#`
+error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:67:53
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
-   |                                                     ^       ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }`
-   |                                                     |
-   |                                                     expected `{`
+   |                                                ---- ^^^^^^^ --------------- the attributes are attached to this branch
+   |                                                |    |
+   |                                                |    help: remove the attributes
+   |                                                the branch belongs to this `else`
 
-error: expected `{`, found `#`
+error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:69:66
    |
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
-   |                                                     --           ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                                     --           ^^^^^^^ -- the attributes are attached to this branch
    |                                                     |            |
-   |                                                     |            expected `{`
-   |                                                     this `if` expression has a condition, but no block
+   |                                                     |            help: remove the attributes
+   |                                                     the branch belongs to this `if`
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:71:67
diff --git a/src/test/ui/parser/bad-interpolated-block.rs b/src/test/ui/parser/bad-interpolated-block.rs
new file mode 100644
index 00000000000..38d53a14bc0
--- /dev/null
+++ b/src/test/ui/parser/bad-interpolated-block.rs
@@ -0,0 +1,15 @@
+#![feature(label_break_value)]
+
+fn main() {}
+
+macro_rules! m {
+    ($b:block) => {
+        'lab: $b; //~ ERROR cannot use a `block` macro fragment here
+        unsafe $b; //~ ERROR cannot use a `block` macro fragment here
+        |x: u8| -> () $b; //~ ERROR cannot use a `block` macro fragment here
+    }
+}
+
+fn foo() {
+    m!({});
+}
diff --git a/src/test/ui/parser/bad-interpolated-block.stderr b/src/test/ui/parser/bad-interpolated-block.stderr
new file mode 100644
index 00000000000..2cbb6a13e74
--- /dev/null
+++ b/src/test/ui/parser/bad-interpolated-block.stderr
@@ -0,0 +1,39 @@
+error: cannot use a `block` macro fragment here
+  --> $DIR/bad-interpolated-block.rs:7:15
+   |
+LL |         'lab: $b;
+   |         ------^^
+   |         |
+   |         the `block` fragment is within this context
+...
+LL |     m!({});
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot use a `block` macro fragment here
+  --> $DIR/bad-interpolated-block.rs:8:16
+   |
+LL |         unsafe $b;
+   |         -------^^
+   |         |
+   |         the `block` fragment is within this context
+...
+LL |     m!({});
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot use a `block` macro fragment here
+  --> $DIR/bad-interpolated-block.rs:9:23
+   |
+LL |         |x: u8| -> () $b;
+   |                       ^^ the `block` fragment is within this context
+...
+LL |     m!({});
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/block-no-opening-brace.rs b/src/test/ui/parser/block-no-opening-brace.rs
new file mode 100644
index 00000000000..e4bb39f6836
--- /dev/null
+++ b/src/test/ui/parser/block-no-opening-brace.rs
@@ -0,0 +1,31 @@
+// edition:2018
+
+#![feature(try_blocks)]
+
+fn main() {}
+
+fn f1() {
+    loop
+        let x = 0; //~ ERROR expected `{`, found keyword `let`
+        drop(0);
+    }
+
+fn f2() {
+    while true
+        let x = 0; //~ ERROR expected `{`, found keyword `let`
+    }
+
+fn f3() {
+    for x in 0..1
+        let x = 0; //~ ERROR expected `{`, found keyword `let`
+    }
+
+fn f4() {
+    try //~ ERROR expected expression, found reserved keyword `try`
+        let x = 0;
+    }
+
+fn f5() {
+    async //~ ERROR async closures are unstable
+        let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let`
+    }
diff --git a/src/test/ui/parser/block-no-opening-brace.stderr b/src/test/ui/parser/block-no-opening-brace.stderr
new file mode 100644
index 00000000000..a88e4ac44cf
--- /dev/null
+++ b/src/test/ui/parser/block-no-opening-brace.stderr
@@ -0,0 +1,53 @@
+error: expected `{`, found keyword `let`
+  --> $DIR/block-no-opening-brace.rs:9:9
+   |
+LL |         let x = 0;
+   |         ^^^-------
+   |         |
+   |         expected `{`
+   |         help: try placing this code inside a block: `{ let x = 0; }`
+
+error: expected `{`, found keyword `let`
+  --> $DIR/block-no-opening-brace.rs:15:9
+   |
+LL |         let x = 0;
+   |         ^^^-------
+   |         |
+   |         expected `{`
+   |         help: try placing this code inside a block: `{ let x = 0; }`
+
+error: expected `{`, found keyword `let`
+  --> $DIR/block-no-opening-brace.rs:20:9
+   |
+LL |         let x = 0;
+   |         ^^^-------
+   |         |
+   |         expected `{`
+   |         help: try placing this code inside a block: `{ let x = 0; }`
+
+error: expected expression, found reserved keyword `try`
+  --> $DIR/block-no-opening-brace.rs:24:5
+   |
+LL |     try
+   |     ^^^ expected expression
+
+error: expected one of `move`, `|`, or `||`, found keyword `let`
+  --> $DIR/block-no-opening-brace.rs:30:9
+   |
+LL |     async
+   |          - expected one of `move`, `|`, or `||`
+LL |         let x = 0;
+   |         ^^^ unexpected token
+
+error[E0658]: async closures are unstable
+  --> $DIR/block-no-opening-brace.rs:29:5
+   |
+LL |     async
+   |     ^^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/parser/bounds-lifetime.rs b/src/test/ui/parser/bounds-lifetime.rs
index 9225cfce94e..c9251ac5321 100644
--- a/src/test/ui/parser/bounds-lifetime.rs
+++ b/src/test/ui/parser/bounds-lifetime.rs
@@ -6,6 +6,6 @@ type A = for<'a: 'b + 'c> fn(); // OK (rejected later by ast_validation)
 type A = for<'a: 'b,> fn(); // OK(rejected later by ast_validation)
 type A = for<'a: 'b +> fn(); // OK (rejected later by ast_validation)
 type A = for<'a, T> fn(); // OK (rejected later by ast_validation)
-type A = for<,> fn(); //~ ERROR expected one of `>`, `const`, identifier, or lifetime, found `,`
+type A = for<,> fn(); //~ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime
 
 fn main() {}
diff --git a/src/test/ui/parser/bounds-lifetime.stderr b/src/test/ui/parser/bounds-lifetime.stderr
index 12b9b61ebd1..e47a21d892b 100644
--- a/src/test/ui/parser/bounds-lifetime.stderr
+++ b/src/test/ui/parser/bounds-lifetime.stderr
@@ -1,8 +1,8 @@
-error: expected one of `>`, `const`, identifier, or lifetime, found `,`
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/bounds-lifetime.rs:9:14
    |
 LL | type A = for<,> fn();
-   |              ^ expected one of `>`, `const`, identifier, or lifetime
+   |              ^ expected one of `#`, `>`, `const`, identifier, or lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/circular_modules_main.rs b/src/test/ui/parser/circular_modules_main.rs
index b85003bf091..1ae36a1f760 100644
--- a/src/test/ui/parser/circular_modules_main.rs
+++ b/src/test/ui/parser/circular_modules_main.rs
@@ -6,5 +6,5 @@ pub fn hi_str() -> String {
 }
 
 fn main() {
-    circular_modules_hello::say_hello();
+    circular_modules_hello::say_hello(); //~ ERROR cannot find function `say_hello` in module
 }
diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr
index 33865fb7bca..90f81c64835 100644
--- a/src/test/ui/parser/circular_modules_main.stderr
+++ b/src/test/ui/parser/circular_modules_main.stderr
@@ -1,8 +1,20 @@
 error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs
-  --> $DIR/circular_modules_main.rs:2:5
+  --> $DIR/circular_modules_main.rs:2:1
    |
 LL | mod circular_modules_hello;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0425]: cannot find function `say_hello` in module `circular_modules_hello`
+  --> $DIR/circular_modules_main.rs:9:29
+   |
+LL |     circular_modules_hello::say_hello();
+   |                             ^^^^^^^^^ not found in `circular_modules_hello`
+   |
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use circular_modules_hello::say_hello;
+   |
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/parser/closure-return-syntax.rs b/src/test/ui/parser/closure-return-syntax.rs
index 54eb791d2bc..c6a08abeff4 100644
--- a/src/test/ui/parser/closure-return-syntax.rs
+++ b/src/test/ui/parser/closure-return-syntax.rs
@@ -3,5 +3,5 @@
 
 fn main() {
     let x = || -> i32 22;
-    //~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
+    //~^ ERROR expected `{`, found `22`
 }
diff --git a/src/test/ui/parser/closure-return-syntax.stderr b/src/test/ui/parser/closure-return-syntax.stderr
index bfb7f98c5f5..1ccdd977305 100644
--- a/src/test/ui/parser/closure-return-syntax.stderr
+++ b/src/test/ui/parser/closure-return-syntax.stderr
@@ -1,8 +1,11 @@
-error: expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
+error: expected `{`, found `22`
   --> $DIR/closure-return-syntax.rs:5:23
    |
 LL |     let x = || -> i32 22;
-   |                       ^^ expected one of `!`, `(`, `+`, `::`, `<`, or `{`
+   |                       ^^
+   |                       |
+   |                       expected `{`
+   |                       help: try placing this code inside a block: `{ 22 }`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/column-offset-1-based.rs b/src/test/ui/parser/column-offset-1-based.rs
index e158e5247db..0c24478c25c 100644
--- a/src/test/ui/parser/column-offset-1-based.rs
+++ b/src/test/ui/parser/column-offset-1-based.rs
@@ -1 +1 @@
-# //~ ERROR expected `[`, found `<eof>`
+# //~ ERROR expected one of `!` or `[`, found `<eof>`
diff --git a/src/test/ui/parser/column-offset-1-based.stderr b/src/test/ui/parser/column-offset-1-based.stderr
index 5cbf3d3e959..766d72a0a5a 100644
--- a/src/test/ui/parser/column-offset-1-based.stderr
+++ b/src/test/ui/parser/column-offset-1-based.stderr
@@ -1,8 +1,8 @@
-error: expected `[`, found `<eof>`
+error: expected one of `!` or `[`, found `<eof>`
   --> $DIR/column-offset-1-based.rs:1:1
    |
 LL | #
-   | ^ expected `[`
+   | ^ expected one of `!` or `[`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/doc-comment-in-if-statement.rs b/src/test/ui/parser/doc-comment-in-if-statement.rs
index c85fe25a7d0..343eac1b81f 100644
--- a/src/test/ui/parser/doc-comment-in-if-statement.rs
+++ b/src/test/ui/parser/doc-comment-in-if-statement.rs
@@ -1,4 +1,5 @@
 fn main() {
     if true /*!*/ {}
-    //~^ ERROR expected `{`, found doc comment `/*!*/`
+    //~^ ERROR outer attributes are not allowed on
+    //~| ERROR expected outer doc comment
 }
diff --git a/src/test/ui/parser/doc-comment-in-if-statement.stderr b/src/test/ui/parser/doc-comment-in-if-statement.stderr
index a720dd68bd0..af21b78733f 100644
--- a/src/test/ui/parser/doc-comment-in-if-statement.stderr
+++ b/src/test/ui/parser/doc-comment-in-if-statement.stderr
@@ -1,10 +1,19 @@
-error: expected `{`, found doc comment `/*!*/`
+error: expected outer doc comment
   --> $DIR/doc-comment-in-if-statement.rs:2:13
    |
 LL |     if true /*!*/ {}
-   |     --      ^^^^^ expected `{`
-   |     |
-   |     this `if` expression has a condition, but no block
+   |             ^^^^^
+   |
+   = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+
+error: outer attributes are not allowed on `if` and `else` branches
+  --> $DIR/doc-comment-in-if-statement.rs:2:13
+   |
+LL |     if true /*!*/ {}
+   |     --      ^^^^^ -- the attributes are attached to this branch
+   |     |       |
+   |     |       help: remove the attributes
+   |     the branch belongs to this `if`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/fn-body-eq-expr-semi.rs b/src/test/ui/parser/fn-body-eq-expr-semi.rs
new file mode 100644
index 00000000000..09444079365
--- /dev/null
+++ b/src/test/ui/parser/fn-body-eq-expr-semi.rs
@@ -0,0 +1,23 @@
+fn main() {}
+
+fn syntax() {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+}
+
+extern {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    //~^ ERROR incorrect function inside `extern` block
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+    //~^ ERROR incorrect function inside `extern` block
+}
+
+trait Foo {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+}
+
+impl Foo for () {
+    fn foo() = 42; //~ ERROR function body cannot be `= expression;`
+    fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;`
+}
diff --git a/src/test/ui/parser/fn-body-eq-expr-semi.stderr b/src/test/ui/parser/fn-body-eq-expr-semi.stderr
new file mode 100644
index 00000000000..739133e0b40
--- /dev/null
+++ b/src/test/ui/parser/fn-body-eq-expr-semi.stderr
@@ -0,0 +1,117 @@
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:4:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:5:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:9:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:11:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:16:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:17:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:21:14
+   |
+LL |     fn foo() = 42;
+   |              ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn foo() { 42 }
+   |              ^    ^
+
+error: function body cannot be `= expression;`
+  --> $DIR/fn-body-eq-expr-semi.rs:22:20
+   |
+LL |     fn bar() -> u8 = 42;
+   |                    ^^^^^
+   |
+help: surround the expression with `{` and `}` instead of `=` and `;`
+   |
+LL |     fn bar() -> u8 { 42 }
+   |                    ^    ^
+
+error: incorrect function inside `extern` block
+  --> $DIR/fn-body-eq-expr-semi.rs:9:8
+   |
+LL | extern {
+   | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL |     fn foo() = 42;
+   |        ^^^   ----- help: remove the invalid body: `;`
+   |        |
+   |        cannot have a body
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: incorrect function inside `extern` block
+  --> $DIR/fn-body-eq-expr-semi.rs:11:8
+   |
+LL | extern {
+   | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+...
+LL |     fn bar() -> u8 = 42;
+   |        ^^^         ----- help: remove the invalid body: `;`
+   |        |
+   |        cannot have a body
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr
index 1142cee9851..d6b36fbb714 100644
--- a/src/test/ui/parser/fn-header-semantic-fail.stderr
+++ b/src/test/ui/parser/fn-header-semantic-fail.stderr
@@ -2,7 +2,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:13:5
    |
 LL |     const async unsafe extern "C" fn ff5() {} // OK.
-   |     -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^-^^^^^------------------------------
    |     |     |
    |     |     `async` because of this
    |     `const` because of this
@@ -45,7 +45,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:21:9
    |
 LL |         const async unsafe extern "C" fn ft5();
-   |         -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^-^^^^^----------------------------
    |         |     |
    |         |     `async` because of this
    |         `const` because of this
@@ -88,7 +88,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:34:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
-   |         -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^-^^^^^------------------------------
    |         |     |
    |         |     `async` because of this
    |         `const` because of this
@@ -97,7 +97,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:46:9
    |
 LL |         const async unsafe extern "C" fn fi5() {}
-   |         -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^-^^^^^------------------------------
    |         |     |
    |         |     `async` because of this
    |         `const` because of this
@@ -160,7 +160,7 @@ error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:55:9
    |
 LL |         const async unsafe extern "C" fn fe5();
-   |         -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^-^^^^^----------------------------
    |         |     |
    |         |     `async` because of this
    |         `const` because of this
diff --git a/src/test/ui/parser/issue-1655.rs b/src/test/ui/parser/issue-1655.rs
index 3d0bf3c1c7b..e9fc6f15346 100644
--- a/src/test/ui/parser/issue-1655.rs
+++ b/src/test/ui/parser/issue-1655.rs
@@ -1,6 +1,5 @@
-// error-pattern:expected `[`, found `vec`
 mod blade_runner {
-    #vec[doc(
+    #vec[doc( //~ ERROR expected one of `!` or `[`, found `vec`
         brief = "Blade Runner is probably the best movie ever",
         desc = "I like that in the world of Blade Runner it is always
                 raining, and that it's always night time. And Aliens
diff --git a/src/test/ui/parser/issue-1655.stderr b/src/test/ui/parser/issue-1655.stderr
index 3f656b63cdb..0c390a0ec56 100644
--- a/src/test/ui/parser/issue-1655.stderr
+++ b/src/test/ui/parser/issue-1655.stderr
@@ -1,8 +1,8 @@
-error: expected `[`, found `vec`
-  --> $DIR/issue-1655.rs:3:6
+error: expected one of `!` or `[`, found `vec`
+  --> $DIR/issue-1655.rs:2:6
    |
 LL |     #vec[doc(
-   |      ^^^ expected `[`
+   |      ^^^ expected one of `!` or `[`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-5806.stderr b/src/test/ui/parser/issue-5806.stderr
index 6cf902ca86e..bdb5c91ff91 100644
--- a/src/test/ui/parser/issue-5806.stderr
+++ b/src/test/ui/parser/issue-5806.stderr
@@ -1,8 +1,8 @@
 error: couldn't read $DIR/../parser: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE)
-  --> $DIR/issue-5806.rs:5:5
+  --> $DIR/issue-5806.rs:5:1
    |
 LL | mod foo;
-   |     ^^^
+   | ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-63116.stderr b/src/test/ui/parser/issue-63116.stderr
index 2beb73d83d2..15cd3df860b 100644
--- a/src/test/ui/parser/issue-63116.stderr
+++ b/src/test/ui/parser/issue-63116.stderr
@@ -12,7 +12,7 @@ error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
 LL | impl W <s(f;Y(;]
    |            ^ expected one of 7 possible tokens
 
-error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, or lifetime, found `;`
+error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, lifetime, or path, found `;`
   --> $DIR/issue-63116.rs:3:15
    |
 LL | impl W <s(f;Y(;]
diff --git a/src/test/ui/parser/issue-63135.rs b/src/test/ui/parser/issue-63135.rs
index 7d46b8904f0..a5a8de85466 100644
--- a/src/test/ui/parser/issue-63135.rs
+++ b/src/test/ui/parser/issue-63135.rs
@@ -1,3 +1,3 @@
-// error-pattern: aborting due to 7 previous errors
+// error-pattern: aborting due to 5 previous errors
 
 fn i(n{...,f #
diff --git a/src/test/ui/parser/issue-63135.stderr b/src/test/ui/parser/issue-63135.stderr
index 04afae93be0..396aec8335d 100644
--- a/src/test/ui/parser/issue-63135.stderr
+++ b/src/test/ui/parser/issue-63135.stderr
@@ -31,23 +31,11 @@ LL | fn i(n{...,f #
    |        |  expected `}`
    |        `..` must be at the end and cannot have a trailing comma
 
-error: expected `[`, found `}`
+error: expected one of `!` or `[`, found `}`
   --> $DIR/issue-63135.rs:3:16
    |
 LL | fn i(n{...,f #
-   |                ^ expected `[`
+   |                ^ expected one of `!` or `[`
 
-error: expected one of `:` or `|`, found `)`
-  --> $DIR/issue-63135.rs:3:16
-   |
-LL | fn i(n{...,f #
-   |                ^ expected one of `:` or `|`
-
-error: expected `;` or `{`, found `<eof>`
-  --> $DIR/issue-63135.rs:3:16
-   |
-LL | fn i(n{...,f #
-   |                ^ expected `;` or `{`
-
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/parser/issue-68730.rs b/src/test/ui/parser/issue-68730.rs
index b570e941775..20e18b4bcbb 100644
--- a/src/test/ui/parser/issue-68730.rs
+++ b/src/test/ui/parser/issue-68730.rs
Binary files differdiff --git a/src/test/ui/parser/issue-68730.stderr b/src/test/ui/parser/issue-68730.stderr
index 090b41d839f..9f8833e17fe 100644
--- a/src/test/ui/parser/issue-68730.stderr
+++ b/src/test/ui/parser/issue-68730.stderr
Binary files differdiff --git a/src/test/ui/parser/issue-68890-2.rs b/src/test/ui/parser/issue-68890-2.rs
new file mode 100644
index 00000000000..ae022460468
--- /dev/null
+++ b/src/test/ui/parser/issue-68890-2.rs
@@ -0,0 +1,6 @@
+fn main() {}
+
+type X<'a> = (?'a) +;
+//~^ ERROR `?` may only modify trait bounds, not lifetime bounds
+//~| ERROR at least one trait is required for an object type
+//~| WARN trait objects without an explicit `dyn` are deprecated
diff --git a/src/test/ui/parser/issue-68890-2.stderr b/src/test/ui/parser/issue-68890-2.stderr
new file mode 100644
index 00000000000..d475c79cb27
--- /dev/null
+++ b/src/test/ui/parser/issue-68890-2.stderr
@@ -0,0 +1,22 @@
+error: `?` may only modify trait bounds, not lifetime bounds
+  --> $DIR/issue-68890-2.rs:3:15
+   |
+LL | type X<'a> = (?'a) +;
+   |               ^
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/issue-68890-2.rs:3:14
+   |
+LL | type X<'a> = (?'a) +;
+   |              ^^^^^^^ help: use `dyn`: `dyn (?'a) +`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/issue-68890-2.rs:3:14
+   |
+LL | type X<'a> = (?'a) +;
+   |              ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/issue-68890.rs b/src/test/ui/parser/issue-68890.rs
index a7c5a5e1300..bab4ed7f800 100644
--- a/src/test/ui/parser/issue-68890.rs
+++ b/src/test/ui/parser/issue-68890.rs
@@ -1,4 +1,4 @@
 enum e{A((?'a a+?+l))}
 //~^ ERROR `?` may only modify trait bounds, not lifetime bounds
 //~| ERROR expected one of `)`, `+`, or `,`
-//~| ERROR expected trait bound, not lifetime bound
+//~| ERROR expected item, found `)`
diff --git a/src/test/ui/parser/issue-68890.stderr b/src/test/ui/parser/issue-68890.stderr
index 9bb8761b67b..2a3bf6b41f0 100644
--- a/src/test/ui/parser/issue-68890.stderr
+++ b/src/test/ui/parser/issue-68890.stderr
@@ -10,11 +10,11 @@ error: expected one of `)`, `+`, or `,`, found `a`
 LL | enum e{A((?'a a+?+l))}
    |               ^ expected one of `)`, `+`, or `,`
 
-error: expected trait bound, not lifetime bound
-  --> $DIR/issue-68890.rs:1:11
+error: expected item, found `)`
+  --> $DIR/issue-68890.rs:1:21
    |
 LL | enum e{A((?'a a+?+l))}
-   |           ^^^
+   |                     ^ expected item
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/labeled-no-colon-expr.rs b/src/test/ui/parser/labeled-no-colon-expr.rs
new file mode 100644
index 00000000000..db9ef52c1ae
--- /dev/null
+++ b/src/test/ui/parser/labeled-no-colon-expr.rs
@@ -0,0 +1,17 @@
+#![feature(label_break_value)]
+
+fn main() {
+    'l0 while false {} //~ ERROR labeled expression must be followed by `:`
+    'l1 for _ in 0..1 {} //~ ERROR labeled expression must be followed by `:`
+    'l2 loop {} //~ ERROR labeled expression must be followed by `:`
+    'l3 {} //~ ERROR labeled expression must be followed by `:`
+    'l4 0; //~ ERROR labeled expression must be followed by `:`
+    //~^ ERROR expected `while`, `for`, `loop` or `{`
+
+    macro_rules! m {
+        ($b:block) => {
+            'l5 $b; //~ ERROR cannot use a `block` macro fragment here
+        }
+    }
+    m!({}); //~ ERROR labeled expression must be followed by `:`
+}
diff --git a/src/test/ui/parser/labeled-no-colon-expr.stderr b/src/test/ui/parser/labeled-no-colon-expr.stderr
new file mode 100644
index 00000000000..4f5e8f78aa0
--- /dev/null
+++ b/src/test/ui/parser/labeled-no-colon-expr.stderr
@@ -0,0 +1,89 @@
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:4:5
+   |
+LL |     'l0 while false {}
+   |     ----^^^^^^^^^^^^^^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:5:5
+   |
+LL |     'l1 for _ in 0..1 {}
+   |     ----^^^^^^^^^^^^^^^^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:6:5
+   |
+LL |     'l2 loop {}
+   |     ----^^^^^^^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:7:5
+   |
+LL |     'l3 {}
+   |     ----^^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/labeled-no-colon-expr.rs:8:9
+   |
+LL |     'l4 0;
+   |         ^ expected `while`, `for`, `loop` or `{` after a label
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:8:9
+   |
+LL |     'l4 0;
+   |     ----^
+   |     |  |
+   |     |  help: add `:` after the label
+   |     the label
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: cannot use a `block` macro fragment here
+  --> $DIR/labeled-no-colon-expr.rs:13:17
+   |
+LL |             'l5 $b;
+   |             ----^^
+   |             |
+   |             the `block` fragment is within this context
+...
+LL |     m!({});
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: labeled expression must be followed by `:`
+  --> $DIR/labeled-no-colon-expr.rs:16:8
+   |
+LL |             'l5 $b;
+   |             ---- help: add `:` after the label
+   |             |
+   |             the label
+...
+LL |     m!({});
+   |        ^^
+   |
+   = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/parser/macro/trait-object-macro-matcher.rs b/src/test/ui/parser/macro/trait-object-macro-matcher.rs
index 80d867d3b56..170ac22780b 100644
--- a/src/test/ui/parser/macro/trait-object-macro-matcher.rs
+++ b/src/test/ui/parser/macro/trait-object-macro-matcher.rs
@@ -2,9 +2,14 @@
 // `ty` matcher in particular doesn't accept a single lifetime
 
 macro_rules! m {
-    ($t: ty) => ( let _: $t; )
+    ($t: ty) => {
+        let _: $t;
+    };
 }
 
 fn main() {
-    m!('static); //~ ERROR expected type, found `'static`
+    m!('static);
+    //~^ ERROR lifetime in trait object type must be followed by `+`
+    //~| ERROR at least one trait is required for an object type
+    //~| WARN trait objects without an explicit `dyn` are deprecated
 }
diff --git a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr
index f02f60e4bfb..230733371dd 100644
--- a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr
+++ b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr
@@ -1,8 +1,22 @@
-error: expected type, found `'static`
-  --> $DIR/trait-object-macro-matcher.rs:9:8
+error: lifetime in trait object type must be followed by `+`
+  --> $DIR/trait-object-macro-matcher.rs:11:8
    |
 LL |     m!('static);
-   |        ^^^^^^^ expected type
+   |        ^^^^^^^
 
-error: aborting due to previous error
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/trait-object-macro-matcher.rs:11:8
+   |
+LL |     m!('static);
+   |        ^^^^^^^ help: use `dyn`: `dyn 'static`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/trait-object-macro-matcher.rs:11:8
+   |
+LL |     m!('static);
+   |        ^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/mod_file_not_exist.rs b/src/test/ui/parser/mod_file_not_exist.rs
index e662c707a38..f4a27b52ec5 100644
--- a/src/test/ui/parser/mod_file_not_exist.rs
+++ b/src/test/ui/parser/mod_file_not_exist.rs
@@ -1,8 +1,9 @@
 // ignore-windows
 
 mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file`
-//~^ HELP name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory
+//~^ HELP to create the module `not_a_real_file`, create file
 
 fn main() {
     assert_eq!(mod_file_aux::bar(), 10);
+    //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux`
 }
diff --git a/src/test/ui/parser/mod_file_not_exist.stderr b/src/test/ui/parser/mod_file_not_exist.stderr
index dadf4b29dcf..087ae9fe3e0 100644
--- a/src/test/ui/parser/mod_file_not_exist.stderr
+++ b/src/test/ui/parser/mod_file_not_exist.stderr
@@ -1,11 +1,18 @@
 error[E0583]: file not found for module `not_a_real_file`
-  --> $DIR/mod_file_not_exist.rs:3:5
+  --> $DIR/mod_file_not_exist.rs:3:1
    |
 LL | mod not_a_real_file;
-   |     ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR"
+   = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs"
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux`
+  --> $DIR/mod_file_not_exist.rs:7:16
+   |
+LL |     assert_eq!(mod_file_aux::bar(), 10);
+   |                ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0583`.
+Some errors have detailed explanations: E0433, E0583.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/parser/mod_file_not_exist_windows.rs b/src/test/ui/parser/mod_file_not_exist_windows.rs
index 0cd9e9c799f..4b7d7a02bbe 100644
--- a/src/test/ui/parser/mod_file_not_exist_windows.rs
+++ b/src/test/ui/parser/mod_file_not_exist_windows.rs
@@ -1,8 +1,9 @@
 // only-windows
 
 mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file`
-//~^ HELP name the file either not_a_real_file.rs or not_a_real_file\mod.rs inside the directory
+//~^ HELP to create the module `not_a_real_file`, create file
 
 fn main() {
     assert_eq!(mod_file_aux::bar(), 10);
+    //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux`
 }
diff --git a/src/test/ui/parser/mod_file_not_exist_windows.stderr b/src/test/ui/parser/mod_file_not_exist_windows.stderr
index 60ae00abab1..d67205cfdf1 100644
--- a/src/test/ui/parser/mod_file_not_exist_windows.stderr
+++ b/src/test/ui/parser/mod_file_not_exist_windows.stderr
@@ -1,11 +1,18 @@
 error[E0583]: file not found for module `not_a_real_file`
-  --> $DIR/mod_file_not_exist_windows.rs:3:5
+  --> $DIR/mod_file_not_exist_windows.rs:3:1
    |
 LL | mod not_a_real_file;
-   |     ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR"
+   = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs"
 
-error: aborting due to previous error
+error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux`
+  --> $DIR/mod_file_not_exist_windows.rs:7:16
+   |
+LL |     assert_eq!(mod_file_aux::bar(), 10);
+   |                ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0583`.
+Some errors have detailed explanations: E0433, E0583.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/parser/mod_file_with_path_attr.stderr b/src/test/ui/parser/mod_file_with_path_attr.stderr
index 004b5d7963a..cd1add73d58 100644
--- a/src/test/ui/parser/mod_file_with_path_attr.stderr
+++ b/src/test/ui/parser/mod_file_with_path_attr.stderr
@@ -1,8 +1,8 @@
 error: couldn't read $DIR/not_a_real_file.rs: $FILE_NOT_FOUND_MSG (os error 2)
-  --> $DIR/mod_file_with_path_attr.rs:4:5
+  --> $DIR/mod_file_with_path_attr.rs:4:1
    |
 LL | mod m;
-   |     ^
+   | ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/regions-out-of-scope-slice.rs b/src/test/ui/parser/regions-out-of-scope-slice.rs
index 21369d0be61..d223619e1de 100644
--- a/src/test/ui/parser/regions-out-of-scope-slice.rs
+++ b/src/test/ui/parser/regions-out-of-scope-slice.rs
@@ -4,7 +4,7 @@ fn foo(cond: bool) {
     let mut x;
 
     if cond {
-        x = &'blk [1,2,3]; //~ ERROR expected `:`, found `[`
+        x = &'blk [1,2,3]; //~ ERROR borrow expressions cannot be annotated with lifetimes
     }
 }
 
diff --git a/src/test/ui/parser/regions-out-of-scope-slice.stderr b/src/test/ui/parser/regions-out-of-scope-slice.stderr
index 8d9bf0b7a04..bbc657ffd61 100644
--- a/src/test/ui/parser/regions-out-of-scope-slice.stderr
+++ b/src/test/ui/parser/regions-out-of-scope-slice.stderr
@@ -1,8 +1,11 @@
-error: expected `:`, found `[`
-  --> $DIR/regions-out-of-scope-slice.rs:7:19
+error: borrow expressions cannot be annotated with lifetimes
+  --> $DIR/regions-out-of-scope-slice.rs:7:13
    |
 LL |         x = &'blk [1,2,3];
-   |                   ^ expected `:`
+   |             ^----^^^^^^^^
+   |              |
+   |              annotated with lifetime here
+   |              help: remove the lifetime annotation
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/stripped-nested-outline-mod-pass.rs b/src/test/ui/parser/stripped-nested-outline-mod-pass.rs
new file mode 100644
index 00000000000..1b4669a439f
--- /dev/null
+++ b/src/test/ui/parser/stripped-nested-outline-mod-pass.rs
@@ -0,0 +1,13 @@
+// Expansion drives parsing, so conditional compilation will strip
+// out outline modules and we will never attempt parsing them.
+
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+mod foo {
+    mod bar {
+        mod baz; // This was an error before.
+    }
+}
diff --git a/src/test/ui/parser/trait-object-lifetime-parens.rs b/src/test/ui/parser/trait-object-lifetime-parens.rs
index c8b0eb684f3..5a5c19f32e8 100644
--- a/src/test/ui/parser/trait-object-lifetime-parens.rs
+++ b/src/test/ui/parser/trait-object-lifetime-parens.rs
@@ -6,9 +6,7 @@ fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not s
 
 fn check<'a>() {
     let _: Box<Trait + ('a)>; //~ ERROR parenthesized lifetime bounds are not supported
-    let _: Box<('a) + Trait>;
-    //~^ ERROR expected type, found `'a`
-    //~| ERROR expected `:`, found `)`
+    let _: Box<('a) + Trait>; //~ ERROR lifetime in trait object type must be followed by `+`
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr
index 319a308c013..1289c248275 100644
--- a/src/test/ui/parser/trait-object-lifetime-parens.stderr
+++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr
@@ -10,19 +10,11 @@ error: parenthesized lifetime bounds are not supported
 LL |     let _: Box<Trait + ('a)>;
    |                        ^^^^ help: remove the parentheses
 
-error: expected `:`, found `)`
-  --> $DIR/trait-object-lifetime-parens.rs:9:19
-   |
-LL |     let _: Box<('a) + Trait>;
-   |                   ^ expected `:`
-
-error: expected type, found `'a`
+error: lifetime in trait object type must be followed by `+`
   --> $DIR/trait-object-lifetime-parens.rs:9:17
    |
 LL |     let _: Box<('a) + Trait>;
-   |         -       ^^ expected type
-   |         |
-   |         while parsing the type for `_`
+   |                 ^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/trait-object-trait-parens.rs b/src/test/ui/parser/trait-object-trait-parens.rs
index a113de14b6f..9fbc938c4dc 100644
--- a/src/test/ui/parser/trait-object-trait-parens.rs
+++ b/src/test/ui/parser/trait-object-trait-parens.rs
@@ -1,15 +1,20 @@
 trait Trait<'a> {}
 
+trait Obj {}
+
 fn f<T: (Copy) + (?Sized) + (for<'a> Trait<'a>)>() {}
 
 fn main() {
-    let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
+    let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
+    //~^ ERROR `?Trait` is not permitted in trait object types
+    //~| ERROR only auto traits can be used as additional traits
+    //~| WARN trait objects without an explicit `dyn` are deprecated
+    let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
     //~^ ERROR `?Trait` is not permitted in trait object types
+    //~| ERROR only auto traits can be used as additional traits
     //~| WARN trait objects without an explicit `dyn` are deprecated
-    let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
-    //~^ WARN trait objects without an explicit `dyn` are deprecated
-    let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
-    //~^ ERROR use of undeclared lifetime name `'a`
-    //~| ERROR `?Trait` is not permitted in trait object types
+    let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
+    //~^ ERROR `?Trait` is not permitted in trait object types
+    //~| ERROR only auto traits can be used as additional traits
     //~| WARN trait objects without an explicit `dyn` are deprecated
 }
diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr
index 4b9f49423cb..7022a66ca1a 100644
--- a/src/test/ui/parser/trait-object-trait-parens.stderr
+++ b/src/test/ui/parser/trait-object-trait-parens.stderr
@@ -1,44 +1,74 @@
 error: `?Trait` is not permitted in trait object types
-  --> $DIR/trait-object-trait-parens.rs:6:25
+  --> $DIR/trait-object-trait-parens.rs:8:24
    |
-LL |     let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
-   |                         ^^^^^^^^
+LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
+   |                        ^^^^^^^^
 
 error: `?Trait` is not permitted in trait object types
-  --> $DIR/trait-object-trait-parens.rs:11:47
+  --> $DIR/trait-object-trait-parens.rs:12:17
    |
-LL |     let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
-   |                                               ^^^^^^^^
+LL |     let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
+   |                 ^^^^^^
+
+error: `?Trait` is not permitted in trait object types
+  --> $DIR/trait-object-trait-parens.rs:16:46
+   |
+LL |     let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
+   |                                              ^^^^^^^^
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/trait-object-trait-parens.rs:6:16
+  --> $DIR/trait-object-trait-parens.rs:8:16
    |
-LL |     let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (Copy) + (?Sized) + (for<'a> Trait<'a>)`
+LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (Obj) + (?Sized) + (for<'a> Trait<'a>)`
    |
    = note: `#[warn(bare_trait_objects)]` on by default
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/trait-object-trait-parens.rs:9:16
+  --> $DIR/trait-object-trait-parens.rs:12:16
    |
-LL |     let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (?Sized) + (for<'a> Trait<'a>) + (Copy)`
+LL |     let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (?Sized) + (for<'a> Trait<'a>) + (Obj)`
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/trait-object-trait-parens.rs:11:16
+  --> $DIR/trait-object-trait-parens.rs:16:16
+   |
+LL |     let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (for<'a> Trait<'a>) + (Obj) + (?Sized)`
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/trait-object-trait-parens.rs:8:35
+   |
+LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
+   |                -----              ^^^^^^^^^^^^^^^^^^^
+   |                |                  |
+   |                |                  additional non-auto trait
+   |                |                  trait alias used in trait object type (additional use)
+   |                first non-auto trait
+   |                trait alias used in trait object type (first use)
+
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/trait-object-trait-parens.rs:12:49
    |
-LL |     let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (for<'a> Trait<'a>) + (Copy) + (?Sized)`
+LL |     let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
+   |                           -------------------   ^^^^^
+   |                           |                     |
+   |                           |                     additional non-auto trait
+   |                           |                     trait alias used in trait object type (additional use)
+   |                           first non-auto trait
+   |                           trait alias used in trait object type (first use)
 
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/trait-object-trait-parens.rs:11:31
+error[E0225]: only auto traits can be used as additional traits in a trait object
+  --> $DIR/trait-object-trait-parens.rs:16:38
    |
-LL | fn main() {
-   |        - help: consider introducing lifetime `'a` here: `<'a>`
-...
-LL |     let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
-   |                               ^^ undeclared lifetime
+LL |     let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
+   |                 -----------------    ^^^^^
+   |                 |                    |
+   |                 |                    additional non-auto trait
+   |                 |                    trait alias used in trait object type (additional use)
+   |                 first non-auto trait
+   |                 trait alias used in trait object type (first use)
 
-error: aborting due to 3 previous errors
+error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0261`.
+For more information about this error, try `rustc --explain E0225`.
diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs
index 11eae2af9c9..7d1cac8a442 100644
--- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs
+++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs
@@ -21,7 +21,7 @@ fn uninhab_union() -> Foo {
 
 fn match_on_uninhab() {
     match uninhab_ref() {
-        //~^ ERROR non-exhaustive patterns: type `&'static !` is non-empty
+        //~^ ERROR non-exhaustive patterns: type `&!` is non-empty
     }
 
     match uninhab_union() {
diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
index 1b1096c977a..e1079f912d0 100644
--- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
+++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
@@ -1,4 +1,4 @@
-error[E0004]: non-exhaustive patterns: type `&'static !` is non-empty
+error[E0004]: non-exhaustive patterns: type `&!` is non-empty
   --> $DIR/always-inhabited-union-ref.rs:23:11
    |
 LL |     match uninhab_ref() {
diff --git a/src/test/ui/privacy/privacy1.rs b/src/test/ui/privacy/privacy1.rs
index fcf7b19572f..e28fd13b97f 100644
--- a/src/test/ui/privacy/privacy1.rs
+++ b/src/test/ui/privacy/privacy1.rs
@@ -74,7 +74,7 @@ mod bar {
         }
         self::baz::A;
         self::baz::A::foo();
-        self::baz::A::bar(); //~ ERROR: method `bar` is private
+        self::baz::A::bar(); //~ ERROR: associated function `bar` is private
         self::baz::A.foo2();
 
         // this used to cause an ICE in privacy traversal.
@@ -92,21 +92,21 @@ pub fn gpub() {}
 fn lol() {
     bar::A;
     bar::A::foo();
-    bar::A::bar(); //~ ERROR: method `bar` is private
+    bar::A::bar(); //~ ERROR: associated function `bar` is private
     bar::A.foo2();
 }
 
 mod foo {
     fn test() {
         ::bar::A::foo();
-        ::bar::A::bar();        //~ ERROR: method `bar` is private
+        ::bar::A::bar();        //~ ERROR: associated function `bar` is private
         ::bar::A.foo2();
         ::bar::baz::A::foo();   //~ ERROR: module `baz` is private
         ::bar::baz::A::bar();   //~ ERROR: module `baz` is private
-                                //~^ ERROR: method `bar` is private
+                                //~^ ERROR: associated function `bar` is private
         ::bar::baz::A.foo2();   //~ ERROR: module `baz` is private
         ::bar::baz::A.bar2();   //~ ERROR: module `baz` is private
-                                //~^ ERROR: method `bar2` is private
+                                //~^ ERROR: associated function `bar2` is private
 
         let _: isize =
         ::bar::B::foo();        //~ ERROR: trait `B` is private
diff --git a/src/test/ui/privacy/privacy1.stderr b/src/test/ui/privacy/privacy1.stderr
index 215df0dc754..ec2bc0d84ac 100644
--- a/src/test/ui/privacy/privacy1.stderr
+++ b/src/test/ui/privacy/privacy1.stderr
@@ -154,31 +154,31 @@ note: the trait `B` is defined here
 LL |     trait B {
    |     ^^^^^^^
 
-error[E0624]: method `bar` is private
+error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:77:9
    |
 LL |         self::baz::A::bar();
    |         ^^^^^^^^^^^^^^^^^
 
-error[E0624]: method `bar` is private
+error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:95:5
    |
 LL |     bar::A::bar();
    |     ^^^^^^^^^^^
 
-error[E0624]: method `bar` is private
+error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:102:9
    |
 LL |         ::bar::A::bar();
    |         ^^^^^^^^^^^^^
 
-error[E0624]: method `bar` is private
+error[E0624]: associated function `bar` is private
   --> $DIR/privacy1.rs:105:9
    |
 LL |         ::bar::baz::A::bar();
    |         ^^^^^^^^^^^^^^^^^^
 
-error[E0624]: method `bar2` is private
+error[E0624]: associated function `bar2` is private
   --> $DIR/privacy1.rs:108:23
    |
 LL |         ::bar::baz::A.bar2();
diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr
index 719dc27ccf4..b10c3a52659 100644
--- a/src/test/ui/privacy/privacy2.stderr
+++ b/src/test/ui/privacy/privacy2.stderr
@@ -10,11 +10,16 @@ error[E0603]: function import `foo` is private
 LL |     use bar::glob::foo;
    |                    ^^^ this function import is private
    |
-note: the function import `foo` is defined here
+note: the function import `foo` is defined here...
   --> $DIR/privacy2.rs:10:13
    |
 LL |         use foo;
    |             ^^^
+note: ...and refers to the function `foo` which is defined here
+  --> $DIR/privacy2.rs:14:1
+   |
+LL | pub fn foo() {}
+   | ^^^^^^^^^^^^ consider importing it directly
 
 error: requires `sized` lang_item
 
diff --git a/src/test/ui/privacy/private-impl-method.rs b/src/test/ui/privacy/private-impl-method.rs
index b5587920f1c..f7be6726c5e 100644
--- a/src/test/ui/privacy/private-impl-method.rs
+++ b/src/test/ui/privacy/private-impl-method.rs
@@ -17,5 +17,5 @@ fn f() {
 fn main() {
     let s = a::Foo { x: 1 };
     s.bar();
-    s.foo();    //~ ERROR method `foo` is private
+    s.foo();    //~ ERROR associated function `foo` is private
 }
diff --git a/src/test/ui/privacy/private-impl-method.stderr b/src/test/ui/privacy/private-impl-method.stderr
index e1da3f47a4e..6833cdb4df9 100644
--- a/src/test/ui/privacy/private-impl-method.stderr
+++ b/src/test/ui/privacy/private-impl-method.stderr
@@ -1,4 +1,4 @@
-error[E0624]: method `foo` is private
+error[E0624]: associated function `foo` is private
   --> $DIR/private-impl-method.rs:20:7
    |
 LL |     s.foo();
diff --git a/src/test/ui/privacy/private-method-cross-crate.rs b/src/test/ui/privacy/private-method-cross-crate.rs
index 4da44e0682b..ab3bbdfe496 100644
--- a/src/test/ui/privacy/private-method-cross-crate.rs
+++ b/src/test/ui/privacy/private-method-cross-crate.rs
@@ -4,5 +4,5 @@ use cci_class_5::kitties::cat;
 
 fn main() {
   let nyan : cat = cat(52, 99);
-  nyan.nap();   //~ ERROR method `nap` is private
+  nyan.nap();   //~ ERROR associated function `nap` is private
 }
diff --git a/src/test/ui/privacy/private-method-cross-crate.stderr b/src/test/ui/privacy/private-method-cross-crate.stderr
index 10e0bfe5b13..6b49063815a 100644
--- a/src/test/ui/privacy/private-method-cross-crate.stderr
+++ b/src/test/ui/privacy/private-method-cross-crate.stderr
@@ -1,4 +1,4 @@
-error[E0624]: method `nap` is private
+error[E0624]: associated function `nap` is private
   --> $DIR/private-method-cross-crate.rs:7:8
    |
 LL |   nyan.nap();
diff --git a/src/test/ui/privacy/private-method-inherited.rs b/src/test/ui/privacy/private-method-inherited.rs
index bc27027e886..2f6454288ae 100644
--- a/src/test/ui/privacy/private-method-inherited.rs
+++ b/src/test/ui/privacy/private-method-inherited.rs
@@ -10,5 +10,5 @@ mod a {
 
 fn main() {
     let x = a::Foo;
-    x.f();  //~ ERROR method `f` is private
+    x.f();  //~ ERROR associated function `f` is private
 }
diff --git a/src/test/ui/privacy/private-method-inherited.stderr b/src/test/ui/privacy/private-method-inherited.stderr
index d2ba591ef0c..5551e1bd759 100644
--- a/src/test/ui/privacy/private-method-inherited.stderr
+++ b/src/test/ui/privacy/private-method-inherited.stderr
@@ -1,4 +1,4 @@
-error[E0624]: method `f` is private
+error[E0624]: associated function `f` is private
   --> $DIR/private-method-inherited.rs:13:7
    |
 LL |     x.f();
diff --git a/src/test/ui/privacy/private-method.rs b/src/test/ui/privacy/private-method.rs
index a9bea520e75..76a642cde1a 100644
--- a/src/test/ui/privacy/private-method.rs
+++ b/src/test/ui/privacy/private-method.rs
@@ -19,5 +19,5 @@ mod kitties {
 
 fn main() {
   let nyan : kitties::Cat = kitties::cat(52, 99);
-  nyan.nap(); //~ ERROR method `nap` is private
+  nyan.nap(); //~ ERROR associated function `nap` is private
 }
diff --git a/src/test/ui/privacy/private-method.stderr b/src/test/ui/privacy/private-method.stderr
index 61fc122e318..583dc123e24 100644
--- a/src/test/ui/privacy/private-method.stderr
+++ b/src/test/ui/privacy/private-method.stderr
@@ -1,4 +1,4 @@
-error[E0624]: method `nap` is private
+error[E0624]: associated function `nap` is private
   --> $DIR/private-method.rs:22:8
    |
 LL |   nyan.nap();
diff --git a/src/test/ui/privacy/restricted/test.stderr b/src/test/ui/privacy/restricted/test.stderr
index aac444b8e3c..e73f723ed0a 100644
--- a/src/test/ui/privacy/restricted/test.stderr
+++ b/src/test/ui/privacy/restricted/test.stderr
@@ -52,13 +52,13 @@ error[E0616]: field `x` of struct `foo::bar::S` is private
 LL |     S::default().x;
    |     ^^^^^^^^^^^^^^
 
-error[E0624]: method `f` is private
+error[E0624]: associated function `f` is private
   --> $DIR/test.rs:32:18
    |
 LL |     S::default().f();
    |                  ^
 
-error[E0624]: method `g` is private
+error[E0624]: associated function `g` is private
   --> $DIR/test.rs:33:5
    |
 LL |     S::g();
@@ -76,13 +76,13 @@ error[E0616]: field `z` of struct `pub_restricted::Universe` is private
 LL |     let _ = u.z;
    |             ^^^
 
-error[E0624]: method `g` is private
+error[E0624]: associated function `g` is private
   --> $DIR/test.rs:45:7
    |
 LL |     u.g();
    |       ^
 
-error[E0624]: method `h` is private
+error[E0624]: associated function `h` is private
   --> $DIR/test.rs:46:7
    |
 LL |     u.h();
diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stdout b/src/test/ui/proc-macro/attribute-spans-preserved.stdout
index faf31712156..cf9a97491f0 100644
--- a/src/test/ui/proc-macro/attribute-spans-preserved.stdout
+++ b/src/test/ui/proc-macro/attribute-spans-preserved.stdout
@@ -1 +1 @@
-fn main () { let y : u32 = "z" ; { let x : u32 = "y" ; } }
+fn main() { let y : u32 = "z" ; { let x : u32 = "y" ; } }
diff --git a/src/test/ui/proc-macro/auxiliary/derive-unstable.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs
index f702df66db1..2ccd3f88200 100644
--- a/src/test/ui/proc-macro/auxiliary/derive-unstable.rs
+++ b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs
@@ -10,5 +10,5 @@ use proc_macro::TokenStream;
 #[proc_macro_derive(Unstable)]
 pub fn derive(_input: TokenStream) -> TokenStream {
 
-    "unsafe fn foo() -> u32 { ::std::intrinsics::init() }".parse().unwrap()
+    "unsafe fn foo() -> u32 { ::std::intrinsics::abort() }".parse().unwrap()
 }
diff --git a/src/test/ui/proc-macro/crt-static.rs b/src/test/ui/proc-macro/crt-static.rs
new file mode 100644
index 00000000000..90e3d422b3c
--- /dev/null
+++ b/src/test/ui/proc-macro/crt-static.rs
@@ -0,0 +1,16 @@
+// Test proc-macro crate can be built without addtional RUSTFLAGS
+// on musl target
+// override -Ctarget-feature=-crt-static from compiletest
+// compile-flags: -Ctarget-feature=
+// ignore-wasm32
+// build-pass
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo)]
+pub fn derive_foo(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
index ea06f6c1aca..15433bebde9 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
@@ -1,4 +1,4 @@
-PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ;
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
index 619b2fd5321..73e407918ec 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
+++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
@@ -1,5 +1,5 @@
 PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S));
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A (identity ! ($crate :: S)) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A(identity ! ($crate :: S)) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -55,7 +55,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S));
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct B (identity ! ($crate :: S)) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct B(identity ! ($crate :: S)) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout
index 5fdc6f8ee96..e125a3e7f17 100644
--- a/src/test/ui/proc-macro/dollar-crate.stdout
+++ b/src/test/ui/proc-macro/dollar-crate.stdout
@@ -1,4 +1,4 @@
-PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ;
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -80,7 +80,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S);
-PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ;
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -120,7 +120,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: #3 bytes(LO..HI),
     },
 ]
-PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ;
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -161,7 +161,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S);
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -202,7 +202,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S);
-PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ;
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
diff --git a/src/test/ui/qualified/qualified-path-params.rs b/src/test/ui/qualified/qualified-path-params.rs
index b1b60b4b73f..65549d909d0 100644
--- a/src/test/ui/qualified/qualified-path-params.rs
+++ b/src/test/ui/qualified/qualified-path-params.rs
@@ -18,7 +18,7 @@ impl S {
 fn main() {
     match 10 {
         <S as Tr>::A::f::<u8> => {}
-    //~^ ERROR expected unit struct, unit variant or constant, found method `<<S as Tr>::A>::f<u8>`
+    //~^ ERROR expected unit struct, unit variant or constant, found associated function
         0 ..= <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
     }
 }
diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr
index 7a74a37021b..7ff43f4404c 100644
--- a/src/test/ui/qualified/qualified-path-params.stderr
+++ b/src/test/ui/qualified/qualified-path-params.stderr
@@ -1,4 +1,4 @@
-error[E0533]: expected unit struct, unit variant or constant, found method `<<S as Tr>::A>::f<u8>`
+error[E0533]: expected unit struct, unit variant or constant, found associated function `<<S as Tr>::A>::f<u8>`
   --> $DIR/qualified-path-params.rs:20:9
    |
 LL |         <S as Tr>::A::f::<u8> => {}
diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs
index 22cf15fb2e4..c6a3cc346fc 100644
--- a/src/test/ui/range/issue-54505-no-std.rs
+++ b/src/test/ui/range/issue-54505-no-std.rs
@@ -15,10 +15,6 @@ use core::ops::RangeBounds;
 #[lang = "eh_personality"]
 extern fn eh_personality() {}
 
-#[cfg(target_os = "windows")]
-#[lang = "eh_unwind_resume"]
-extern fn eh_unwind_resume() {}
-
 
 // take a reference to any built-in range
 fn take_range(_r: &impl RangeBounds<i8>) {}
diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr
index aead80fa500..90934061132 100644
--- a/src/test/ui/range/issue-54505-no-std.stderr
+++ b/src/test/ui/range/issue-54505-no-std.stderr
@@ -1,7 +1,7 @@
 error: `#[panic_handler]` function required, but not found
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:28:16
+  --> $DIR/issue-54505-no-std.rs:24:16
    |
 LL |     take_range(0..1);
    |                ^^^^
@@ -13,7 +13,7 @@ LL |     take_range(0..1);
                  found struct `core::ops::Range<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:33:16
+  --> $DIR/issue-54505-no-std.rs:29:16
    |
 LL |     take_range(1..);
    |                ^^^
@@ -25,7 +25,7 @@ LL |     take_range(1..);
                  found struct `core::ops::RangeFrom<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:38:16
+  --> $DIR/issue-54505-no-std.rs:34:16
    |
 LL |     take_range(..);
    |                ^^
@@ -37,7 +37,7 @@ LL |     take_range(..);
                  found struct `core::ops::RangeFull`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:43:16
+  --> $DIR/issue-54505-no-std.rs:39:16
    |
 LL |     take_range(0..=1);
    |                ^^^^^
@@ -49,7 +49,7 @@ LL |     take_range(0..=1);
                  found struct `core::ops::RangeInclusive<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:48:16
+  --> $DIR/issue-54505-no-std.rs:44:16
    |
 LL |     take_range(..5);
    |                ^^^
@@ -61,7 +61,7 @@ LL |     take_range(..5);
                  found struct `core::ops::RangeTo<{integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-54505-no-std.rs:53:16
+  --> $DIR/issue-54505-no-std.rs:49:16
    |
 LL |     take_range(..=42);
    |                ^^^^^
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr
index a33d3583552..06e1b0f1ac2 100644
--- a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr
@@ -1,32 +1,54 @@
-error[E0623]: lifetime mismatch
+error[E0491]: in type `&'b &'a usize`, reference has a longer lifetime than the data it references
   --> $DIR/regions-free-region-ordering-caller.rs:11:12
    |
-LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |                     ---------     ---------
-   |                     |
-   |                     these two types are declared with different lifetimes...
 LL |     let z: Option<&'b &'a usize> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime `'b` as defined on the function body at 10:14
+  --> $DIR/regions-free-region-ordering-caller.rs:10:14
+   |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |              ^^
+note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 10:10
+  --> $DIR/regions-free-region-ordering-caller.rs:10:10
+   |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          ^^
 
-error[E0623]: lifetime mismatch
+error[E0491]: in type `&'b Paramd<'a>`, reference has a longer lifetime than the data it references
   --> $DIR/regions-free-region-ordering-caller.rs:17:12
    |
-LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |                     ---------     ---------
-   |                     |
-   |                     these two types are declared with different lifetimes...
-LL |     let y: Paramd<'a> = Paramd { x: a };
 LL |     let z: Option<&'b Paramd<'a>> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime `'b` as defined on the function body at 15:14
+  --> $DIR/regions-free-region-ordering-caller.rs:15:14
+   |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |              ^^
+note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 15:10
+  --> $DIR/regions-free-region-ordering-caller.rs:15:10
+   |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          ^^
 
-error[E0623]: lifetime mismatch
+error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
   --> $DIR/regions-free-region-ordering-caller.rs:22:12
    |
-LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
-   |                     ---------     --------- these two types are declared with different lifetimes...
 LL |     let z: Option<&'a &'b usize> = None;
-   |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `b` flows into `a` here
+   |            ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime `'a` as defined on the function body at 21:10
+  --> $DIR/regions-free-region-ordering-caller.rs:21:10
+   |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          ^^
+note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 21:14
+  --> $DIR/regions-free-region-ordering-caller.rs:21:14
+   |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |              ^^
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0623`.
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.rs b/src/test/ui/regions/regions-free-region-ordering-caller.rs
index c0b12f23cdb..2bf4734cf73 100644
--- a/src/test/ui/regions/regions-free-region-ordering-caller.rs
+++ b/src/test/ui/regions/regions-free-region-ordering-caller.rs
@@ -8,18 +8,18 @@
 struct Paramd<'a> { x: &'a usize }
 
 fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
-    let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0623
+    let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0491
     //[nll]~^ ERROR lifetime may not live long enough
 }
 
 fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
     let y: Paramd<'a> = Paramd { x: a };
-    let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0623
+    let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0491
     //[nll]~^ ERROR lifetime may not live long enough
 }
 
 fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
-    let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0623
+    let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0491
     //[nll]~^ ERROR lifetime may not live long enough
 }
 
diff --git a/src/test/ui/repr/repr-align-assign.stderr b/src/test/ui/repr/repr-align-assign.stderr
index 192312d165b..b878ae0d173 100644
--- a/src/test/ui/repr/repr-align-assign.stderr
+++ b/src/test/ui/repr/repr-align-assign.stderr
@@ -24,3 +24,4 @@ LL | #[repr(align="8")]
 
 error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0693`.
diff --git a/src/test/ui/resolve/raw-ident-in-path.rs b/src/test/ui/resolve/raw-ident-in-path.rs
new file mode 100644
index 00000000000..1bcbef59437
--- /dev/null
+++ b/src/test/ui/resolve/raw-ident-in-path.rs
@@ -0,0 +1,5 @@
+// Regression test for issue #63882.
+
+type A = crate::r#break; //~ ERROR cannot find type `r#break` in module `crate`
+
+fn main() {}
diff --git a/src/test/ui/resolve/raw-ident-in-path.stderr b/src/test/ui/resolve/raw-ident-in-path.stderr
new file mode 100644
index 00000000000..f2efcbc8e85
--- /dev/null
+++ b/src/test/ui/resolve/raw-ident-in-path.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `r#break` in module `crate`
+  --> $DIR/raw-ident-in-path.rs:3:17
+   |
+LL | type A = crate::r#break;
+   |                 ^^^^^^^ not found in `crate`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
index 7becb9c5b60..c2fb8fa1eb6 100644
--- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
+++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
@@ -8,3 +8,4 @@ LL | struct S;
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0739`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
index 3ea58a3728a..834f6a409f5 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
@@ -1,18 +1,18 @@
 error: inherent impls cannot be `const`
-  --> $DIR/inherent-impl.rs:9:1
+  --> $DIR/inherent-impl.rs:9:12
    |
 LL | impl const S {}
-   | ^^^^^-----^^^^^
+   |      ----- ^ inherent impl for this type
    |      |
    |      `const` because of this
    |
    = note: only trait implementations may be annotated with `const`
 
 error: inherent impls cannot be `const`
-  --> $DIR/inherent-impl.rs:12:1
+  --> $DIR/inherent-impl.rs:12:12
    |
 LL | impl const T {}
-   | ^^^^^-----^^^^^
+   |      ----- ^ inherent impl for this type
    |      |
    |      `const` because of this
    |
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
index 6afcf24cd3e..57374b7e3bb 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr
@@ -2,7 +2,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
    |
 LL |     async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
-   |                          -         -               ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                          -         -               ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
    |                          |         |
    |                          |         let's call the lifetime of this reference `'1`
    |                          let's call the lifetime of this reference `'2`
@@ -11,7 +11,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75
    |
 LL |     async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
-   |                          -          -                                     ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                          -          -                                     ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
    |                          |          |
    |                          |          let's call the lifetime of this reference `'1`
    |                          let's call the lifetime of this reference `'2`
@@ -20,7 +20,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
    |
 LL |     async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
-   |                  --              -                             ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+   |                  --              -                             ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
    |                  |               |
    |                  |               let's call the lifetime of this reference `'1`
    |                  lifetime `'a` defined here
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
index a659e448785..17099201d11 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
@@ -2,7 +2,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46
    |
 LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
-   |                    -         -               ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                    -         -               ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
    |                    |         |
    |                    |         let's call the lifetime of this reference `'1`
    |                    let's call the lifetime of this reference `'2`
@@ -11,7 +11,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:69
    |
 LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
-   |                    -          -                                     ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                    -          -                                     ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
    |                    |          |
    |                    |          let's call the lifetime of this reference `'1`
    |                    let's call the lifetime of this reference `'2`
@@ -20,7 +20,7 @@ error: lifetime may not live long enough
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58
    |
 LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
-   |            --  ---- has type `std::pin::Pin<&'1 Foo>`    ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+   |            --  ---- has type `std::pin::Pin<&'1 Foo>`    ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
    |            |
    |            lifetime `'a` defined here
 
diff --git a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr
index 57d0929c50a..c10b8824e6d 100644
--- a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr
+++ b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr
@@ -6,7 +6,7 @@ LL |     async fn ref_self(&self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:19:9
@@ -16,7 +16,7 @@ LL |     async fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                             |
    |                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:23:9
@@ -26,7 +26,7 @@ LL |     async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:27:9
@@ -36,7 +36,7 @@ LL |     async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:31:9
@@ -46,7 +46,7 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                             |
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self-async.rs:35:9
@@ -56,7 +56,7 @@ LL |     async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                         |
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/lt-ref-self.nll.stderr b/src/test/ui/self/elision/lt-ref-self.nll.stderr
index b51b5a0ba38..e2de743b8f6 100644
--- a/src/test/ui/self/elision/lt-ref-self.nll.stderr
+++ b/src/test/ui/self/elision/lt-ref-self.nll.stderr
@@ -6,7 +6,7 @@ LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 |
    |                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:17:9
@@ -16,7 +16,7 @@ LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:21:9
@@ -26,7 +26,7 @@ LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:25:9
@@ -36,7 +36,7 @@ LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:29:9
@@ -46,7 +46,7 @@ LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/lt-ref-self.rs:33:9
@@ -56,7 +56,7 @@ LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                   |
    |                                   let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr
index 46e828390b0..19496a5ef6d 100644
--- a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr
+++ b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr
@@ -6,7 +6,7 @@ LL |     async fn ref_self(&mut self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:19:9
@@ -16,7 +16,7 @@ LL |     async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                             |
    |                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:23:9
@@ -26,7 +26,7 @@ LL |     async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:27:9
@@ -36,7 +36,7 @@ LL |     async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:31:9
@@ -46,7 +46,7 @@ LL |     async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                             |
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self-async.rs:35:9
@@ -56,7 +56,7 @@ LL |     async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                             |
    |                                             let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-self.nll.stderr b/src/test/ui/self/elision/ref-mut-self.nll.stderr
index 6c8c030e5ff..94bfc5f4a81 100644
--- a/src/test/ui/self/elision/ref-mut-self.nll.stderr
+++ b/src/test/ui/self/elision/ref-mut-self.nll.stderr
@@ -6,7 +6,7 @@ LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
    |                 |
    |                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:17:9
@@ -16,7 +16,7 @@ LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:21:9
@@ -26,7 +26,7 @@ LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:25:9
@@ -36,7 +36,7 @@ LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:29:9
@@ -46,7 +46,7 @@ LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-self.rs:33:9
@@ -56,7 +56,7 @@ LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
index 99340800790..94671c7c87a 100644
--- a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
+++ b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr
@@ -6,7 +6,7 @@ LL |     async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:17:9
@@ -16,7 +16,7 @@ LL |     async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:21:9
@@ -26,7 +26,7 @@ LL |     async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:25:9
@@ -36,7 +36,7 @@ LL |     async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u
    |                                               |
    |                                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct-async.rs:29:9
@@ -46,7 +46,7 @@ LL |     async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u
    |                                               |
    |                                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-struct.nll.stderr b/src/test/ui/self/elision/ref-mut-struct.nll.stderr
index e3886444db2..c9e7479ea5d 100644
--- a/src/test/ui/self/elision/ref-mut-struct.nll.stderr
+++ b/src/test/ui/self/elision/ref-mut-struct.nll.stderr
@@ -6,7 +6,7 @@ LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                         |
    |                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:15:9
@@ -16,7 +16,7 @@ LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                 |
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:19:9
@@ -26,7 +26,7 @@ LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                 |
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:23:9
@@ -36,7 +36,7 @@ LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
    |                                         |
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-mut-struct.rs:27:9
@@ -46,7 +46,7 @@ LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
    |                                         |
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/self/elision/ref-self.nll.stderr b/src/test/ui/self/elision/ref-self.nll.stderr
index ecac1ce3378..d1fd209102e 100644
--- a/src/test/ui/self/elision/ref-self.nll.stderr
+++ b/src/test/ui/self/elision/ref-self.nll.stderr
@@ -6,7 +6,7 @@ LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 |
    |                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:27:9
@@ -16,7 +16,7 @@ LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       |
    |                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:31:9
@@ -26,7 +26,7 @@ LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:35:9
@@ -36,7 +36,7 @@ LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:39:9
@@ -46,7 +46,7 @@ LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:43:9
@@ -56,7 +56,7 @@ LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-self.rs:47:9
@@ -66,7 +66,7 @@ LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                      |
    |                                      let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/self/elision/ref-struct-async.nll.stderr b/src/test/ui/self/elision/ref-struct-async.nll.stderr
index bcbf79bc039..9361b6f3f81 100644
--- a/src/test/ui/self/elision/ref-struct-async.nll.stderr
+++ b/src/test/ui/self/elision/ref-struct-async.nll.stderr
@@ -6,7 +6,7 @@ LL |     async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                               |
    |                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:17:9
@@ -16,7 +16,7 @@ LL |     async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:21:9
@@ -26,7 +26,7 @@ LL |     async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                       |
    |                                       let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:25:9
@@ -36,7 +36,7 @@ LL |     async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                               |
    |                                               let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct-async.rs:29:9
@@ -46,7 +46,7 @@ LL |     async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                           |
    |                                           let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/self/elision/ref-struct.nll.stderr b/src/test/ui/self/elision/ref-struct.nll.stderr
index 39e7631f31e..e1cc38b7c95 100644
--- a/src/test/ui/self/elision/ref-struct.nll.stderr
+++ b/src/test/ui/self/elision/ref-struct.nll.stderr
@@ -6,7 +6,7 @@ LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                         |
    |                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:15:9
@@ -16,7 +16,7 @@ LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                 |
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:19:9
@@ -26,7 +26,7 @@ LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                 |
    |                                 let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:23:9
@@ -36,7 +36,7 @@ LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                         |
    |                                         let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: lifetime may not live long enough
   --> $DIR/ref-struct.rs:27:9
@@ -46,7 +46,7 @@ LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                     |
    |                                     let's call the lifetime of this reference `'2`
 LL |         f
-   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |         ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/shadowed/shadowed-use-visibility.stderr b/src/test/ui/shadowed/shadowed-use-visibility.stderr
index cd8ec13794c..2244f3a46b2 100644
--- a/src/test/ui/shadowed/shadowed-use-visibility.stderr
+++ b/src/test/ui/shadowed/shadowed-use-visibility.stderr
@@ -4,11 +4,16 @@ error[E0603]: module import `bar` is private
 LL |     use foo::bar::f as g;
    |              ^^^ this module import is private
    |
-note: the module import `bar` is defined here
+note: the module import `bar` is defined here...
   --> $DIR/shadowed-use-visibility.rs:4:9
    |
 LL |     use foo as bar;
    |         ^^^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/shadowed-use-visibility.rs:1:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module import `f` is private
   --> $DIR/shadowed-use-visibility.rs:15:10
@@ -16,11 +21,16 @@ error[E0603]: module import `f` is private
 LL | use bar::f::f;
    |          ^ this module import is private
    |
-note: the module import `f` is defined here
+note: the module import `f` is defined here...
   --> $DIR/shadowed-use-visibility.rs:11:9
    |
 LL |     use foo as f;
    |         ^^^^^^^^
+note: ...and refers to the module `foo` which is defined here
+  --> $DIR/shadowed-use-visibility.rs:1:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/auxiliary/transitive_dep_three.rs b/src/test/ui/span/auxiliary/transitive_dep_three.rs
new file mode 100644
index 00000000000..99b51625ac3
--- /dev/null
+++ b/src/test/ui/span/auxiliary/transitive_dep_three.rs
@@ -0,0 +1,9 @@
+#[macro_export]
+macro_rules! define_parse_error {
+    () => {
+        #[macro_export]
+        macro_rules! parse_error {
+            () => { parse error }
+        }
+    }
+}
diff --git a/src/test/ui/span/auxiliary/transitive_dep_two.rs b/src/test/ui/span/auxiliary/transitive_dep_two.rs
new file mode 100644
index 00000000000..5110c42765b
--- /dev/null
+++ b/src/test/ui/span/auxiliary/transitive_dep_two.rs
@@ -0,0 +1,3 @@
+extern crate transitive_dep_three;
+
+transitive_dep_three::define_parse_error!();
diff --git a/src/test/ui/span/transitive-dep-span.rs b/src/test/ui/span/transitive-dep-span.rs
new file mode 100644
index 00000000000..b445d389c56
--- /dev/null
+++ b/src/test/ui/span/transitive-dep-span.rs
@@ -0,0 +1,13 @@
+// Tests that we properly serialize/deserialize spans from transitive dependencies
+// (e.g. imported SourceFiles)
+//
+// The order of these next lines is important, since we need
+// transitive_dep_two.rs to be able to reference transitive_dep_three.rs
+//
+// aux-build: transitive_dep_three.rs
+// aux-build: transitive_dep_two.rs
+// compile-flags: -Z macro-backtrace
+
+extern crate transitive_dep_two;
+
+transitive_dep_two::parse_error!(); //~ ERROR expected one of
diff --git a/src/test/ui/span/transitive-dep-span.stderr b/src/test/ui/span/transitive-dep-span.stderr
new file mode 100644
index 00000000000..68d8911a435
--- /dev/null
+++ b/src/test/ui/span/transitive-dep-span.stderr
@@ -0,0 +1,19 @@
+error: expected one of `!` or `::`, found `error`
+  --> $DIR/auxiliary/transitive_dep_three.rs:6:27
+   |
+LL | /         macro_rules! parse_error {
+LL | |             () => { parse error }
+   | |                           ^^^^^ expected one of `!` or `::`
+LL | |         }
+   | |_________- in this expansion of `transitive_dep_two::parse_error!`
+   | 
+  ::: $DIR/transitive-dep-span.rs:13:1
+   |
+LL |   transitive_dep_two::parse_error!();
+   |   -----------------------------------
+   |   |
+   |   in this macro invocation
+   |   in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/type-annotations-needed-expr.stderr b/src/test/ui/span/type-annotations-needed-expr.stderr
index 2b92f9b93bf..35d994e194f 100644
--- a/src/test/ui/span/type-annotations-needed-expr.stderr
+++ b/src/test/ui/span/type-annotations-needed-expr.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     let _ = (vec![1,2,3]).into_iter().sum() as f64;
    |                                       ^^^
    |                                       |
-   |                                       cannot infer type for type parameter `S` declared on the method `sum`
+   |                                       cannot infer type for type parameter `S` declared on the associated function `sum`
    |                                       help: consider specifying the type argument in the method call: `sum::<S>`
    |
    = note: type must be known at this point
diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr
index 03b1ef69ca0..6e19d79e48f 100644
--- a/src/test/ui/specialization/defaultimpl/validation.stderr
+++ b/src/test/ui/specialization/defaultimpl/validation.stderr
@@ -1,8 +1,8 @@
 error: inherent impls cannot be `default`
-  --> $DIR/validation.rs:7:1
+  --> $DIR/validation.rs:7:14
    |
 LL | default impl S {}
-   | -------^^^^^^^
+   | -------      ^ inherent impl for this type
    | |
    | `default` because of this
    |
diff --git a/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs b/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs
new file mode 100644
index 00000000000..6ec0d261d51
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs
@@ -0,0 +1,6 @@
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+pub trait SpecTrait {
+    fn method(&self);
+}
diff --git a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs
new file mode 100644
index 00000000000..03cab00b0fb
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs
@@ -0,0 +1,32 @@
+// Test that associated types in trait objects are not considered to be
+// constrained.
+
+#![feature(min_specialization)]
+
+trait Specializable {
+    fn f();
+}
+
+trait B<T> {
+    type Y;
+}
+
+trait C {
+    type Y;
+}
+
+impl<A: ?Sized> Specializable for A {
+    default fn f() {}
+}
+
+impl<'a, T> Specializable for dyn B<T, Y = T> + 'a {
+    //~^ ERROR specializing impl repeats parameter `T`
+    fn f() {}
+}
+
+impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a {
+    //~^ ERROR specializing impl repeats parameter `T`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr
new file mode 100644
index 00000000000..6345cee2c37
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr
@@ -0,0 +1,20 @@
+error: specializing impl repeats parameter `T`
+  --> $DIR/dyn-trait-assoc-types.rs:22:1
+   |
+LL | / impl<'a, T> Specializable for dyn B<T, Y = T> + 'a {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: specializing impl repeats parameter `T`
+  --> $DIR/dyn-trait-assoc-types.rs:27:1
+   |
+LL | / impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs b/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs
new file mode 100644
index 00000000000..723ed71c3e9
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs
@@ -0,0 +1,16 @@
+// Check that specialization traits can't be implemented without a feature.
+
+// gate-test-min_specialization
+
+// aux-build:specialization-trait.rs
+
+extern crate specialization_trait;
+
+struct A {}
+
+impl specialization_trait::SpecTrait for A {
+    //~^ ERROR implementing `rustc_specialization_trait` traits is unstable
+    fn method(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr b/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr
new file mode 100644
index 00000000000..934103d49dc
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr
@@ -0,0 +1,10 @@
+error: implementing `rustc_specialization_trait` traits is unstable
+  --> $DIR/impl_specialization_trait.rs:11:1
+   |
+LL | impl specialization_trait::SpecTrait for A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(min_specialization)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs b/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs
new file mode 100644
index 00000000000..98d7f919435
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs
@@ -0,0 +1,30 @@
+// Test that specializing on the well-formed predicates of the trait and
+// self-type of an impl is allowed.
+
+// check-pass
+
+#![feature(min_specialization)]
+
+struct OrdOnly<T: Ord>(T);
+
+trait SpecTrait<U> {
+    fn f();
+}
+
+impl<T, U> SpecTrait<U> for T {
+    default fn f() {}
+}
+
+impl<T: Ord> SpecTrait<()> for OrdOnly<T> {
+    fn f() {}
+}
+
+impl<T: Ord> SpecTrait<OrdOnly<T>> for () {
+    fn f() {}
+}
+
+impl<T: Ord, U: Ord, V: Ord> SpecTrait<(OrdOnly<T>, OrdOnly<U>)> for &[OrdOnly<V>] {
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.rs b/src/test/ui/specialization/min_specialization/repeated_projection_type.rs
new file mode 100644
index 00000000000..f21f39f0669
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.rs
@@ -0,0 +1,24 @@
+// Test that projection bounds can't be specialized on.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+trait Id {
+    type This;
+}
+impl<T> Id for T {
+    type This = T;
+}
+
+impl<T: Id> X for T {
+    default fn f() {}
+}
+
+impl<I, V: Id<This = (I,)>> X for V {
+    //~^ ERROR cannot specialize on
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
new file mode 100644
index 00000000000..7cc4357a704
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
@@ -0,0 +1,11 @@
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id[0]::This[0]) }, (I,)))`
+  --> $DIR/repeated_projection_type.rs:19:1
+   |
+LL | / impl<I, V: Id<This = (I,)>> X for V {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs b/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs
new file mode 100644
index 00000000000..49bfacec0ae
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs
@@ -0,0 +1,19 @@
+// Test that directly specializing on repeated lifetime parameters is not
+// allowed.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+
+impl<'a> X for (&'a u8, &'a u8) {
+    //~^ ERROR specializing impl repeats parameter `'a`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr b/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr
new file mode 100644
index 00000000000..ce9309f7012
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr
@@ -0,0 +1,11 @@
+error: specializing impl repeats parameter `'a`
+  --> $DIR/repeating_lifetimes.rs:14:1
+   |
+LL | / impl<'a> X for (&'a u8, &'a u8) {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/repeating_param.rs b/src/test/ui/specialization/min_specialization/repeating_param.rs
new file mode 100644
index 00000000000..5a1c97fd321
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/repeating_param.rs
@@ -0,0 +1,17 @@
+// Test that specializing on two type parameters being equal is not allowed.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+impl<T> X for (T, T) {
+    //~^ ERROR specializing impl repeats parameter `T`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/repeating_param.stderr b/src/test/ui/specialization/min_specialization/repeating_param.stderr
new file mode 100644
index 00000000000..8b4be1c4995
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/repeating_param.stderr
@@ -0,0 +1,11 @@
+error: specializing impl repeats parameter `T`
+  --> $DIR/repeating_param.rs:12:1
+   |
+LL | / impl<T> X for (T, T) {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/spec-iter.rs b/src/test/ui/specialization/min_specialization/spec-iter.rs
new file mode 100644
index 00000000000..e17e9dd5f13
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/spec-iter.rs
@@ -0,0 +1,20 @@
+// Check that we can specialize on a concrete iterator type. This requires us
+// to consider which parameters in the parent impl are constrained.
+
+// check-pass
+
+#![feature(min_specialization)]
+
+trait SpecFromIter<T> {
+    fn f(&self);
+}
+
+impl<'a, T: 'a, I: Iterator<Item = &'a T>> SpecFromIter<T> for I {
+    default fn f(&self) {}
+}
+
+impl<'a, T> SpecFromIter<T> for std::slice::Iter<'a, T> {
+    fn f(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/spec-reference.rs b/src/test/ui/specialization/min_specialization/spec-reference.rs
new file mode 100644
index 00000000000..377889e2cca
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/spec-reference.rs
@@ -0,0 +1,19 @@
+// Check that lifetime parameters are allowed in specializing impls.
+
+// check-pass
+
+#![feature(min_specialization)]
+
+trait MySpecTrait {
+    fn f();
+}
+
+impl<T> MySpecTrait for T {
+    default fn f() {}
+}
+
+impl<'a, T: ?Sized> MySpecTrait for &'a T {
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialization_marker.rs b/src/test/ui/specialization/min_specialization/specialization_marker.rs
new file mode 100644
index 00000000000..93462d02ea5
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialization_marker.rs
@@ -0,0 +1,17 @@
+// Test that `rustc_unsafe_specialization_marker` is only allowed on marker traits.
+
+#![feature(rustc_attrs)]
+
+#[rustc_unsafe_specialization_marker]
+trait SpecMarker {
+    fn f();
+    //~^ ERROR marker traits
+}
+
+#[rustc_unsafe_specialization_marker]
+trait SpecMarker2 {
+    type X;
+    //~^ ERROR marker traits
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialization_marker.stderr b/src/test/ui/specialization/min_specialization/specialization_marker.stderr
new file mode 100644
index 00000000000..ffeced19821
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialization_marker.stderr
@@ -0,0 +1,15 @@
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/specialization_marker.rs:7:5
+   |
+LL |     fn f();
+   |     ^^^^^^^
+
+error[E0714]: marker traits cannot have associated items
+  --> $DIR/specialization_marker.rs:13:5
+   |
+LL |     type X;
+   |     ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0714`.
diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.rs b/src/test/ui/specialization/min_specialization/specialization_super_trait.rs
new file mode 100644
index 00000000000..145f376edf9
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialization_super_trait.rs
@@ -0,0 +1,18 @@
+// Test that supertraits can't be assumed in impls of
+// `rustc_specialization_trait`, as such impls would
+// allow specializing on the supertrait.
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+trait SpecMarker: Default {
+    fn f();
+}
+
+impl<T: Default> SpecMarker for T {
+    //~^ ERROR cannot specialize
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr
new file mode 100644
index 00000000000..154c839c6da
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr
@@ -0,0 +1,11 @@
+error: cannot specialize on trait `std::default::Default`
+  --> $DIR/specialization_super_trait.rs:13:1
+   |
+LL | / impl<T: Default> SpecMarker for T {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.rs b/src/test/ui/specialization/min_specialization/specialization_trait.rs
new file mode 100644
index 00000000000..d597278d296
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialization_trait.rs
@@ -0,0 +1,26 @@
+// Test that `rustc_specialization_trait` requires always applicable impls.
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+trait SpecMarker {
+    fn f();
+}
+
+impl SpecMarker for &'static u8 {
+    //~^ ERROR cannot specialize
+    fn f() {}
+}
+
+impl<T> SpecMarker for (T, T) {
+    //~^ ERROR specializing impl
+    fn f() {}
+}
+
+impl<T: Clone> SpecMarker for [T] {
+    //~^ ERROR cannot specialize
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_trait.stderr
new file mode 100644
index 00000000000..4357d2318fc
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialization_trait.stderr
@@ -0,0 +1,29 @@
+error: cannot specialize on `'static` lifetime
+  --> $DIR/specialization_trait.rs:11:1
+   |
+LL | / impl SpecMarker for &'static u8 {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: specializing impl repeats parameter `T`
+  --> $DIR/specialization_trait.rs:16:1
+   |
+LL | / impl<T> SpecMarker for (T, T) {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: cannot specialize on trait `std::clone::Clone`
+  --> $DIR/specialization_trait.rs:21:1
+   |
+LL | / impl<T: Clone> SpecMarker for [T] {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_marker.rs b/src/test/ui/specialization/min_specialization/specialize_on_marker.rs
new file mode 100644
index 00000000000..4219bd13b18
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialize_on_marker.rs
@@ -0,0 +1,24 @@
+// Test that specializing on a `rustc_unsafe_specialization_marker` trait is
+// allowed.
+
+// check-pass
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_unsafe_specialization_marker]
+trait SpecMarker {}
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+
+impl<T: SpecMarker> X for T {
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs b/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs
new file mode 100644
index 00000000000..abbab5c23db
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs
@@ -0,0 +1,27 @@
+// Test that specializing on a `rustc_specialization_trait` trait is allowed.
+
+// check-pass
+
+#![feature(min_specialization)]
+#![feature(rustc_attrs)]
+
+#[rustc_specialization_trait]
+trait SpecTrait {
+    fn g(&self);
+}
+
+trait X {
+    fn f(&self);
+}
+
+impl<T> X for T {
+    default fn f(&self) {}
+}
+
+impl<T: SpecTrait> X for T {
+    fn f(&self) {
+        self.g();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_static.rs b/src/test/ui/specialization/min_specialization/specialize_on_static.rs
new file mode 100644
index 00000000000..dd1b05401e6
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialize_on_static.rs
@@ -0,0 +1,18 @@
+// Test that directly specializing on `'static` is not allowed.
+
+#![feature(min_specialization)]
+
+trait X {
+    fn f();
+}
+
+impl<T> X for &'_ T {
+    default fn f() {}
+}
+
+impl X for &'static u8 {
+    //~^ ERROR cannot specialize on `'static` lifetime
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_static.stderr b/src/test/ui/specialization/min_specialization/specialize_on_static.stderr
new file mode 100644
index 00000000000..d1809d6dfbb
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialize_on_static.stderr
@@ -0,0 +1,11 @@
+error: cannot specialize on `'static` lifetime
+  --> $DIR/specialize_on_static.rs:13:1
+   |
+LL | / impl X for &'static u8 {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.rs b/src/test/ui/specialization/min_specialization/specialize_on_trait.rs
new file mode 100644
index 00000000000..0588442c320
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialize_on_trait.rs
@@ -0,0 +1,20 @@
+// Test that specializing on a trait is not allowed in general.
+
+#![feature(min_specialization)]
+
+trait SpecMarker {}
+
+trait X {
+    fn f();
+}
+
+impl<T> X for T {
+    default fn f() {}
+}
+
+impl<T: SpecMarker> X for T {
+    //~^ ERROR cannot specialize on trait `SpecMarker`
+    fn f() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr
new file mode 100644
index 00000000000..35445fd09b9
--- /dev/null
+++ b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr
@@ -0,0 +1,11 @@
+error: cannot specialize on trait `SpecMarker`
+  --> $DIR/specialize_on_trait.rs:15:1
+   |
+LL | / impl<T: SpecMarker> X for T {
+LL | |
+LL | |     fn f() {}
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/static/static-method-privacy.rs b/src/test/ui/static/static-method-privacy.rs
index b637037f60e..9ee59b320ed 100644
--- a/src/test/ui/static/static-method-privacy.rs
+++ b/src/test/ui/static/static-method-privacy.rs
@@ -6,5 +6,5 @@ mod a {
 }
 
 fn main() {
-    let _ = a::S::new();    //~ ERROR method `new` is private
+    let _ = a::S::new();    //~ ERROR associated function `new` is private
 }
diff --git a/src/test/ui/static/static-method-privacy.stderr b/src/test/ui/static/static-method-privacy.stderr
index 14ca9f58301..78d211438cc 100644
--- a/src/test/ui/static/static-method-privacy.stderr
+++ b/src/test/ui/static/static-method-privacy.stderr
@@ -1,4 +1,4 @@
-error[E0624]: method `new` is private
+error[E0624]: associated function `new` is private
   --> $DIR/static-method-privacy.rs:9:13
    |
 LL |     let _ = a::S::new();
diff --git a/src/test/ui/suggestions/const-no-type.rs b/src/test/ui/suggestions/const-no-type.rs
index 99200a965dd..6b79697e983 100644
--- a/src/test/ui/suggestions/const-no-type.rs
+++ b/src/test/ui/suggestions/const-no-type.rs
@@ -43,4 +43,4 @@ static S = Vec::<String>::new();
 static mut SM = "abc";
 //~^ ERROR missing type for `static mut` item
 //~| HELP provide a type for the item
-//~| SUGGESTION &'static str
+//~| SUGGESTION &str
diff --git a/src/test/ui/suggestions/const-no-type.stderr b/src/test/ui/suggestions/const-no-type.stderr
index c4f17109dc5..a7b5aa5e5b1 100644
--- a/src/test/ui/suggestions/const-no-type.stderr
+++ b/src/test/ui/suggestions/const-no-type.stderr
@@ -14,7 +14,7 @@ error: missing type for `static mut` item
   --> $DIR/const-no-type.rs:43:12
    |
 LL | static mut SM = "abc";
-   |            ^^ help: provide a type for the item: `SM: &'static str`
+   |            ^^ help: provide a type for the item: `SM: &str`
 
 error: missing type for `const` item
   --> $DIR/const-no-type.rs:14:7
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr
index a715c565946..c343071ac3e 100644
--- a/src/test/ui/suggestions/suggest-methods.stderr
+++ b/src/test/ui/suggestions/suggest-methods.stderr
@@ -5,19 +5,19 @@ LL | struct Foo;
    | ----------- method `bat` not found for this
 ...
 LL |     f.bat(1.0);
-   |       ^^^ help: there is a method with a similar name: `bar`
+   |       ^^^ help: there is an associated function with a similar name: `bar`
 
 error[E0599]: no method named `is_emtpy` found for struct `std::string::String` in the current scope
   --> $DIR/suggest-methods.rs:21:15
    |
 LL |     let _ = s.is_emtpy();
-   |               ^^^^^^^^ help: there is a method with a similar name: `is_empty`
+   |               ^^^^^^^^ help: there is an associated function with a similar name: `is_empty`
 
 error[E0599]: no method named `count_eos` found for type `u32` in the current scope
   --> $DIR/suggest-methods.rs:25:19
    |
 LL |     let _ = 63u32.count_eos();
-   |                   ^^^^^^^^^ help: there is a method with a similar name: `count_zeros`
+   |                   ^^^^^^^^^ help: there is an associated function with a similar name: `count_zeros`
 
 error[E0599]: no method named `count_o` found for type `u32` in the current scope
   --> $DIR/suggest-methods.rs:28:19
diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.stderr b/src/test/ui/syntax-trait-polarity-feature-gate.stderr
index ed76377278b..5d4c1b354f7 100644
--- a/src/test/ui/syntax-trait-polarity-feature-gate.stderr
+++ b/src/test/ui/syntax-trait-polarity-feature-gate.stderr
@@ -1,8 +1,8 @@
 error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
-  --> $DIR/syntax-trait-polarity-feature-gate.rs:7:1
+  --> $DIR/syntax-trait-polarity-feature-gate.rs:7:6
    |
 LL | impl !Send for TestType {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |      ^^^^^
    |
    = note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
    = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable
diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/syntax-trait-polarity.stderr
index fef3a650888..5777e0ade90 100644
--- a/src/test/ui/syntax-trait-polarity.stderr
+++ b/src/test/ui/syntax-trait-polarity.stderr
@@ -1,29 +1,35 @@
 error: inherent impls cannot be negative
-  --> $DIR/syntax-trait-polarity.rs:7:1
+  --> $DIR/syntax-trait-polarity.rs:7:7
    |
 LL | impl !TestType {}
-   | ^^^^^^^^^^^^^^^^^
+   |      -^^^^^^^^ inherent impl for this type
+   |      |
+   |      negative because of this
 
 error[E0198]: negative impls cannot be unsafe
-  --> $DIR/syntax-trait-polarity.rs:12:1
+  --> $DIR/syntax-trait-polarity.rs:12:13
    |
 LL | unsafe impl !Send for TestType {}
-   | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
+   | ------      -^^^^
+   | |           |
+   | |           negative because of this
    | unsafe because of this
 
 error: inherent impls cannot be negative
-  --> $DIR/syntax-trait-polarity.rs:19:1
+  --> $DIR/syntax-trait-polarity.rs:19:10
    |
 LL | impl<T> !TestType2<T> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |         -^^^^^^^^^^^^ inherent impl for this type
+   |         |
+   |         negative because of this
 
 error[E0198]: negative impls cannot be unsafe
-  --> $DIR/syntax-trait-polarity.rs:22:1
+  --> $DIR/syntax-trait-polarity.rs:22:16
    |
 LL | unsafe impl<T> !Send for TestType2<T> {}
-   | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
+   | ------         -^^^^
+   | |              |
+   | |              negative because of this
    | unsafe because of this
 
 error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`)
diff --git a/src/test/ui/test-panic-while-printing.rs b/src/test/ui/test-panic-while-printing.rs
new file mode 100644
index 00000000000..23f45407c1a
--- /dev/null
+++ b/src/test/ui/test-panic-while-printing.rs
@@ -0,0 +1,24 @@
+// compile-flags:--test
+// run-pass
+// ignore-emscripten no subprocess support
+
+use std::fmt;
+use std::fmt::{Display, Formatter};
+
+pub struct A(Vec<u32>);
+
+impl Display for A {
+    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
+        self.0[0];
+        Ok(())
+    }
+}
+
+#[test]
+fn main() {
+    let result = std::panic::catch_unwind(|| {
+        let a = A(vec![]);
+        eprintln!("{}", a);
+    });
+    assert!(result.is_err());
+}
diff --git a/src/test/ui/traits/trait-item-privacy.rs b/src/test/ui/traits/trait-item-privacy.rs
index 8507d8ef17e..1ea1d65df62 100644
--- a/src/test/ui/traits/trait-item-privacy.rs
+++ b/src/test/ui/traits/trait-item-privacy.rs
@@ -69,7 +69,7 @@ fn check_method() {
     S.c(); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
     let c = &S as &dyn C;
-    c.a(); //~ ERROR method `a` is private
+    c.a(); //~ ERROR associated function `a` is private
     c.b(); // OK
     c.c(); // OK
 
@@ -81,7 +81,7 @@ fn check_method() {
     //~^ ERROR no function or associated item named `b` found
     S::c(&S); // OK
     // a, b, c are resolved as inherent items, their traits don't need to be in scope
-    C::a(&S); //~ ERROR method `a` is private
+    C::a(&S); //~ ERROR associated function `a` is private
     C::b(&S); // OK
     C::c(&S); // OK
 }
diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr
index 2c0591c95f6..4b40c6405c4 100644
--- a/src/test/ui/traits/trait-item-privacy.stderr
+++ b/src/test/ui/traits/trait-item-privacy.stderr
@@ -36,7 +36,7 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
 LL | use method::B;
    |
 
-error[E0624]: method `a` is private
+error[E0624]: associated function `a` is private
   --> $DIR/trait-item-privacy.rs:72:7
    |
 LL |     c.a();
@@ -73,7 +73,7 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
 LL | use method::B;
    |
 
-error[E0624]: method `a` is private
+error[E0624]: associated function `a` is private
   --> $DIR/trait-item-privacy.rs:84:5
    |
 LL |     C::a(&S);
diff --git a/src/test/ui/traits/trait-method-private.stderr b/src/test/ui/traits/trait-method-private.stderr
index 10552acb348..035c1ea092b 100644
--- a/src/test/ui/traits/trait-method-private.stderr
+++ b/src/test/ui/traits/trait-method-private.stderr
@@ -1,4 +1,4 @@
-error[E0624]: method `method` is private
+error[E0624]: associated function `method` is private
   --> $DIR/trait-method-private.rs:19:9
    |
 LL |     foo.method();
diff --git a/src/test/ui/traits/trait-safety-inherent-impl.stderr b/src/test/ui/traits/trait-safety-inherent-impl.stderr
index c398785d394..0738d2973e2 100644
--- a/src/test/ui/traits/trait-safety-inherent-impl.stderr
+++ b/src/test/ui/traits/trait-safety-inherent-impl.stderr
@@ -1,14 +1,10 @@
 error[E0197]: inherent impls cannot be unsafe
-  --> $DIR/trait-safety-inherent-impl.rs:5:1
+  --> $DIR/trait-safety-inherent-impl.rs:5:13
    |
-LL |   unsafe impl SomeStruct {
-   |   ^-----
-   |   |
-   |  _unsafe because of this
+LL | unsafe impl SomeStruct {
+   | ------      ^^^^^^^^^^ inherent impl for this type
    | |
-LL | |     fn foo(self) { }
-LL | | }
-   | |_^
+   | unsafe because of this
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
index 63182a6bd95..a83ff370151 100644
--- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
+++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr
@@ -1,8 +1,10 @@
 error[E0568]: auto traits cannot have super traits
-  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:7:1
+  --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:7:19
    |
 LL | auto trait Magic: Copy {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -----  ^^^^ help: remove the super traits
+   |            |
+   |            auto trait cannot have super traits
 
 error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied
   --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:23
diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr
index c72876e050f..4e781318329 100644
--- a/src/test/ui/transmute/main.stderr
+++ b/src/test/ui/transmute/main.stderr
@@ -4,8 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     transmute(x)
    |     ^^^^^^^^^
    |
-   = note: source type: `<C as TypeConstructor<'a>>::T` (size can vary because of <C as TypeConstructor>::T)
-   = note: target type: `<C as TypeConstructor<'b>>::T` (size can vary because of <C as TypeConstructor>::T)
+   = note: `<C as TypeConstructor>::T` does not have a fixed size
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/main.rs:20:17
diff --git a/src/test/ui/type-inference/or_else-multiple-type-params.stderr b/src/test/ui/type-inference/or_else-multiple-type-params.stderr
index b9258b20f5a..24122e65867 100644
--- a/src/test/ui/type-inference/or_else-multiple-type-params.stderr
+++ b/src/test/ui/type-inference/or_else-multiple-type-params.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |         .or_else(|err| {
    |          ^^^^^^^
    |          |
-   |          cannot infer type for type parameter `F` declared on the method `or_else`
+   |          cannot infer type for type parameter `F` declared on the associated function `or_else`
    |          help: consider specifying the type arguments in the method call: `or_else::<F, O>`
 
 error: aborting due to previous error
diff --git a/src/test/ui/type-inference/sort_by_key.stderr b/src/test/ui/type-inference/sort_by_key.stderr
index e74c0dfa5e2..bb108adcd64 100644
--- a/src/test/ui/type-inference/sort_by_key.stderr
+++ b/src/test/ui/type-inference/sort_by_key.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     lst.sort_by_key(|&(v, _)| v.iter().sum());
    |         ^^^^^^^^^^^                    --- help: consider specifying the type argument in the method call: `sum::<S>`
    |         |
-   |         cannot infer type for type parameter `K` declared on the method `sort_by_key`
+   |         cannot infer type for type parameter `K` declared on the associated function `sort_by_key`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
index 8755bcded9d..e3976293277 100644
--- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
+++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
@@ -1,8 +1,10 @@
 error[E0568]: auto traits cannot have super traits
-  --> $DIR/typeck-auto-trait-no-supertraits-2.rs:3:1
+  --> $DIR/typeck-auto-trait-no-supertraits-2.rs:3:20
    |
 LL | auto trait Magic : Sized where Option<Self> : Magic {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -----   ^^^^^ help: remove the super traits
+   |            |
+   |            auto trait cannot have super traits
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
index 5a388834909..b1602e3642e 100644
--- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
+++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
@@ -1,8 +1,10 @@
 error[E0568]: auto traits cannot have super traits
-  --> $DIR/typeck-auto-trait-no-supertraits.rs:27:1
+  --> $DIR/typeck-auto-trait-no-supertraits.rs:27:19
    |
 LL | auto trait Magic: Copy {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            -----  ^^^^ help: remove the super traits
+   |            |
+   |            auto trait cannot have super traits
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
index f2d02f70f4a..dc86ab30dfe 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
@@ -70,7 +70,7 @@ LL | static TEST3: _ = "test";
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `&'static str`
+   |               help: replace `_` with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:15:15
@@ -232,7 +232,7 @@ LL |     static FN_TEST3: _ = "test";
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `&'static str`
+   |                      help: replace `_` with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:88:22
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs
index e8c767b13e9..e6470aa6d64 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.rs
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs
@@ -49,8 +49,8 @@ fn main() {
     <u8 as Tr::Y>::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::Y`
     <u8 as E::Y>::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module
 
-    let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
+    let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found associated function `Dr::Z`
     <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
-    let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
+    let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found associated function `Dr::Z`
     <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `u16`
 }
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
index e5e6ed9fac9..7177ca49085 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
@@ -35,10 +35,10 @@ error[E0576]: cannot find method or associated constant `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:22:17
    |
 LL |     fn Y() {}
-   |     --------- similarly named method `Y` defined here
+   |     --------- similarly named associated function `Y` defined here
 ...
 LL |     <u8 as Tr>::N;
-   |                 ^ help: a method with a similar name exists: `Y`
+   |                 ^ help: an associated function with a similar name exists: `Y`
 
 error[E0576]: cannot find method or associated constant `N` in enum `E`
   --> $DIR/ufcs-partially-resolved.rs:23:16
@@ -166,7 +166,7 @@ error[E0576]: cannot find method or associated constant `NN` in `Tr::Y`
 LL |     <u8 as Tr::Y>::NN;
    |                    ^^ not found in `Tr::Y`
 
-error[E0575]: expected associated type, found method `Dr::Z`
+error[E0575]: expected associated type, found associated function `Dr::Z`
   --> $DIR/ufcs-partially-resolved.rs:52:12
    |
 LL |     type X = u16;
@@ -181,16 +181,16 @@ error[E0575]: expected method or associated constant, found associated type `Dr:
   --> $DIR/ufcs-partially-resolved.rs:53:5
    |
 LL |     fn Z() {}
-   |     --------- similarly named method `Z` defined here
+   |     --------- similarly named associated function `Z` defined here
 ...
 LL |     <u8 as Dr>::X;
    |     ^^^^^^^^^^^^-
    |                 |
-   |                 help: a method with a similar name exists: `Z`
+   |                 help: an associated function with a similar name exists: `Z`
    |
    = note: can't use a type alias as a constructor
 
-error[E0575]: expected associated type, found method `Dr::Z`
+error[E0575]: expected associated type, found associated function `Dr::Z`
   --> $DIR/ufcs-partially-resolved.rs:54:12
    |
 LL |     type X = u16;
diff --git a/src/test/ui/unsafe/unsafe-block-without-braces.stderr b/src/test/ui/unsafe/unsafe-block-without-braces.stderr
index 13e0c3681fa..895f33638f9 100644
--- a/src/test/ui/unsafe/unsafe-block-without-braces.stderr
+++ b/src/test/ui/unsafe/unsafe-block-without-braces.stderr
@@ -1,10 +1,11 @@
 error: expected `{`, found `std`
   --> $DIR/unsafe-block-without-braces.rs:3:9
    |
-LL |     unsafe //{
-   |           - expected `{`
 LL |         std::mem::transmute::<f32, u32>(1.0);
-   |         ^^^ unexpected token
+   |         ^^^----------------------------------
+   |         |
+   |         expected `{`
+   |         help: try placing this code inside a block: `{ std::mem::transmute::<f32, u32>(1.0); }`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/xc-private-method.rs b/src/test/ui/xc-private-method.rs
index e95cab93d75..f05994646b3 100644
--- a/src/test/ui/xc-private-method.rs
+++ b/src/test/ui/xc-private-method.rs
@@ -4,8 +4,8 @@ extern crate xc_private_method_lib;
 
 fn main() {
     let _ = xc_private_method_lib::Struct::static_meth_struct();
-    //~^ ERROR: method `static_meth_struct` is private
+    //~^ ERROR: associated function `static_meth_struct` is private
 
     let _ = xc_private_method_lib::Enum::static_meth_enum();
-    //~^ ERROR: method `static_meth_enum` is private
+    //~^ ERROR: associated function `static_meth_enum` is private
 }
diff --git a/src/test/ui/xc-private-method.stderr b/src/test/ui/xc-private-method.stderr
index 91bec2551c1..6a68bef90ef 100644
--- a/src/test/ui/xc-private-method.stderr
+++ b/src/test/ui/xc-private-method.stderr
@@ -1,10 +1,10 @@
-error[E0624]: method `static_meth_struct` is private
+error[E0624]: associated function `static_meth_struct` is private
   --> $DIR/xc-private-method.rs:6:13
    |
 LL |     let _ = xc_private_method_lib::Struct::static_meth_struct();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0624]: method `static_meth_enum` is private
+error[E0624]: associated function `static_meth_enum` is private
   --> $DIR/xc-private-method.rs:9:13
    |
 LL |     let _ = xc_private_method_lib::Enum::static_meth_enum();
diff --git a/src/test/ui/xc-private-method2.rs b/src/test/ui/xc-private-method2.rs
index f11b251082b..92946923f6e 100644
--- a/src/test/ui/xc-private-method2.rs
+++ b/src/test/ui/xc-private-method2.rs
@@ -4,8 +4,8 @@ extern crate xc_private_method_lib;
 
 fn main() {
     let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();
-    //~^ ERROR method `meth_struct` is private
+    //~^ ERROR associated function `meth_struct` is private
 
     let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum();
-    //~^ ERROR method `meth_enum` is private
+    //~^ ERROR associated function `meth_enum` is private
 }
diff --git a/src/test/ui/xc-private-method2.stderr b/src/test/ui/xc-private-method2.stderr
index 36ad850fb19..84a8b9817c0 100644
--- a/src/test/ui/xc-private-method2.stderr
+++ b/src/test/ui/xc-private-method2.stderr
@@ -1,10 +1,10 @@
-error[E0624]: method `meth_struct` is private
+error[E0624]: associated function `meth_struct` is private
   --> $DIR/xc-private-method2.rs:6:52
    |
 LL |     let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();
    |                                                    ^^^^^^^^^^^
 
-error[E0624]: method `meth_enum` is private
+error[E0624]: associated function `meth_enum` is private
   --> $DIR/xc-private-method2.rs:9:55
    |
 LL |     let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum();
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject bda50510d1daf6e9c53ad6ccf603da6e0fa8103
+Subproject 7019b3ed3d539db7429d10a343b69be8c426b57
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject 329923edec41d0ddbea7f30ab12fca0436d459a
+Subproject 23549a8c362a403026432f65a6cb398cb10d44b
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 424bac88c85..b04012af515 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2779,7 +2779,7 @@ impl<'test> TestCx<'test> {
                 Command::new(&nodejs)
                     .arg(root.join("src/tools/rustdoc-js/tester.js"))
                     .arg(out_dir.parent().expect("no parent"))
-                    .arg(&self.testpaths.file.file_stem().expect("couldn't get file stem")),
+                    .arg(self.testpaths.file.with_extension("js")),
             );
             if !res.status.success() {
                 self.fatal_proc_rec("rustdoc-js test failed!", &res);
@@ -3204,7 +3204,9 @@ impl<'test> TestCx<'test> {
         let json = cflags.contains("--error-format json")
             || cflags.contains("--error-format pretty-json")
             || cflags.contains("--error-format=json")
-            || cflags.contains("--error-format=pretty-json");
+            || cflags.contains("--error-format=pretty-json")
+            || cflags.contains("--output-format json")
+            || cflags.contains("--output-format=json");
 
         let mut normalized = output.to_string();
 
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 974c8be95ec17cd986251d7700cd432a3957693
+Subproject 0ff05c4cfe534321b194bf3bedf028df92ef519
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 5fbb986286a..b389cd0373c 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -1,11 +1,10 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-# This script publishes the new "current" toolstate in the toolstate repo (not to be
-# confused with publishing the test results, which happens in
-# `src/ci/docker/x86_64-gnu-tools/checktools.sh`).
-# It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts
-# when a new commit lands on `master` (i.e., after it passed all checks on `auto`).
+# This script computes the new "current" toolstate for the toolstate repo (not to be
+# confused with publishing the test results, which happens in `src/bootstrap/toolstate.rs`).
+# It gets called from `src/ci/publish_toolstate.sh` when a new commit lands on `master`
+# (i.e., after it passed all checks on `auto`).
 
 from __future__ import print_function
 
diff --git a/src/tools/rustdoc-js-std/tester.js b/src/tools/rustdoc-js-std/tester.js
index d5f0ab9f429..08930ff1227 100644
--- a/src/tools/rustdoc-js-std/tester.js
+++ b/src/tools/rustdoc-js-std/tester.js
@@ -1,6 +1,5 @@
 const fs = require('fs');
-
-const TEST_FOLDER = 'src/test/rustdoc-js-std/';
+const path = require('path');
 
 function getNextStep(content, pos, stop) {
     while (pos < content.length && content[pos] !== stop &&
@@ -246,17 +245,16 @@ function readFileMatching(dir, name, extension) {
 }
 
 function main(argv) {
-    if (argv.length !== 3) {
-        console.error("Expected toolchain to check as argument (for example \
-                       'x86_64-apple-darwin')");
+    if (argv.length !== 4) {
+        console.error("USAGE: node tester.js STD_DOCS TEST_FOLDER");
         return 1;
     }
-    var toolchain = argv[2];
+    var std_docs = argv[2];
+    var test_folder = argv[3];
 
-    var mainJs = readFileMatching("build/" + toolchain + "/doc/", "main", ".js");
-    var ALIASES = readFileMatching("build/" + toolchain + "/doc/", "aliases", ".js");
-    var searchIndex = readFileMatching("build/" + toolchain + "/doc/",
-                                       "search-index", ".js").split("\n");
+    var mainJs = readFileMatching(std_docs, "main", ".js");
+    var ALIASES = readFileMatching(std_docs, "aliases", ".js");
+    var searchIndex = readFileMatching(std_docs, "search-index", ".js").split("\n");
     if (searchIndex[searchIndex.length - 1].length === 0) {
         searchIndex.pop();
     }
@@ -265,7 +263,7 @@ function main(argv) {
     finalJS = "";
 
     var arraysToLoad = ["itemTypes"];
-    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS",
+    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER",
                            "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA",
                            "TY_PRIMITIVE", "TY_KEYWORD",
                            "levenshtein_row2"];
@@ -287,8 +285,8 @@ function main(argv) {
 
     var errors = 0;
 
-    fs.readdirSync(TEST_FOLDER).forEach(function(file) {
-        var loadedFile = loadContent(readFile(TEST_FOLDER + file) +
+    fs.readdirSync(test_folder).forEach(function(file) {
+        var loadedFile = loadContent(readFile(path.join(test_folder, file)) +
                                'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
         const expected = loadedFile.EXPECTED;
         const query = loadedFile.QUERY;
@@ -338,7 +336,7 @@ function main(argv) {
             console.log("OK");
         }
     });
-    return errors;
+    return errors > 0 ? 1 : 0;
 }
 
 process.exit(main(process.argv));
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 833ce5d1370..143e1a7480d 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -1,8 +1,7 @@
 const fs = require('fs');
+const path = require('path');
 const { spawnSync } = require('child_process');
 
-const TEST_FOLDER = 'src/test/rustdoc-js/';
-
 function getNextStep(content, pos, stop) {
     while (pos < content.length && content[pos] !== stop &&
            (content[pos] === ' ' || content[pos] === '\t' || content[pos] === '\n')) {
@@ -232,7 +231,7 @@ function load_files(out_folder, crate) {
     finalJS = "";
 
     var arraysToLoad = ["itemTypes"];
-    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS",
+    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER",
                            "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA",
                            "TY_PRIMITIVE", "TY_KEYWORD",
                            "levenshtein_row2"];
@@ -266,10 +265,11 @@ function main(argv) {
     var errors = 0;
 
     for (var j = 3; j < argv.length; ++j) {
-        const test_name = argv[j];
+        const test_file = argv[j];
+        const test_name = path.basename(test_file, ".js");
 
         process.stdout.write('Checking "' + test_name + '" ... ');
-        if (!fs.existsSync(TEST_FOLDER + test_name + ".js")) {
+        if (!fs.existsSync(test_file)) {
             errors += 1;
             console.error("FAILED");
             console.error("==> Missing '" + test_name + ".js' file...");
@@ -279,7 +279,7 @@ function main(argv) {
         const test_out_folder = out_folder + test_name;
 
         var [loaded, index] = load_files(test_out_folder, test_name);
-        var loadedFile = loadContent(readFile(TEST_FOLDER + test_name + ".js") +
+        var loadedFile = loadContent(readFile(test_file) +
                                'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
         const expected = loadedFile.EXPECTED;
         const query = loadedFile.QUERY;
@@ -328,7 +328,7 @@ function main(argv) {
             console.log("OK");
         }
     }
-    return errors;
+    return errors > 0 ? 1 : 0;
 }
 
 process.exit(main(process.argv));
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index 43cae31f33f..f984e5b61a5 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -5,8 +5,7 @@ authors = ["Alex Crichton <alex@alexcrichton.com>"]
 edition = "2018"
 
 [dependencies]
+cargo_metadata = "0.9.1"
 regex = "1"
-serde = { version = "1.0.8", features = ["derive"] }
-serde_json = "1.0.2"
 lazy_static = "1"
 walkdir = "2"
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 7a20a96130c..1ffc415fb24 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -1,13 +1,11 @@
-//! Checks the licenses of third-party dependencies by inspecting vendors.
+//! Checks the licenses of third-party dependencies.
 
-use std::collections::{BTreeSet, HashMap, HashSet};
-use std::fs;
+use cargo_metadata::{Metadata, Package, PackageId, Resolve};
+use std::collections::{BTreeSet, HashSet};
 use std::path::Path;
-use std::process::Command;
-
-use serde::Deserialize;
-use serde_json;
 
+/// These are licenses that are allowed for all crates, including the runtime,
+/// rustc, tools, etc.
 const LICENSES: &[&str] = &[
     "MIT/Apache-2.0",
     "MIT / Apache-2.0",
@@ -25,261 +23,268 @@ const LICENSES: &[&str] = &[
 /// should be considered bugs. Exceptions are only allowed in Rust
 /// tooling. It is _crucial_ that no exception crates be dependencies
 /// of the Rust runtime (std/test).
-const EXCEPTIONS: &[&str] = &[
-    "mdbook",             // MPL2, mdbook
-    "openssl",            // BSD+advertising clause, cargo, mdbook
-    "pest",               // MPL2, mdbook via handlebars
-    "arrayref",           // BSD-2-Clause, mdbook via handlebars via pest
-    "thread-id",          // Apache-2.0, mdbook
-    "toml-query",         // MPL-2.0, mdbook
-    "is-match",           // MPL-2.0, mdbook
-    "cssparser",          // MPL-2.0, rustdoc
-    "smallvec",           // MPL-2.0, rustdoc
-    "rdrand",             // ISC, mdbook, rustfmt
-    "fuchsia-cprng",      // BSD-3-Clause, mdbook, rustfmt
-    "fuchsia-zircon-sys", // BSD-3-Clause, rustdoc, rustc, cargo
-    "fuchsia-zircon",     // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir)
-    "cssparser-macros",   // MPL-2.0, rustdoc
-    "selectors",          // MPL-2.0, rustdoc
-    "clippy_lints",       // MPL-2.0, rls
-    "colored",            // MPL-2.0, rustfmt
-    "ordslice",           // Apache-2.0, rls
-    "cloudabi",           // BSD-2-Clause, (rls -> crossbeam-channel 0.2 -> rand 0.5)
-    "ryu",                // Apache-2.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
-    "utf8parse",          // Apache-2.0 OR MIT, cargo via strip-ansi-escapes
-    "vte",                // Apache-2.0 OR MIT, cargo via strip-ansi-escapes
-    "sized-chunks",       // MPL-2.0+, cargo via im-rc
-    "bitmaps",            // MPL-2.0+, cargo via im-rc
+const EXCEPTIONS: &[(&str, &str)] = &[
+    ("mdbook", "MPL-2.0"),                  // mdbook
+    ("openssl", "Apache-2.0"),              // cargo, mdbook
+    ("arrayref", "BSD-2-Clause"),           // mdbook via handlebars via pest
+    ("toml-query", "MPL-2.0"),              // mdbook
+    ("toml-query_derive", "MPL-2.0"),       // mdbook
+    ("is-match", "MPL-2.0"),                // mdbook
+    ("rdrand", "ISC"),                      // mdbook, rustfmt
+    ("fuchsia-cprng", "BSD-3-Clause"),      // mdbook, rustfmt
+    ("fuchsia-zircon-sys", "BSD-3-Clause"), // rustdoc, rustc, cargo
+    ("fuchsia-zircon", "BSD-3-Clause"),     // rustdoc, rustc, cargo (jobserver & tempdir)
+    ("colored", "MPL-2.0"),                 // rustfmt
+    ("ordslice", "Apache-2.0"),             // rls
+    ("cloudabi", "BSD-2-Clause"),           // (rls -> crossbeam-channel 0.2 -> rand 0.5)
+    ("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
     // FIXME: this dependency violates the documentation comment above:
-    "fortanix-sgx-abi",   // MPL-2.0+, libstd but only for `sgx` target
-    "dunce",              // CC0-1.0 mdbook-linkcheck
-    "codespan-reporting", // Apache-2.0 mdbook-linkcheck
-    "codespan",           // Apache-2.0 mdbook-linkcheck
-    "crossbeam-channel",  // MIT/Apache-2.0 AND BSD-2-Clause, cargo
+    ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target
+    ("dunce", "CC0-1.0"),            // mdbook-linkcheck
+    ("codespan-reporting", "Apache-2.0"), // mdbook-linkcheck
+    ("codespan", "Apache-2.0"),      // mdbook-linkcheck
+    ("crossbeam-channel", "MIT/Apache-2.0 AND BSD-2-Clause"), // cargo
 ];
 
+/// These are the root crates that are part of the runtime. The licenses for
+/// these and all their dependencies *must not* be in the exception list.
+const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
+
 /// Which crates to check against the whitelist?
-const WHITELIST_CRATES: &[CrateVersion<'_>] =
-    &[CrateVersion("rustc", "0.0.0"), CrateVersion("rustc_codegen_llvm", "0.0.0")];
+const WHITELIST_CRATES: &[&str] = &["rustc", "rustc_codegen_llvm"];
 
 /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible.
-const WHITELIST: &[Crate<'_>] = &[
-    Crate("adler32"),
-    Crate("aho-corasick"),
-    Crate("annotate-snippets"),
-    Crate("ansi_term"),
-    Crate("arrayvec"),
-    Crate("atty"),
-    Crate("autocfg"),
-    Crate("backtrace"),
-    Crate("backtrace-sys"),
-    Crate("bitflags"),
-    Crate("build_const"),
-    Crate("byteorder"),
-    Crate("c2-chacha"),
-    Crate("cc"),
-    Crate("cfg-if"),
-    Crate("chalk-engine"),
-    Crate("chalk-macros"),
-    Crate("cloudabi"),
-    Crate("cmake"),
-    Crate("compiler_builtins"),
-    Crate("crc"),
-    Crate("crc32fast"),
-    Crate("crossbeam-deque"),
-    Crate("crossbeam-epoch"),
-    Crate("crossbeam-queue"),
-    Crate("crossbeam-utils"),
-    Crate("datafrog"),
-    Crate("dlmalloc"),
-    Crate("either"),
-    Crate("ena"),
-    Crate("env_logger"),
-    Crate("filetime"),
-    Crate("flate2"),
-    Crate("fortanix-sgx-abi"),
-    Crate("fuchsia-zircon"),
-    Crate("fuchsia-zircon-sys"),
-    Crate("getopts"),
-    Crate("getrandom"),
-    Crate("hashbrown"),
-    Crate("humantime"),
-    Crate("indexmap"),
-    Crate("itertools"),
-    Crate("jobserver"),
-    Crate("kernel32-sys"),
-    Crate("lazy_static"),
-    Crate("libc"),
-    Crate("libz-sys"),
-    Crate("lock_api"),
-    Crate("log"),
-    Crate("log_settings"),
-    Crate("measureme"),
-    Crate("memchr"),
-    Crate("memmap"),
-    Crate("memoffset"),
-    Crate("miniz-sys"),
-    Crate("miniz_oxide"),
-    Crate("miniz_oxide_c_api"),
-    Crate("nodrop"),
-    Crate("num_cpus"),
-    Crate("owning_ref"),
-    Crate("parking_lot"),
-    Crate("parking_lot_core"),
-    Crate("pkg-config"),
-    Crate("polonius-engine"),
-    Crate("ppv-lite86"),
-    Crate("proc-macro2"),
-    Crate("punycode"),
-    Crate("quick-error"),
-    Crate("quote"),
-    Crate("rand"),
-    Crate("rand_chacha"),
-    Crate("rand_core"),
-    Crate("rand_hc"),
-    Crate("rand_isaac"),
-    Crate("rand_pcg"),
-    Crate("rand_xorshift"),
-    Crate("redox_syscall"),
-    Crate("redox_termios"),
-    Crate("regex"),
-    Crate("regex-syntax"),
-    Crate("remove_dir_all"),
-    Crate("rustc-demangle"),
-    Crate("rustc-hash"),
-    Crate("rustc-rayon"),
-    Crate("rustc-rayon-core"),
-    Crate("rustc_version"),
-    Crate("scoped-tls"),
-    Crate("scopeguard"),
-    Crate("semver"),
-    Crate("semver-parser"),
-    Crate("serde"),
-    Crate("serde_derive"),
-    Crate("smallvec"),
-    Crate("stable_deref_trait"),
-    Crate("syn"),
-    Crate("synstructure"),
-    Crate("tempfile"),
-    Crate("termcolor"),
-    Crate("terminon"),
-    Crate("termion"),
-    Crate("termize"),
-    Crate("thread_local"),
-    Crate("ucd-util"),
-    Crate("unicode-normalization"),
-    Crate("unicode-script"),
-    Crate("unicode-security"),
-    Crate("unicode-width"),
-    Crate("unicode-xid"),
-    Crate("unreachable"),
-    Crate("utf8-ranges"),
-    Crate("vcpkg"),
-    Crate("version_check"),
-    Crate("void"),
-    Crate("wasi"),
-    Crate("winapi"),
-    Crate("winapi-build"),
-    Crate("winapi-i686-pc-windows-gnu"),
-    Crate("winapi-util"),
-    Crate("winapi-x86_64-pc-windows-gnu"),
-    Crate("wincolor"),
-    Crate("hermit-abi"),
+///
+/// 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 WHITELIST: &[&str] = &[
+    "adler32",
+    "aho-corasick",
+    "annotate-snippets",
+    "ansi_term",
+    "arrayvec",
+    "atty",
+    "autocfg",
+    "backtrace",
+    "backtrace-sys",
+    "bitflags",
+    "byteorder",
+    "c2-chacha",
+    "cc",
+    "cfg-if",
+    "cloudabi",
+    "cmake",
+    "compiler_builtins",
+    "crc32fast",
+    "crossbeam-deque",
+    "crossbeam-epoch",
+    "crossbeam-queue",
+    "crossbeam-utils",
+    "datafrog",
+    "dlmalloc",
+    "either",
+    "ena",
+    "env_logger",
+    "filetime",
+    "flate2",
+    "fortanix-sgx-abi",
+    "fuchsia-zircon",
+    "fuchsia-zircon-sys",
+    "getopts",
+    "getrandom",
+    "hashbrown",
+    "hermit-abi",
+    "humantime",
+    "indexmap",
+    "itertools",
+    "jobserver",
+    "kernel32-sys",
+    "lazy_static",
+    "libc",
+    "libz-sys",
+    "lock_api",
+    "log",
+    "log_settings",
+    "measureme",
+    "memchr",
+    "memmap",
+    "memoffset",
+    "miniz_oxide",
+    "nodrop",
+    "num_cpus",
+    "parking_lot",
+    "parking_lot_core",
+    "pkg-config",
+    "polonius-engine",
+    "ppv-lite86",
+    "proc-macro2",
+    "punycode",
+    "quick-error",
+    "quote",
+    "rand",
+    "rand_chacha",
+    "rand_core",
+    "rand_hc",
+    "rand_isaac",
+    "rand_pcg",
+    "rand_xorshift",
+    "redox_syscall",
+    "redox_termios",
+    "regex",
+    "regex-syntax",
+    "remove_dir_all",
+    "rustc-demangle",
+    "rustc-hash",
+    "rustc-rayon",
+    "rustc-rayon-core",
+    "rustc_version",
+    "scoped-tls",
+    "scopeguard",
+    "semver",
+    "semver-parser",
+    "serde",
+    "serde_derive",
+    "smallvec",
+    "stable_deref_trait",
+    "syn",
+    "synstructure",
+    "tempfile",
+    "termcolor",
+    "termion",
+    "termize",
+    "thread_local",
+    "ucd-util",
+    "unicode-normalization",
+    "unicode-script",
+    "unicode-security",
+    "unicode-width",
+    "unicode-xid",
+    "utf8-ranges",
+    "vcpkg",
+    "version_check",
+    "wasi",
+    "winapi",
+    "winapi-build",
+    "winapi-i686-pc-windows-gnu",
+    "winapi-util",
+    "winapi-x86_64-pc-windows-gnu",
+    "wincolor",
 ];
 
-// Some types for Serde to deserialize the output of `cargo metadata` to.
-
-#[derive(Deserialize)]
-struct Output {
-    resolve: Resolve,
-}
-
-#[derive(Deserialize)]
-struct Resolve {
-    nodes: Vec<ResolveNode>,
-}
-
-#[derive(Deserialize)]
-struct ResolveNode {
-    id: String,
-    dependencies: Vec<String>,
-}
-
-/// A unique identifier for a crate.
-#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
-struct Crate<'a>(&'a str); // (name)
-
-#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
-struct CrateVersion<'a>(&'a str, &'a str); // (name, version)
-
-impl Crate<'_> {
-    pub fn id_str(&self) -> String {
-        format!("{} ", self.0)
-    }
-}
-
-impl<'a> CrateVersion<'a> {
-    /// Returns the struct and whether or not the dependency is in-tree.
-    pub fn from_str(s: &'a str) -> (Self, bool) {
-        let mut parts = s.split(' ');
-        let name = parts.next().unwrap();
-        let version = parts.next().unwrap();
-        let path = parts.next().unwrap();
-
-        let is_path_dep = path.starts_with("(path+");
-
-        (CrateVersion(name, version), is_path_dep)
-    }
-
-    pub fn id_str(&self) -> String {
-        format!("{} {}", self.0, self.1)
-    }
+/// Dependency checks.
+///
+/// `path` is path to the `src` directory, `cargo` is path to the cargo executable.
+pub fn check(path: &Path, cargo: &Path, bad: &mut bool) {
+    let mut cmd = cargo_metadata::MetadataCommand::new();
+    cmd.cargo_path(cargo)
+        .manifest_path(path.parent().unwrap().join("Cargo.toml"))
+        .features(cargo_metadata::CargoOpt::AllFeatures);
+    let metadata = t!(cmd.exec());
+    check_exceptions(&metadata, bad);
+    check_whitelist(&metadata, bad);
+    check_crate_duplicate(&metadata, bad);
 }
 
-impl<'a> From<CrateVersion<'a>> for Crate<'a> {
-    fn from(cv: CrateVersion<'a>) -> Crate<'a> {
-        Crate(cv.0)
+/// Check that all licenses are in the valid list in `LICENSES`.
+///
+/// Packages listed in `EXCEPTIONS` are allowed for tools.
+fn check_exceptions(metadata: &Metadata, bad: &mut bool) {
+    // Validate the EXCEPTIONS list hasn't changed.
+    for (name, license) in EXCEPTIONS {
+        // Check that the package actually exists.
+        if !metadata.packages.iter().any(|p| p.name == *name) {
+            println!(
+                "could not find exception package `{}`\n\
+                Remove from EXCEPTIONS list if it is no longer used.",
+                name
+            );
+            *bad = true;
+        }
+        // Check that the license hasn't changed.
+        for pkg in metadata.packages.iter().filter(|p| p.name == *name) {
+            if pkg.name == "fuchsia-cprng" {
+                // This package doesn't declare a license expression. Manual
+                // inspection of the license file is necessary, which appears
+                // to be BSD-3-Clause.
+                assert!(pkg.license.is_none());
+                continue;
+            }
+            match &pkg.license {
+                None => {
+                    println!(
+                        "dependency exception `{}` does not declare a license expression",
+                        pkg.id
+                    );
+                    *bad = true;
+                }
+                Some(pkg_license) => {
+                    if pkg_license.as_str() != *license {
+                        println!("dependency exception `{}` license has changed", name);
+                        println!("    previously `{}` now `{}`", license, pkg_license);
+                        println!("    update EXCEPTIONS for the new license");
+                        *bad = true;
+                    }
+                }
+            }
+        }
     }
-}
 
-/// Checks the dependency at the given path. Changes `bad` to `true` if a check failed.
-///
-/// Specifically, this checks that the license is correct.
-pub fn check(path: &Path, bad: &mut bool) {
-    // Check licences.
-    let path = path.join("../vendor");
-    assert!(path.exists(), "vendor directory missing");
-    let mut saw_dir = false;
-    for dir in t!(path.read_dir()) {
-        saw_dir = true;
-        let dir = t!(dir);
+    let exception_names: Vec<_> = EXCEPTIONS.iter().map(|(name, _license)| *name).collect();
+    let runtime_ids = compute_runtime_crates(metadata);
 
-        // Skip our exceptions.
-        let is_exception = EXCEPTIONS.iter().any(|exception| {
-            dir.path().to_str().unwrap().contains(&format!("vendor/{}", exception))
-        });
-        if is_exception {
+    // Check if any package does not have a valid license.
+    for pkg in &metadata.packages {
+        if pkg.source.is_none() {
+            // No need to check local packages.
             continue;
         }
-
-        let toml = dir.path().join("Cargo.toml");
-        *bad = !check_license(&toml) || *bad;
+        if !runtime_ids.contains(&pkg.id) && exception_names.contains(&pkg.name.as_str()) {
+            continue;
+        }
+        let license = match &pkg.license {
+            Some(license) => license,
+            None => {
+                println!("dependency `{}` does not define a license expression", pkg.id,);
+                *bad = true;
+                continue;
+            }
+        };
+        if !LICENSES.contains(&license.as_str()) {
+            if pkg.name == "fortanix-sgx-abi" {
+                // This is a specific exception because SGX is considered
+                // "third party". See
+                // https://github.com/rust-lang/rust/issues/62620 for more. In
+                // general, these should never be added.
+                continue;
+            }
+            println!("invalid license `{}` in `{}`", license, pkg.id);
+            *bad = true;
+        }
     }
-    assert!(saw_dir, "no vendored source");
 }
 
 /// Checks the dependency of `WHITELIST_CRATES` at the given path. Changes `bad` to `true` if a
 /// check failed.
 ///
 /// Specifically, this checks that the dependencies are on the `WHITELIST`.
-pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) {
-    // Get dependencies from Cargo metadata.
-    let resolve = get_deps(path, cargo);
-
+fn check_whitelist(metadata: &Metadata, bad: &mut bool) {
+    // Check that the WHITELIST does not have unused entries.
+    for name in WHITELIST {
+        if !metadata.packages.iter().any(|p| p.name == *name) {
+            println!(
+                "could not find whitelisted package `{}`\n\
+                Remove from WHITELIST list if it is no longer used.",
+                name
+            );
+            *bad = true;
+        }
+    }
     // Get the whitelist in a convenient form.
     let whitelist: HashSet<_> = WHITELIST.iter().cloned().collect();
 
@@ -287,122 +292,59 @@ pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) {
     let mut visited = BTreeSet::new();
     let mut unapproved = BTreeSet::new();
     for &krate in WHITELIST_CRATES.iter() {
-        let mut bad = check_crate_whitelist(&whitelist, &resolve, &mut visited, krate, false);
+        let pkg = pkg_from_name(metadata, krate);
+        let mut bad = check_crate_whitelist(&whitelist, metadata, &mut visited, pkg);
         unapproved.append(&mut bad);
     }
 
     if !unapproved.is_empty() {
         println!("Dependencies not on the whitelist:");
         for dep in unapproved {
-            println!("* {}", dep.id_str());
+            println!("* {}", dep);
         }
         *bad = true;
     }
-
-    check_crate_duplicate(&resolve, bad);
-}
-
-fn check_license(path: &Path) -> bool {
-    if !path.exists() {
-        panic!("{} does not exist", path.display());
-    }
-    let contents = t!(fs::read_to_string(&path));
-
-    let mut found_license = false;
-    for line in contents.lines() {
-        if !line.starts_with("license") {
-            continue;
-        }
-        let license = extract_license(line);
-        if !LICENSES.contains(&&*license) {
-            println!("invalid license {} in {}", license, path.display());
-            return false;
-        }
-        found_license = true;
-        break;
-    }
-    if !found_license {
-        println!("no license in {}", path.display());
-        return false;
-    }
-
-    true
-}
-
-fn extract_license(line: &str) -> String {
-    let first_quote = line.find('"');
-    let last_quote = line.rfind('"');
-    if let (Some(f), Some(l)) = (first_quote, last_quote) {
-        let license = &line[f + 1..l];
-        license.into()
-    } else {
-        "bad-license-parse".into()
-    }
-}
-
-/// Gets the dependencies of the crate at the given path using `cargo metadata`.
-fn get_deps(path: &Path, cargo: &Path) -> Resolve {
-    // Run `cargo metadata` to get the set of dependencies.
-    let output = Command::new(cargo)
-        .arg("metadata")
-        .arg("--format-version")
-        .arg("1")
-        .arg("--manifest-path")
-        .arg(path.join("../Cargo.toml"))
-        .output()
-        .expect("Unable to run `cargo metadata`")
-        .stdout;
-    let output = String::from_utf8_lossy(&output);
-    let output: Output = serde_json::from_str(&output).unwrap();
-
-    output.resolve
 }
 
 /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
 /// the whitelist. Returns a list of illegal dependencies.
 fn check_crate_whitelist<'a>(
-    whitelist: &'a HashSet<Crate<'_>>,
-    resolve: &'a Resolve,
-    visited: &mut BTreeSet<CrateVersion<'a>>,
-    krate: CrateVersion<'a>,
-    must_be_on_whitelist: bool,
-) -> BTreeSet<Crate<'a>> {
+    whitelist: &'a HashSet<&'static str>,
+    metadata: &'a Metadata,
+    visited: &mut BTreeSet<&'a PackageId>,
+    krate: &'a Package,
+) -> BTreeSet<&'a PackageId> {
     // This will contain bad deps.
     let mut unapproved = BTreeSet::new();
 
     // Check if we have already visited this crate.
-    if visited.contains(&krate) {
+    if visited.contains(&krate.id) {
         return unapproved;
     }
 
-    visited.insert(krate);
+    visited.insert(&krate.id);
 
     // If this path is in-tree, we don't require it to be on the whitelist.
-    if must_be_on_whitelist {
+    if krate.source.is_some() {
         // If this dependency is not on `WHITELIST`, add to bad set.
-        if !whitelist.contains(&krate.into()) {
-            unapproved.insert(krate.into());
+        if !whitelist.contains(krate.name.as_str()) {
+            unapproved.insert(&krate.id);
         }
     }
 
-    // Do a DFS in the crate graph (it's a DAG, so we know we have no cycles!).
-    let to_check = resolve
-        .nodes
-        .iter()
-        .find(|n| n.id.starts_with(&krate.id_str()))
-        .expect("crate does not exist");
+    // Do a DFS in the crate graph.
+    let to_check = deps_of(metadata, &krate.id);
 
-    for dep in to_check.dependencies.iter() {
-        let (krate, is_path_dep) = CrateVersion::from_str(dep);
-
-        let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate, !is_path_dep);
+    for dep in to_check {
+        let mut bad = check_crate_whitelist(whitelist, metadata, visited, dep);
         unapproved.append(&mut bad);
     }
 
     unapproved
 }
 
-fn check_crate_duplicate(resolve: &Resolve, bad: &mut bool) {
+/// Prevents multiple versions of some expensive crates.
+fn check_crate_duplicate(metadata: &Metadata, bad: &mut bool) {
     const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[
         // These two crates take quite a long time to build, so don't allow two versions of them
         // to accidentally sneak into our dependency graph, in order to ensure we keep our CI times
@@ -410,19 +352,97 @@ fn check_crate_duplicate(resolve: &Resolve, bad: &mut bool) {
         "cargo",
         "rustc-ap-syntax",
     ];
-    let mut name_to_id: HashMap<_, Vec<_>> = HashMap::new();
-    for node in resolve.nodes.iter() {
-        name_to_id.entry(node.id.split_whitespace().next().unwrap()).or_default().push(&node.id);
-    }
 
-    for name in FORBIDDEN_TO_HAVE_DUPLICATES {
-        if name_to_id[name].len() <= 1 {
-            continue;
-        }
-        println!("crate `{}` is duplicated in `Cargo.lock`", name);
-        for id in name_to_id[name].iter() {
-            println!("  * {}", id);
+    for &name in FORBIDDEN_TO_HAVE_DUPLICATES {
+        let matches: Vec<_> = metadata.packages.iter().filter(|pkg| pkg.name == name).collect();
+        match matches.len() {
+            0 => {
+                println!(
+                    "crate `{}` is missing, update `check_crate_duplicate` \
+                    if it is no longer used",
+                    name
+                );
+                *bad = true;
+            }
+            1 => {}
+            _ => {
+                println!(
+                    "crate `{}` is duplicated in `Cargo.lock`, \
+                    it is too expensive to build multiple times, \
+                    so make sure only one version appears across all dependencies",
+                    name
+                );
+                for pkg in matches {
+                    println!("  * {}", pkg.id);
+                }
+                *bad = true;
+            }
         }
-        *bad = true;
+    }
+}
+
+/// Returns a list of dependencies for the given package.
+fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> {
+    let resolve = metadata.resolve.as_ref().unwrap();
+    let node = resolve
+        .nodes
+        .iter()
+        .find(|n| &n.id == pkg_id)
+        .unwrap_or_else(|| panic!("could not find `{}` in resolve", pkg_id));
+    node.deps
+        .iter()
+        .map(|dep| {
+            metadata.packages.iter().find(|pkg| pkg.id == dep.pkg).unwrap_or_else(|| {
+                panic!("could not find dep `{}` for pkg `{}` in resolve", dep.pkg, pkg_id)
+            })
+        })
+        .collect()
+}
+
+/// Finds a package with the given name.
+fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package {
+    let mut i = metadata.packages.iter().filter(|p| p.name == name);
+    let result =
+        i.next().unwrap_or_else(|| panic!("could not find package `{}` in package list", name));
+    assert!(i.next().is_none(), "more than one package found for `{}`", name);
+    result
+}
+
+/// Finds all the packages that are in the rust runtime.
+fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> {
+    let resolve = metadata.resolve.as_ref().unwrap();
+    let mut result = HashSet::new();
+    for name in RUNTIME_CRATES {
+        let id = &pkg_from_name(metadata, name).id;
+        normal_deps_of_r(resolve, id, &mut result);
+    }
+    result
+}
+
+/// Recursively find all normal dependencies.
+fn normal_deps_of_r<'a>(
+    resolve: &'a Resolve,
+    pkg_id: &'a PackageId,
+    result: &mut HashSet<&'a PackageId>,
+) {
+    if !result.insert(pkg_id) {
+        return;
+    }
+    let node = resolve
+        .nodes
+        .iter()
+        .find(|n| &n.id == pkg_id)
+        .unwrap_or_else(|| panic!("could not find `{}` in resolve", pkg_id));
+    // Don't care about dev-dependencies.
+    // Build dependencies *shouldn't* matter unless they do some kind of
+    // codegen. For now we'll assume they don't.
+    let deps = node.deps.iter().filter(|node_dep| {
+        node_dep
+            .dep_kinds
+            .iter()
+            .any(|kind_info| kind_info.kind == cargo_metadata::DependencyKind::Normal)
+    });
+    for dep in deps {
+        normal_deps_of_r(resolve, &dep.pkg, result);
     }
 }
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index ec8b14c288a..e2856c69055 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -1,8 +1,8 @@
 //! Tidy checks source code in this repository.
 //!
 //! This program runs all of the various tidy checks for style, cleanliness,
-//! etc. This is run by default on `make check` and as part of the auto
-//! builders.
+//! etc. This is run by default on `./x.py test` and as part of the auto
+//! builders. The tidy checks can be executed with `./x.py test tidy`.
 
 #![deny(warnings)]
 
@@ -30,10 +30,7 @@ fn main() {
     pal::check(&path, &mut bad);
     unstable_book::check(&path, collected, &mut bad);
     unit_tests::check(&path, &mut bad);
-    if !args.iter().any(|s| *s == "--no-vendor") {
-        deps::check(&path, &mut bad);
-    }
-    deps::check_whitelist(&path, &cargo, &mut bad);
+    deps::check(&path, &cargo, &mut bad);
     extdeps::check(&path, &mut bad);
     ui_tests::check(&path, &mut bad);
     error_codes_check::check(&path, &mut bad);
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index 349829d8725..247e85603cf 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -59,6 +59,8 @@ const EXCEPTION_PATHS: &[&str] = &[
     "src/libstd/sys_common/mod.rs",
     "src/libstd/sys_common/net.rs",
     "src/libstd/sys_common/backtrace.rs",
+    // panic_unwind shims
+    "src/libstd/panicking.rs",
     "src/libterm", // Not sure how to make this crate portable, but test crate needs it.
     "src/libtest", // Probably should defer to unstable `std::sys` APIs.
     "src/libstd/sync/mpsc", // some tests are only run on non-emscripten
diff --git a/triagebot.toml b/triagebot.toml
index a174dd1e7f3..ec327715833 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -11,23 +11,25 @@ allow-unauthenticated = [
 [assign]
 
 [ping.icebreakers-llvm]
+alias = ["llvm", "llvms"]
 message = """\
 Hey LLVM ICE-breakers! This bug has been identified as a good
 "LLVM ICE-breaking candidate". In case it's useful, here are some
 [instructions] for tackling these sorts of bugs. Maybe take a look?
 Thanks! <3
 
-[instructions]: https://rust-lang.github.io/rustc-guide/ice-breaker/llvm.html
+[instructions]: https://rustc-dev-guide.rust-lang.org/ice-breaker/llvm.html
 """
 label = "ICEBreaker-LLVM"
 
 [ping.icebreakers-cleanup-crew]
+alias = ["cleanup", "cleanups", "shrink", "reduce", "bisect"]
 message = """\
 Hey Cleanup Crew ICE-breakers! This bug has been identified as a good
 "Cleanup ICE-breaking candidate". In case it's useful, here are some
 [instructions] for tackling these sorts of bugs. Maybe take a look?
 Thanks! <3
 
-[instructions]: https://rust-lang.github.io/rustc-guide/ice-breaker/cleanup-crew.html
+[instructions]: https://rustc-dev-guide.rust-lang.org/ice-breaker/cleanup-crew.html
 """
 label = "ICEBreaker-Cleanup-Crew"