about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock181
-rw-r--r--RELEASES.md149
-rw-r--r--appveyor.yml9
-rw-r--r--config.toml.example3
-rw-r--r--src/bootstrap/Cargo.toml4
-rw-r--r--src/bootstrap/bin/rustc.rs32
-rw-r--r--src/bootstrap/builder.rs23
-rw-r--r--src/bootstrap/compile.rs12
-rw-r--r--src/bootstrap/config.rs3
-rwxr-xr-xsrc/bootstrap/configure.py2
-rw-r--r--src/bootstrap/dist.rs13
-rw-r--r--src/bootstrap/doc.rs8
-rw-r--r--src/bootstrap/lib.rs4
-rw-r--r--src/bootstrap/sanity.rs5
-rw-r--r--src/bootstrap/test.rs5
-rw-r--r--src/ci/docker/arm-android/Dockerfile2
-rw-r--r--src/ci/docker/dist-various-1/Dockerfile2
-rwxr-xr-xsrc/ci/docker/dist-various-2/build-wasi-toolchain.sh2
-rw-r--r--src/ci/docker/dist-x86_64-musl/Dockerfile8
-rw-r--r--src/ci/docker/scripts/android-sdk.sh16
-rwxr-xr-xsrc/ci/docker/scripts/freebsd-toolchain.sh6
m---------src/doc/embedded-book0
-rw-r--r--src/doc/man/rustc.16
m---------src/doc/nomicon0
m---------src/doc/reference0
-rw-r--r--src/doc/robots.txt8
-rw-r--r--src/doc/rustc/src/command-line-arguments.md7
-rw-r--r--src/doc/unstable-book/book.toml1
-rw-r--r--src/doc/unstable-book/src/library-features/borrow-state.md7
-rw-r--r--src/doc/unstable-book/src/library-features/fnbox.md32
-rw-r--r--src/liballoc/Cargo.toml2
-rw-r--r--src/liballoc/benches/btree/set.rs114
-rw-r--r--src/liballoc/boxed.rs56
-rw-r--r--src/liballoc/collections/binary_heap.rs4
-rw-r--r--src/liballoc/collections/btree/map.rs4
-rw-r--r--src/liballoc/collections/btree/set.rs302
-rw-r--r--src/liballoc/collections/linked_list.rs4
-rw-r--r--src/liballoc/collections/vec_deque.rs4
-rw-r--r--src/liballoc/lib.rs6
-rw-r--r--src/liballoc/prelude/mod.rs1
-rw-r--r--src/liballoc/raw_vec.rs4
-rw-r--r--src/liballoc/tests/btree/set.rs61
-rw-r--r--src/libarena/Cargo.toml1
-rw-r--r--src/libarena/lib.rs157
-rw-r--r--src/libcore/benches/ascii.rs2
-rw-r--r--src/libcore/benches/iter.rs10
-rw-r--r--src/libcore/borrow.rs4
-rw-r--r--src/libcore/cell.rs38
-rw-r--r--src/libcore/cmp.rs6
-rw-r--r--src/libcore/convert.rs30
-rw-r--r--src/libcore/fmt/builders.rs90
-rw-r--r--src/libcore/future/future.rs18
-rw-r--r--src/libcore/hint.rs27
-rw-r--r--src/libcore/intrinsics.rs10
-rw-r--r--src/libcore/iter/range.rs61
-rw-r--r--src/libcore/iter/traits/iterator.rs112
-rw-r--r--src/libcore/mem.rs34
-rw-r--r--src/libcore/ops/arith.rs43
-rw-r--r--src/libcore/ops/range.rs22
-rw-r--r--src/libcore/slice/mod.rs147
-rw-r--r--src/libcore/slice/sort.rs89
-rw-r--r--src/libcore/str/mod.rs2
-rw-r--r--src/libcore/sync/atomic.rs27
-rw-r--r--src/libcore/task/mod.rs2
-rw-r--r--src/libcore/task/wake.rs153
-rw-r--r--src/libcore/tests/fmt/builders.rs52
-rw-r--r--src/libcore/tests/iter.rs61
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/libcore/tests/slice.rs118
-rw-r--r--src/libfmt_macros/lib.rs1
-rw-r--r--src/libpanic_unwind/lib.rs2
-rw-r--r--src/libproc_macro/bridge/rpc.rs36
-rw-r--r--src/libproc_macro/lib.rs4
-rw-r--r--src/librustc/Cargo.toml1
-rw-r--r--src/librustc/arena.rs206
-rw-r--r--src/librustc/dep_graph/dep_node.rs211
-rw-r--r--src/librustc/hir/def_id.rs3
-rw-r--r--src/librustc/hir/intravisit.rs6
-rw-r--r--src/librustc/hir/lowering.rs661
-rw-r--r--src/librustc/hir/mod.rs12
-rw-r--r--src/librustc/hir/print.rs6
-rw-r--r--src/librustc/ich/hcx.rs8
-rw-r--r--src/librustc/infer/error_reporting/mod.rs52
-rw-r--r--src/librustc/infer/opaque_types/mod.rs80
-rw-r--r--src/librustc/lib.rs4
-rw-r--r--src/librustc/lint/builtin.rs153
-rw-r--r--src/librustc/lint/context.rs113
-rw-r--r--src/librustc/lint/internal.rs109
-rw-r--r--src/librustc/lint/mod.rs31
-rw-r--r--src/librustc/middle/resolve_lifetime.rs2
-rw-r--r--src/librustc/mir/interpret/error.rs34
-rw-r--r--src/librustc/mir/interpret/mod.rs4
-rw-r--r--src/librustc/mir/mod.rs112
-rw-r--r--src/librustc/mir/tcx.rs119
-rw-r--r--src/librustc/mir/visit.rs18
-rw-r--r--src/librustc/query/mod.rs922
-rw-r--r--src/librustc/session/code_stats.rs8
-rw-r--r--src/librustc/session/config.rs38
-rw-r--r--src/librustc/session/mod.rs30
-rw-r--r--src/librustc/traits/mod.rs8
-rw-r--r--src/librustc/traits/specialize/mod.rs5
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs13
-rw-r--r--src/librustc/traits/structural_impls.rs2
-rw-r--r--src/librustc/ty/codec.rs56
-rw-r--r--src/librustc/ty/context.rs42
-rw-r--r--src/librustc/ty/layout.rs4
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc/ty/query/config.rs848
-rw-r--r--src/librustc/ty/query/mod.rs736
-rw-r--r--src/librustc/ty/query/plumbing.rs311
-rw-r--r--src/librustc/ty/structural_impls.rs2
-rw-r--r--src/librustc/ty/trait_def.rs2
-rw-r--r--src/librustc/util/common.rs9
-rw-r--r--src/librustc/util/profiling.rs440
-rw-r--r--src/librustc_allocator/lib.rs1
-rw-r--r--src/librustc_asan/Cargo.toml2
-rw-r--r--src/librustc_borrowck/lib.rs1
-rw-r--r--src/librustc_codegen_llvm/abi.rs3
-rw-r--r--src/librustc_codegen_llvm/attributes.rs2
-rw-r--r--src/librustc_codegen_llvm/back/link.rs6
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs10
-rw-r--r--src/librustc_codegen_llvm/back/write.rs89
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs124
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs11
-rw-r--r--src/librustc_codegen_llvm/debuginfo/type_names.rs62
-rw-r--r--src/librustc_codegen_llvm/lib.rs5
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs5
-rw-r--r--src/librustc_codegen_llvm/type_of.rs34
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs2
-rw-r--r--src/librustc_codegen_ssa/back/write.rs44
-rw-r--r--src/librustc_codegen_ssa/base.rs11
-rw-r--r--src/librustc_codegen_ssa/lib.rs1
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs6
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs15
-rw-r--r--src/librustc_codegen_ssa/mir/place.rs20
-rw-r--r--src/librustc_codegen_ssa/mir/statement.rs12
-rw-r--r--src/librustc_codegen_utils/lib.rs1
-rw-r--r--src/librustc_data_structures/Cargo.toml2
-rw-r--r--src/librustc_data_structures/graph/dominators/mod.rs47
-rw-r--r--src/librustc_data_structures/jobserver.rs128
-rw-r--r--src/librustc_driver/lib.rs5
-rw-r--r--src/librustc_errors/lib.rs1
-rw-r--r--src/librustc_incremental/lib.rs1
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs26
-rw-r--r--src/librustc_interface/interface.rs5
-rw-r--r--src/librustc_interface/lib.rs1
-rw-r--r--src/librustc_interface/passes.rs14
-rw-r--r--src/librustc_interface/util.rs4
-rw-r--r--src/librustc_lint/builtin.rs401
-rw-r--r--src/librustc_lint/lib.rs29
-rw-r--r--src/librustc_lint/nonstandard_style.rs41
-rw-r--r--src/librustc_lint/types.rs67
-rw-r--r--src/librustc_lint/unused.rs78
-rw-r--r--src/librustc_lsan/Cargo.toml2
-rw-r--r--src/librustc_macros/src/query.rs22
-rw-r--r--src/librustc_metadata/creader.rs2
-rw-r--r--src/librustc_metadata/lib.rs1
-rw-r--r--src/librustc_mir/borrow_check/borrow_set.rs2
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs106
-rw-r--r--src/librustc_mir/borrow_check/flows.rs2
-rw-r--r--src/librustc_mir/borrow_check/mod.rs238
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs12
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs20
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/facts.rs12
-rw-r--r--src/librustc_mir/borrow_check/nll/invalidation.rs41
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs130
-rw-r--r--src/librustc_mir/borrow_check/place_ext.rs2
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs4
-rw-r--r--src/librustc_mir/borrow_check/prefixes.rs2
-rw-r--r--src/librustc_mir/build/block.rs2
-rw-r--r--src/librustc_mir/build/expr/as_place.rs2
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs10
-rw-r--r--src/librustc_mir/build/expr/stmt.rs6
-rw-r--r--src/librustc_mir/build/matches/mod.rs12
-rw-r--r--src/librustc_mir/build/matches/test.rs3
-rw-r--r--src/librustc_mir/build/misc.rs2
-rw-r--r--src/librustc_mir/const_eval.rs27
-rw-r--r--src/librustc_mir/dataflow/drop_flag_effects.rs4
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs11
-rw-r--r--src/librustc_mir/dataflow/mod.rs7
-rw-r--r--src/librustc_mir/dataflow/move_paths/abs_domain.rs7
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs12
-rw-r--r--src/librustc_mir/dataflow/move_paths/mod.rs79
-rw-r--r--src/librustc_mir/diagnostics.rs4
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs4
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs12
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs4
-rw-r--r--src/librustc_mir/interpret/cast.rs4
-rw-r--r--src/librustc_mir/interpret/eval_context.rs120
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs8
-rw-r--r--src/librustc_mir/interpret/memory.rs8
-rw-r--r--src/librustc_mir/interpret/operand.rs51
-rw-r--r--src/librustc_mir/interpret/place.rs134
-rw-r--r--src/librustc_mir/interpret/snapshot.rs19
-rw-r--r--src/librustc_mir/interpret/terminator.rs51
-rw-r--r--src/librustc_mir/interpret/traits.rs14
-rw-r--r--src/librustc_mir/interpret/validity.rs12
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/librustc_mir/lints.rs4
-rw-r--r--src/librustc_mir/monomorphize/collector.rs3
-rw-r--r--src/librustc_mir/transform/add_moves_for_packed_drops.rs2
-rw-r--r--src/librustc_mir/transform/add_retag.rs8
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs6
-rw-r--r--src/librustc_mir/transform/const_prop.rs10
-rw-r--r--src/librustc_mir/transform/generator.rs2
-rw-r--r--src/librustc_mir/transform/inline.rs5
-rw-r--r--src/librustc_mir/transform/instcombine.rs8
-rw-r--r--src/librustc_mir/transform/lower_128bit.rs8
-rw-r--r--src/librustc_mir/transform/mod.rs5
-rw-r--r--src/librustc_mir/transform/promote_consts.rs18
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs99
-rw-r--r--src/librustc_mir/transform/uniform_array_move_out.rs4
-rw-r--r--src/librustc_mir/util/alignment.rs4
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs6
-rw-r--r--src/librustc_msan/Cargo.toml2
-rw-r--r--src/librustc_passes/lib.rs1
-rw-r--r--src/librustc_privacy/lib.rs1
-rw-r--r--src/librustc_resolve/error_reporting.rs313
-rw-r--r--src/librustc_resolve/lib.rs167
-rw-r--r--src/librustc_resolve/resolve_imports.rs61
-rw-r--r--src/librustc_save_analysis/lib.rs25
-rw-r--r--src/librustc_target/abi/mod.rs12
-rw-r--r--src/librustc_target/lib.rs1
-rw-r--r--src/librustc_target/spec/wasm32_base.rs9
-rw-r--r--src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs9
-rw-r--r--src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs3
-rw-r--r--src/librustc_traits/lib.rs1
-rw-r--r--src/librustc_tsan/Cargo.toml2
-rw-r--r--src/librustc_typeck/astconv.rs40
-rw-r--r--src/librustc_typeck/check/_match.rs1
-rw-r--r--src/librustc_typeck/check/method/probe.rs46
-rw-r--r--src/librustc_typeck/check/method/suggest.rs64
-rw-r--r--src/librustc_typeck/check/op.rs76
-rw-r--r--src/librustc_typeck/check/wfcheck.rs4
-rw-r--r--src/librustc_typeck/collect.rs6
-rw-r--r--src/librustc_typeck/lib.rs8
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/clean/auto_trait.rs2
-rw-r--r--src/librustdoc/clean/blanket_impl.rs2
-rw-r--r--src/librustdoc/clean/inline.rs10
-rw-r--r--src/librustdoc/clean/mod.rs6
-rw-r--r--src/librustdoc/html/layout.rs4
-rw-r--r--src/librustdoc/html/render.rs121
-rw-r--r--src/librustdoc/html/static/main.js10
-rw-r--r--src/librustdoc/html/static/rustdoc.css14
-rw-r--r--src/librustdoc/html/static/source-script.js34
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs10
-rw-r--r--src/libserialize/serialize.rs3
-rw-r--r--src/libstd/Cargo.toml3
-rw-r--r--src/libstd/collections/hash/set.rs6
-rw-r--r--src/libstd/f32.rs10
-rw-r--r--src/libstd/f64.rs10
-rw-r--r--src/libstd/ffi/os_str.rs1
-rw-r--r--src/libstd/fs.rs39
-rw-r--r--src/libstd/future.rs61
-rw-r--r--src/libstd/io/stdio.rs51
-rw-r--r--src/libstd/keyword_docs.rs55
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/macros.rs6
-rw-r--r--src/libstd/num.rs2
-rw-r--r--src/libstd/panic.rs6
-rw-r--r--src/libstd/path.rs4
-rw-r--r--src/libstd/process.rs16
-rw-r--r--src/libstd/sys/cloudabi/shims/fs.rs10
-rw-r--r--src/libstd/sys/cloudabi/shims/pipe.rs10
-rw-r--r--src/libstd/sys/cloudabi/thread.rs3
-rw-r--r--src/libstd/sys/redox/fs.rs50
-rw-r--r--src/libstd/sys/redox/pipe.rs10
-rw-r--r--src/libstd/sys/redox/thread.rs3
-rw-r--r--src/libstd/sys/sgx/abi/mod.rs6
-rw-r--r--src/libstd/sys/sgx/abi/reloc.rs2
-rw-r--r--src/libstd/sys/sgx/abi/tls.rs10
-rw-r--r--src/libstd/sys/sgx/abi/usercalls/alloc.rs8
-rw-r--r--src/libstd/sys/sgx/abi/usercalls/mod.rs4
-rw-r--r--src/libstd/sys/sgx/abi/usercalls/raw.rs29
-rw-r--r--src/libstd/sys/sgx/alloc.rs14
-rw-r--r--src/libstd/sys/sgx/condvar.rs5
-rw-r--r--src/libstd/sys/sgx/fs.rs10
-rw-r--r--src/libstd/sys/sgx/mod.rs11
-rw-r--r--src/libstd/sys/sgx/pipe.rs15
-rw-r--r--src/libstd/sys/sgx/rwlock.rs44
-rw-r--r--src/libstd/sys/sgx/stdio.rs18
-rw-r--r--src/libstd/sys/sgx/thread.rs22
-rw-r--r--src/libstd/sys/sgx/waitqueue.rs18
-rw-r--r--src/libstd/sys/unix/fs.rs33
-rw-r--r--src/libstd/sys/unix/pipe.rs10
-rw-r--r--src/libstd/sys/unix/stdio.rs30
-rw-r--r--src/libstd/sys/unix/thread.rs3
-rw-r--r--src/libstd/sys/unix/time.rs27
-rw-r--r--src/libstd/sys/wasi/args.rs50
-rw-r--r--src/libstd/sys/wasi/ext/ffi.rs57
-rw-r--r--src/libstd/sys/wasi/ext/fs.rs412
-rw-r--r--src/libstd/sys/wasi/ext/io.rs142
-rw-r--r--src/libstd/sys/wasi/ext/mod.rs8
-rw-r--r--src/libstd/sys/wasi/fd.rs34
-rw-r--r--src/libstd/sys/wasi/fs.rs681
-rw-r--r--src/libstd/sys/wasi/net.rs202
-rw-r--r--src/libstd/sys/wasi/os.rs17
-rw-r--r--src/libstd/sys/wasi/pipe.rs10
-rw-r--r--src/libstd/sys/wasi/process.rs4
-rw-r--r--src/libstd/sys/wasi/stdio.rs35
-rw-r--r--src/libstd/sys/wasi/thread.rs3
-rw-r--r--src/libstd/sys/wasi/time.rs4
-rw-r--r--src/libstd/sys/wasm/fs.rs10
-rw-r--r--src/libstd/sys/wasm/pipe.rs10
-rw-r--r--src/libstd/sys/wasm/thread.rs3
-rw-r--r--src/libstd/sys/windows/fs.rs10
-rw-r--r--src/libstd/sys/windows/handle.rs14
-rw-r--r--src/libstd/sys/windows/pipe.rs10
-rw-r--r--src/libstd/sys/windows/thread.rs3
-rw-r--r--src/libstd/sys/windows/time.rs24
-rw-r--r--src/libstd/sys_common/at_exit_imp.rs5
-rw-r--r--src/libstd/sys_common/fs.rs41
-rw-r--r--src/libstd/sys_common/mod.rs10
-rw-r--r--src/libstd/sys_common/os_str_bytes.rs2
-rw-r--r--src/libstd/sys_common/thread.rs3
-rw-r--r--src/libstd/sys_common/wtf8.rs4
-rw-r--r--src/libstd/thread/mod.rs5
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/diagnostics/metadata.rs4
-rw-r--r--src/libsyntax/early_buffered_lints.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs16
-rw-r--r--src/libsyntax/feature_gate.rs67
-rw-r--r--src/libsyntax/json.rs24
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/parse/lexer/mod.rs32
-rw-r--r--src/libsyntax/parse/parser.rs44
-rw-r--r--src/libsyntax/print/pprust.rs14
-rw-r--r--src/libsyntax/source_map.rs16
-rw-r--r--src/libsyntax_ext/format.rs4
-rw-r--r--src/libsyntax_ext/lib.rs1
-rw-r--r--src/libsyntax_ext/proc_macro_server.rs6
-rw-r--r--src/libsyntax_pos/hygiene.rs3
-rw-r--r--src/libsyntax_pos/lib.rs14
-rw-r--r--src/libsyntax_pos/span_encoding.rs186
-rw-r--r--src/libsyntax_pos/symbol.rs6
-rw-r--r--src/libterm/Cargo.toml10
-rw-r--r--src/libterm/lib.rs201
-rw-r--r--src/libterm/terminfo/mod.rs265
-rw-r--r--src/libterm/terminfo/parm.rs669
-rw-r--r--src/libterm/terminfo/parser/compiled.rs346
-rw-r--r--src/libterm/terminfo/searcher.rs84
-rw-r--r--src/libterm/win.rs203
-rw-r--r--src/libtest/Cargo.toml3
-rw-r--r--src/libtest/README.md13
-rw-r--r--src/libtest/formatters/json.rs208
-rw-r--r--src/libtest/formatters/mod.rs22
-rw-r--r--src/libtest/formatters/pretty.rs232
-rw-r--r--src/libtest/formatters/terse.rs235
-rw-r--r--src/libtest/lib.rs2228
-rw-r--r--src/libtest/stats.rs922
-rw-r--r--src/libunwind/Cargo.toml9
-rw-r--r--src/libunwind/build.rs67
m---------src/llvm-project0
-rw-r--r--src/rustllvm/ArchiveWrapper.cpp28
-rw-r--r--src/rustllvm/PassWrapper.cpp11
-rw-r--r--src/rustllvm/RustWrapper.cpp31
m---------src/stdsimd0
-rw-r--r--src/test/codegen/fn-impl-trait-self.rs15
-rw-r--r--src/test/codegen/noreturn-uninhabited.rs32
-rw-r--r--src/test/compile-fail/must_use-in-stdlib-traits.rs4
-rw-r--r--src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs10
-rw-r--r--src/test/incremental/callee_caller_cross_crate/b.rs4
-rw-r--r--src/test/incremental/change_add_field/struct_point.rs14
-rw-r--r--src/test/incremental/change_crate_order/main.rs2
-rw-r--r--src/test/incremental/change_private_fn/struct_point.rs10
-rw-r--r--src/test/incremental/change_private_fn_cc/struct_point.rs10
-rw-r--r--src/test/incremental/change_private_impl_method/struct_point.rs10
-rw-r--r--src/test/incremental/change_private_impl_method_cc/struct_point.rs10
-rw-r--r--src/test/incremental/change_pub_inherent_method_body/struct_point.rs10
-rw-r--r--src/test/incremental/change_pub_inherent_method_sig/struct_point.rs10
-rw-r--r--src/test/incremental/dirty_clean.rs8
-rw-r--r--src/test/incremental/hashes/call_expressions.rs10
-rw-r--r--src/test/incremental/hashes/closure_expressions.rs8
-rw-r--r--src/test/incremental/hashes/enum_constructors.rs24
-rw-r--r--src/test/incremental/hashes/for_loops.rs4
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs20
-rw-r--r--src/test/incremental/hashes/if_expressions.rs10
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs60
-rw-r--r--src/test/incremental/hashes/let_expressions.rs18
-rw-r--r--src/test/incremental/hashes/loop_expressions.rs8
-rw-r--r--src/test/incremental/hashes/match_expressions.rs18
-rw-r--r--src/test/incremental/hashes/struct_constructors.rs14
-rw-r--r--src/test/incremental/hashes/unary_and_binary_exprs.rs4
-rw-r--r--src/test/incremental/hashes/while_let_loops.rs6
-rw-r--r--src/test/incremental/hashes/while_loops.rs2
-rw-r--r--src/test/incremental/hello_world.rs4
-rw-r--r--src/test/incremental/ich_method_call_trait_scope.rs4
-rw-r--r--src/test/incremental/rlib_cross_crate/b.rs8
-rw-r--r--src/test/incremental/string_constant.rs4
-rw-r--r--src/test/incremental/struct_add_field.rs6
-rw-r--r--src/test/incremental/struct_change_field_name.rs6
-rw-r--r--src/test/incremental/struct_change_field_type.rs6
-rw-r--r--src/test/incremental/struct_change_field_type_cross_crate/b.rs6
-rw-r--r--src/test/incremental/struct_change_nothing.rs6
-rw-r--r--src/test/incremental/struct_remove_field.rs6
-rw-r--r--src/test/incremental/type_alias_cross_crate/b.rs8
-rw-r--r--src/test/mir-opt/match_false_edges.rs4
-rw-r--r--src/test/run-make-fulldeps/lto-dylib-dep/Makefile10
-rw-r--r--src/test/run-make-fulldeps/lto-dylib-dep/a_dylib.rs4
-rw-r--r--src/test/run-make-fulldeps/lto-dylib-dep/main.rs6
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-lto/Makefile6
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile11
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs1
-rw-r--r--src/test/run-make-fulldeps/pgo-gen/Makefile6
-rw-r--r--src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py4
-rw-r--r--src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs19
-rw-r--r--src/test/run-pass/array-slice-vec/vec-macro-no-std.rs2
-rw-r--r--src/test/run-pass/async-await.rs40
-rw-r--r--src/test/run-pass/auxiliary/arc_wake.rs40
-rw-r--r--src/test/run-pass/extern/extern-prelude-core.rs2
-rw-r--r--src/test/run-pass/extern/extern-prelude-core.stderr2
-rw-r--r--src/test/run-pass/for-loop-while/for-loop-no-std.rs2
-rw-r--r--src/test/run-pass/format-no-std.rs2
-rw-r--r--src/test/run-pass/futures-api.rs26
-rw-r--r--src/test/run-pass/issue-59020.rs27
-rw-r--r--src/test/run-pass/issues/issue-58463.rs8
-rw-r--r--src/test/run-pass/structs-enums/unit-like-struct-drop-run.rs3
-rw-r--r--src/test/run-pass/traits/auxiliary/trait_alias.rs13
-rw-r--r--src/test/run-pass/traits/trait-alias-import-cross-crate.rs14
-rw-r--r--src/test/run-pass/traits/trait-alias-import.rs38
-rw-r--r--src/test/run-pass/unsized-locals/box-fnonce.rs8
-rw-r--r--src/test/run-pass/unsized-locals/fnbox-compat.rs12
-rw-r--r--src/test/rustdoc-js/search-short-types.js8
-rw-r--r--src/test/rustdoc-js/search-short-types.rs68
-rw-r--r--src/test/rustdoc-js/substring.js8
-rw-r--r--src/test/rustdoc-js/substring.rs21
-rw-r--r--src/test/rustdoc/auxiliary/intra-links-external-traits.rs6
-rw-r--r--src/test/rustdoc/intra-links-external-traits.rs12
-rw-r--r--src/test/rustdoc/useless_lifetime_bound.rs13
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-for-crate.rs18
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs12
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs12
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-tool-test.rs12
-rw-r--r--src/test/ui-fulldeps/gated-plugin.stderr3
-rw-r--r--src/test/ui-fulldeps/hash-stable-is-unstable.stderr15
-rw-r--r--src/test/ui-fulldeps/internal-lints/default_hash_types.rs22
-rw-r--r--src/test/ui-fulldeps/internal-lints/default_hash_types.stderr39
-rw-r--r--src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs49
-rw-r--r--src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr196
-rw-r--r--src/test/ui/allocator-submodule.rs2
-rw-r--r--src/test/ui/allocator-submodule.stderr2
-rw-r--r--src/test/ui/associated-item/associated-item-enum.rs20
-rw-r--r--src/test/ui/associated-item/associated-item-enum.stderr36
-rw-r--r--src/test/ui/async-fn-multiple-lifetimes.rs5
-rw-r--r--src/test/ui/async-fn-multiple-lifetimes.stderr34
-rw-r--r--src/test/ui/auto-ref-slice-plus-ref.stderr2
-rw-r--r--src/test/ui/auxiliary/issue-59764.rs18
-rw-r--r--src/test/ui/block-result/issue-3563.stderr2
-rw-r--r--src/test/ui/bogus-tag.stderr6
-rw-r--r--src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr2
-rw-r--r--src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr36
-rw-r--r--src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr22
-rw-r--r--src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr36
-rw-r--r--src/test/ui/borrowck/two-phase-nonrecv-autoref.rs16
-rw-r--r--src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.ast.stderr36
-rw-r--r--src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr40
-rw-r--r--src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr40
-rw-r--r--src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr35
-rw-r--r--src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr35
-rw-r--r--src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs66
-rw-r--r--src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.stderr14
-rw-r--r--src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.rs43
-rw-r--r--src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr40
-rw-r--r--src/test/ui/cast/cast-ptr-to-int-const.stderr6
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr3
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr3
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr3
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr3
-rw-r--r--src/test/ui/consts/const-deref-ptr.stderr3
-rw-r--r--src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr3
-rw-r--r--src/test/ui/consts/const-eval/feature-gate-const_panic.stderr9
-rw-r--r--src/test/ui/consts/const-eval/match-test-ptr-null.rs4
-rw-r--r--src/test/ui/consts/const-eval/match-test-ptr-null.stderr7
-rw-r--r--src/test/ui/consts/const_arg_local.rs13
-rw-r--r--src/test/ui/consts/const_arg_local.stderr8
-rw-r--r--src/test/ui/consts/const_arg_promotable.rs12
-rw-r--r--src/test/ui/consts/const_arg_promotable.stderr8
-rw-r--r--src/test/ui/consts/const_arg_wrapper.rs12
-rw-r--r--src/test/ui/consts/const_arg_wrapper.stderr8
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr12
-rw-r--r--src/test/ui/consts/projection_qualif.stderr3
-rw-r--r--src/test/ui/custom_attribute.stderr9
-rw-r--r--src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr4
-rw-r--r--src/test/ui/dep-graph/dep-graph-caller-callee.rs4
-rw-r--r--src/test/ui/dep-graph/dep-graph-caller-callee.stderr10
-rw-r--r--src/test/ui/dep-graph/dep-graph-struct-signature.rs30
-rw-r--r--src/test/ui/dep-graph/dep-graph-struct-signature.stderr70
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs4
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr10
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs4
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr12
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl.rs10
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl.stderr22
-rw-r--r--src/test/ui/dep-graph/dep-graph-type-alias.rs10
-rw-r--r--src/test/ui/dep-graph/dep-graph-type-alias.stderr20
-rw-r--r--src/test/ui/dep-graph/dep-graph-variance-alias.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-variance-alias.stderr4
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.rs6
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.stderr20
-rw-r--r--src/test/ui/error-codes/E0254.rs1
-rw-r--r--src/test/ui/error-codes/E0254.stderr2
-rw-r--r--src/test/ui/error-codes/E0259.rs2
-rw-r--r--src/test/ui/error-codes/E0260.rs1
-rw-r--r--src/test/ui/error-codes/E0260.stderr2
-rw-r--r--src/test/ui/error-codes/E0395.rs4
-rw-r--r--src/test/ui/error-codes/E0395.stderr3
-rw-r--r--src/test/ui/error-codes/E0396.stderr3
-rw-r--r--src/test/ui/error-codes/E0658.stderr3
-rw-r--r--src/test/ui/explore-issue-38412.stderr21
-rw-r--r--src/test/ui/feature-gate-optimize_attribute.rs10
-rw-r--r--src/test/ui/feature-gate-optimize_attribute.stderr15
-rw-r--r--src/test/ui/feature-gate/feature-gate-c_variadic.stderr3
-rw-r--r--src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi.stderr126
-rw-r--r--src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-allow_fail.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr9
-rw-r--r--src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr9
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm2.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-assoc-type-defaults.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await.stderr9
-rw-r--r--src/test/ui/feature-gates/feature-gate-box-expr.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-box_patterns.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-box_syntax.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-box_syntax.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs36
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr54
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-concat_idents.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-concat_idents2.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-concat_idents3.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_fn.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_generics.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_transmute.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_transmute.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-custom_attribute.stderr39
-rw-r--r--src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr51
-rw-r--r--src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-decl_macro.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-decl_macro.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_alias.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_cfg.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_keyword.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_masked.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-dropck-ugeh.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-existential-type.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-extern_types.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-external_doc.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-fundamental.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-generators.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr21
-rw-r--r--src/test/ui/feature-gates/feature-gate-global_asm.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-is_sorted.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-label_break_value.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-link_args.stderr9
-rw-r--r--src/test/ui/feature-gates/feature-gate-link_cfg.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-linkage.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-lint-reasons.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-log_syntax.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-log_syntax2.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr9
-rw-r--r--src/test/ui/feature-gates/feature-gate-main.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-may-dangle.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-min_const_fn.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-naked_functions.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-never_type.stderr15
-rw-r--r--src/test/ui/feature-gates/feature-gate-no-debug.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-no_core.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr39
-rw-r--r--src/test/ui/feature-gates/feature-gate-non_exhaustive.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-plugin.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-repr-simd.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-repr128.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-repr_align_enum.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-repr_align_enum.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-simd.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-slice-patterns.stderr18
-rw-r--r--src/test/ui/feature-gates/feature-gate-start.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-static-nobundle.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-thread_local.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-trace_macros.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-trait-alias.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-try_blocks.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-try_reserve.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_ascription.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr21
-rw-r--r--src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr9
-rw-r--r--src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr9
-rw-r--r--src/test/ui/feature-gates/feature-gate-unboxed-closures.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-underscore_const_names.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr3
-rw-r--r--src/test/ui/feature-gates/feature-gate-untagged_unions.stderr9
-rw-r--r--src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr3
-rw-r--r--src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr3
-rw-r--r--src/test/ui/fn/fn-compare-mismatch.stderr8
-rw-r--r--src/test/ui/imports/local-modularized-tricky-fail-2.stderr9
-rw-r--r--src/test/ui/inference/inference_unstable_forced.stderr3
-rw-r--r--src/test/ui/issue-59756.fixed17
-rw-r--r--src/test/ui/issue-59756.rs17
-rw-r--r--src/test/ui/issue-59756.stderr15
-rw-r--r--src/test/ui/issue-59764.rs136
-rw-r--r--src/test/ui/issue-59764.stderr241
-rw-r--r--src/test/ui/issues/issue-17458.stderr3
-rw-r--r--src/test/ui/issues/issue-18294.stderr3
-rw-r--r--src/test/ui/issues/issue-20313.stderr3
-rw-r--r--src/test/ui/issues/issue-22933-2.rs2
-rw-r--r--src/test/ui/issues/issue-22933-2.stderr6
-rw-r--r--src/test/ui/issues/issue-23024.stderr3
-rw-r--r--src/test/ui/issues/issue-23173.rs12
-rw-r--r--src/test/ui/issues/issue-23173.stderr12
-rw-r--r--src/test/ui/issues/issue-23217.rs3
-rw-r--r--src/test/ui/issues/issue-23217.stderr8
-rw-r--r--src/test/ui/issues/issue-23302-1.stderr2
-rw-r--r--src/test/ui/issues/issue-23302-2.stderr2
-rw-r--r--src/test/ui/issues/issue-25826.stderr3
-rw-r--r--src/test/ui/issues/issue-28344.stderr4
-rw-r--r--src/test/ui/issues/issue-28971.rs4
-rw-r--r--src/test/ui/issues/issue-28971.stderr10
-rw-r--r--src/test/ui/issues/issue-30560.rs9
-rw-r--r--src/test/ui/issues/issue-30560.stderr8
-rw-r--r--src/test/ui/issues/issue-32655.stderr6
-rw-r--r--src/test/ui/issues/issue-32829.stderr3
-rw-r--r--src/test/ui/issues/issue-34209.rs3
-rw-r--r--src/test/ui/issues/issue-34209.stderr11
-rw-r--r--src/test/ui/issues/issue-36163.stderr2
-rw-r--r--src/test/ui/issues/issue-37887.stderr3
-rw-r--r--src/test/ui/issues/issue-49074.stderr3
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr2
-rw-r--r--src/test/ui/issues/issue-51279.stderr3
-rw-r--r--src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr5
-rw-r--r--src/test/ui/issues/issue-51714.rs1
-rw-r--r--src/test/ui/issues/issue-51714.stderr8
-rw-r--r--src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr3
-rw-r--r--src/test/ui/issues/issue-54974.rs16
-rw-r--r--src/test/ui/issues/issue-55324.rs14
-rw-r--r--src/test/ui/issues/issue-58885.rs21
-rw-r--r--src/test/ui/issues/issue-59001.rs17
-rw-r--r--src/test/ui/issues/issue-59488.rs26
-rw-r--r--src/test/ui/issues/issue-59488.stderr81
-rw-r--r--src/test/ui/linkage4.stderr3
-rw-r--r--src/test/ui/macros/macro-multiple-matcher-bindings.rs13
-rw-r--r--src/test/ui/macros/macro-multiple-matcher-bindings.stderr57
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-1.rs4
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-1.stderr8
-rw-r--r--src/test/ui/macros/macro-reexport-removed.stderr3
-rw-r--r--src/test/ui/macros/macros-in-extern.stderr9
-rw-r--r--src/test/ui/missing/missing-alloc_error_handler.rs2
-rw-r--r--src/test/ui/missing/missing-allocator.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument-callee.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr4
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr4
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr4
-rw-r--r--src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr2
-rw-r--r--src/test/ui/nll/extra-unused-mut.rs19
-rw-r--r--src/test/ui/nll/get_default.nll.stderr84
-rw-r--r--src/test/ui/nll/region-ends-after-if-condition.nll.stderr39
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr16
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr16
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr20
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr20
-rw-r--r--src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr32
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr8
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr16
-rw-r--r--src/test/ui/panic-runtime/needs-gate.stderr6
-rw-r--r--src/test/ui/parser/recover-missing-semi.rs13
-rw-r--r--src/test/ui/parser/recover-missing-semi.stderr39
-rw-r--r--src/test/ui/print_type_sizes/multiple_types.stdout4
-rw-r--r--src/test/ui/print_type_sizes/niche-filling.stdout28
-rw-r--r--src/test/ui/print_type_sizes/padding.stdout10
-rw-r--r--src/test/ui/print_type_sizes/repr-align.stdout4
-rw-r--r--src/test/ui/print_type_sizes/variants.stdout4
-rw-r--r--src/test/ui/proc-macro/attr-stmt-expr.stderr6
-rw-r--r--src/test/ui/proc-macro/derive-helper-shadowing.stderr3
-rw-r--r--src/test/ui/proc-macro/derive-still-gated.stderr3
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.stdout40
-rw-r--r--src/test/ui/proc-macro/dollar-crate.stdout120
-rw-r--r--src/test/ui/proc-macro/expand-to-unstable-2.stderr3
-rw-r--r--src/test/ui/proc-macro/issue-41211.stderr3
-rw-r--r--src/test/ui/proc-macro/macros-in-extern.stderr9
-rw-r--r--src/test/ui/proc-macro/more-gates.stderr15
-rw-r--r--src/test/ui/proc-macro/proc-macro-attributes.stderr3
-rw-r--r--src/test/ui/proc-macro/proc-macro-gates.stderr48
-rw-r--r--src/test/ui/proc-macro/proc-macro-gates2.stderr6
-rw-r--r--src/test/ui/reserved/reserved-attr-on-macro.stderr3
-rw-r--r--src/test/ui/resolve/resolve-variant-assoc-item.rs4
-rw-r--r--src/test/ui/resolve/resolve-variant-assoc-item.stderr8
-rw-r--r--src/test/ui/resolve_self_super_hint.rs1
-rw-r--r--src/test/ui/resolve_self_super_hint.stderr8
-rw-r--r--src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs8
-rw-r--r--src/test/ui/rfc1445/feature-gate.no_gate.stderr3
-rw-r--r--src/test/ui/rust-2018/remove-extern-crate.fixed1
-rw-r--r--src/test/ui/rust-2018/remove-extern-crate.rs1
-rw-r--r--src/test/ui/rust-2018/remove-extern-crate.stderr8
-rw-r--r--src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr2
-rw-r--r--src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr2
-rw-r--r--src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs2
-rw-r--r--src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr4
-rw-r--r--src/test/ui/span/gated-features-attr-spans.stderr3
-rw-r--r--src/test/ui/span/issue-36530.stderr9
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr3
-rw-r--r--src/test/ui/specialization/specialization-feature-gate-default.stderr3
-rw-r--r--src/test/ui/stability-attribute/stability-attribute-issue.rs4
-rw-r--r--src/test/ui/stability-attribute/stability-attribute-issue.stderr6
-rw-r--r--src/test/ui/stmt_expr_attrs_no_feature.rs16
-rw-r--r--src/test/ui/stmt_expr_attrs_no_feature.stderr27
-rw-r--r--src/test/ui/suggestions/attribute-typos.stderr9
-rw-r--r--src/test/ui/suggestions/suggest-methods.stderr6
-rw-r--r--src/test/ui/suggestions/suggest-variants.rs3
-rw-r--r--src/test/ui/suggestions/suggest-variants.stderr65
-rw-r--r--src/test/ui/syntax-trait-polarity-feature-gate.stderr3
-rw-r--r--src/test/ui/target-feature-gate.stderr3
-rw-r--r--src/test/ui/trace_macros-gate.stderr12
-rw-r--r--src/test/ui/traits/trait-alias-ambiguous.rs24
-rw-r--r--src/test/ui/traits/trait-alias-ambiguous.stderr20
-rw-r--r--src/test/ui/try-block/try-block-bad-type.stderr2
-rw-r--r--src/test/ui/try-block/try-block-catch.rs10
-rw-r--r--src/test/ui/try-block/try-block-catch.stderr10
-rw-r--r--src/test/ui/ufcs/ufcs-partially-resolved.rs4
-rw-r--r--src/test/ui/ufcs/ufcs-partially-resolved.stderr8
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr3
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr6
-rw-r--r--src/test/ui/unnecessary-extern-crate.rs2
-rw-r--r--src/test/ui/use/use-associated-const.rs13
-rw-r--r--src/test/ui/use/use-associated-const.stderr9
-rw-r--r--src/test/ui/use/use-from-trait-xc.stderr6
-rw-r--r--src/test/ui/use/use-from-trait.rs17
-rw-r--r--src/test/ui/use/use-from-trait.stderr12
-rw-r--r--src/test/ui/utf8_idents.stderr12
-rw-r--r--src/tools/build-manifest/src/main.rs2
m---------src/tools/cargo0
m---------src/tools/clippy16
-rw-r--r--src/tools/compiletest/src/header.rs6
-rw-r--r--src/tools/compiletest/src/runtest.rs7
m---------src/tools/miri28
m---------src/tools/rls0
-rw-r--r--src/tools/rustc-workspace-hack/Cargo.toml2
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--src/tools/tidy/src/unstable_book.rs8
-rw-r--r--src/tools/unstable-book-gen/src/main.rs14
780 files changed, 17550 insertions, 7955 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2bf8d81f1aa..1ad9dbd4ea5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -17,7 +17,7 @@ dependencies = [
 name = "alloc"
 version = "0.0.0"
 dependencies = [
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -54,6 +54,7 @@ name = "arena"
 version = "0.0.0"
 dependencies = [
  "rustc_data_structures 0.0.0",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -105,8 +106,8 @@ name = "backtrace-sys"
 version = "0.1.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
@@ -157,8 +158,8 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -317,7 +318,7 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.28"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -373,9 +374,8 @@ version = "0.0.212"
 dependencies = [
  "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy-mini-macro-test 0.2.0",
- "clippy_dev 0.0.1",
  "clippy_lints 0.0.212",
- "compiletest_rs 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiletest_rs 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -391,17 +391,6 @@ name = "clippy-mini-macro-test"
 version = "0.2.0"
 
 [[package]]
-name = "clippy_dev"
-version = "0.0.1"
-dependencies = [
- "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "clippy_lints"
 version = "0.0.212"
 dependencies = [
@@ -432,10 +421,10 @@ dependencies = [
 
 [[package]]
 name = "cmake"
-version = "0.1.33"
+version = "0.1.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -464,10 +453,10 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.8"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
 
@@ -494,7 +483,7 @@ dependencies = [
 
 [[package]]
 name = "compiletest_rs"
-version = "0.3.19"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -672,7 +661,7 @@ name = "curl-sys"
 version = "0.4.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -750,7 +739,7 @@ name = "dlmalloc"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
@@ -916,7 +905,7 @@ name = "fortanix-sgx-abi"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
 
@@ -1218,7 +1207,7 @@ name = "jemalloc-sys"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1287,7 +1276,7 @@ name = "libgit2-sys"
 version = "0.7.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1301,7 +1290,7 @@ name = "libnghttp2-sys"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1310,7 +1299,7 @@ name = "libssh2-sys"
 version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1319,20 +1308,11 @@ dependencies = [
 ]
 
 [[package]]
-name = "libtest"
-version = "0.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_term 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "libz-sys"
 version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1397,7 +1377,7 @@ name = "lzma-sys"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1495,6 +1475,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "measureme"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "memchr"
 version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1520,7 +1510,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "minifier"
-version = "0.0.28"
+version = "0.0.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1531,7 +1521,7 @@ name = "miniz-sys"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1548,7 +1538,7 @@ name = "miniz_oxide_c_api"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1620,10 +1610,12 @@ dependencies = [
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiletest_rs 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiletest_rs 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-workspace-hack 1.0.0",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1723,7 +1715,7 @@ name = "openssl-src"
 version = "111.1.0+1.1.1a"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1731,7 +1723,7 @@ name = "openssl-sys"
 version = "0.9.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-src 111.1.0+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1768,7 +1760,7 @@ dependencies = [
 name = "panic_abort"
 version = "0.0.0"
 dependencies = [
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1778,7 +1770,7 @@ name = "panic_unwind"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "unwind 0.0.0",
@@ -1962,8 +1954,8 @@ version = "0.0.0"
 name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -2055,18 +2047,6 @@ dependencies = [
 
 [[package]]
 name = "rand"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand"
 version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -2094,14 +2074,6 @@ dependencies = [
 
 [[package]]
 name = "rand_core"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand_core"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -2283,7 +2255,7 @@ dependencies = [
  "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-process 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2366,6 +2338,7 @@ dependencies = [
  "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "measureme 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2498,7 +2471,7 @@ name = "rustc-demangle"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-std-workspace-core 1.0.0",
 ]
 
@@ -2559,7 +2532,7 @@ version = "1.0.0"
 dependencies = [
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2597,8 +2570,8 @@ version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -2620,7 +2593,7 @@ dependencies = [
 name = "rustc_codegen_llvm"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2632,7 +2605,7 @@ name = "rustc_codegen_ssa"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2815,7 +2788,7 @@ name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2824,8 +2797,8 @@ version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -2886,8 +2859,8 @@ version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -2972,11 +2945,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_term"
-version = "0.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
 name = "rustc_tools_util"
 version = "0.1.1"
 
@@ -3007,8 +2975,8 @@ version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -3039,7 +3007,7 @@ dependencies = [
 name = "rustdoc"
 version = "0.0.0"
 dependencies = [
- "minifier 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3274,8 +3242,8 @@ version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
  "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3460,6 +3428,10 @@ dependencies = [
 
 [[package]]
 name = "term"
+version = "0.0.0"
+
+[[package]]
+name = "term"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -3498,8 +3470,9 @@ dependencies = [
 name = "test"
 version = "0.0.0"
 dependencies = [
- "libtest 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
+ "term 0.0.0",
 ]
 
 [[package]]
@@ -3848,7 +3821,8 @@ dependencies = [
 name = "unwind"
 version = "0.0.0"
 dependencies = [
- "compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -4033,19 +4007,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010"
 "checksum cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8dfe3adeb30f7938e6c1dd5327f29235d8ada3e898aeb08c343005ec2915a2"
 "checksum cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "585784cac9b05c93a53b17a0b24a5cdd1dfdda5256f030e089b549d2390cc720"
-"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
+"checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83"
 "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
 "checksum chalk-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17ec698a6f053a23bfbe646d9f2fde4b02abc19125595270a99e6f44ae0bdd1a"
 "checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e"
 "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
 "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-"checksum cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "704fbf3bb5149daab0afb255dbea24a1f08d2f4099cedb9baab6d470d4c5eefb"
+"checksum cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "96210eec534fc3fbfc0452a63769424eaa80205fda6cea98e5b61cb3d97bcec8"
 "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc"
 "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
 "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
-"checksum compiler_builtins 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "a28c3898d0c57b26fa6f92de141ba665fa5ac5179f795db06db408be84302395"
-"checksum compiletest_rs 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "56c799b1f7142badf3b047b4c1f2074cc96b6b784fb2432f2ed9c87da0a03749"
+"checksum compiler_builtins 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4ada53ac629568219809178f988ca2aac9889e9a847379588c097d30ce185145"
+"checksum compiletest_rs 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "17a60483b7d4d1534db7b77458a03d5d8a93a707432a04978dfe87ea43bb61b1"
 "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
 "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887"
 "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
@@ -4131,7 +4105,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1"
 "checksum libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4"
 "checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d"
-"checksum libtest 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a51ac59582b915cdfc426dada72c6d9eba95818a6b481ca340f5c7152166837"
 "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
 "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"
 "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
@@ -4146,10 +4119,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
 "checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f"
 "checksum mdbook 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba0d44cb4089c741b9a91f3e5218298a40699c2f3a070a85014eed290c60819"
+"checksum measureme 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "36bb2b263a6795d352035024d6b30ce465bb79a5e5280d74c3b5f8464c657bcc"
 "checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
 "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
-"checksum minifier 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "3a2898502751dcc9d66b6fff57f3cf63cc91605e83e1a33515396f5027f8e4ca"
+"checksum minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4950cb2617b1933e2da0446e864dfe0d6a22c22ff72297996c46e6a63b210b"
 "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649"
 "checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
 "checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e"
@@ -4204,10 +4178,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
 "checksum racer 2.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "37c88638777cc178684cf648ca0e1dad56646ce105b8593dfe665c436300adc3"
 "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
-"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
 "checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a"
 "checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a"
-"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
 "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
 "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
 "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
@@ -4242,7 +4214,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544"
 "checksum rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "526e7b6d2707a5b9bec3927d424ad70fa3cfc68e0ac1b75e46cdbbc95adc5108"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-"checksum rustc_term 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c69abe7f181d2ea8d2f7b44a4aa86f4b4a567444bcfcf51ed45ede957fbf064"
 "checksum rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c5a95edfa0c893236ae4778bb7c4752760e4c0d245e19b5eff33c5aa5eb9dc"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
 "checksum rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "af7c21531a91512a4a51b490be6ba1c8eff34fdda0dc5bf87dc28d86748aac56"
diff --git a/RELEASES.md b/RELEASES.md
index a49e072e9ea..fcaaa73bdc0 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,149 @@
+Version 1.34.0 (2019-04-11)
+==========================
+
+Language
+--------
+- [You can now use `#[deprecated = "reason"]`][58166] as a shorthand for
+  `#[deprecated(note = "reason")]`. This was previously allowed by mistake
+  but had no effect.
+- [You can now accept token streams in `#[attr()]`,`#[attr[]]`, and
+  `#[attr{}]` procedural macros.][57367]
+- [You can now write `extern crate self as foo;`][57407] to import your
+  crate's root into the extern prelude.
+
+
+Compiler
+--------
+- [You can now target `riscv64imac-unknown-none-elf` and
+  `riscv64gc-unknown-none-elf`.][58406]
+- [You can now enable linker plugin LTO optimisations with
+  `-C linker-plugin-lto`.][58057] This allows rustc to compile your Rust code
+  into LLVM bitcode allowing LLVM to perform LTO optimisations across C/C++ FFI
+  boundaries.
+- [You can now target `powerpc64-unknown-freebsd`.][57809]
+
+
+Libraries
+---------
+- [The trait bounds have been removed on some of `HashMap<K, V, S>`'s and
+  `HashSet<T, S>`'s basic methods.][58370] Most notably you no longer require
+  the `Hash` trait to create an iterator.
+- [The `Ord` trait bounds have been removed on some of `BinaryHeap<T>`'s basic
+  methods.][58421] Most notably you no longer require the `Ord` trait to create
+  an iterator.
+- [The methods `overflowing_neg` and `wrapping_neg` are now `const` functions
+  for all numeric types.][58044]
+- [Indexing a `str` is now generic over all types that
+  implement `SliceIndex<str>`.][57604]
+- [`str::trim`, `str::trim_matches`, `str::trim_{start, end}`, and
+  `str::trim_{start, end}_matches` are now `#[must_use]`][57106] and will
+  produce a warning if their returning type is unused.
+- [The methods `checked_pow`, `saturating_pow`, `wrapping_pow`, and
+  `overflowing_pow` are now available for all numeric types.][57873] These are
+  equivalvent to methods such as `wrapping_add` for the `pow` operation.
+
+
+Stabilized APIs
+---------------
+
+#### std & core
+* [`Any::type_id`]
+* [`Error::type_id`]
+* [`atomic::AtomicI16`]
+* [`atomic::AtomicI32`]
+* [`atomic::AtomicI64`]
+* [`atomic::AtomicI8`]
+* [`atomic::AtomicU16`]
+* [`atomic::AtomicU32`]
+* [`atomic::AtomicU64`]
+* [`atomic::AtomicU8`]
+* [`convert::Infallible`]
+* [`convert::TryFrom`]
+* [`convert::TryInto`]
+* [`iter::from_fn`]
+* [`iter::successors`]
+* [`num::NonZeroI128`]
+* [`num::NonZeroI16`]
+* [`num::NonZeroI32`]
+* [`num::NonZeroI64`]
+* [`num::NonZeroI8`]
+* [`num::NonZeroIsize`]
+* [`slice::sort_by_cached_key`]
+* [`str::escape_debug`]
+* [`str::escape_default`]
+* [`str::escape_unicode`]
+* [`str::split_ascii_whitespace`]
+
+#### std
+* [`Instant::checked_add`]
+* [`Instant::checked_sub`]
+* [`SystemTime::checked_add`]
+* [`SystemTime::checked_sub`]
+
+Cargo
+-----
+- [You can now use alternative registries to crates.io.][cargo/6654]
+
+Misc
+----
+- [You can now use the `?` operator in your documentation tests without manually
+  adding `fn main() -> Result<(), _> {}`.][56470]
+
+Compatibility Notes
+-------------------
+- [`Command::before_exec` is now deprecated in favor of the
+  unsafe method `Command::pre_exec`.][58059]
+- [Use of `ATOMIC_{BOOL, ISIZE, USIZE}_INIT` is now deprecated.][57425] As you
+  can now use `const` functions in `static` variables.
+
+[58370]: https://github.com/rust-lang/rust/pull/58370/
+[58406]: https://github.com/rust-lang/rust/pull/58406/
+[58421]: https://github.com/rust-lang/rust/pull/58421/
+[58166]: https://github.com/rust-lang/rust/pull/58166/
+[58044]: https://github.com/rust-lang/rust/pull/58044/
+[58057]: https://github.com/rust-lang/rust/pull/58057/
+[58059]: https://github.com/rust-lang/rust/pull/58059/
+[57809]: https://github.com/rust-lang/rust/pull/57809/
+[57873]: https://github.com/rust-lang/rust/pull/57873/
+[57604]: https://github.com/rust-lang/rust/pull/57604/
+[57367]: https://github.com/rust-lang/rust/pull/57367/
+[57407]: https://github.com/rust-lang/rust/pull/57407/
+[57425]: https://github.com/rust-lang/rust/pull/57425/
+[57106]: https://github.com/rust-lang/rust/pull/57106/
+[56470]: https://github.com/rust-lang/rust/pull/56470/
+[cargo/6654]: https://github.com/rust-lang/cargo/pull/6654/
+[`Any::type_id`]: https://doc.rust-lang.org/std/any/trait.Any.html#tymethod.type_id
+[`Error::type_id`]: https://doc.rust-lang.org/std/error/trait.Error.html#tymethod.type_id
+[`atomic::AtomicI16`]: https://doc.rust-lang.org/std/atomic/struct.AtomicI16.html
+[`atomic::AtomicI32`]: https://doc.rust-lang.org/std/atomic/struct.AtomicI32.html
+[`atomic::AtomicI64`]: https://doc.rust-lang.org/std/atomic/struct.AtomicI64.html
+[`atomic::AtomicI8`]: https://doc.rust-lang.org/std/atomic/struct.AtomicI8.html
+[`atomic::AtomicU16`]: https://doc.rust-lang.org/std/atomic/struct.AtomicU16.html
+[`atomic::AtomicU32`]: https://doc.rust-lang.org/std/atomic/struct.AtomicU32.html
+[`atomic::AtomicU64`]: https://doc.rust-lang.org/std/atomic/struct.AtomicU64.html
+[`atomic::AtomicU8`]: https://doc.rust-lang.org/std/atomic/struct.AtomicU8.html
+[`convert::Infallible`]: https://doc.rust-lang.org/std/convert/enum.Infallible.html
+[`convert::TryFrom`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html
+[`convert::TryInto`]: https://doc.rust-lang.org/std/convert/trait.TryInto.html
+[`iter::from_fn`]: https://doc.rust-lang.org/std/iter/fn.from_fn.html
+[`iter::successors`]: https://doc.rust-lang.org/std/iter/fn.successors.html
+[`num::NonZeroI128`]: https://doc.rust-lang.org/std/num/struct.NonZeroI128.html
+[`num::NonZeroI16`]: https://doc.rust-lang.org/std/num/struct.NonZeroI16.html
+[`num::NonZeroI32`]: https://doc.rust-lang.org/std/num/struct.NonZeroI32.html
+[`num::NonZeroI64`]: https://doc.rust-lang.org/std/num/struct.NonZeroI64.html
+[`num::NonZeroI8`]: https://doc.rust-lang.org/std/num/struct.NonZeroI8.html
+[`num::NonZeroIsize`]: https://doc.rust-lang.org/std/num/struct.NonZeroIsize.html
+[`slice::sort_by_cached_key`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by_cached_key
+[`str::escape_debug`]: https://doc.rust-lang.org/std/primitive.str.html#method.escape_debug
+[`str::escape_default`]: https://doc.rust-lang.org/std/primitive.str.html#method.escape_default
+[`str::escape_unicode`]: https://doc.rust-lang.org/std/primitive.str.html#method.escape_unicode
+[`str::split_ascii_whitespace`]: https://doc.rust-lang.org/std/primitive.str.html#method.split_ascii_whitespace
+[`Instant::checked_add`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.checked_add
+[`Instant::checked_sub`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.checked_sub
+[`SystemTime::checked_add`]: https://doc.rust-lang.org/std/time/struct.SystemTime.html#method.checked_add
+[`SystemTime::checked_sub`]: https://doc.rust-lang.org/std/time/struct.SystemTime.html#method.checked_sub
+
+
 Version 1.33.0 (2019-02-28)
 ==========================
 
@@ -99,6 +245,8 @@ Stabilized APIs
 
 Cargo
 -----
+- [You can now publish crates that require a feature flag to compile with
+  `cargo publish --features` or `cargo publish --all-features`.][cargo/6453]
 - [Cargo should now rebuild a crate if a file was modified during the initial
   build.][cargo/6484]
 
@@ -135,6 +283,7 @@ Compatibility Notes
 [57535]: https://github.com/rust-lang/rust/pull/57535/
 [57566]: https://github.com/rust-lang/rust/pull/57566/
 [57615]: https://github.com/rust-lang/rust/pull/57615/
+[cargo/6453]: https://github.com/rust-lang/cargo/pull/6453/
 [cargo/6484]: https://github.com/rust-lang/cargo/pull/6484/
 [`unix::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.read_exact_at
 [`unix::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at
diff --git a/appveyor.yml b/appveyor.yml
index 6aac5f07172..be960dc13af 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -14,6 +14,9 @@ environment:
     MSYS_BITS: 64
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
     SCRIPT: python x.py test
+    # FIXME(#59637)
+    NO_DEBUG_ASSERTIONS: 1
+    NO_LLVM_ASSERTIONS: 1
   - CI_JOB_NAME: i686-msvc-1
     MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
@@ -59,6 +62,9 @@ environment:
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
     MINGW_DIR: mingw32
+    # FIXME(#59637)
+    NO_DEBUG_ASSERTIONS: 1
+    NO_LLVM_ASSERTIONS: 1
   - CI_JOB_NAME: i686-mingw-2
     MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
@@ -73,6 +79,9 @@ environment:
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
     MINGW_DIR: mingw64
+    # FIXME(#59637)
+    NO_DEBUG_ASSERTIONS: 1
+    NO_LLVM_ASSERTIONS: 1
 
   # 32/64 bit MSVC and GNU deployment
   - CI_JOB_NAME: dist-x86_64-msvc
diff --git a/config.toml.example b/config.toml.example
index 5e0a2fbf0d3..8b2153cd2e6 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -421,6 +421,9 @@
 # development of NLL
 #test-compare-mode = false
 
+# Use LLVM libunwind as the implementation for Rust's unwinder.
+#llvm-libunwind = false
+
 # =============================================================================
 # Options for specific targets
 #
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 0f7b6c22e1c..d4ffd4ad396 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -36,11 +36,11 @@ test = false
 
 [dependencies]
 build_helper = { path = "../build_helper" }
-cmake = "0.1.23"
+cmake = "0.1.38"
 filetime = "0.2"
 num_cpus = "1.0"
 getopts = "0.2"
-cc = "1.0.1"
+cc = "1.0.35"
 libc = "0.2"
 serde = "1.0.8"
 serde_derive = "1.0.8"
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 7429492f914..a76584093fc 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -187,33 +187,6 @@ fn main() {
             cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));
         }
 
-        // Build all crates in the `std` facade with `-Z emit-stack-sizes` to add stack usage
-        // information.
-        //
-        // When you use this `-Z` flag with Cargo you get stack usage information on all crates
-        // compiled from source, and when you are using LTO you also get information on pre-compiled
-        // crates like `core` and `std`, even if they were not compiled with `-Z emit-stack-sizes`.
-        // However, there's an exception: `compiler_builtins`. This crate is special and doesn't
-        // participate in LTO because it's always linked as a separate object file. For this reason
-        // it's impossible to get stack usage information about `compiler-builtins` using
-        // `RUSTFLAGS` + Cargo, or `cargo rustc`.
-        //
-        // To make the stack usage information of all crates under the `std` facade available to
-        // Cargo based stack usage analysis tools, in both LTO and non-LTO mode, we compile them
-        // with the `-Z emit-stack-sizes` flag. The `RUSTC_EMIT_STACK_SIZES` var helps us apply this
-        // flag only to the crates in the `std` facade. The `-Z` flag is known to currently work
-        // with targets that produce ELF files so we limit its use flag to those targets.
-        //
-        // NOTE(japaric) if this ever causes problem with an LLVM upgrade or any PR feel free to
-        // remove it or comment it out
-        if env::var_os("RUSTC_EMIT_STACK_SIZES").is_some()
-            && (target.contains("-linux-")
-                || target.contains("-none-eabi")
-                || target.ends_with("-none-elf"))
-        {
-            cmd.arg("-Zemit-stack-sizes");
-        }
-
         if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") {
             cmd.arg("-C").arg(format!("codegen-units={}", s));
         }
@@ -316,6 +289,11 @@ fn main() {
         }
     }
 
+    // This is required for internal lints.
+    if stage != "0" {
+        cmd.arg("-Zunstable-options");
+    }
+
     // Force all crates compiled by this compiler to (a) be unstable and (b)
     // allow the `rustc_private` feature to link to other unstable crates
     // also in the sysroot. We also do this for host crates, since those
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 8d3c8fc435c..522466314d6 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -634,7 +634,28 @@ impl<'a> Builder<'a> {
         if compiler.is_snapshot(self) {
             self.rustc_snapshot_libdir()
         } else {
-            self.sysroot(compiler).join(libdir(&compiler.host))
+            match self.config.libdir_relative() {
+                Some(relative_libdir) if compiler.stage >= 1
+                    => self.sysroot(compiler).join(relative_libdir),
+                _ => self.sysroot(compiler).join(libdir(&compiler.host))
+            }
+        }
+    }
+
+    /// Returns the compiler's relative libdir where it stores the dynamic libraries that
+    /// it itself links against.
+    ///
+    /// For example this returns `lib` on Unix and `bin` on
+    /// Windows.
+    pub fn libdir_relative(&self, compiler: Compiler) -> &Path {
+        if compiler.is_snapshot(self) {
+            libdir(&self.config.build).as_ref()
+        } else {
+            match self.config.libdir_relative() {
+                Some(relative_libdir) if compiler.stage >= 1
+                    => relative_libdir,
+                _ => libdir(&compiler.host).as_ref()
+            }
         }
     }
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 237f5c0ea2f..66443d472d3 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -20,7 +20,7 @@ use filetime::FileTime;
 use serde_json;
 
 use crate::dist;
-use crate::util::{exe, libdir, is_dylib};
+use crate::util::{exe, is_dylib};
 use crate::{Compiler, Mode, GitRepo};
 use crate::native;
 
@@ -97,8 +97,6 @@ impl Step for Std {
         let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage));
         builder.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage,
                 &compiler.host, target));
-        // compile with `-Z emit-stack-sizes`; see bootstrap/src/rustc.rs for more details
-        cargo.env("RUSTC_EMIT_STACK_SIZES", "1");
         run_cargo(builder,
                   &mut cargo,
                   &libstd_stamp(builder, compiler, target),
@@ -397,8 +395,6 @@ impl Step for Test {
         let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage));
         builder.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage,
                 &compiler.host, target));
-        // compile with `-Z emit-stack-sizes`; see bootstrap/src/rustc.rs for more details
-        cargo.env("RUSTC_EMIT_STACK_SIZES", "1");
         run_cargo(builder,
                   &mut cargo,
                   &libtest_stamp(builder, compiler, target),
@@ -1005,13 +1001,13 @@ impl Step for Assemble {
 
         // Link in all dylibs to the libdir
         let sysroot = builder.sysroot(target_compiler);
-        let sysroot_libdir = sysroot.join(libdir(&*host));
-        t!(fs::create_dir_all(&sysroot_libdir));
+        let rustc_libdir = builder.rustc_libdir(target_compiler);
+        t!(fs::create_dir_all(&rustc_libdir));
         let src_libdir = builder.sysroot_libdir(build_compiler, host);
         for f in builder.read_dir(&src_libdir) {
             let filename = f.file_name().into_string().unwrap();
             if is_dylib(&filename) {
-                builder.copy(&f.path(), &sysroot_libdir.join(&filename));
+                builder.copy(&f.path(), &rustc_libdir.join(&filename));
             }
         }
 
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index cb71550c12d..0c31c41ceda 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -48,6 +48,7 @@ pub struct Config {
     pub exclude: Vec<PathBuf>,
     pub rustc_error_format: Option<String>,
     pub test_compare_mode: bool,
+    pub llvm_libunwind: bool,
 
     pub run_host_only: bool,
 
@@ -329,6 +330,7 @@ struct Rust {
     remap_debuginfo: Option<bool>,
     jemalloc: Option<bool>,
     test_compare_mode: Option<bool>,
+    llvm_libunwind: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -548,6 +550,7 @@ impl Config {
             set(&mut config.rust_rpath, rust.rpath);
             set(&mut config.jemalloc, rust.jemalloc);
             set(&mut config.test_compare_mode, rust.test_compare_mode);
+            set(&mut config.llvm_libunwind, rust.llvm_libunwind);
             set(&mut config.backtrace, rust.backtrace);
             set(&mut config.channel, rust.channel.clone());
             set(&mut config.rust_dist_src, rust.dist_src);
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index b2d8f2d8ebf..ade8afee7c1 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -68,6 +68,8 @@ o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
 o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")
 o("ldflags", "llvm.ldflags", "build LLVM with these extra linker flags")
 
+o("llvm-libunwind", "rust.llvm_libunwind", "use LLVM libunwind")
+
 # Optimization and debugging options. These may be overridden by the release
 # channel, etc.
 o("optimize", "rust.optimize", "build optimized rust code")
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index d982330a616..61a7705bd6c 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -18,7 +18,7 @@ use build_helper::output;
 
 use crate::{Compiler, Mode, LLVM_TOOLS};
 use crate::channel;
-use crate::util::{libdir, is_dylib, exe};
+use crate::util::{is_dylib, exe};
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::compile;
 use crate::tool::{self, Tool};
@@ -473,7 +473,7 @@ impl Step for Rustc {
         fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
             let host = compiler.host;
             let src = builder.sysroot(compiler);
-            let libdir = libdir(&host);
+            let libdir = builder.rustc_libdir(compiler);
 
             // Copy rustc/rustdoc binaries
             t!(fs::create_dir_all(image.join("bin")));
@@ -481,13 +481,15 @@ impl Step for Rustc {
 
             builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755);
 
+            let libdir_relative = builder.libdir_relative(compiler);
+
             // Copy runtime DLLs needed by the compiler
-            if libdir != "bin" {
-                for entry in builder.read_dir(&src.join(libdir)) {
+            if libdir_relative.to_str() != Some("bin") {
+                for entry in builder.read_dir(&libdir) {
                     let name = entry.file_name();
                     if let Some(s) = name.to_str() {
                         if is_dylib(s) {
-                            builder.install(&entry.path(), &image.join(libdir), 0o644);
+                            builder.install(&entry.path(), &image.join(&libdir_relative), 0o644);
                         }
                     }
                 }
@@ -899,6 +901,7 @@ impl Step for Src {
             "src/libstd",
             "src/libunwind",
             "src/libtest",
+            "src/libterm",
             "src/libprofiler_builtins",
             "src/stdsimd",
             "src/libproc_macro",
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index d831d2f1af2..330f66c1df0 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -277,7 +277,7 @@ impl Step for TheBook {
         builder.ensure(Rustbook {
             target,
             name: INTERNER.intern_string(name.to_string()),
-            version: RustbookVersion::MdBook1,
+            version: RustbookVersion::MdBook2,
         });
 
         // building older edition redirects
@@ -286,21 +286,21 @@ impl Step for TheBook {
         builder.ensure(Rustbook {
             target,
             name: INTERNER.intern_string(source_name),
-            version: RustbookVersion::MdBook1,
+            version: RustbookVersion::MdBook2,
         });
 
         let source_name = format!("{}/second-edition", name);
         builder.ensure(Rustbook {
             target,
             name: INTERNER.intern_string(source_name),
-            version: RustbookVersion::MdBook1,
+            version: RustbookVersion::MdBook2,
         });
 
         let source_name = format!("{}/2018-edition", name);
         builder.ensure(Rustbook {
             target,
             name: INTERNER.intern_string(source_name),
-            version: RustbookVersion::MdBook1,
+            version: RustbookVersion::MdBook2,
         });
 
         // build the version info page and CSS
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 2394ae7fb79..bcd28e9cf5e 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -506,6 +506,9 @@ impl Build {
     fn std_features(&self) -> String {
         let mut features = "panic-unwind".to_string();
 
+        if self.config.llvm_libunwind {
+            features.push_str(" llvm-libunwind");
+        }
         if self.config.backtrace {
             features.push_str(" backtrace");
         }
@@ -1275,6 +1278,7 @@ impl Build {
     fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
         if self.config.dry_run { return; }
         let dst = dstdir.join(src.file_name().unwrap());
+        self.verbose_than(1, &format!("Install {:?} to {:?}", src, dst));
         t!(fs::create_dir_all(dstdir));
         drop(fs::remove_file(&dst));
         {
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index b9f456e9100..fa6857cdc11 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -131,6 +131,11 @@ pub fn check(build: &mut Build) {
             continue;
         }
 
+        // We don't use a C compiler on wasm32
+        if target.contains("wasm32") {
+            continue;
+        }
+
         if !build.config.dry_run {
             cmd_finder.must_have(build.cc(*target));
             if let Some(ar) = build.ar(*target) {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 881bea5d97e..c552f607960 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1016,7 +1016,10 @@ impl Step for Compiletest {
         // Also provide `rust_test_helpers` for the host.
         builder.ensure(native::TestHelpers { target: compiler.host });
 
-        builder.ensure(native::TestHelpers { target });
+        // wasm32 can't build the test helpers
+        if !target.contains("wasm32") {
+            builder.ensure(native::TestHelpers { target });
+        }
         builder.ensure(RemoteCopyLibs { compiler, target });
 
         let mut cmd = builder.tool_cmd(Tool::Compiletest);
diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile
index e10ccd56a4a..bbf700ae233 100644
--- a/src/ci/docker/arm-android/Dockerfile
+++ b/src/ci/docker/arm-android/Dockerfile
@@ -23,7 +23,7 @@ RUN dpkg --add-architecture i386 && \
 
 COPY scripts/android-sdk.sh /scripts/
 RUN . /scripts/android-sdk.sh && \
-    download_and_create_avd 4333796 armeabi-v7a 18
+    download_and_create_avd 4333796 armeabi-v7a 18 5264690
 
 ENV PATH=$PATH:/android/sdk/emulator
 ENV PATH=$PATH:/android/sdk/tools
diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile
index f80293b182e..a722a418391 100644
--- a/src/ci/docker/dist-various-1/Dockerfile
+++ b/src/ci/docker/dist-various-1/Dockerfile
@@ -109,7 +109,9 @@ ENV TARGETS=$TARGETS,thumbv6m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
+ENV TARGETS=$TARGETS,thumbv8m.base-none-eabi
 ENV TARGETS=$TARGETS,thumbv8m.main-none-eabi
+ENV TARGETS=$TARGETS,thumbv8m.main-none-eabihf
 ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv64imac-unknown-none-elf
diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
index a15fb8cae25..965286e5bcf 100755
--- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
@@ -12,7 +12,7 @@ export PATH=`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH
 git clone https://github.com/CraneStation/wasi-sysroot
 
 cd wasi-sysroot
-git reset --hard 320054e84f8f2440def3b1c8700cedb8fd697bf8
+git reset --hard e5f14be38362f1ab83302895a6e74b2ffd0e2302
 make -j$(nproc) INSTALL_DIR=/wasm32-unknown-wasi install
 
 cd ..
diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile
index 560df2f3a57..21a9023a458 100644
--- a/src/ci/docker/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/dist-x86_64-musl/Dockerfile
@@ -21,8 +21,8 @@ WORKDIR /build/
 
 COPY scripts/musl-toolchain.sh /build/
 # We need to mitigate rust-lang/rust#34978 when compiling musl itself as well
-RUN CFLAGS="-Wa,-mrelax-relocations=no" \
-    CXXFLAGS="-Wa,-mrelax-relocations=no" \
+RUN CFLAGS="-Wa,-mrelax-relocations=no -Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \
+    CXXFLAGS="-Wa,-mrelax-relocations=no -Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \
     bash musl-toolchain.sh x86_64 && rm -rf build
 
 COPY scripts/sccache.sh /scripts/
@@ -38,7 +38,9 @@ ENV RUST_CONFIGURE_ARGS \
 # way to produce "super compatible" binaries.
 #
 # See: https://github.com/rust-lang/rust/issues/34978
-ENV CFLAGS_x86_64_unknown_linux_musl=-Wa,-mrelax-relocations=no
+# And: https://github.com/rust-lang/rust/issues/59411
+ENV CFLAGS_x86_64_unknown_linux_musl="-Wa,-mrelax-relocations=no -Wa,--compress-debug-sections=none \
+    -Wl,--compress-debug-sections=none"
 
 ENV HOSTS=x86_64-unknown-linux-musl \
     CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc \
diff --git a/src/ci/docker/scripts/android-sdk.sh b/src/ci/docker/scripts/android-sdk.sh
index 179f63fc830..e78e3795c04 100644
--- a/src/ci/docker/scripts/android-sdk.sh
+++ b/src/ci/docker/scripts/android-sdk.sh
@@ -20,11 +20,19 @@ download_sysimage() {
     # The output from sdkmanager is so noisy that it will occupy all of the 4 MB
     # log extremely quickly. Thus we must silence all output.
     yes | sdkmanager --licenses > /dev/null
-    yes | sdkmanager platform-tools emulator \
+    yes | sdkmanager platform-tools \
         "platforms;android-$api" \
         "system-images;android-$api;default;$abi" > /dev/null
 }
 
+download_emulator() {
+    # Download a pinned version of the emulator since upgrades can cause issues
+    curl -fo emulator.zip "https://dl.google.com/android/repository/emulator-linux-$1.zip"
+    rm -rf "${ANDROID_HOME}/emulator"
+    unzip -q emulator.zip -d "${ANDROID_HOME}"
+    rm -f emulator.zip
+}
+
 create_avd() {
     abi=$1
     api=$2
@@ -40,11 +48,12 @@ download_and_create_avd() {
     download_sdk $1
     download_sysimage $2 $3
     create_avd $2 $3
+    download_emulator $4
 }
 
 # Usage:
 #
-#       setup_android_sdk 4333796 armeabi-v7a 18
+#       download_and_create_avd 4333796 armeabi-v7a 18 5264690
 #
 # 4333796 =>
 #   SDK tool version.
@@ -53,3 +62,6 @@ download_and_create_avd() {
 #   System image ABI
 # 18 =>
 #   Android API Level (18 = Android 4.3 = Jelly Bean MR2)
+# 5264690 =>
+#   Android Emulator version.
+#   Copy from the "build_id" in the `/android/sdk/emulator/emulator -version` output
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index 04483e24925..b1ac490a878 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -1,4 +1,6 @@
 #!/bin/bash
+# ignore-tidy-linelength
+
 set -eux
 
 arch=$1
@@ -55,7 +57,9 @@ for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared; do
   files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
 done
 
-URL=https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
+# Originally downloaded from:
+# https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
+URL=https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
 curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
 
 # Fix up absolute symlinks from the system image.  This can be removed
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject 07fd3880ea0874d82b1d9ed30ad3427ec98b4e8
+Subproject 7989c723607ef5b13b57208022259e6c771e11d
diff --git a/src/doc/man/rustc.1 b/src/doc/man/rustc.1
index 8f611063dbe..3788e3c864e 100644
--- a/src/doc/man/rustc.1
+++ b/src/doc/man/rustc.1
@@ -261,12 +261,12 @@ full debug info with variable and type information.
 .RE
 .TP
 \fBopt\-level\fR=\fIVAL\fR
-Optimize with possible levels 0\[en]3
+Optimize with possible levels 0\[en]3, s (optimize for size), or z (for minimal size)
 
 .SH ENVIRONMENT
 
-Some of these affect the output of the compiler, while others affect programs
-which link to the standard library.
+Some of these affect only test harness programs (generated via rustc --test);
+others affect all programs which link to the Rust standard library.
 
 .TP
 \fBRUST_TEST_THREADS\fR
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject f1ff93b66844493a7b03101c7df66ac958c6241
+Subproject c02e0e7754a76886e55b976a3a4fac20100cd35
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 27ad493a10364e907ec476e2ad61e8a1614b57e
+Subproject 98f90ff4de8e588f651f0fb493b5c7496551cd5
diff --git a/src/doc/robots.txt b/src/doc/robots.txt
index a54ec508c1b..61ee12739fb 100644
--- a/src/doc/robots.txt
+++ b/src/doc/robots.txt
@@ -17,3 +17,11 @@ 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: /book/first-edition/
+Disallow: /book/second-edition/
+Disallow: /stable/book/first-edition/
+Disallow: /stable/book/second-edition/
+Disallow: /beta/book/first-edition/
+Disallow: /beta/book/second-edition/
+Disallow: /nightly/book/first-edition/
+Disallow: /nightly/book/second-edition/
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index d7e789b5a11..dfb40284ef6 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -86,6 +86,13 @@ This flag will set which lints should be set to the [deny level](lints/levels.ht
 
 This flag will set which lints should be set to the [forbid level](lints/levels.html#forbid).
 
+## `-Z`: set unstable options
+
+This flag will allow you to set unstable options of rustc. In order to set multiple options,
+the -Z flag can be used multiple times. For example: `rustc -Z verbose -Z time`.
+Specifying options with -Z is only available on nightly. To view all available options
+run: `rustc -Z help`.
+
 ## `--cap-lints`: set the most restrictive lint level
 
 This flag lets you 'cap' lints, for more, [see here](lints/levels.html#capping-lints).
diff --git a/src/doc/unstable-book/book.toml b/src/doc/unstable-book/book.toml
index 5534340f0db..5b2e19bd7aa 100644
--- a/src/doc/unstable-book/book.toml
+++ b/src/doc/unstable-book/book.toml
@@ -1,2 +1,3 @@
 [book]
 title = "The Rust Unstable Book"
+author = "The Rust Community"
diff --git a/src/doc/unstable-book/src/library-features/borrow-state.md b/src/doc/unstable-book/src/library-features/borrow-state.md
new file mode 100644
index 00000000000..304b8dffe98
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/borrow-state.md
@@ -0,0 +1,7 @@
+# `borrow_state`
+
+The tracking issue for this feature is: [#27733]
+
+[#27733]: https://github.com/rust-lang/rust/issues/27733
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md
new file mode 100644
index 00000000000..cb3386b7152
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/fnbox.md
@@ -0,0 +1,32 @@
+# `fnbox`
+
+The tracking issue for this feature is [#28796]
+
+[#28796]: https://github.com/rust-lang/rust/issues/28796
+
+------------------------
+
+This had been a temporary alternative to the following impls:
+
+```rust,ignore
+impl<A, F> FnOnce for Box<F> where F: FnOnce<A> + ?Sized {}
+impl<A, F> FnMut for Box<F> where F: FnMut<A> + ?Sized {}
+impl<A, F> Fn for Box<F> where F: Fn<A> + ?Sized {}
+```
+
+The impls are parallel to these (relatively old) impls:
+
+```rust,ignore
+impl<A, F> FnOnce for &mut F where F: FnMut<A> + ?Sized {}
+impl<A, F> FnMut for &mut F where F: FnMut<A> + ?Sized {}
+impl<A, F> Fn for &mut F where F: Fn<A> + ?Sized {}
+impl<A, F> FnOnce for &F where F: Fn<A> + ?Sized {}
+impl<A, F> FnMut for &F where F: Fn<A> + ?Sized {}
+impl<A, F> Fn for &F where F: Fn<A> + ?Sized {}
+```
+
+Before the introduction of [`unsized_locals`][unsized_locals], we had been unable to provide the former impls. That means, unlike `&dyn Fn()` or `&mut dyn FnMut()` we could not use `Box<dyn FnOnce()>` at that time.
+
+[unsized_locals]: language-features/unsized-locals.html
+
+`FnBox()` is an alternative approach to `Box<dyn FnBox()>` is delegated to `FnBox::call_box` which doesn't need unsized locals. As we now have `Box<dyn FnOnce()>` working, the `fnbox` feature is going to be removed.
diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml
index f6d6c1de8f5..ddf0044c506 100644
--- a/src/liballoc/Cargo.toml
+++ b/src/liballoc/Cargo.toml
@@ -12,7 +12,7 @@ path = "lib.rs"
 
 [dependencies]
 core = { path = "../libcore" }
-compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.10", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
 rand = "0.6"
diff --git a/src/liballoc/benches/btree/set.rs b/src/liballoc/benches/btree/set.rs
index 08e1db5fbb7..6357ea3ea11 100644
--- a/src/liballoc/benches/btree/set.rs
+++ b/src/liballoc/benches/btree/set.rs
@@ -3,59 +3,49 @@ use std::collections::BTreeSet;
 use rand::{thread_rng, Rng};
 use test::{black_box, Bencher};
 
-fn random(n1: u32, n2: u32) -> [BTreeSet<usize>; 2] {
+fn random(n: usize) -> BTreeSet<usize> {
     let mut rng = thread_rng();
-    let mut set1 = BTreeSet::new();
-    let mut set2 = BTreeSet::new();
-    for _ in 0..n1 {
-        let i = rng.gen::<usize>();
-        set1.insert(i);
+    let mut set = BTreeSet::new();
+    while set.len() < n {
+        set.insert(rng.gen());
     }
-    for _ in 0..n2 {
-        let i = rng.gen::<usize>();
-        set2.insert(i);
-    }
-    [set1, set2]
+    assert_eq!(set.len(), n);
+    set
 }
 
-fn staggered(n1: u32, n2: u32) -> [BTreeSet<u32>; 2] {
-    let mut even = BTreeSet::new();
-    let mut odd = BTreeSet::new();
-    for i in 0..n1 {
-        even.insert(i * 2);
-    }
-    for i in 0..n2 {
-        odd.insert(i * 2 + 1);
+fn neg(n: usize) -> BTreeSet<i32> {
+    let mut set = BTreeSet::new();
+    for i in -(n as i32)..=-1 {
+        set.insert(i);
     }
-    [even, odd]
+    assert_eq!(set.len(), n);
+    set
 }
 
-fn neg_vs_pos(n1: u32, n2: u32) -> [BTreeSet<i32>; 2] {
-    let mut neg = BTreeSet::new();
-    let mut pos = BTreeSet::new();
-    for i in -(n1 as i32)..=-1 {
-        neg.insert(i);
-    }
-    for i in 1..=(n2 as i32) {
-        pos.insert(i);
+fn pos(n: usize) -> BTreeSet<i32> {
+    let mut set = BTreeSet::new();
+    for i in 1..=(n as i32) {
+        set.insert(i);
     }
-    [neg, pos]
+    assert_eq!(set.len(), n);
+    set
 }
 
-fn pos_vs_neg(n1: u32, n2: u32) -> [BTreeSet<i32>; 2] {
-    let mut neg = BTreeSet::new();
-    let mut pos = BTreeSet::new();
-    for i in -(n1 as i32)..=-1 {
-        neg.insert(i);
-    }
-    for i in 1..=(n2 as i32) {
-        pos.insert(i);
+
+fn stagger(n1: usize, factor: usize) -> [BTreeSet<u32>; 2] {
+    let n2 = n1 * factor;
+    let mut sets = [BTreeSet::new(), BTreeSet::new()];
+    for i in 0..(n1 + n2) {
+        let b = i % (factor + 1) != 0;
+        sets[b as usize].insert(i as u32);
     }
-    [pos, neg]
+    assert_eq!(sets[0].len(), n1);
+    assert_eq!(sets[1].len(), n2);
+    sets
 }
 
-macro_rules! set_intersection_bench {
-    ($name: ident, $sets: expr) => {
+macro_rules! set_bench {
+    ($name: ident, $set_func: ident, $result_func: ident, $sets: expr) => {
         #[bench]
         pub fn $name(b: &mut Bencher) {
             // setup
@@ -63,26 +53,36 @@ macro_rules! set_intersection_bench {
 
             // measure
             b.iter(|| {
-                let x = sets[0].intersection(&sets[1]).count();
+                let x = sets[0].$set_func(&sets[1]).$result_func();
                 black_box(x);
             })
         }
     };
 }
 
-set_intersection_bench! {intersect_random_100,          random(100, 100)}
-set_intersection_bench! {intersect_random_10k,          random(10_000, 10_000)}
-set_intersection_bench! {intersect_random_10_vs_10k,    random(10, 10_000)}
-set_intersection_bench! {intersect_random_10k_vs_10,    random(10_000, 10)}
-set_intersection_bench! {intersect_staggered_100,       staggered(100, 100)}
-set_intersection_bench! {intersect_staggered_10k,       staggered(10_000, 10_000)}
-set_intersection_bench! {intersect_staggered_10_vs_10k, staggered(10, 10_000)}
-set_intersection_bench! {intersect_staggered_10k_vs_10, staggered(10_000, 10)}
-set_intersection_bench! {intersect_neg_vs_pos_100,      neg_vs_pos(100, 100)}
-set_intersection_bench! {intersect_neg_vs_pos_10k,      neg_vs_pos(10_000, 10_000)}
-set_intersection_bench! {intersect_neg_vs_pos_10_vs_10k,neg_vs_pos(10, 10_000)}
-set_intersection_bench! {intersect_neg_vs_pos_10k_vs_10,neg_vs_pos(10_000, 10)}
-set_intersection_bench! {intersect_pos_vs_neg_100,      pos_vs_neg(100, 100)}
-set_intersection_bench! {intersect_pos_vs_neg_10k,      pos_vs_neg(10_000, 10_000)}
-set_intersection_bench! {intersect_pos_vs_neg_10_vs_10k,pos_vs_neg(10, 10_000)}
-set_intersection_bench! {intersect_pos_vs_neg_10k_vs_10,pos_vs_neg(10_000, 10)}
+set_bench! {intersection_100_neg_vs_100_pos, intersection, count, [neg(100), pos(100)]}
+set_bench! {intersection_100_neg_vs_10k_pos, intersection, count, [neg(100), pos(10_000)]}
+set_bench! {intersection_100_pos_vs_100_neg, intersection, count, [pos(100), neg(100)]}
+set_bench! {intersection_100_pos_vs_10k_neg, intersection, count, [pos(100), neg(10_000)]}
+set_bench! {intersection_10k_neg_vs_100_pos, intersection, count, [neg(10_000), pos(100)]}
+set_bench! {intersection_10k_neg_vs_10k_pos, intersection, count, [neg(10_000), pos(10_000)]}
+set_bench! {intersection_10k_pos_vs_100_neg, intersection, count, [pos(10_000), neg(100)]}
+set_bench! {intersection_10k_pos_vs_10k_neg, intersection, count, [pos(10_000), neg(10_000)]}
+set_bench! {intersection_random_100_vs_100, intersection, count, [random(100), random(100)]}
+set_bench! {intersection_random_100_vs_10k, intersection, count, [random(100), random(10_000)]}
+set_bench! {intersection_random_10k_vs_100, intersection, count, [random(10_000), random(100)]}
+set_bench! {intersection_random_10k_vs_10k, intersection, count, [random(10_000), random(10_000)]}
+set_bench! {intersection_staggered_100_vs_100, intersection, count, stagger(100, 1)}
+set_bench! {intersection_staggered_10k_vs_10k, intersection, count, stagger(10_000, 1)}
+set_bench! {intersection_staggered_100_vs_10k, intersection, count, stagger(100, 100)}
+set_bench! {difference_random_100_vs_100, difference, count, [random(100), random(100)]}
+set_bench! {difference_random_100_vs_10k, difference, count, [random(100), random(10_000)]}
+set_bench! {difference_random_10k_vs_100, difference, count, [random(10_000), random(100)]}
+set_bench! {difference_random_10k_vs_10k, difference, count, [random(10_000), random(10_000)]}
+set_bench! {difference_staggered_100_vs_100, difference, count, stagger(100, 1)}
+set_bench! {difference_staggered_10k_vs_10k, difference, count, stagger(10_000, 1)}
+set_bench! {difference_staggered_100_vs_10k, difference, count, stagger(100, 100)}
+set_bench! {is_subset_100_vs_100, is_subset, clone, [pos(100), pos(100)]}
+set_bench! {is_subset_100_vs_10k, is_subset, clone, [pos(100), pos(10_000)]}
+set_bench! {is_subset_10k_vs_100, is_subset, clone, [pos(10_000), pos(100)]}
+set_bench! {is_subset_10k_vs_10k, is_subset, clone, [pos(10_000), pos(10_000)]}
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index b2315c6a739..6a6a9146e24 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -63,6 +63,8 @@
 //!
 //! [dereferencing]: ../../std/ops/trait.Deref.html
 //! [`Box`]: struct.Box.html
+//! [`Global`]: ../alloc/struct.Global.html
+//! [`Layout`]: ../alloc/struct.Layout.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -81,7 +83,7 @@ use core::ops::{
     CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState
 };
 use core::ptr::{self, NonNull, Unique};
-use core::task::{Waker, Poll};
+use core::task::{Context, Poll};
 
 use crate::vec::Vec;
 use crate::raw_vec::RawVec;
@@ -694,6 +696,28 @@ impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {
 #[stable(feature = "fused", since = "1.26.0")]
 impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {}
 
+#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
+impl<A, F: FnOnce<A> + ?Sized> FnOnce<A> for Box<F> {
+    type Output = <F as FnOnce<A>>::Output;
+
+    extern "rust-call" fn call_once(self, args: A) -> Self::Output {
+        <F as FnOnce<A>>::call_once(*self, args)
+    }
+}
+
+#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
+impl<A, F: FnMut<A> + ?Sized> FnMut<A> for Box<F> {
+    extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output {
+        <F as FnMut<A>>::call_mut(self, args)
+    }
+}
+
+#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
+impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
+    extern "rust-call" fn call(&self, args: A) -> Self::Output {
+        <F as Fn<A>>::call(self, args)
+    }
+}
 
 /// `FnBox` is a version of the `FnOnce` intended for use with boxed
 /// closure objects. The idea is that where one would normally store a
@@ -735,9 +759,7 @@ impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {}
 #[rustc_paren_sugar]
 #[unstable(feature = "fnbox",
            reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
-pub trait FnBox<A> {
-    type Output;
-
+pub trait FnBox<A>: FnOnce<A> {
     fn call_box(self: Box<Self>, args: A) -> Self::Output;
 }
 
@@ -746,33 +768,11 @@ pub trait FnBox<A> {
 impl<A, F> FnBox<A> for F
     where F: FnOnce<A>
 {
-    type Output = F::Output;
-
     fn call_box(self: Box<F>, args: A) -> F::Output {
         self.call_once(args)
     }
 }
 
-#[unstable(feature = "fnbox",
-           reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
-impl<A, R> FnOnce<A> for Box<dyn FnBox<A, Output = R> + '_> {
-    type Output = R;
-
-    extern "rust-call" fn call_once(self, args: A) -> R {
-        self.call_box(args)
-    }
-}
-
-#[unstable(feature = "fnbox",
-           reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")]
-impl<A, R> FnOnce<A> for Box<dyn FnBox<A, Output = R> + Send + '_> {
-    type Output = R;
-
-    extern "rust-call" fn call_once(self, args: A) -> R {
-        self.call_box(args)
-    }
-}
-
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
 
@@ -914,7 +914,7 @@ impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
 impl<F: ?Sized + Future + Unpin> Future for Box<F> {
     type Output = F::Output;
 
-    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
-        F::poll(Pin::new(&mut *self), waker)
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        F::poll(Pin::new(&mut *self), cx)
     }
 }
diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs
index a171f128c24..8c142a3d317 100644
--- a/src/liballoc/collections/binary_heap.rs
+++ b/src/liballoc/collections/binary_heap.rs
@@ -1177,9 +1177,7 @@ impl<T: Ord> BinaryHeap<T> {
 
         self.reserve(lower);
 
-        for elem in iterator {
-            self.push(elem);
-        }
+        iterator.for_each(move |elem| self.push(elem));
     }
 }
 
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index ce29978856f..6b079fc87cc 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -1727,9 +1727,9 @@ impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
 impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
     #[inline]
     fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
-        for (k, v) in iter {
+        iter.into_iter().for_each(move |(k, v)| {
             self.insert(k, v);
-        }
+        });
     }
 }
 
diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs
index 2be6455ad59..16a96ca19b8 100644
--- a/src/liballoc/collections/btree/set.rs
+++ b/src/liballoc/collections/btree/set.rs
@@ -3,7 +3,7 @@
 
 use core::borrow::Borrow;
 use core::cmp::Ordering::{self, Less, Greater, Equal};
-use core::cmp::{min, max};
+use core::cmp::max;
 use core::fmt::{self, Debug};
 use core::iter::{Peekable, FromIterator, FusedIterator};
 use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeBounds};
@@ -118,17 +118,36 @@ pub struct Range<'a, T: 'a> {
 /// [`difference`]: struct.BTreeSet.html#method.difference
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Difference<'a, T: 'a> {
-    a: Peekable<Iter<'a, T>>,
-    b: Peekable<Iter<'a, T>>,
+    inner: DifferenceInner<'a, T>,
+}
+enum DifferenceInner<'a, T: 'a> {
+    Stitch {
+        self_iter: Iter<'a, T>,
+        other_iter: Peekable<Iter<'a, T>>,
+    },
+    Search {
+        self_iter: Iter<'a, T>,
+        other_set: &'a BTreeSet<T>,
+    },
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
 impl<T: fmt::Debug> fmt::Debug for Difference<'_, T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("Difference")
-         .field(&self.a)
-         .field(&self.b)
-         .finish()
+        match &self.inner {
+            DifferenceInner::Stitch {
+                self_iter,
+                other_iter,
+            } => f
+                .debug_tuple("Difference")
+                .field(&self_iter)
+                .field(&other_iter)
+                .finish(),
+            DifferenceInner::Search {
+                self_iter,
+                other_set: _,
+            } => f.debug_tuple("Difference").field(&self_iter).finish(),
+        }
     }
 }
 
@@ -164,17 +183,36 @@ impl<T: fmt::Debug> fmt::Debug for SymmetricDifference<'_, T> {
 /// [`intersection`]: struct.BTreeSet.html#method.intersection
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Intersection<'a, T: 'a> {
-    a: Peekable<Iter<'a, T>>,
-    b: Peekable<Iter<'a, T>>,
+    inner: IntersectionInner<'a, T>,
+}
+enum IntersectionInner<'a, T: 'a> {
+    Stitch {
+        small_iter: Iter<'a, T>, // for size_hint, should be the smaller of the sets
+        other_iter: Iter<'a, T>,
+    },
+    Search {
+        small_iter: Iter<'a, T>,
+        large_set: &'a BTreeSet<T>,
+    },
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
 impl<T: fmt::Debug> fmt::Debug for Intersection<'_, T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("Intersection")
-         .field(&self.a)
-         .field(&self.b)
-         .finish()
+        match &self.inner {
+            IntersectionInner::Stitch {
+                small_iter,
+                other_iter,
+            } => f
+                .debug_tuple("Intersection")
+                .field(&small_iter)
+                .field(&other_iter)
+                .finish(),
+            IntersectionInner::Search {
+                small_iter,
+                large_set: _,
+            } => f.debug_tuple("Intersection").field(&small_iter).finish(),
+        }
     }
 }
 
@@ -201,6 +239,14 @@ impl<T: fmt::Debug> fmt::Debug for Union<'_, T> {
     }
 }
 
+// This constant is used by functions that compare two sets.
+// It estimates the relative size at which searching performs better
+// than iterating, based on the benchmarks in
+// https://github.com/ssomers/rust_bench_btreeset_intersection;
+// It's used to divide rather than multiply sizes, to rule out overflow,
+// and it's a power of two to make that division cheap.
+const ITER_PERFORMANCE_TIPPING_SIZE_DIFF: usize = 16;
+
 impl<T: Ord> BTreeSet<T> {
     /// Makes a new `BTreeSet` with a reasonable choice of B.
     ///
@@ -268,9 +314,24 @@ impl<T: Ord> BTreeSet<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
-        Difference {
-            a: self.iter().peekable(),
-            b: other.iter().peekable(),
+        if self.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
+            // Self is bigger than or not much smaller than other set.
+            // Iterate both sets jointly, spotting matches along the way.
+            Difference {
+                inner: DifferenceInner::Stitch {
+                    self_iter: self.iter(),
+                    other_iter: other.iter().peekable(),
+                },
+            }
+        } else {
+            // Self is much smaller than other set, or both sets are empty.
+            // Iterate the small set, searching for matches in the large set.
+            Difference {
+                inner: DifferenceInner::Search {
+                    self_iter: self.iter(),
+                    other_set: other,
+                },
+            }
         }
     }
 
@@ -326,9 +387,29 @@ impl<T: Ord> BTreeSet<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>) -> Intersection<'a, T> {
-        Intersection {
-            a: self.iter().peekable(),
-            b: other.iter().peekable(),
+        let (small, other) = if self.len() <= other.len() {
+            (self, other)
+        } else {
+            (other, self)
+        };
+        if small.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
+            // Small set is not much smaller than other set.
+            // Iterate both sets jointly, spotting matches along the way.
+            Intersection {
+                inner: IntersectionInner::Stitch {
+                    small_iter: small.iter(),
+                    other_iter: other.iter(),
+                },
+            }
+        } else {
+            // Big difference in number of elements, or both sets are empty.
+            // Iterate the small set, searching for matches in the large set.
+            Intersection {
+                inner: IntersectionInner::Search {
+                    small_iter: small.iter(),
+                    large_set: other,
+                },
+            }
         }
     }
 
@@ -462,28 +543,44 @@ impl<T: Ord> BTreeSet<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_subset(&self, other: &BTreeSet<T>) -> bool {
-        // Stolen from TreeMap
-        let mut x = self.iter();
-        let mut y = other.iter();
-        let mut a = x.next();
-        let mut b = y.next();
-        while a.is_some() {
-            if b.is_none() {
-                return false;
-            }
+        // Same result as self.difference(other).next().is_none()
+        // but the 3 paths below are faster (in order: hugely, 20%, 5%).
+        if self.len() > other.len() {
+            false
+        } else if self.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
+            // Self is not much smaller than other set.
+            // Stolen from TreeMap
+            let mut x = self.iter();
+            let mut y = other.iter();
+            let mut a = x.next();
+            let mut b = y.next();
+            while a.is_some() {
+                if b.is_none() {
+                    return false;
+                }
 
-            let a1 = a.unwrap();
-            let b1 = b.unwrap();
+                let a1 = a.unwrap();
+                let b1 = b.unwrap();
 
-            match b1.cmp(a1) {
-                Less => (),
-                Greater => return false,
-                Equal => a = x.next(),
-            }
+                match b1.cmp(a1) {
+                    Less => (),
+                    Greater => return false,
+                    Equal => a = x.next(),
+                }
 
-            b = y.next();
+                b = y.next();
+            }
+            true
+        } else {
+            // Big difference in number of elements, or both sets are empty.
+            // Iterate the small set, searching for matches in the large set.
+            for next in self {
+                if !other.contains(next) {
+                    return false;
+                }
+            }
+            true
         }
-        true
     }
 
     /// Returns `true` if the set is a superset of another,
@@ -786,9 +883,9 @@ impl<'a, T> IntoIterator for &'a BTreeSet<T> {
 impl<T: Ord> Extend<T> for BTreeSet<T> {
     #[inline]
     fn extend<Iter: IntoIterator<Item = T>>(&mut self, iter: Iter) {
-        for elem in iter {
+        iter.into_iter().for_each(move |elem| {
             self.insert(elem);
-        }
+        });
     }
 }
 
@@ -1001,8 +1098,22 @@ fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>, short: Ordering, long: Ordering
 impl<T> Clone for Difference<'_, T> {
     fn clone(&self) -> Self {
         Difference {
-            a: self.a.clone(),
-            b: self.b.clone(),
+            inner: match &self.inner {
+                DifferenceInner::Stitch {
+                    self_iter,
+                    other_iter,
+                } => DifferenceInner::Stitch {
+                    self_iter: self_iter.clone(),
+                    other_iter: other_iter.clone(),
+                },
+                DifferenceInner::Search {
+                    self_iter,
+                    other_set,
+                } => DifferenceInner::Search {
+                    self_iter: self_iter.clone(),
+                    other_set,
+                },
+            },
         }
     }
 }
@@ -1011,24 +1122,52 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
     type Item = &'a T;
 
     fn next(&mut self) -> Option<&'a T> {
-        loop {
-            match cmp_opt(self.a.peek(), self.b.peek(), Less, Less) {
-                Less => return self.a.next(),
-                Equal => {
-                    self.a.next();
-                    self.b.next();
-                }
-                Greater => {
-                    self.b.next();
+        match &mut self.inner {
+            DifferenceInner::Stitch {
+                self_iter,
+                other_iter,
+            } => {
+                let mut self_next = self_iter.next()?;
+                loop {
+                    match other_iter
+                        .peek()
+                        .map_or(Less, |other_next| Ord::cmp(self_next, other_next))
+                    {
+                        Less => return Some(self_next),
+                        Equal => {
+                            self_next = self_iter.next()?;
+                            other_iter.next();
+                        }
+                        Greater => {
+                            other_iter.next();
+                        }
+                    }
                 }
             }
+            DifferenceInner::Search {
+                self_iter,
+                other_set,
+            } => loop {
+                let self_next = self_iter.next()?;
+                if !other_set.contains(&self_next) {
+                    return Some(self_next);
+                }
+            },
         }
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let a_len = self.a.len();
-        let b_len = self.b.len();
-        (a_len.saturating_sub(b_len), Some(a_len))
+        let (self_len, other_len) = match &self.inner {
+            DifferenceInner::Stitch {
+                self_iter,
+                other_iter
+            } => (self_iter.len(), other_iter.len()),
+            DifferenceInner::Search {
+                self_iter,
+                other_set
+            } => (self_iter.len(), other_set.len()),
+        };
+        (self_len.saturating_sub(other_len), Some(self_len))
     }
 }
 
@@ -1073,8 +1212,22 @@ impl<T: Ord> FusedIterator for SymmetricDifference<'_, T> {}
 impl<T> Clone for Intersection<'_, T> {
     fn clone(&self) -> Self {
         Intersection {
-            a: self.a.clone(),
-            b: self.b.clone(),
+            inner: match &self.inner {
+                IntersectionInner::Stitch {
+                    small_iter,
+                    other_iter,
+                } => IntersectionInner::Stitch {
+                    small_iter: small_iter.clone(),
+                    other_iter: other_iter.clone(),
+                },
+                IntersectionInner::Search {
+                    small_iter,
+                    large_set,
+                } => IntersectionInner::Search {
+                    small_iter: small_iter.clone(),
+                    large_set,
+                },
+            },
         }
     }
 }
@@ -1083,24 +1236,39 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> {
     type Item = &'a T;
 
     fn next(&mut self) -> Option<&'a T> {
-        loop {
-            match Ord::cmp(self.a.peek()?, self.b.peek()?) {
-                Less => {
-                    self.a.next();
-                }
-                Equal => {
-                    self.b.next();
-                    return self.a.next();
-                }
-                Greater => {
-                    self.b.next();
+        match &mut self.inner {
+            IntersectionInner::Stitch {
+                small_iter,
+                other_iter,
+            } => {
+                let mut small_next = small_iter.next()?;
+                let mut other_next = other_iter.next()?;
+                loop {
+                    match Ord::cmp(small_next, other_next) {
+                        Less => small_next = small_iter.next()?,
+                        Greater => other_next = other_iter.next()?,
+                        Equal => return Some(small_next),
+                    }
                 }
             }
+            IntersectionInner::Search {
+                small_iter,
+                large_set,
+            } => loop {
+                let small_next = small_iter.next()?;
+                if large_set.contains(&small_next) {
+                    return Some(small_next);
+                }
+            },
         }
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, Some(min(self.a.len(), self.b.len())))
+        let min_len = match &self.inner {
+            IntersectionInner::Stitch { small_iter, .. } => small_iter.len(),
+            IntersectionInner::Search { small_iter, .. } => small_iter.len(),
+        };
+        (0, Some(min_len))
     }
 }
 
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index c2ee2e63156..d6d84a4f083 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -1107,9 +1107,7 @@ impl<T> Extend<T> for LinkedList<T> {
 
 impl<I: IntoIterator> SpecExtend<I> for LinkedList<I::Item> {
     default fn spec_extend(&mut self, iter: I) {
-        for elt in iter {
-            self.push_back(elt);
-        }
+        iter.into_iter().for_each(move |elt| self.push_back(elt));
     }
 }
 
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs
index 4e90f783ec6..4bea615ab86 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -2677,9 +2677,7 @@ impl<'a, T> IntoIterator for &'a mut VecDeque<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Extend<A> for VecDeque<A> {
     fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
-        for elt in iter {
-            self.push_back(elt);
-        }
+        iter.into_iter().for_each(move |elt| self.push_back(elt));
     }
 }
 
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 90ff56814fb..7f3acc933d4 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -51,10 +51,7 @@
 //! default global allocator. It is not compatible with the libc allocator API.
 
 #![allow(unused_attributes)]
-#![unstable(feature = "alloc",
-            reason = "this library is unlikely to be stabilized in its current \
-                      form or name",
-            issue = "27783")]
+#![stable(feature = "alloc", since = "1.36.0")]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
        test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
@@ -107,6 +104,7 @@
 #![feature(unboxed_closures)]
 #![feature(unicode_internals)]
 #![feature(unsize)]
+#![feature(unsized_locals)]
 #![feature(allocator_internals)]
 #![feature(on_unimplemented)]
 #![feature(rustc_const_unstable)]
diff --git a/src/liballoc/prelude/mod.rs b/src/liballoc/prelude/mod.rs
index 33cc51d1732..0534ad3edc7 100644
--- a/src/liballoc/prelude/mod.rs
+++ b/src/liballoc/prelude/mod.rs
@@ -5,7 +5,6 @@
 //!
 //! ```
 //! # #![allow(unused_imports)]
-//! # #![feature(alloc)]
 //! #![feature(alloc_prelude)]
 //! extern crate alloc;
 //! use alloc::prelude::v1::*;
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index fe28fe5095c..d1fc5ac3b30 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -256,7 +256,7 @@ impl<T, A: Alloc> RawVec<T, A> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc, raw_vec_internals)]
+    /// # #![feature(raw_vec_internals)]
     /// # extern crate alloc;
     /// # use std::ptr;
     /// # use alloc::raw_vec::RawVec;
@@ -460,7 +460,7 @@ impl<T, A: Alloc> RawVec<T, A> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(alloc, raw_vec_internals)]
+    /// # #![feature(raw_vec_internals)]
     /// # extern crate alloc;
     /// # use std::ptr;
     /// # use alloc::raw_vec::RawVec;
diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs
index 4f5168f1ce5..d52814118b3 100644
--- a/src/liballoc/tests/btree/set.rs
+++ b/src/liballoc/tests/btree/set.rs
@@ -69,6 +69,20 @@ fn test_intersection() {
     check_intersection(&[11, 1, 3, 77, 103, 5, -5],
                        &[2, 11, 77, -9, -42, 5, 3],
                        &[3, 5, 11, 77]);
+    let large = (0..1000).collect::<Vec<_>>();
+    check_intersection(&[], &large, &[]);
+    check_intersection(&large, &[], &[]);
+    check_intersection(&[-1], &large, &[]);
+    check_intersection(&large, &[-1], &[]);
+    check_intersection(&[0], &large, &[0]);
+    check_intersection(&large, &[0], &[0]);
+    check_intersection(&[999], &large, &[999]);
+    check_intersection(&large, &[999], &[999]);
+    check_intersection(&[1000], &large, &[]);
+    check_intersection(&large, &[1000], &[]);
+    check_intersection(&[11, 5000, 1, 3, 77, 8924, 103],
+                       &large,
+                       &[1, 3, 11, 77, 103]);
 }
 
 #[test]
@@ -84,6 +98,18 @@ fn test_difference() {
     check_difference(&[-5, 11, 22, 33, 40, 42],
                      &[-12, -5, 14, 23, 34, 38, 39, 50],
                      &[11, 22, 33, 40, 42]);
+    let large = (0..1000).collect::<Vec<_>>();
+    check_difference(&[], &large, &[]);
+    check_difference(&[-1], &large, &[-1]);
+    check_difference(&[0], &large, &[]);
+    check_difference(&[999], &large, &[]);
+    check_difference(&[1000], &large, &[1000]);
+    check_difference(&[11, 5000, 1, 3, 77, 8924, 103],
+                     &large,
+                     &[5000, 8924]);
+    check_difference(&large, &[], &large);
+    check_difference(&large, &[-1], &large);
+    check_difference(&large, &[1000], &large);
 }
 
 #[test]
@@ -115,6 +141,41 @@ fn test_union() {
 }
 
 #[test]
+// Only tests the simple function definition with respect to intersection
+fn test_is_disjoint() {
+    let one = [1].into_iter().collect::<BTreeSet<_>>();
+    let two = [2].into_iter().collect::<BTreeSet<_>>();
+    assert!(one.is_disjoint(&two));
+}
+
+#[test]
+// Also tests the trivial function definition of is_superset
+fn test_is_subset() {
+    fn is_subset(a: &[i32], b: &[i32]) -> bool {
+        let set_a = a.iter().collect::<BTreeSet<_>>();
+        let set_b = b.iter().collect::<BTreeSet<_>>();
+        set_a.is_subset(&set_b)
+    }
+
+    assert_eq!(is_subset(&[], &[]), true);
+    assert_eq!(is_subset(&[], &[1, 2]), true);
+    assert_eq!(is_subset(&[0], &[1, 2]), false);
+    assert_eq!(is_subset(&[1], &[1, 2]), true);
+    assert_eq!(is_subset(&[2], &[1, 2]), true);
+    assert_eq!(is_subset(&[3], &[1, 2]), false);
+    assert_eq!(is_subset(&[1, 2], &[1]), false);
+    assert_eq!(is_subset(&[1, 2], &[1, 2]), true);
+    assert_eq!(is_subset(&[1, 2], &[2, 3]), false);
+    let large = (0..1000).collect::<Vec<_>>();
+    assert_eq!(is_subset(&[], &large), true);
+    assert_eq!(is_subset(&large, &[]), false);
+    assert_eq!(is_subset(&[-1], &large), false);
+    assert_eq!(is_subset(&[0], &large), true);
+    assert_eq!(is_subset(&[1, 2], &large), true);
+    assert_eq!(is_subset(&[999, 1000], &large), false);
+}
+
+#[test]
 fn test_zip() {
     let mut x = BTreeSet::new();
     x.insert(5);
diff --git a/src/libarena/Cargo.toml b/src/libarena/Cargo.toml
index 82fc64ba64e..aa1bf38b995 100644
--- a/src/libarena/Cargo.toml
+++ b/src/libarena/Cargo.toml
@@ -11,3 +11,4 @@ crate-type = ["dylib"]
 
 [dependencies]
 rustc_data_structures = { path = "../librustc_data_structures" }
+smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 8ae046c0796..cfe317a00f9 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -12,8 +12,8 @@
        test(no_crate_inject, attr(deny(warnings))))]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
-#![feature(alloc)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(raw_vec_internals)]
@@ -23,7 +23,9 @@
 
 extern crate alloc;
 
+use rustc_data_structures::cold_path;
 use rustc_data_structures::sync::MTLock;
+use smallvec::SmallVec;
 
 use std::cell::{Cell, RefCell};
 use std::cmp;
@@ -55,6 +57,8 @@ pub struct TypedArena<T> {
 struct TypedArenaChunk<T> {
     /// The raw storage for the arena chunk.
     storage: RawVec<T>,
+    /// The number of valid entries in the chunk.
+    entries: usize,
 }
 
 impl<T> TypedArenaChunk<T> {
@@ -62,6 +66,7 @@ impl<T> TypedArenaChunk<T> {
     unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
         TypedArenaChunk {
             storage: RawVec::with_capacity(capacity),
+            entries: 0,
         }
     }
 
@@ -149,6 +154,34 @@ impl<T> TypedArena<T> {
         }
     }
 
+    #[inline]
+    fn can_allocate(&self, len: usize) -> bool {
+        let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
+        let at_least_bytes = len.checked_mul(mem::size_of::<T>()).unwrap();
+        available_capacity_bytes >= at_least_bytes
+    }
+
+    /// Ensures there's enough space in the current chunk to fit `len` objects.
+    #[inline]
+    fn ensure_capacity(&self, len: usize) {
+        if !self.can_allocate(len) {
+            self.grow(len);
+            debug_assert!(self.can_allocate(len));
+        }
+    }
+
+    #[inline]
+    unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T {
+        assert!(mem::size_of::<T>() != 0);
+        assert!(len != 0);
+
+        self.ensure_capacity(len);
+
+        let start_ptr = self.ptr.get();
+        self.ptr.set(start_ptr.add(len));
+        start_ptr
+    }
+
     /// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable
     /// reference to it. Will panic if passed a zero-sized types.
     ///
@@ -161,21 +194,64 @@ impl<T> TypedArena<T> {
     where
         T: Copy,
     {
+        unsafe {
+            let len = slice.len();
+            let start_ptr = self.alloc_raw_slice(len);
+            slice.as_ptr().copy_to_nonoverlapping(start_ptr, len);
+            slice::from_raw_parts_mut(start_ptr, len)
+        }
+    }
+
+    #[inline]
+    pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
         assert!(mem::size_of::<T>() != 0);
-        assert!(slice.len() != 0);
+        let mut iter = iter.into_iter();
+        let size_hint = iter.size_hint();
 
-        let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
-        let at_least_bytes = slice.len() * mem::size_of::<T>();
-        if available_capacity_bytes < at_least_bytes {
-            self.grow(slice.len());
-        }
+        match size_hint {
+            (min, Some(max)) if min == max => {
+                // We know the exact number of elements the iterator will produce here
+                let len = min;
 
-        unsafe {
-            let start_ptr = self.ptr.get();
-            let arena_slice = slice::from_raw_parts_mut(start_ptr, slice.len());
-            self.ptr.set(start_ptr.add(arena_slice.len()));
-            arena_slice.copy_from_slice(slice);
-            arena_slice
+                if len == 0 {
+                    return &mut [];
+                }
+
+                self.ensure_capacity(len);
+
+                let slice = self.ptr.get();
+
+                unsafe {
+                    let mut ptr = self.ptr.get();
+                    for _ in 0..len {
+                        // Write into uninitialized memory.
+                        ptr::write(ptr, iter.next().unwrap());
+                        // Advance the pointer.
+                        ptr = ptr.offset(1);
+                        // Update the pointer per iteration so if `iter.next()` panics
+                        // we destroy the correct amount
+                        self.ptr.set(ptr);
+                    }
+                    slice::from_raw_parts_mut(slice, len)
+                }
+            }
+            _ => {
+                cold_path(move || -> &mut [T] {
+                    let mut vec: SmallVec<[_; 8]> = iter.collect();
+                    if vec.is_empty() {
+                        return &mut [];
+                    }
+                    // Move the content to the arena by copying it and then forgetting
+                    // the content of the SmallVec
+                    unsafe {
+                        let len = vec.len();
+                        let start_ptr = self.alloc_raw_slice(len);
+                        vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
+                        vec.set_len(0);
+                        slice::from_raw_parts_mut(start_ptr, len)
+                    }
+                })
+            }
         }
     }
 
@@ -189,6 +265,7 @@ impl<T> TypedArena<T> {
             if let Some(last_chunk) = chunks.last_mut() {
                 let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
                 let currently_used_cap = used_bytes / mem::size_of::<T>();
+                last_chunk.entries = currently_used_cap;
                 if last_chunk.storage.reserve_in_place(currently_used_cap, n) {
                     self.end.set(last_chunk.end());
                     return;
@@ -222,8 +299,7 @@ impl<T> TypedArena<T> {
                 let len = chunks_borrow.len();
                 // If `T` is ZST, code below has no effect.
                 for mut chunk in chunks_borrow.drain(..len-1) {
-                    let cap = chunk.storage.cap();
-                    chunk.destroy(cap);
+                    chunk.destroy(chunk.entries);
                 }
             }
         }
@@ -265,8 +341,7 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena<T> {
                 self.clear_last_chunk(&mut last_chunk);
                 // The last chunk will be dropped. Destroy all other chunks.
                 for chunk in chunks_borrow.iter_mut() {
-                    let cap = chunk.storage.cap();
-                    chunk.destroy(cap);
+                    chunk.destroy(chunk.entries);
                 }
             }
             // RawVec handles deallocation of `last_chunk` and `self.chunks`.
@@ -410,6 +485,54 @@ impl DroplessArena {
             arena_slice
         }
     }
+
+    #[inline]
+    pub fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
+        let mut iter = iter.into_iter();
+        assert!(mem::size_of::<T>() != 0);
+        assert!(!mem::needs_drop::<T>());
+
+        let size_hint = iter.size_hint();
+
+        match size_hint {
+            (min, Some(max)) if min == max => {
+                // We know the exact number of elements the iterator will produce here
+                let len = min;
+
+                if len == 0 {
+                    return &mut []
+                }
+                let size = len.checked_mul(mem::size_of::<T>()).unwrap();
+                let mem = self.alloc_raw(size, mem::align_of::<T>()) as *mut _ as *mut T;
+                unsafe {
+                    for i in 0..len {
+                        ptr::write(mem.offset(i as isize), iter.next().unwrap())
+                    }
+                    slice::from_raw_parts_mut(mem, len)
+                }
+            }
+            (_, _) => {
+                cold_path(move || -> &mut [T] {
+                    let mut vec: SmallVec<[_; 8]> = iter.collect();
+                    if vec.is_empty() {
+                        return &mut [];
+                    }
+                    // Move the content to the arena by copying it and then forgetting
+                    // the content of the SmallVec
+                    unsafe {
+                        let len = vec.len();
+                        let start_ptr = self.alloc_raw(
+                            len * mem::size_of::<T>(),
+                            mem::align_of::<T>()
+                        ) as *mut _ as *mut T;
+                        vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
+                        vec.set_len(0);
+                        slice::from_raw_parts_mut(start_ptr, len)
+                    }
+                })
+            }
+        }
+    }
 }
 
 #[derive(Default)]
diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs
index 635537e3121..10b6cc61d99 100644
--- a/src/libcore/benches/ascii.rs
+++ b/src/libcore/benches/ascii.rs
@@ -2,7 +2,7 @@
 // after wrap-adding 0x1F:
 //
 //     b'a' + 0x1F == 0x80 == 0b1000_0000
-//     b'z' + 0x1F == 0x98 == 0b10011000
+//     b'z' + 0x1F == 0x98 == 0b1001_1000
 //
 // Lower-case ASCII 'z' is the last byte that has its highest bit unset
 // after wrap-adding 0x05:
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index 825bd368bdf..7dcfad8306f 100644
--- a/src/libcore/benches/iter.rs
+++ b/src/libcore/benches/iter.rs
@@ -334,3 +334,13 @@ fn bench_filter_chain_ref_count(b: &mut Bencher) {
         (0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
     })
 }
+
+#[bench]
+fn bench_partial_cmp(b: &mut Bencher) {
+    b.iter(|| (0..100000).map(black_box).partial_cmp((0..100000).map(black_box)))
+}
+
+#[bench]
+fn bench_lt(b: &mut Bencher) {
+    b.iter(|| (0..100000).map(black_box).lt((0..100000).map(black_box)))
+}
diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs
index 89668dc0650..4d58aaca941 100644
--- a/src/libcore/borrow.rs
+++ b/src/libcore/borrow.rs
@@ -32,6 +32,10 @@
 /// on the identical behavior of these additional trait implementations.
 /// These traits will likely appear as additional trait bounds.
 ///
+/// In particular `Eq`, `Ord` and `Hash` must be equivalent for
+/// borrowed and owned values: `x.borrow() == y.borrow()` should give the
+/// same result as `x == y`.
+///
 /// If generic code merely needs to work for all types that can
 /// provide a reference to related type `T`, it is often better to use
 /// [`AsRef<T>`] as more types can safely implement it.
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 80dd51acc9e..5325b339151 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -955,6 +955,44 @@ impl<T: ?Sized> RefCell<T> {
             &mut *self.value.get()
         }
     }
+
+    /// Immutably borrows the wrapped value, returning an error if the value is
+    /// currently mutably borrowed.
+    ///
+    /// # Safety
+    ///
+    /// Unlike `RefCell::borrow`, this method is unsafe because it does not
+    /// return a `Ref`, thus leaving the borrow flag untouched. Mutably
+    /// borrowing the `RefCell` while the reference returned by this method
+    /// is alive is undefined behaviour.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(borrow_state)]
+    /// use std::cell::RefCell;
+    ///
+    /// let c = RefCell::new(5);
+    ///
+    /// {
+    ///     let m = c.borrow_mut();
+    ///     assert!(unsafe { c.try_borrow_unguarded() }.is_err());
+    /// }
+    ///
+    /// {
+    ///     let m = c.borrow();
+    ///     assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
+    /// }
+    /// ```
+    #[unstable(feature = "borrow_state", issue = "27733")]
+    #[inline]
+    pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
+        if !is_writing(self.borrow.get()) {
+            Ok(&*self.value.get())
+        } else {
+            Err(BorrowError { _private: () })
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 807b35e1af1..14908108fc5 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -286,13 +286,13 @@ pub struct AssertParamIsEq<T: Eq + ?Sized> { _field: ::marker::PhantomData<T> }
 #[derive(Clone, Copy, PartialEq, Debug, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Ordering {
-    /// An ordering where a compared value is less [than another].
+    /// An ordering where a compared value is less than another.
     #[stable(feature = "rust1", since = "1.0.0")]
     Less = -1,
-    /// An ordering where a compared value is equal [to another].
+    /// An ordering where a compared value is equal to another.
     #[stable(feature = "rust1", since = "1.0.0")]
     Equal = 0,
-    /// An ordering where a compared value is greater [than another].
+    /// An ordering where a compared value is greater than another.
     #[stable(feature = "rust1", since = "1.0.0")]
     Greater = 1,
 }
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index a6c65e890a5..e903bd936c4 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -105,11 +105,13 @@ pub const fn identity<T>(x: T) -> T { x }
 /// `&T` or write a custom function.
 ///
 ///
-/// `AsRef` is very similar to, but serves a slightly different purpose than [`Borrow`]:
+/// `AsRef` has the same signature as [`Borrow`], but `Borrow` is different in few aspects:
 ///
-/// - Use `AsRef` when the goal is to simply convert into a reference
-/// - Use `Borrow` when the goal is related to writing code that is agnostic to
-///   the type of borrow and whether it is a reference or value
+/// - Unlike `AsRef`, `Borrow` has a blanket impl for any `T`, and can be used to accept either
+///   a reference or a value.
+/// - `Borrow` also requires that `Hash`, `Eq` and `Ord` for borrowed value are
+///   equivalent to those of the owned value. For this reason, if you want to
+///   borrow only a single field of a struct you can implement `AsRef`, but not `Borrow`.
 ///
 /// [`Borrow`]: ../../std/borrow/trait.Borrow.html
 ///
@@ -427,6 +429,26 @@ pub trait TryInto<T>: Sized {
 /// When the `!` type is stablized `Infallible` and `!` will be
 /// equivalent.
 ///
+/// `TryFrom<T>` can be implemented as follows:
+///
+/// ```
+/// use std::convert::TryFrom;
+///
+/// struct SuperiorThanZero(i32);
+///
+/// impl TryFrom<i32> for SuperiorThanZero {
+///     type Error = &'static str;
+///
+///     fn try_from(value: i32) -> Result<Self, Self::Error> {
+///         if value < 0 {
+///             Err("SuperiorThanZero only accepts value superior than zero!")
+///         } else {
+///             Ok(SuperiorThanZero(value))
+///         }
+///     }
+/// }
+/// ```
+///
 /// # Examples
 ///
 /// As described, [`i32`] implements `TryFrom<i64>`:
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs
index 45994c2b4f0..df3852973b8 100644
--- a/src/libcore/fmt/builders.rs
+++ b/src/libcore/fmt/builders.rs
@@ -11,7 +11,7 @@ impl<'a> PadAdapter<'a> {
         fmt.wrap_buf(move |buf| {
             *slot = Some(PadAdapter {
                 buf,
-                on_newline: false,
+                on_newline: true,
             });
             slot.as_mut().unwrap()
         })
@@ -128,22 +128,21 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut DebugStruct<'a, 'b> {
         self.result = self.result.and_then(|_| {
-            let prefix = if self.has_fields {
-                ","
-            } else {
-                " {"
-            };
-
             if self.is_pretty() {
+                if !self.has_fields {
+                    self.fmt.write_str(" {\n")?;
+                }
                 let mut slot = None;
                 let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot);
-                writer.write_str(prefix)?;
-                writer.write_str("\n")?;
                 writer.write_str(name)?;
                 writer.write_str(": ")?;
-                value.fmt(&mut writer)
+                value.fmt(&mut writer)?;
+                writer.write_str(",\n")
             } else {
-                write!(self.fmt, "{} {}: ", prefix, name)?;
+                let prefix = if self.has_fields { ", " } else { " { " };
+                self.fmt.write_str(prefix)?;
+                self.fmt.write_str(name)?;
+                self.fmt.write_str(": ")?;
                 value.fmt(self.fmt)
             }
         });
@@ -184,7 +183,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
         if self.has_fields {
             self.result = self.result.and_then(|_| {
                 if self.is_pretty() {
-                    self.fmt.write_str("\n}")
+                    self.fmt.write_str("}")
                 } else {
                     self.fmt.write_str(" }")
                 }
@@ -275,21 +274,17 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut DebugTuple<'a, 'b> {
         self.result = self.result.and_then(|_| {
-            let (prefix, space) = if self.fields > 0 {
-                (",", " ")
-            } else {
-                ("(", "")
-            };
-
             if self.is_pretty() {
+                if self.fields == 0 {
+                    self.fmt.write_str("(\n")?;
+                }
                 let mut slot = None;
                 let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot);
-                writer.write_str(prefix)?;
-                writer.write_str("\n")?;
-                value.fmt(&mut writer)
+                value.fmt(&mut writer)?;
+                writer.write_str(",\n")
             } else {
+                let prefix = if self.fields == 0 { "(" } else { ", " };
                 self.fmt.write_str(prefix)?;
-                self.fmt.write_str(space)?;
                 value.fmt(self.fmt)
             }
         });
@@ -326,10 +321,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
     pub fn finish(&mut self) -> fmt::Result {
         if self.fields > 0 {
             self.result = self.result.and_then(|_| {
-                if self.is_pretty() {
-                    self.fmt.write_str("\n")?;
-                }
-                if self.fields == 1 && self.empty_name {
+                if self.fields == 1 && self.empty_name && !self.is_pretty() {
                     self.fmt.write_str(",")?;
                 }
                 self.fmt.write_str(")")
@@ -353,14 +345,13 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
     fn entry(&mut self, entry: &dyn fmt::Debug) {
         self.result = self.result.and_then(|_| {
             if self.is_pretty() {
+                if !self.has_fields {
+                    self.fmt.write_str("\n")?;
+                }
                 let mut slot = None;
                 let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot);
-                writer.write_str(if self.has_fields {
-                    ",\n"
-                } else {
-                    "\n"
-                })?;
-                entry.fmt(&mut writer)
+                entry.fmt(&mut writer)?;
+                writer.write_str(",\n")
             } else {
                 if self.has_fields {
                     self.fmt.write_str(", ")?
@@ -372,15 +363,6 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
         self.has_fields = true;
     }
 
-    pub fn finish(&mut self) {
-        let prefix = if self.is_pretty() && self.has_fields {
-            "\n"
-        } else {
-            ""
-        };
-        self.result = self.result.and_then(|_| self.fmt.write_str(prefix));
-    }
-
     fn is_pretty(&self) -> bool {
         self.fmt.alternate()
     }
@@ -421,7 +403,7 @@ pub struct DebugSet<'a, 'b: 'a> {
 }
 
 pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
-    let result = write!(fmt, "{{");
+    let result = fmt.write_str("{");
     DebugSet {
         inner: DebugInner {
             fmt,
@@ -519,7 +501,6 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn finish(&mut self) -> fmt::Result {
-        self.inner.finish();
         self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
     }
 }
@@ -559,7 +540,7 @@ pub struct DebugList<'a, 'b: 'a> {
 }
 
 pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
-    let result = write!(fmt, "[");
+    let result = fmt.write_str("[");
     DebugList {
         inner: DebugInner {
             fmt,
@@ -657,7 +638,6 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn finish(&mut self) -> fmt::Result {
-        self.inner.finish();
         self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
     }
 }
@@ -699,7 +679,7 @@ pub struct DebugMap<'a, 'b: 'a> {
 }
 
 pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
-    let result = write!(fmt, "{{");
+    let result = fmt.write_str("{");
     DebugMap {
         fmt,
         result,
@@ -734,16 +714,15 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
         self.result = self.result.and_then(|_| {
             if self.is_pretty() {
+                if !self.has_fields {
+                    self.fmt.write_str("\n")?;
+                }
                 let mut slot = None;
                 let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot);
-                writer.write_str(if self.has_fields {
-                    ",\n"
-                } else {
-                    "\n"
-                })?;
                 key.fmt(&mut writer)?;
                 writer.write_str(": ")?;
-                value.fmt(&mut writer)
+                value.fmt(&mut writer)?;
+                writer.write_str(",\n")
             } else {
                 if self.has_fields {
                     self.fmt.write_str(", ")?
@@ -818,12 +797,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn finish(&mut self) -> fmt::Result {
-        let prefix = if self.is_pretty() && self.has_fields {
-            "\n"
-        } else {
-            ""
-        };
-        self.result.and_then(|_| write!(self.fmt, "{}}}", prefix))
+        self.result.and_then(|_| self.fmt.write_str("}"))
     }
 
     fn is_pretty(&self) -> bool {
diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs
index a143b54a61f..114a6b93367 100644
--- a/src/libcore/future/future.rs
+++ b/src/libcore/future/future.rs
@@ -5,7 +5,7 @@
 use marker::Unpin;
 use ops;
 use pin::Pin;
-use task::{Poll, Waker};
+use task::{Context, Poll};
 
 /// A future represents an asynchronous computation.
 ///
@@ -44,8 +44,9 @@ pub trait Future {
     /// Once a future has finished, clients should not `poll` it again.
     ///
     /// When a future is not ready yet, `poll` returns `Poll::Pending` and
-    /// stores a clone of the [`Waker`] to be woken once the future can
-    /// make progress. For example, a future waiting for a socket to become
+    /// stores a clone of the [`Waker`] copied from the current [`Context`].
+    /// This [`Waker`] is then woken once the future can make progress.
+    /// For example, a future waiting for a socket to become
     /// readable would call `.clone()` on the [`Waker`] and store it.
     /// When a signal arrives elsewhere indicating that the socket is readable,
     /// `[Waker::wake]` is called and the socket future's task is awoken.
@@ -88,16 +89,17 @@ pub trait Future {
     ///
     /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
     /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
+    /// [`Context`]: ../task/struct.Context.html
     /// [`Waker`]: ../task/struct.Waker.html
     /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
-    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output>;
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
 }
 
 impl<F: ?Sized + Future + Unpin> Future for &mut F {
     type Output = F::Output;
 
-    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
-        F::poll(Pin::new(&mut **self), waker)
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        F::poll(Pin::new(&mut **self), cx)
     }
 }
 
@@ -108,7 +110,7 @@ where
 {
     type Output = <<P as ops::Deref>::Target as Future>::Output;
 
-    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
-        Pin::get_mut(self).as_mut().poll(waker)
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        Pin::get_mut(self).as_mut().poll(cx)
     }
 }
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index d1ccc148654..d43e6c49f4c 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -50,15 +50,28 @@ pub unsafe fn unreachable_unchecked() -> ! {
     intrinsics::unreachable()
 }
 
-/// Save power or switch hyperthreads in a busy-wait spin-loop.
+/// Signals the processor that it is entering a busy-wait spin-loop.
 ///
-/// This function is deliberately more primitive than
-/// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and
-/// does not directly yield to the system's scheduler.
-/// In some cases it might be useful to use a combination of both functions.
-/// Careful benchmarking is advised.
+/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
+/// power or switching hyper-threads.
 ///
-/// On some platforms this function may not do anything at all.
+/// This function is different than [`std::thread::yield_now`] which directly yields to the
+/// system's scheduler, whereas `spin_loop` only signals the processor that it is entering a
+/// busy-wait spin-loop without yielding control to the system's scheduler.
+///
+/// Using a busy-wait spin-loop with `spin_loop` is ideally used in situations where a
+/// contended lock is held by another thread executed on a different CPU and where the waiting
+/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's
+/// scheduler, no overhead for switching threads occurs. However, if the thread holding the
+/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice
+/// before switching to the thread that holds the lock. If the contending lock is held by a thread
+/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to
+/// use [`std::thread::yield_now`].
+///
+/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
+/// do anything at all.
+///
+/// [`std::thread::yield_now`]: ../../std/thread/fn.yield_now.html
 #[inline]
 #[unstable(feature = "renamed_spin_loop", issue = "55002")]
 pub fn spin_loop() {
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 75a33394e3d..05acd7bd011 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -737,16 +737,6 @@ extern "rust-intrinsic" {
     ///
     /// There are a few things that `transmute` is really useful for.
     ///
-    /// Getting the bitpattern of a floating point type (or, more generally,
-    /// type punning, when `T` and `U` aren't pointers):
-    ///
-    /// ```
-    /// let bitpattern = unsafe {
-    ///     std::mem::transmute::<f32, u32>(1.0)
-    /// };
-    /// assert_eq!(bitpattern, 0x3F800000);
-    /// ```
-    ///
     /// Turning a pointer into a function pointer. This is *not* portable to
     /// machines where function pointers and data pointers have different sizes.
     ///
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index e7efd9728b9..aefed1890fe 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -68,11 +68,9 @@ macro_rules! step_impl_unsigned {
                    issue = "42168")]
         impl Step for $t {
             #[inline]
-            #[allow(trivial_numeric_casts)]
             fn steps_between(start: &$t, end: &$t) -> Option<usize> {
                 if *start < *end {
-                    // Note: We assume $t <= usize here
-                    Some((*end - *start) as usize)
+                    usize::try_from(*end - *start).ok()
                 } else {
                     Some(0)
                 }
@@ -98,13 +96,11 @@ macro_rules! step_impl_signed {
                    issue = "42168")]
         impl Step for $t {
             #[inline]
-            #[allow(trivial_numeric_casts)]
             fn steps_between(start: &$t, end: &$t) -> Option<usize> {
                 if *start < *end {
-                    // Note: We assume $t <= isize here
-                    // Use .wrapping_sub and cast to usize to compute the
-                    // difference that may not fit inside the range of isize.
-                    Some((*end as isize).wrapping_sub(*start as isize) as usize)
+                    // Use .wrapping_sub and cast to unsigned to compute the
+                    // difference that may not fit inside the range of $t.
+                    usize::try_from(end.wrapping_sub(*start) as $unsigned).ok()
                 } else {
                     Some(0)
                 }
@@ -134,46 +130,9 @@ macro_rules! step_impl_signed {
     )*)
 }
 
-macro_rules! step_impl_no_between {
-    ($($t:ty)*) => ($(
-        #[unstable(feature = "step_trait",
-                   reason = "likely to be replaced by finer-grained traits",
-                   issue = "42168")]
-        impl Step for $t {
-            #[inline]
-            fn steps_between(_start: &Self, _end: &Self) -> Option<usize> {
-                None
-            }
-
-            #[inline]
-            fn add_usize(&self, n: usize) -> Option<Self> {
-                self.checked_add(n as $t)
-            }
-
-            step_identical_methods!();
-        }
-    )*)
-}
-
-step_impl_unsigned!(usize u8 u16);
-#[cfg(not(target_pointer_width = "16"))]
-step_impl_unsigned!(u32);
-#[cfg(target_pointer_width = "16")]
-step_impl_no_between!(u32);
+step_impl_unsigned!(usize u8 u16 u32 u64 u128);
 step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
-#[cfg(not(target_pointer_width = "16"))]
-step_impl_signed!([i32: u32]);
-#[cfg(target_pointer_width = "16")]
-step_impl_no_between!(i32);
-#[cfg(target_pointer_width = "64")]
-step_impl_unsigned!(u64);
-#[cfg(target_pointer_width = "64")]
-step_impl_signed!([i64: u64]);
-// If the target pointer width is not 64-bits, we
-// assume here that it is less than 64-bits.
-#[cfg(not(target_pointer_width = "64"))]
-step_impl_no_between!(u64 i64);
-step_impl_no_between!(u128 i128);
+step_impl_signed!([i32: u32] [i64: u64] [i128: u128]);
 
 macro_rules! range_exact_iter_impl {
     ($($t:ty)*) => ($(
@@ -229,7 +188,7 @@ impl<A: Step> Iterator for ops::Range<A> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         match Step::steps_between(&self.start, &self.end) {
             Some(hint) => (hint, Some(hint)),
-            None => (0, None)
+            None => (usize::MAX, None)
         }
     }
 
@@ -273,8 +232,8 @@ range_incl_exact_iter_impl!(u8 u16 i8 i16);
 //
 // They need to guarantee that .size_hint() is either exact, or that
 // the upper bound is None when it does not fit the type limits.
-range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
-range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
+range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128);
+range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128);
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: Step> DoubleEndedIterator for ops::Range<A> {
@@ -350,7 +309,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
 
         match Step::steps_between(&self.start, &self.end) {
             Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
-            None => (0, None),
+            None => (usize::MAX, None),
         }
     }
 
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index ca7feed0712..6df4a457655 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -2435,145 +2435,61 @@ pub trait Iterator {
     /// Determines if the elements of this `Iterator` are unequal to those of
     /// another.
     #[stable(feature = "iter_order", since = "1.5.0")]
-    fn ne<I>(mut self, other: I) -> bool where
+    fn ne<I>(self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialEq<I::Item>,
         Self: Sized,
     {
-        let mut other = other.into_iter();
-
-        loop {
-            let x = match self.next() {
-                None => return other.next().is_some(),
-                Some(val) => val,
-            };
-
-            let y = match other.next() {
-                None => return true,
-                Some(val) => val,
-            };
-
-            if x != y { return true }
-        }
+        !self.eq(other)
     }
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// less than those of another.
     #[stable(feature = "iter_order", since = "1.5.0")]
-    fn lt<I>(mut self, other: I) -> bool where
+    fn lt<I>(self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
         Self: Sized,
     {
-        let mut other = other.into_iter();
-
-        loop {
-            let x = match self.next() {
-                None => return other.next().is_some(),
-                Some(val) => val,
-            };
-
-            let y = match other.next() {
-                None => return false,
-                Some(val) => val,
-            };
-
-            match x.partial_cmp(&y) {
-                Some(Ordering::Less) => return true,
-                Some(Ordering::Equal) => (),
-                Some(Ordering::Greater) => return false,
-                None => return false,
-            }
-        }
+        self.partial_cmp(other) == Some(Ordering::Less)
     }
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// less or equal to those of another.
     #[stable(feature = "iter_order", since = "1.5.0")]
-    fn le<I>(mut self, other: I) -> bool where
+    fn le<I>(self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
         Self: Sized,
     {
-        let mut other = other.into_iter();
-
-        loop {
-            let x = match self.next() {
-                None => { other.next(); return true; },
-                Some(val) => val,
-            };
-
-            let y = match other.next() {
-                None => return false,
-                Some(val) => val,
-            };
-
-            match x.partial_cmp(&y) {
-                Some(Ordering::Less) => return true,
-                Some(Ordering::Equal) => (),
-                Some(Ordering::Greater) => return false,
-                None => return false,
-            }
+        match self.partial_cmp(other) {
+            Some(Ordering::Less) | Some(Ordering::Equal) => true,
+            _ => false,
         }
     }
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// greater than those of another.
     #[stable(feature = "iter_order", since = "1.5.0")]
-    fn gt<I>(mut self, other: I) -> bool where
+    fn gt<I>(self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
         Self: Sized,
     {
-        let mut other = other.into_iter();
-
-        loop {
-            let x = match self.next() {
-                None => { other.next(); return false; },
-                Some(val) => val,
-            };
-
-            let y = match other.next() {
-                None => return true,
-                Some(val) => val,
-            };
-
-            match x.partial_cmp(&y) {
-                Some(Ordering::Less) => return false,
-                Some(Ordering::Equal) => (),
-                Some(Ordering::Greater) => return true,
-                None => return false,
-            }
-        }
+        self.partial_cmp(other) == Some(Ordering::Greater)
     }
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// greater than or equal to those of another.
     #[stable(feature = "iter_order", since = "1.5.0")]
-    fn ge<I>(mut self, other: I) -> bool where
+    fn ge<I>(self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
         Self: Sized,
     {
-        let mut other = other.into_iter();
-
-        loop {
-            let x = match self.next() {
-                None => return other.next().is_none(),
-                Some(val) => val,
-            };
-
-            let y = match other.next() {
-                None => return true,
-                Some(val) => val,
-            };
-
-            match x.partial_cmp(&y) {
-                Some(Ordering::Less) => return false,
-                Some(Ordering::Equal) => (),
-                Some(Ordering::Greater) => return true,
-                None => return false,
-            }
+        match self.partial_cmp(other) {
+            Some(Ordering::Greater) | Some(Ordering::Equal) => true,
+            _ => false,
         }
     }
 
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 66bcf1f7d01..e8874265547 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -1152,15 +1152,6 @@ impl<T> MaybeUninit<T> {
         MaybeUninit { uninit: () }
     }
 
-    /// Deprecated before stabilization.
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
-    #[inline(always)]
-    // FIXME: still used by stdsimd
-    // #[rustc_deprecated(since = "1.35.0", reason = "use `uninit` instead")]
-    pub const fn uninitialized() -> MaybeUninit<T> {
-        Self::uninit()
-    }
-
     /// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
     /// filled with `0` bytes. It depends on `T` whether that already makes for
     /// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
@@ -1221,14 +1212,6 @@ impl<T> MaybeUninit<T> {
         }
     }
 
-    /// Deprecated before stabilization.
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
-    #[inline(always)]
-    #[rustc_deprecated(since = "1.35.0", reason = "use `write` instead")]
-    pub fn set(&mut self, val: T) -> &mut T {
-        self.write(val)
-    }
-
     /// Gets a pointer to the contained value. Reading from this pointer or turning it
     /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
     ///
@@ -1346,15 +1329,6 @@ impl<T> MaybeUninit<T> {
         ManuallyDrop::into_inner(self.value)
     }
 
-    /// Deprecated before stabilization.
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
-    #[inline(always)]
-    // FIXME: still used by stdsimd
-    // #[rustc_deprecated(since = "1.35.0", reason = "use `assume_init` instead")]
-    pub unsafe fn into_initialized(self) -> T {
-        self.assume_init()
-    }
-
     /// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject
     /// to the usual drop handling.
     ///
@@ -1417,14 +1391,6 @@ impl<T> MaybeUninit<T> {
         self.as_ptr().read()
     }
 
-    /// Deprecated before stabilization.
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
-    #[inline(always)]
-    #[rustc_deprecated(since = "1.35.0", reason = "use `read` instead")]
-    pub unsafe fn read_initialized(&self) -> T {
-        self.read()
-    }
-
     /// Gets a reference to the contained value.
     ///
     /// # Safety
diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs
index 28c9ff94dee..8139305f530 100644
--- a/src/libcore/ops/arith.rs
+++ b/src/libcore/ops/arith.rs
@@ -220,21 +220,21 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 /// // derive `Eq` and `PartialEq`.
 /// #[derive(Debug, Eq, PartialEq)]
 /// struct Rational {
-///     nominator: usize,
+///     numerator: usize,
 ///     denominator: usize,
 /// }
 ///
 /// impl Rational {
-///     fn new(nominator: usize, denominator: usize) -> Self {
+///     fn new(numerator: usize, denominator: usize) -> Self {
 ///         if denominator == 0 {
 ///             panic!("Zero is an invalid denominator!");
 ///         }
 ///
 ///         // Reduce to lowest terms by dividing by the greatest common
 ///         // divisor.
-///         let gcd = gcd(nominator, denominator);
+///         let gcd = gcd(numerator, denominator);
 ///         Rational {
-///             nominator: nominator / gcd,
+///             numerator: numerator / gcd,
 ///             denominator: denominator / gcd,
 ///         }
 ///     }
@@ -245,9 +245,9 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///     type Output = Self;
 ///
 ///     fn mul(self, rhs: Self) -> Self {
-///         let nominator = self.nominator * rhs.nominator;
+///         let numerator = self.numerator * rhs.numerator;
 ///         let denominator = self.denominator * rhs.denominator;
-///         Rational::new(nominator, denominator)
+///         Rational::new(numerator, denominator)
 ///     }
 /// }
 ///
@@ -340,21 +340,21 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 /// // derive `Eq` and `PartialEq`.
 /// #[derive(Debug, Eq, PartialEq)]
 /// struct Rational {
-///     nominator: usize,
+///     numerator: usize,
 ///     denominator: usize,
 /// }
 ///
 /// impl Rational {
-///     fn new(nominator: usize, denominator: usize) -> Self {
+///     fn new(numerator: usize, denominator: usize) -> Self {
 ///         if denominator == 0 {
 ///             panic!("Zero is an invalid denominator!");
 ///         }
 ///
 ///         // Reduce to lowest terms by dividing by the greatest common
 ///         // divisor.
-///         let gcd = gcd(nominator, denominator);
+///         let gcd = gcd(numerator, denominator);
 ///         Rational {
-///             nominator: nominator / gcd,
+///             numerator: numerator / gcd,
 ///             denominator: denominator / gcd,
 ///         }
 ///     }
@@ -365,13 +365,13 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 ///     type Output = Self;
 ///
 ///     fn div(self, rhs: Self) -> Self::Output {
-///         if rhs.nominator == 0 {
+///         if rhs.numerator == 0 {
 ///             panic!("Cannot divide by zero-valued `Rational`!");
 ///         }
 ///
-///         let nominator = self.nominator * rhs.denominator;
-///         let denominator = self.denominator * rhs.nominator;
-///         Rational::new(nominator, denominator)
+///         let numerator = self.numerator * rhs.denominator;
+///         let denominator = self.denominator * rhs.numerator;
+///         Rational::new(numerator, denominator)
 ///     }
 /// }
 ///
@@ -537,6 +537,21 @@ rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
 macro_rules! rem_impl_float {
     ($($t:ty)*) => ($(
+
+        /// The remainder from the division of two floats.
+        ///
+        /// The remainder has the same sign as the dividend and is computed as:
+        /// `x - (x / y).trunc() * y`.
+        ///
+        /// # Examples
+        /// ```
+        /// let x: f32 = 50.50;
+        /// let y: f32 = 8.125;
+        /// let remainder = x - (x / y).trunc() * y;
+        ///
+        /// // The answer to both operations is 1.75
+        /// assert_eq!(x % y, remainder);
+        /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         impl Rem for $t {
             type Output = $t;
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index 4f71c8e7949..5b6023f2e2c 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -85,7 +85,10 @@ pub struct Range<Idx> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "{:?}..{:?}", self.start, self.end)
+        self.start.fmt(fmt)?;
+        write!(fmt, "..")?;
+        self.end.fmt(fmt)?;
+        Ok(())
     }
 }
 
@@ -184,7 +187,9 @@ pub struct RangeFrom<Idx> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "{:?}..", self.start)
+        self.start.fmt(fmt)?;
+        write!(fmt, "..")?;
+        Ok(())
     }
 }
 
@@ -266,7 +271,9 @@ pub struct RangeTo<Idx> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "..{:?}", self.end)
+        write!(fmt, "..")?;
+        self.end.fmt(fmt)?;
+        Ok(())
     }
 }
 
@@ -467,7 +474,10 @@ impl<Idx> RangeInclusive<Idx> {
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "{:?}..={:?}", self.start, self.end)
+        self.start.fmt(fmt)?;
+        write!(fmt, "..=")?;
+        self.end.fmt(fmt)?;
+        Ok(())
     }
 }
 
@@ -602,7 +612,9 @@ pub struct RangeToInclusive<Idx> {
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "..={:?}", self.end)
+        write!(fmt, "..=")?;
+        self.end.fmt(fmt)?;
+        Ok(())
     }
 }
 
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 4eb5bddb5d2..122ef9c79c2 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -1585,6 +1585,153 @@ impl<T> [T] {
         sort::quicksort(self, |a, b| f(a).lt(&f(b)));
     }
 
+    /// Reorder the slice such that the element at `index` is at its final sorted position.
+    ///
+    /// This reordering has the additional property that any value at position `i < index` will be
+    /// less than or equal to any value at a position `j > index`. Additionally, this reordering is
+    /// unstable (i.e. any number of equal elements may end up at position `index`), in-place
+    /// (i.e. does not allocate), and `O(n)` worst-case. This function is also/ known as "kth
+    /// element" in other libraries. It returns a triplet of the following values: all elements less
+    /// than the one at the given index, the value at the given index, and all elements greater than
+    /// the one at the given index.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
+    /// used for [`sort_unstable`].
+    ///
+    /// [`sort_unstable`]: #method.sort_unstable
+    ///
+    /// # Panics
+    ///
+    /// Panics when `index >= len()`, meaning it always panics on empty slices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_partition_at_index)]
+    ///
+    /// let mut v = [-5i32, 4, 1, -3, 2];
+    ///
+    /// // Find the median
+    /// v.partition_at_index(2);
+    ///
+    /// // We are only guaranteed the slice will be one of the following, based on the way we sort
+    /// // about the specified index.
+    /// assert!(v == [-3, -5, 1, 2, 4] ||
+    ///         v == [-5, -3, 1, 2, 4] ||
+    ///         v == [-3, -5, 1, 4, 2] ||
+    ///         v == [-5, -3, 1, 4, 2]);
+    /// ```
+    #[unstable(feature = "slice_partition_at_index", issue = "55300")]
+    #[inline]
+    pub fn partition_at_index(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T])
+        where T: Ord
+    {
+        let mut f = |a: &T, b: &T| a.lt(b);
+        sort::partition_at_index(self, index, &mut f)
+    }
+
+    /// Reorder the slice with a comparator function such that the element at `index` is at its
+    /// final sorted position.
+    ///
+    /// This reordering has the additional property that any value at position `i < index` will be
+    /// less than or equal to any value at a position `j > index` using the comparator function.
+    /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
+    /// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function
+    /// is also known as "kth element" in other libraries. It returns a triplet of the following
+    /// values: all elements less than the one at the given index, the value at the given index,
+    /// and all elements greater than the one at the given index, using the provided comparator
+    /// function.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
+    /// used for [`sort_unstable`].
+    ///
+    /// [`sort_unstable`]: #method.sort_unstable
+    ///
+    /// # Panics
+    ///
+    /// Panics when `index >= len()`, meaning it always panics on empty slices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_partition_at_index)]
+    ///
+    /// let mut v = [-5i32, 4, 1, -3, 2];
+    ///
+    /// // Find the median as if the slice were sorted in descending order.
+    /// v.partition_at_index_by(2, |a, b| b.cmp(a));
+    ///
+    /// // We are only guaranteed the slice will be one of the following, based on the way we sort
+    /// // about the specified index.
+    /// assert!(v == [2, 4, 1, -5, -3] ||
+    ///         v == [2, 4, 1, -3, -5] ||
+    ///         v == [4, 2, 1, -5, -3] ||
+    ///         v == [4, 2, 1, -3, -5]);
+    /// ```
+    #[unstable(feature = "slice_partition_at_index", issue = "55300")]
+    #[inline]
+    pub fn partition_at_index_by<F>(&mut self, index: usize, mut compare: F)
+                                    -> (&mut [T], &mut T, &mut [T])
+        where F: FnMut(&T, &T) -> Ordering
+    {
+        let mut f = |a: &T, b: &T| compare(a, b) == Less;
+        sort::partition_at_index(self, index, &mut f)
+    }
+
+    /// Reorder the slice with a key extraction function such that the element at `index` is at its
+    /// final sorted position.
+    ///
+    /// This reordering has the additional property that any value at position `i < index` will be
+    /// less than or equal to any value at a position `j > index` using the key extraction function.
+    /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
+    /// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function
+    /// is also known as "kth element" in other libraries. It returns a triplet of the following
+    /// values: all elements less than the one at the given index, the value at the given index, and
+    /// all elements greater than the one at the given index, using the provided key extraction
+    /// function.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on the quickselect portion of the same quicksort algorithm
+    /// used for [`sort_unstable`].
+    ///
+    /// [`sort_unstable`]: #method.sort_unstable
+    ///
+    /// # Panics
+    ///
+    /// Panics when `index >= len()`, meaning it always panics on empty slices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_partition_at_index)]
+    ///
+    /// let mut v = [-5i32, 4, 1, -3, 2];
+    ///
+    /// // Return the median as if the array were sorted according to absolute value.
+    /// v.partition_at_index_by_key(2, |a| a.abs());
+    ///
+    /// // We are only guaranteed the slice will be one of the following, based on the way we sort
+    /// // about the specified index.
+    /// assert!(v == [1, 2, -3, 4, -5] ||
+    ///         v == [1, 2, -3, -5, 4] ||
+    ///         v == [2, 1, -3, 4, -5] ||
+    ///         v == [2, 1, -3, -5, 4]);
+    /// ```
+    #[unstable(feature = "slice_partition_at_index", issue = "55300")]
+    #[inline]
+    pub fn partition_at_index_by_key<K, F>(&mut self, index: usize, mut f: F)
+                                           -> (&mut [T], &mut T, &mut [T])
+        where F: FnMut(&T) -> K, K: Ord
+    {
+        let mut g = |a: &T, b: &T| f(a).lt(&f(b));
+        sort::partition_at_index(self, index, &mut g)
+    }
+
     /// Moves all consecutive repeated elements to the end of the slice according to the
     /// [`PartialEq`] trait implementation.
     ///
diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs
index 3f84faa0499..68f1fb4b526 100644
--- a/src/libcore/slice/sort.rs
+++ b/src/libcore/slice/sort.rs
@@ -691,3 +691,92 @@ pub fn quicksort<T, F>(v: &mut [T], mut is_less: F)
 
     recurse(v, &mut is_less, None, limit);
 }
+
+fn partition_at_index_loop<'a, T, F>( mut v: &'a mut [T], mut index: usize, is_less: &mut F
+                                    , mut pred: Option<&'a T>) where F: FnMut(&T, &T) -> bool
+{
+    loop {
+        // For slices of up to this length it's probably faster to simply sort them.
+        const MAX_INSERTION: usize = 10;
+        if v.len() <= MAX_INSERTION {
+            insertion_sort(v, is_less);
+            return;
+        }
+
+        // Choose a pivot
+        let (pivot, _) = choose_pivot(v, is_less);
+
+        // If the chosen pivot is equal to the predecessor, then it's the smallest element in the
+        // slice. Partition the slice into elements equal to and elements greater than the pivot.
+        // This case is usually hit when the slice contains many duplicate elements.
+        if let Some(p) = pred {
+            if !is_less(p, &v[pivot]) {
+                let mid = partition_equal(v, pivot, is_less);
+
+                // If we've passed our index, then we're good.
+                if mid > index {
+                    return;
+                }
+
+                // Otherwise, continue sorting elements greater than the pivot.
+                v = &mut v[mid..];
+                index = index - mid;
+                pred = None;
+                continue;
+            }
+        }
+
+        let (mid, _) = partition(v, pivot, is_less);
+
+        // Split the slice into `left`, `pivot`, and `right`.
+        let (left, right) = {v}.split_at_mut(mid);
+        let (pivot, right) = right.split_at_mut(1);
+        let pivot = &pivot[0];
+
+        if mid < index {
+            v = right;
+            index = index - mid - 1;
+            pred = Some(pivot);
+        } else if mid > index {
+            v = left;
+        } else {
+            // If mid == index, then we're done, since partition() guaranteed that all elements
+            // after mid are greater than or equal to mid.
+            return;
+        }
+    }
+}
+
+pub fn partition_at_index<T, F>(v: &mut [T], index: usize, mut is_less: F)
+                                -> (&mut [T], &mut T, &mut [T]) where F: FnMut(&T, &T) -> bool
+{
+    use cmp::Ordering::Less;
+    use cmp::Ordering::Greater;
+
+    if index >= v.len() {
+        panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
+    }
+
+    if mem::size_of::<T>() == 0 {
+        // Sorting has no meaningful behavior on zero-sized types. Do nothing.
+    } else if index == v.len() - 1 {
+        // Find max element and place it in the last position of the array. We're free to use
+        // `unwrap()` here because we know v must not be empty.
+        let (max_index, _) = v.iter().enumerate().max_by(
+            |&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap();
+        v.swap(max_index, index);
+    } else if index == 0 {
+        // Find min element and place it in the first position of the array. We're free to use
+        // `unwrap()` here because we know v must not be empty.
+        let (min_index, _) = v.iter().enumerate().min_by(
+            |&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap();
+        v.swap(min_index, index);
+    } else {
+        partition_at_index_loop(v, index, &mut is_less, None);
+    }
+
+    let (left, right) = v.split_at_mut(index);
+    let (pivot, right) = right.split_at_mut(1);
+    let pivot = &mut pivot[0];
+    (left, pivot, right)
+}
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index f54d7badc3a..8d28be621d6 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -2712,7 +2712,7 @@ impl str {
     /// All kinds of ASCII whitespace are considered:
     ///
     /// ```
-    /// let mut iter = " Mary   had\ta little  \n\t lamb".split_whitespace();
+    /// let mut iter = " Mary   had\ta little  \n\t lamb".split_ascii_whitespace();
     /// assert_eq!(Some("Mary"), iter.next());
     /// assert_eq!(Some("had"), iter.next());
     /// assert_eq!(Some("a"), iter.next());
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 04a49d25301..26b59969e18 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -124,15 +124,28 @@ use fmt;
 
 use hint::spin_loop;
 
-/// Save power or switch hyperthreads in a busy-wait spin-loop.
+/// Signals the processor that it is entering a busy-wait spin-loop.
 ///
-/// This function is deliberately more primitive than
-/// [`std::thread::yield_now`](../../../std/thread/fn.yield_now.html) and
-/// does not directly yield to the system's scheduler.
-/// In some cases it might be useful to use a combination of both functions.
-/// Careful benchmarking is advised.
+/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
+/// power or switching hyper-threads.
 ///
-/// On some platforms this function may not do anything at all.
+/// This function is different than [`std::thread::yield_now`] which directly yields to the
+/// system's scheduler, whereas `spin_loop_hint` only signals the processor that it is entering a
+/// busy-wait spin-loop without yielding control to the system's scheduler.
+///
+/// Using a busy-wait spin-loop with `spin_loop_hint` is ideally used in situations where a
+/// contended lock is held by another thread executed on a different CPU and where the waiting
+/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's
+/// scheduler, no overhead for switching threads occurs. However, if the thread holding the
+/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice
+/// before switching to the thread that holds the lock. If the contending lock is held by a thread
+/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to
+/// use [`std::thread::yield_now`].
+///
+/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
+/// do anything at all.
+///
+/// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html
 #[inline]
 #[stable(feature = "spin_loop_hint", since = "1.24.0")]
 pub fn spin_loop_hint() {
diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs
index 9b8f5981162..29bae69ea83 100644
--- a/src/libcore/task/mod.rs
+++ b/src/libcore/task/mod.rs
@@ -8,4 +8,4 @@ mod poll;
 pub use self::poll::Poll;
 
 mod wake;
-pub use self::wake::{Waker, RawWaker, RawWakerVTable};
+pub use self::wake::{Context, Waker, RawWaker, RawWakerVTable};
diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs
index 12f812d3bed..006cbbb6ce6 100644
--- a/src/libcore/task/wake.rs
+++ b/src/libcore/task/wake.rs
@@ -3,7 +3,7 @@
             issue = "50547")]
 
 use fmt;
-use marker::Unpin;
+use marker::{PhantomData, Unpin};
 
 /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`]
 /// which provides customized wakeup behavior.
@@ -36,6 +36,10 @@ impl RawWaker {
     /// The `vtable` customizes the behavior of a `Waker` which gets created
     /// from a `RawWaker`. For each operation on the `Waker`, the associated
     /// function in the `vtable` of the underlying `RawWaker` will be called.
+    #[rustc_promotable]
+    #[unstable(feature = "futures_api",
+            reason = "futures in libcore are unstable",
+            issue = "50547")]
     pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
         RawWaker {
             data,
@@ -63,21 +67,124 @@ pub struct RawWakerVTable {
     /// required for this additional instance of a [`RawWaker`] and associated
     /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup
     /// of the same task that would have been awoken by the original [`RawWaker`].
-    pub clone: unsafe fn(*const ()) -> RawWaker,
+    clone: unsafe fn(*const ()) -> RawWaker,
 
     /// This function will be called when `wake` is called on the [`Waker`].
     /// It must wake up the task associated with this [`RawWaker`].
     ///
-    /// The implemention of this function must not consume the provided data
+    /// The implementation of this function must make sure to release any
+    /// resources that are associated with this instance of a [`RawWaker`] and
+    /// associated task.
+    wake: unsafe fn(*const ()),
+
+    /// This function will be called when `wake_by_ref` is called on the [`Waker`].
+    /// It must wake up the task associated with this [`RawWaker`].
+    ///
+    /// This function is similar to `wake`, but must not consume the provided data
     /// pointer.
-    pub wake: unsafe fn(*const ()),
+    wake_by_ref: unsafe fn(*const ()),
 
     /// This function gets called when a [`RawWaker`] gets dropped.
     ///
     /// The implementation of this function must make sure to release any
     /// resources that are associated with this instance of a [`RawWaker`] and
     /// associated task.
-    pub drop: unsafe fn(*const ()),
+    drop: unsafe fn(*const ()),
+}
+
+impl RawWakerVTable {
+    /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`,
+    /// `wake_by_ref`, and `drop` functions.
+    ///
+    /// # `clone`
+    ///
+    /// This function will be called when the [`RawWaker`] gets cloned, e.g. when
+    /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned.
+    ///
+    /// The implementation of this function must retain all resources that are
+    /// required for this additional instance of a [`RawWaker`] and associated
+    /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup
+    /// of the same task that would have been awoken by the original [`RawWaker`].
+    ///
+    /// # `wake`
+    ///
+    /// This function will be called when `wake` is called on the [`Waker`].
+    /// It must wake up the task associated with this [`RawWaker`].
+    ///
+    /// The implementation of this function must make sure to release any
+    /// resources that are associated with this instance of a [`RawWaker`] and
+    /// associated task.
+    ///
+    /// # `wake_by_ref`
+    ///
+    /// This function will be called when `wake_by_ref` is called on the [`Waker`].
+    /// It must wake up the task associated with this [`RawWaker`].
+    ///
+    /// This function is similar to `wake`, but must not consume the provided data
+    /// pointer.
+    ///
+    /// # `drop`
+    ///
+    /// This function gets called when a [`RawWaker`] gets dropped.
+    ///
+    /// The implementation of this function must make sure to release any
+    /// resources that are associated with this instance of a [`RawWaker`] and
+    /// associated task.
+    #[rustc_promotable]
+    #[unstable(feature = "futures_api",
+            reason = "futures in libcore are unstable",
+            issue = "50547")]
+    pub const fn new(
+        clone: unsafe fn(*const ()) -> RawWaker,
+        wake: unsafe fn(*const ()),
+        wake_by_ref: unsafe fn(*const ()),
+        drop: unsafe fn(*const ()),
+    ) -> Self {
+        Self {
+            clone,
+            wake,
+            wake_by_ref,
+            drop,
+        }
+    }
+}
+
+/// The `Context` of an asynchronous task.
+///
+/// Currently, `Context` only serves to provide access to a `&Waker`
+/// which can be used to wake the current task.
+pub struct Context<'a> {
+    waker: &'a Waker,
+    // Ensure we future-proof against variance changes by forcing
+    // the lifetime to be invariant (argument-position lifetimes
+    // are contravariant while return-position lifetimes are
+    // covariant).
+    _marker: PhantomData<fn(&'a ()) -> &'a ()>,
+}
+
+impl<'a> Context<'a> {
+    /// Create a new `Context` from a `&Waker`.
+    #[inline]
+    pub fn from_waker(waker: &'a Waker) -> Self {
+        Context {
+            waker,
+            _marker: PhantomData,
+        }
+    }
+
+    /// Returns a reference to the `Waker` for the current task.
+    #[inline]
+    pub fn waker(&self) -> &'a Waker {
+        &self.waker
+    }
+}
+
+impl fmt::Debug for Context<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Context")
+            .field("waker", &self.waker)
+            .finish()
+    }
 }
 
 /// A `Waker` is a handle for waking up a task by notifying its executor that it
@@ -98,14 +205,34 @@ unsafe impl Sync for Waker {}
 
 impl Waker {
     /// Wake up the task associated with this `Waker`.
-    pub fn wake(&self) {
+    #[inline]
+    pub fn wake(self) {
         // The actual wakeup call is delegated through a virtual function call
         // to the implementation which is defined by the executor.
+        let wake = self.waker.vtable.wake;
+        let data = self.waker.data;
+
+        // Don't call `drop` -- the waker will be consumed by `wake`.
+        crate::mem::forget(self);
 
-        // SAFETY: This is safe because `Waker::new_unchecked` is the only way
+        // SAFETY: This is safe because `Waker::from_raw` is the only way
         // to initialize `wake` and `data` requiring the user to acknowledge
         // that the contract of `RawWaker` is upheld.
-        unsafe { (self.waker.vtable.wake)(self.waker.data) }
+        unsafe { (wake)(data) };
+    }
+
+    /// Wake up the task associated with this `Waker` without consuming the `Waker`.
+    ///
+    /// This is similar to `wake`, but may be slightly less efficient in the case
+    /// where an owned `Waker` is available. This method should be preferred to
+    /// calling `waker.clone().wake()`.
+    #[inline]
+    pub fn wake_by_ref(&self) {
+        // The actual wakeup call is delegated through a virtual function call
+        // to the implementation which is defined by the executor.
+
+        // SAFETY: see `wake`
+        unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) }
     }
 
     /// Returns `true` if this `Waker` and another `Waker` have awoken the same task.
@@ -115,6 +242,7 @@ impl Waker {
     /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task.
     ///
     /// This function is primarily used for optimization purposes.
+    #[inline]
     pub fn will_wake(&self, other: &Waker) -> bool {
         self.waker == other.waker
     }
@@ -124,7 +252,8 @@ impl Waker {
     /// The behavior of the returned `Waker` is undefined if the contract defined
     /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld.
     /// Therefore this method is unsafe.
-    pub unsafe fn new_unchecked(waker: RawWaker) -> Waker {
+    #[inline]
+    pub unsafe fn from_raw(waker: RawWaker) -> Waker {
         Waker {
             waker,
         }
@@ -132,9 +261,10 @@ impl Waker {
 }
 
 impl Clone for Waker {
+    #[inline]
     fn clone(&self) -> Self {
         Waker {
-            // SAFETY: This is safe because `Waker::new_unchecked` is the only way
+            // SAFETY: This is safe because `Waker::from_raw` is the only way
             // to initialize `clone` and `data` requiring the user to acknowledge
             // that the contract of [`RawWaker`] is upheld.
             waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
@@ -143,8 +273,9 @@ impl Clone for Waker {
 }
 
 impl Drop for Waker {
+    #[inline]
     fn drop(&mut self) {
-        // SAFETY: This is safe because `Waker::new_unchecked` is the only way
+        // SAFETY: This is safe because `Waker::from_raw` is the only way
         // to initialize `drop` and `data` requiring the user to acknowledge
         // that the contract of `RawWaker` is upheld.
         unsafe { (self.waker.vtable.drop)(self.waker.data) }
diff --git a/src/libcore/tests/fmt/builders.rs b/src/libcore/tests/fmt/builders.rs
index fd7192cc151..e4b75fe1fa2 100644
--- a/src/libcore/tests/fmt/builders.rs
+++ b/src/libcore/tests/fmt/builders.rs
@@ -30,7 +30,7 @@ mod debug_struct {
         assert_eq!("Foo { bar: true }", format!("{:?}", Foo));
         assert_eq!(
 "Foo {
-    bar: true
+    bar: true,
 }",
                    format!("{:#?}", Foo));
     }
@@ -52,7 +52,7 @@ mod debug_struct {
         assert_eq!(
 "Foo {
     bar: true,
-    baz: 10/20
+    baz: 10/20,
 }",
                    format!("{:#?}", Foo));
     }
@@ -87,9 +87,9 @@ mod debug_struct {
 "Bar {
     foo: Foo {
         bar: true,
-        baz: 10/20
+        baz: 10/20,
     },
-    hello: \"world\"
+    hello: \"world\",
 }",
                    format!("{:#?}", Bar));
     }
@@ -127,7 +127,7 @@ mod debug_tuple {
         assert_eq!("Foo(true)", format!("{:?}", Foo));
         assert_eq!(
 "Foo(
-    true
+    true,
 )",
                    format!("{:#?}", Foo));
     }
@@ -149,7 +149,7 @@ mod debug_tuple {
         assert_eq!(
 "Foo(
     true,
-    10/20
+    10/20,
 )",
                    format!("{:#?}", Foo));
     }
@@ -184,9 +184,9 @@ mod debug_tuple {
 "Bar(
     Foo(
         true,
-        10/20
+        10/20,
     ),
-    \"world\"
+    \"world\",
 )",
                    format!("{:#?}", Bar));
     }
@@ -224,7 +224,7 @@ mod debug_map {
         assert_eq!("{\"bar\": true}", format!("{:?}", Foo));
         assert_eq!(
 "{
-    \"bar\": true
+    \"bar\": true,
 }",
                    format!("{:#?}", Foo));
     }
@@ -246,7 +246,7 @@ mod debug_map {
         assert_eq!(
 "{
     \"bar\": true,
-    10: 10/20
+    10: 10/20,
 }",
                    format!("{:#?}", Foo));
     }
@@ -282,12 +282,12 @@ mod debug_map {
 "{
     \"foo\": {
         \"bar\": true,
-        10: 10/20
+        10: 10/20,
     },
     {
         \"bar\": true,
-        10: 10/20
-    }: \"world\"
+        10: 10/20,
+    }: \"world\",
 }",
                    format!("{:#?}", Bar));
     }
@@ -325,7 +325,7 @@ mod debug_set {
         assert_eq!("{true}", format!("{:?}", Foo));
         assert_eq!(
 "{
-    true
+    true,
 }",
                    format!("{:#?}", Foo));
     }
@@ -347,7 +347,7 @@ mod debug_set {
         assert_eq!(
 "{
     true,
-    10/20
+    10/20,
 }",
                    format!("{:#?}", Foo));
     }
@@ -382,9 +382,9 @@ mod debug_set {
 "{
     {
         true,
-        10/20
+        10/20,
     },
-    \"world\"
+    \"world\",
 }",
                    format!("{:#?}", Bar));
     }
@@ -422,7 +422,7 @@ mod debug_list {
         assert_eq!("[true]", format!("{:?}", Foo));
         assert_eq!(
 "[
-    true
+    true,
 ]",
                    format!("{:#?}", Foo));
     }
@@ -444,7 +444,7 @@ mod debug_list {
         assert_eq!(
 "[
     true,
-    10/20
+    10/20,
 ]",
                    format!("{:#?}", Foo));
     }
@@ -479,9 +479,9 @@ mod debug_list {
 "[
     [
         true,
-        10/20
+        10/20,
     ],
-    \"world\"
+    \"world\",
 ]",
                    format!("{:#?}", Bar));
     }
@@ -513,31 +513,31 @@ fn test_formatting_parameters_are_forwarded() {
     assert_eq!(format!("{:#03?}", struct_), "
 Foo {
     bar: 1024,
-    baz: 007
+    baz: 007,
 }
     ".trim());
     assert_eq!(format!("{:#03?}", tuple), "
 (
     1024,
-    007
+    007,
 )
     ".trim());
     assert_eq!(format!("{:#03?}", list), "
 [
     1024,
-    007
+    007,
 ]
     ".trim());
     assert_eq!(format!("{:#03?}", map), r#"
 {
     "bar": 1024,
-    "baz": 007
+    "baz": 007,
 }
     "#.trim());
     assert_eq!(format!("{:#03?}", set), "
 {
     007,
-    1024
+    1024,
 }
     ".trim());
 }
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index a3f0b02e2fe..d5b581d336d 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -1,4 +1,5 @@
 use core::cell::Cell;
+use core::convert::TryFrom;
 use core::iter::*;
 use core::{i8, i16, isize};
 use core::usize;
@@ -1801,6 +1802,66 @@ fn test_range_inclusive_folds() {
 }
 
 #[test]
+fn test_range_size_hint() {
+    use core::usize::MAX as UMAX;
+    assert_eq!((0..0usize).size_hint(), (0, Some(0)));
+    assert_eq!((0..100usize).size_hint(), (100, Some(100)));
+    assert_eq!((0..UMAX).size_hint(), (UMAX, Some(UMAX)));
+
+    let umax = u128::try_from(UMAX).unwrap();
+    assert_eq!((0..0u128).size_hint(), (0, Some(0)));
+    assert_eq!((0..100u128).size_hint(), (100, Some(100)));
+    assert_eq!((0..umax).size_hint(), (UMAX, Some(UMAX)));
+    assert_eq!((0..umax + 1).size_hint(), (UMAX, None));
+
+    use core::isize::{MAX as IMAX, MIN as IMIN};
+    assert_eq!((0..0isize).size_hint(), (0, Some(0)));
+    assert_eq!((-100..100isize).size_hint(), (200, Some(200)));
+    assert_eq!((IMIN..IMAX).size_hint(), (UMAX, Some(UMAX)));
+
+    let imin = i128::try_from(IMIN).unwrap();
+    let imax = i128::try_from(IMAX).unwrap();
+    assert_eq!((0..0i128).size_hint(), (0, Some(0)));
+    assert_eq!((-100..100i128).size_hint(), (200, Some(200)));
+    assert_eq!((imin..imax).size_hint(), (UMAX, Some(UMAX)));
+    assert_eq!((imin..imax + 1).size_hint(), (UMAX, None));
+}
+
+#[test]
+fn test_range_inclusive_size_hint() {
+    use core::usize::MAX as UMAX;
+    assert_eq!((1..=0usize).size_hint(), (0, Some(0)));
+    assert_eq!((0..=0usize).size_hint(), (1, Some(1)));
+    assert_eq!((0..=100usize).size_hint(), (101, Some(101)));
+    assert_eq!((0..=UMAX - 1).size_hint(), (UMAX, Some(UMAX)));
+    assert_eq!((0..=UMAX).size_hint(), (UMAX, None));
+
+    let umax = u128::try_from(UMAX).unwrap();
+    assert_eq!((1..=0u128).size_hint(), (0, Some(0)));
+    assert_eq!((0..=0u128).size_hint(), (1, Some(1)));
+    assert_eq!((0..=100u128).size_hint(), (101, Some(101)));
+    assert_eq!((0..=umax - 1).size_hint(), (UMAX, Some(UMAX)));
+    assert_eq!((0..=umax).size_hint(), (UMAX, None));
+    assert_eq!((0..=umax + 1).size_hint(), (UMAX, None));
+
+    use core::isize::{MAX as IMAX, MIN as IMIN};
+    assert_eq!((0..=-1isize).size_hint(), (0, Some(0)));
+    assert_eq!((0..=0isize).size_hint(), (1, Some(1)));
+    assert_eq!((-100..=100isize).size_hint(), (201, Some(201)));
+    assert_eq!((IMIN..=IMAX - 1).size_hint(), (UMAX, Some(UMAX)));
+    assert_eq!((IMIN..=IMAX).size_hint(), (UMAX, None));
+
+    let imin = i128::try_from(IMIN).unwrap();
+    let imax = i128::try_from(IMAX).unwrap();
+    assert_eq!((0..=-1i128).size_hint(), (0, Some(0)));
+    assert_eq!((0..=0i128).size_hint(), (1, Some(1)));
+    assert_eq!((-100..=100i128).size_hint(), (201, Some(201)));
+    assert_eq!((imin..=imax - 1).size_hint(), (UMAX, Some(UMAX)));
+    assert_eq!((imin..=imax).size_hint(), (UMAX, None));
+    assert_eq!((imin..=imax + 1).size_hint(), (UMAX, None));
+}
+
+#[test]
 fn test_repeat() {
     let mut it = repeat(42);
     assert_eq!(it.next(), Some(42));
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 5e0dbb7ab2f..392a0ffabe3 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -18,6 +18,7 @@
 #![feature(raw)]
 #![feature(slice_patterns)]
 #![feature(sort_internals)]
+#![feature(slice_partition_at_index)]
 #![feature(specialization)]
 #![feature(step_trait)]
 #![feature(str_internals)]
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 4946fd52a7e..007283b5f69 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -1093,6 +1093,124 @@ fn sort_unstable() {
     assert!(v == [0xDEADBEEF]);
 }
 
+#[test]
+#[cfg(not(target_arch = "wasm32"))]
+#[cfg(not(miri))] // Miri does not support entropy
+fn partition_at_index() {
+    use core::cmp::Ordering::{Equal, Greater, Less};
+    use rand::rngs::SmallRng;
+    use rand::seq::SliceRandom;
+    use rand::{FromEntropy, Rng};
+
+    let mut rng = SmallRng::from_entropy();
+
+    for len in (2..21).chain(500..501) {
+        let mut orig = vec![0; len];
+
+        for &modulus in &[5, 10, 1000] {
+            for _ in 0..10 {
+                for i in 0..len {
+                    orig[i] = rng.gen::<i32>() % modulus;
+                }
+
+                let v_sorted = {
+                    let mut v = orig.clone();
+                    v.sort();
+                    v
+                };
+
+                // Sort in default order.
+                for pivot in 0..len {
+                    let mut v = orig.clone();
+                    v.partition_at_index(pivot);
+
+                    assert_eq!(v_sorted[pivot], v[pivot]);
+                    for i in 0..pivot {
+                        for j in pivot..len {
+                            assert!(v[i] <= v[j]);
+                        }
+                    }
+                }
+
+                // Sort in ascending order.
+                for pivot in 0..len {
+                    let mut v = orig.clone();
+                    let (left, pivot, right) = v.partition_at_index_by(pivot, |a, b| a.cmp(b));
+
+                    assert_eq!(left.len() + right.len(), len - 1);
+
+                    for l in left {
+                        assert!(l <= pivot);
+                        for r in right.iter_mut() {
+                            assert!(l <= r);
+                            assert!(pivot <= r);
+                        }
+                    }
+                }
+
+                // Sort in descending order.
+                let sort_descending_comparator = |a: &i32, b: &i32| b.cmp(a);
+                let v_sorted_descending = {
+                    let mut v = orig.clone();
+                    v.sort_by(sort_descending_comparator);
+                    v
+                };
+
+                for pivot in 0..len {
+                    let mut v = orig.clone();
+                    v.partition_at_index_by(pivot, sort_descending_comparator);
+
+                    assert_eq!(v_sorted_descending[pivot], v[pivot]);
+                    for i in 0..pivot {
+                        for j in pivot..len {
+                            assert!(v[j] <= v[i]);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Sort at index using a completely random comparison function.
+    // This will reorder the elements *somehow*, but won't panic.
+    let mut v = [0; 500];
+    for i in 0..v.len() {
+        v[i] = i as i32;
+    }
+
+    for pivot in 0..v.len() {
+        v.partition_at_index_by(pivot, |_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap());
+        v.sort();
+        for i in 0..v.len() {
+            assert_eq!(v[i], i as i32);
+        }
+    }
+
+    // Should not panic.
+    [(); 10].partition_at_index(0);
+    [(); 10].partition_at_index(5);
+    [(); 10].partition_at_index(9);
+    [(); 100].partition_at_index(0);
+    [(); 100].partition_at_index(50);
+    [(); 100].partition_at_index(99);
+
+    let mut v = [0xDEADBEEFu64];
+    v.partition_at_index(0);
+    assert!(v == [0xDEADBEEF]);
+}
+
+#[test]
+#[should_panic(expected = "index 0 greater than length of slice")]
+fn partition_at_index_zero_length() {
+    [0i32; 0].partition_at_index(0);
+}
+
+#[test]
+#[should_panic(expected = "index 20 greater than length of slice")]
+fn partition_at_index_past_length() {
+    [0i32; 10].partition_at_index(20);
+}
+
 pub mod memchr {
     use core::slice::memchr::{memchr, memrchr};
 
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index aacd6cec565..2536121c7a3 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -9,6 +9,7 @@
        test(attr(deny(warnings))))]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(nll)]
 #![feature(rustc_private)]
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index 9d3d8f6185b..72ddafb420c 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -19,8 +19,6 @@
 
 #![deny(rust_2018_idioms)]
 
-#![feature(allocator_api)]
-#![feature(alloc)]
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
 #![feature(libc)]
diff --git a/src/libproc_macro/bridge/rpc.rs b/src/libproc_macro/bridge/rpc.rs
index 4289f33ffd5..5018be74f89 100644
--- a/src/libproc_macro/bridge/rpc.rs
+++ b/src/libproc_macro/bridge/rpc.rs
@@ -24,32 +24,22 @@ pub(super) trait DecodeMut<'a, 's, S>: Sized {
 }
 
 macro_rules! rpc_encode_decode {
-    (uleb128 $ty:ty) => {
+    (le $ty:ty) => {
         impl<S> Encode<S> for $ty {
-            fn encode(mut self, w: &mut Writer, s: &mut S) {
-                let mut byte = 0x80;
-                while byte & 0x80 != 0 {
-                    byte = (self & 0x7f) as u8;
-                    self >>= 7;
-                    if self != 0 {
-                        byte |= 0x80;
-                    }
-                    byte.encode(w, s);
-                }
+            fn encode(self, w: &mut Writer, _: &mut S) {
+                w.write_all(&self.to_le_bytes()).unwrap();
             }
         }
 
         impl<S> DecodeMut<'_, '_, S> for $ty {
-            fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
-                let mut byte = 0x80;
-                let mut v = 0;
-                let mut shift = 0;
-                while byte & 0x80 != 0 {
-                    byte = u8::decode(r, s);
-                    v |= ((byte & 0x7f) as Self) << shift;
-                    shift += 7;
-                }
-                v
+            fn decode(r: &mut Reader<'_>, _: &mut S) -> Self {
+                const N: usize = ::std::mem::size_of::<$ty>();
+
+                let mut bytes = [0; N];
+                bytes.copy_from_slice(&r[..N]);
+                *r = &r[N..];
+
+                Self::from_le_bytes(bytes)
             }
         }
     };
@@ -136,8 +126,8 @@ impl<S> DecodeMut<'_, '_, S> for u8 {
     }
 }
 
-rpc_encode_decode!(uleb128 u32);
-rpc_encode_decode!(uleb128 usize);
+rpc_encode_decode!(le u32);
+rpc_encode_decode!(le usize);
 
 impl<S> Encode<S> for bool {
     fn encode(self, w: &mut Writer, s: &mut S) {
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 03905f3e705..1e0f1ed578a 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -160,9 +160,7 @@ impl iter::FromIterator<TokenTree> for TokenStream {
 impl iter::FromIterator<TokenStream> for TokenStream {
     fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
         let mut builder = bridge::client::TokenStreamBuilder::new();
-        for stream in streams {
-            builder.push(stream.0);
-        }
+        streams.into_iter().for_each(|stream| builder.push(stream.0));
         TokenStream(builder.build())
     }
 }
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index f07111ef647..2876024beb1 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -36,6 +36,7 @@ byteorder = { version = "1.1", features = ["i128"]}
 chalk-engine = { version = "0.9.0", default-features=false }
 rustc_fs_util = { path = "../librustc_fs_util" }
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
+measureme = "0.2.1"
 
 # Note that these dependencies are a lie, they're just here to get linkage to
 # work.
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
new file mode 100644
index 00000000000..e9751a23f12
--- /dev/null
+++ b/src/librustc/arena.rs
@@ -0,0 +1,206 @@
+use arena::{TypedArena, DroplessArena};
+use std::mem;
+use std::ptr;
+use std::slice;
+use std::cell::RefCell;
+use std::marker::PhantomData;
+use smallvec::SmallVec;
+
+#[macro_export]
+macro_rules! arena_types {
+    ($macro:path, $args:tt, $tcx:lifetime) => (
+        $macro!($args, [
+            [] vtable_method: Option<(
+                rustc::hir::def_id::DefId,
+                rustc::ty::subst::SubstsRef<$tcx>
+            )>,
+            [few] mir_keys: rustc::util::nodemap::DefIdSet,
+            [decode] specialization_graph: rustc::traits::specialization_graph::Graph,
+        ], $tcx);
+    )
+}
+
+macro_rules! arena_for_type {
+    ([][$ty:ty]) => {
+        TypedArena<$ty>
+    };
+    ([few $(, $attrs:ident)*][$ty:ty]) => {
+        PhantomData<$ty>
+    };
+    ([$ignore:ident $(, $attrs:ident)*]$args:tt) => {
+        arena_for_type!([$($attrs),*]$args)
+    };
+}
+
+macro_rules! declare_arena {
+    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
+        #[derive(Default)]
+        pub struct Arena<$tcx> {
+            dropless: DroplessArena,
+            drop: DropArena,
+            $($name: arena_for_type!($a[$ty]),)*
+        }
+    }
+}
+
+macro_rules! which_arena_for_type {
+    ([][$arena:expr]) => {
+        Some($arena)
+    };
+    ([few$(, $attrs:ident)*][$arena:expr]) => {
+        None
+    };
+    ([$ignore:ident$(, $attrs:ident)*]$args:tt) => {
+        which_arena_for_type!([$($attrs),*]$args)
+    };
+}
+
+macro_rules! impl_arena_allocatable {
+    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
+        $(
+            impl ArenaAllocatable for $ty {}
+            unsafe impl<$tcx> ArenaField<$tcx> for $ty {
+                #[inline]
+                fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a TypedArena<Self>> {
+                    which_arena_for_type!($a[&_arena.$name])
+                }
+            }
+        )*
+    }
+}
+
+arena_types!(declare_arena, [], 'tcx);
+
+arena_types!(impl_arena_allocatable, [], 'tcx);
+
+pub trait ArenaAllocatable {}
+
+impl<T: Copy> ArenaAllocatable for T {}
+
+pub unsafe trait ArenaField<'tcx>: Sized {
+    /// Returns a specific arena to allocate from.
+    /// If None is returned, the DropArena will be used.
+    fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>>;
+}
+
+unsafe impl<'tcx, T> ArenaField<'tcx> for T {
+    #[inline]
+    default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>> {
+        panic!()
+    }
+}
+
+impl<'tcx> Arena<'tcx> {
+    #[inline]
+    pub fn alloc<T: ArenaAllocatable>(&self, value: T) -> &mut T {
+        if !mem::needs_drop::<T>() {
+            return self.dropless.alloc(value);
+        }
+        match <T as ArenaField<'tcx>>::arena(self) {
+            Some(arena) => arena.alloc(value),
+            None => unsafe { self.drop.alloc(value) },
+        }
+    }
+
+    pub fn alloc_from_iter<
+        T: ArenaAllocatable,
+        I: IntoIterator<Item = T>
+    >(
+        &'a self,
+        iter: I
+    ) -> &'a mut [T] {
+        if !mem::needs_drop::<T>() {
+            return self.dropless.alloc_from_iter(iter);
+        }
+        match <T as ArenaField<'tcx>>::arena(self) {
+            Some(arena) => arena.alloc_from_iter(iter),
+            None => unsafe { self.drop.alloc_from_iter(iter) },
+        }
+    }
+}
+
+/// Calls the destructor for an object when dropped.
+struct DropType {
+    drop_fn: unsafe fn(*mut u8),
+    obj: *mut u8,
+}
+
+unsafe fn drop_for_type<T>(to_drop: *mut u8) {
+    std::ptr::drop_in_place(to_drop as *mut T)
+}
+
+impl Drop for DropType {
+    fn drop(&mut self) {
+        unsafe {
+            (self.drop_fn)(self.obj)
+        }
+    }
+}
+
+/// An arena which can be used to allocate any type.
+/// Allocating in this arena is unsafe since the type system
+/// doesn't know which types it contains. In order to
+/// allocate safely, you must store a PhantomData<T>
+/// alongside this arena for each type T you allocate.
+#[derive(Default)]
+struct DropArena {
+    /// A list of destructors to run when the arena drops.
+    /// Ordered so `destructors` gets dropped before the arena
+    /// since its destructor can reference memory in the arena.
+    destructors: RefCell<Vec<DropType>>,
+    arena: DroplessArena,
+}
+
+impl DropArena {
+    #[inline]
+    unsafe fn alloc<T>(&self, object: T) -> &mut T {
+        let mem = self.arena.alloc_raw(
+            mem::size_of::<T>(),
+            mem::align_of::<T>()
+        ) as *mut _ as *mut T;
+        // Write into uninitialized memory.
+        ptr::write(mem, object);
+        let result = &mut *mem;
+        // Record the destructor after doing the allocation as that may panic
+        // and would cause `object`'s destuctor to run twice if it was recorded before
+        self.destructors.borrow_mut().push(DropType {
+            drop_fn: drop_for_type::<T>,
+            obj: result as *mut T as *mut u8,
+        });
+        result
+    }
+
+    #[inline]
+    unsafe fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
+        let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect();
+        if vec.is_empty() {
+            return &mut [];
+        }
+        let len = vec.len();
+
+        let start_ptr = self.arena.alloc_raw(
+            len.checked_mul(mem::size_of::<T>()).unwrap(),
+            mem::align_of::<T>()
+        ) as *mut _ as *mut T;
+
+        let mut destructors = self.destructors.borrow_mut();
+        // Reserve space for the destructors so we can't panic while adding them
+        destructors.reserve(len);
+
+        // Move the content to the arena by copying it and then forgetting
+        // the content of the SmallVec
+        vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
+        mem::forget(vec.drain());
+
+        // Record the destructors after doing the allocation as that may panic
+        // and would cause `object`'s destuctor to run twice if it was recorded before
+        for i in 0..len {
+            destructors.push(DropType {
+                drop_fn: drop_for_type::<T>,
+                obj: start_ptr.offset(i as isize) as *mut u8,
+            });
+        }
+
+        slice::from_raw_parts_mut(start_ptr, len)
+    }
+}
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 03fa5c04ec7..e5bf9a27ab0 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -65,8 +65,7 @@ use crate::traits::query::{
     CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal,
     CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
 };
-use crate::ty::{TyCtxt, FnSig, Instance, InstanceDef,
-         ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty};
+use crate::ty::{self, TyCtxt, ParamEnvAnd, Ty};
 use crate::ty::subst::SubstsRef;
 
 // erase!() just makes tokens go away. It's used to specify which macro argument
@@ -432,211 +431,13 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
     // Represents metadata from an extern crate.
     [eval_always] CrateMetadata(CrateNum),
 
-    // Represents different phases in the compiler.
-    [] RegionScopeTree(DefId),
-    [eval_always] Coherence,
-    [eval_always] CoherenceInherentImplOverlapCheck,
-    [] CoherenceCheckTrait(DefId),
-    [eval_always] PrivacyAccessLevels(CrateNum),
-    [eval_always] CheckPrivateInPublic(CrateNum),
-    [eval_always] Analysis(CrateNum),
-
-    // Represents the MIR for a fn; also used as the task node for
-    // things read/modify that MIR.
-    [] MirShim { instance_def: InstanceDef<'tcx> },
-
-    [] BorrowCheckKrate,
-    [] BorrowCheck(DefId),
-    [] MirBorrowCheck(DefId),
-    [] UnsafetyCheckResult(DefId),
-    [] UnsafeDeriveOnReprPacked(DefId),
-
-    [] LintMod(DefId),
-    [] CheckModAttrs(DefId),
-    [] CheckModLoops(DefId),
-    [] CheckModUnstableApiUsage(DefId),
-    [] CheckModItemTypes(DefId),
-    [] CheckModPrivacy(DefId),
-    [] CheckModIntrinsics(DefId),
-    [] CheckModLiveness(DefId),
-    [] CheckModImplWf(DefId),
-    [] CollectModItemTypes(DefId),
-
-    [] Reachability,
-    [] CrateVariances,
-
-    // Nodes representing bits of computed IR in the tcx. Each shared
-    // table in the tcx (or elsewhere) maps to one of these
-    // nodes.
-    [] AssociatedItems(DefId),
-    [] ExplicitPredicatesOfItem(DefId),
-    [] PredicatesDefinedOnItem(DefId),
-    [] InferredOutlivesOf(DefId),
-    [] InferredOutlivesCrate(CrateNum),
-    [] SuperPredicatesOfItem(DefId),
-    [] TraitDefOfItem(DefId),
-    [] AdtDefOfItem(DefId),
-    [] ImplTraitRef(DefId),
-    [] ImplPolarity(DefId),
-    [] Issue33140SelfTy(DefId),
-    [] FnSignature(DefId),
-    [] CoerceUnsizedInfo(DefId),
-
-    [] ItemVarianceConstraints(DefId),
-    [] ItemVariances(DefId),
-    [] IsConstFn(DefId),
-    [] IsPromotableConstFn(DefId),
-    [] IsForeignItem(DefId),
-    [] TypeParamPredicates { item_id: DefId, param_id: DefId },
-    [] SizedConstraint(DefId),
-    [] DtorckConstraint(DefId),
-    [] AdtDestructor(DefId),
-    [] AssociatedItemDefIds(DefId),
-    [eval_always] InherentImpls(DefId),
-    [] TypeckBodiesKrate,
-    [] TypeckTables(DefId),
-    [] UsedTraitImports(DefId),
-    [] HasTypeckTables(DefId),
-    [] ConstEval { param_env: ParamEnvAnd<'tcx, GlobalId<'tcx>> },
-    [] ConstEvalRaw { param_env: ParamEnvAnd<'tcx, GlobalId<'tcx>> },
-    [] CheckMatch(DefId),
-    [] SymbolName { instance: Instance<'tcx> },
-    [] SpecializationGraph(DefId),
-    [] ObjectSafety(DefId),
-    [] FulfillObligation { param_env: ParamEnv<'tcx>, trait_ref: PolyTraitRef<'tcx> },
-    [] VtableMethods { trait_ref: PolyTraitRef<'tcx> },
-
-    [] IsCopy { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> },
-    [] IsSized { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> },
-    [] IsFreeze { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> },
-    [] NeedsDrop { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> },
-    [] Layout { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> },
-
-    // The set of impls for a given trait.
-    [] TraitImpls(DefId),
-
     [eval_always] AllLocalTraitImpls,
 
     [anon] TraitSelect,
 
-    [] ParamEnv(DefId),
-    [] DescribeDef(DefId),
-
-    // FIXME(mw): DefSpans are not really inputs since they are derived from
-    // HIR. But at the moment HIR hashing still contains some hacks that allow
-    // to make type debuginfo to be source location independent. Declaring
-    // DefSpan an input makes sure that changes to these are always detected
-    // regardless of HIR hashing.
-    [eval_always] DefSpan(DefId),
-    [] LookupStability(DefId),
-    [] LookupDeprecationEntry(DefId),
-    [] ConstIsRvaluePromotableToStatic(DefId),
-    [] RvaluePromotableMap(DefId),
-    [] ImplParent(DefId),
-    [] TraitOfItem(DefId),
-    [] IsReachableNonGeneric(DefId),
-    [] IsUnreachableLocalDefinition(DefId),
-    [] IsMirAvailable(DefId),
-    [] ItemAttrs(DefId),
-    [] CodegenFnAttrs(DefId),
-    [] FnArgNames(DefId),
-    [] RenderedConst(DefId),
-    [] DylibDepFormats(CrateNum),
-    [] IsCompilerBuiltins(CrateNum),
-    [] HasGlobalAllocator(CrateNum),
-    [] HasPanicHandler(CrateNum),
-    [eval_always] ExternCrate(DefId),
-    [] Specializes { impl1: DefId, impl2: DefId },
-    [eval_always] InScopeTraits(DefIndex),
-    [eval_always] ModuleExports(DefId),
-    [] IsSanitizerRuntime(CrateNum),
-    [] IsProfilerRuntime(CrateNum),
-    [] GetPanicStrategy(CrateNum),
-    [] IsNoBuiltins(CrateNum),
-    [] ImplDefaultness(DefId),
-    [] CheckItemWellFormed(DefId),
-    [] CheckTraitItemWellFormed(DefId),
-    [] CheckImplItemWellFormed(DefId),
-    [] ReachableNonGenerics(CrateNum),
-    [] EntryFn(CrateNum),
-    [] PluginRegistrarFn(CrateNum),
-    [] ProcMacroDeclsStatic(CrateNum),
-    [eval_always] CrateDisambiguator(CrateNum),
-    [eval_always] CrateHash(CrateNum),
-    [eval_always] OriginalCrateName(CrateNum),
-    [eval_always] ExtraFileName(CrateNum),
-
-    [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId },
-    [] AllTraitImplementations(CrateNum),
-
-    [] DllimportForeignItems(CrateNum),
-    [] IsDllimportForeignItem(DefId),
-    [] IsStaticallyIncludedForeignItem(DefId),
-    [] NativeLibraryKind(DefId),
-    [eval_always] LinkArgs,
-
-    [] ResolveLifetimes(CrateNum),
-    [] NamedRegion(DefIndex),
-    [] IsLateBound(DefIndex),
-    [] ObjectLifetimeDefaults(DefIndex),
-
-    [] Visibility(DefId),
-    [eval_always] DepKind(CrateNum),
-    [eval_always] CrateName(CrateNum),
-    [] ItemChildren(DefId),
-    [] ExternModStmtCnum(DefId),
-    [eval_always] GetLibFeatures,
-    [] DefinedLibFeatures(CrateNum),
-    [eval_always] GetLangItems,
-    [] DefinedLangItems(CrateNum),
-    [] MissingLangItems(CrateNum),
-    [] VisibleParentMap,
-    [eval_always] MissingExternCrateItem(CrateNum),
-    [eval_always] UsedCrateSource(CrateNum),
-    [eval_always] PostorderCnums,
-
-    [eval_always] Freevars(DefId),
-    [eval_always] MaybeUnusedTraitImport(DefId),
-    [eval_always] MaybeUnusedExternCrates,
-    [eval_always] NamesImportedByGlobUse(DefId),
-    [eval_always] StabilityIndex,
-    [eval_always] AllTraits,
-    [eval_always] AllCrateNums,
-    [] ExportedSymbols(CrateNum),
-    [eval_always] CollectAndPartitionMonoItems,
-    [] IsCodegenedItem(DefId),
-    [] CodegenUnit(InternedString),
-    [] BackendOptimizationLevel(CrateNum),
     [] CompileCodegenUnit(InternedString),
-    [eval_always] OutputFilenames,
-    [] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>),
-    [] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
-    [] ImpliedOutlivesBounds(CanonicalTyGoal<'tcx>),
-    [] DropckOutlives(CanonicalTyGoal<'tcx>),
-    [] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
-    [] EvaluateGoal(traits::ChalkCanonicalGoal<'tcx>),
-    [] TypeOpAscribeUserType(CanonicalTypeOpAscribeUserTypeGoal<'tcx>),
-    [] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
-    [] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>),
-    [] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>),
-    [] TypeOpNormalizeTy(CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>),
-    [] TypeOpNormalizePredicate(CanonicalTypeOpNormalizeGoal<'tcx, Predicate<'tcx>>),
-    [] TypeOpNormalizePolyFnSig(CanonicalTypeOpNormalizeGoal<'tcx, PolyFnSig<'tcx>>),
-    [] TypeOpNormalizeFnSig(CanonicalTypeOpNormalizeGoal<'tcx, FnSig<'tcx>>),
-
-    [] SubstituteNormalizeAndTestPredicates { key: (DefId, SubstsRef<'tcx>) },
-    [] MethodAutoderefSteps(CanonicalTyGoal<'tcx>),
-
-    [eval_always] TargetFeaturesWhitelist,
-
-    [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
-
-    [eval_always] Features,
-
-    [] ForeignModules(CrateNum),
-
-    [] UpstreamMonomorphizations(CrateNum),
-    [] UpstreamMonomorphizationsFor(DefId),
+
+    [eval_always] Analysis(CrateNum),
 ]);
 
 pub trait RecoverKey<'tcx>: Sized {
@@ -655,6 +456,12 @@ impl RecoverKey<'tcx> for DefId {
     }
 }
 
+impl RecoverKey<'tcx> for DefIndex {
+    fn recover(tcx: TyCtxt<'_, 'tcx, 'tcx>, dep_node: &DepNode) -> Option<Self> {
+        dep_node.extract_def_id(tcx).map(|id| id.index)
+    }
+}
+
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
     const CAN_RECONSTRUCT_QUERY_KEY: bool;
 
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index 397843fd75a..8536f38e48c 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -1,5 +1,4 @@
-use crate::ty;
-use crate::ty::TyCtxt;
+use crate::ty::{self, TyCtxt};
 use crate::hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX;
 use rustc_data_structures::indexed_vec::Idx;
 use serialize;
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 6689b0c26fb..c2265eeb30d 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -490,7 +490,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_ty(ty);
             visitor.visit_generics(generics)
         }
-        ItemKind::Existential(ExistTy { ref generics, ref bounds, impl_trait_fn: _ }) => {
+        ItemKind::Existential(ExistTy {
+            ref generics,
+            ref bounds,
+            ..
+        }) => {
             visitor.visit_id(item.hir_id);
             walk_generics(visitor, generics);
             walk_list!(visitor, visit_param_bound, bounds);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 7dfb16602a3..2a255523676 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -66,7 +66,7 @@ use syntax::symbol::{keywords, Symbol};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::parse::token::Token;
 use syntax::visit::{self, Visitor};
-use syntax_pos::{Span, MultiSpan};
+use syntax_pos::Span;
 
 const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
 
@@ -318,6 +318,49 @@ enum AnonymousLifetimeMode {
 
     /// Pass responsibility to `resolve_lifetime` code for all cases.
     PassThrough,
+
+    /// Used in the return types of `async fn` where there exists
+    /// exactly one argument-position elided lifetime.
+    ///
+    /// In `async fn`, we lower the arguments types using the `CreateParameter`
+    /// mode, meaning that non-`dyn` elided lifetimes are assigned a fresh name.
+    /// If any corresponding elided lifetimes appear in the output, we need to
+    /// replace them with references to the fresh name assigned to the corresponding
+    /// elided lifetime in the arguments.
+    ///
+    /// For **Modern cases**, replace the anonymous parameter with a
+    /// reference to a specific freshly-named lifetime that was
+    /// introduced in argument
+    ///
+    /// For **Dyn Bound** cases, pass responsibility to
+    /// `resole_lifetime` code.
+    Replace(LtReplacement),
+}
+
+/// The type of elided lifetime replacement to perform on `async fn` return types.
+#[derive(Copy, Clone)]
+enum LtReplacement {
+    /// Fresh name introduced by the single non-dyn elided lifetime
+    /// in the arguments of the async fn.
+    Some(ParamName),
+
+    /// There is no single non-dyn elided lifetime because no lifetimes
+    /// appeared in the arguments.
+    NoLifetimes,
+
+    /// There is no single non-dyn elided lifetime because multiple
+    /// lifetimes appeared in the arguments.
+    MultipleLifetimes,
+}
+
+/// Calculates the `LtReplacement` to use for elided lifetimes in the return
+/// type based on the fresh elided lifetimes introduced in argument position.
+fn get_elided_lt_replacement(arg_position_lifetimes: &[(Span, ParamName)]) -> LtReplacement {
+    match arg_position_lifetimes {
+        [] => LtReplacement::NoLifetimes,
+        [(_span, param)] => LtReplacement::Some(*param),
+        _ => LtReplacement::MultipleLifetimes,
+    }
 }
 
 struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[NodeId; 1]> }
@@ -778,53 +821,63 @@ impl<'a> LoweringContext<'a> {
 
         let params = lifetimes_to_define
             .into_iter()
-            .map(|(span, hir_name)| {
-                let LoweredNodeId { node_id, hir_id } = self.next_id();
-
-                // Get the name we'll use to make the def-path. Note
-                // that collisions are ok here and this shouldn't
-                // really show up for end-user.
-                let (str_name, kind) = match hir_name {
-                    ParamName::Plain(ident) => (
-                        ident.as_interned_str(),
-                        hir::LifetimeParamKind::InBand,
-                    ),
-                    ParamName::Fresh(_) => (
-                        keywords::UnderscoreLifetime.name().as_interned_str(),
-                        hir::LifetimeParamKind::Elided,
-                    ),
-                    ParamName::Error => (
-                        keywords::UnderscoreLifetime.name().as_interned_str(),
-                        hir::LifetimeParamKind::Error,
-                    ),
-                };
-
-                // Add a definition for the in-band lifetime def.
-                self.resolver.definitions().create_def_with_parent(
-                    parent_id.index,
-                    node_id,
-                    DefPathData::LifetimeParam(str_name),
-                    DefIndexAddressSpace::High,
-                    Mark::root(),
-                    span,
-                );
-
-                hir::GenericParam {
-                    hir_id,
-                    name: hir_name,
-                    attrs: hir_vec![],
-                    bounds: hir_vec![],
-                    span,
-                    pure_wrt_drop: false,
-                    kind: hir::GenericParamKind::Lifetime { kind }
-                }
-            })
+            .map(|(span, hir_name)| self.lifetime_to_generic_param(
+                span, hir_name, parent_id.index,
+            ))
             .chain(in_band_ty_params.into_iter())
             .collect();
 
         (params, res)
     }
 
+    /// Converts a lifetime into a new generic parameter.
+    fn lifetime_to_generic_param(
+        &mut self,
+        span: Span,
+        hir_name: ParamName,
+        parent_index: DefIndex,
+    ) -> hir::GenericParam {
+        let LoweredNodeId { node_id, hir_id } = self.next_id();
+
+        // Get the name we'll use to make the def-path. Note
+        // that collisions are ok here and this shouldn't
+        // really show up for end-user.
+        let (str_name, kind) = match hir_name {
+            ParamName::Plain(ident) => (
+                ident.as_interned_str(),
+                hir::LifetimeParamKind::InBand,
+            ),
+            ParamName::Fresh(_) => (
+                keywords::UnderscoreLifetime.name().as_interned_str(),
+                hir::LifetimeParamKind::Elided,
+            ),
+            ParamName::Error => (
+                keywords::UnderscoreLifetime.name().as_interned_str(),
+                hir::LifetimeParamKind::Error,
+            ),
+        };
+
+        // Add a definition for the in-band lifetime def.
+        self.resolver.definitions().create_def_with_parent(
+            parent_index,
+            node_id,
+            DefPathData::LifetimeParam(str_name),
+            DefIndexAddressSpace::High,
+            Mark::root(),
+            span,
+        );
+
+        hir::GenericParam {
+            hir_id,
+            name: hir_name,
+            attrs: hir_vec![],
+            bounds: hir_vec![],
+            span,
+            pure_wrt_drop: false,
+            kind: hir::GenericParamKind::Lifetime { kind }
+        }
+    }
+
     /// When there is a reference to some lifetime `'a`, and in-band
     /// lifetimes are enabled, then we want to push that lifetime into
     /// the vector of names to define later. In that case, it will get
@@ -928,6 +981,13 @@ impl<'a> LoweringContext<'a> {
             |this| {
                 this.collect_in_band_defs(parent_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
+                    // the return type that assumes that all in-scope lifetimes have
+                    // already been added to either `in_scope_lifetimes` or
+                    // `lifetimes_to_define`. If we swapped the order of these two,
+                    // in-band-lifetimes introduced by generics or where-clauses
+                    // wouldn't have been added yet.
                     let generics = this.lower_generics(
                         generics,
                         ImplTraitContext::Universal(&mut params),
@@ -1426,42 +1486,62 @@ impl<'a> LoweringContext<'a> {
 
         self.with_hir_id_owner(exist_ty_node_id, |lctx| {
             let LoweredNodeId { node_id: _, hir_id } = lctx.next_id();
-            let exist_ty_item_kind = hir::ItemKind::Existential(hir::ExistTy {
+            let exist_ty_item = hir::ExistTy {
                 generics: hir::Generics {
                     params: lifetime_defs,
                     where_clause: hir::WhereClause {
                         hir_id,
-                        predicates: Vec::new().into(),
+                        predicates: hir_vec![],
                     },
                     span,
                 },
                 bounds: hir_bounds,
                 impl_trait_fn: fn_def_id,
-            });
-            let exist_ty_id = lctx.lower_node_id(exist_ty_node_id);
-            // Generate an `existential type Foo: Trait;` declaration.
-            trace!("creating existential type with id {:#?}", exist_ty_id);
-
-            trace!("exist ty def index: {:#?}", exist_ty_def_index);
-            let exist_ty_item = hir::Item {
-                hir_id: exist_ty_id.hir_id,
-                ident: keywords::Invalid.ident(),
-                attrs: Default::default(),
-                node: exist_ty_item_kind,
-                vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited),
-                span: exist_ty_span,
+                origin: hir::ExistTyOrigin::ReturnImplTrait,
             };
 
-            // Insert the item into the global list. This usually happens
-            // automatically for all AST items. But this existential type item
-            // does not actually exist in the AST.
-            lctx.insert_item(exist_ty_item);
+            trace!("exist ty from impl trait def index: {:#?}", exist_ty_def_index);
+            let exist_ty_id = lctx.generate_existential_type(
+                exist_ty_node_id,
+                exist_ty_item,
+                span,
+                exist_ty_span,
+            );
 
             // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
             hir::TyKind::Def(hir::ItemId { id: exist_ty_id.hir_id }, lifetimes)
         })
     }
 
+    /// Registers a new existential type with the proper NodeIds and
+    /// returns the lowered node ID for the existential type.
+    fn generate_existential_type(
+        &mut self,
+        exist_ty_node_id: NodeId,
+        exist_ty_item: hir::ExistTy,
+        span: Span,
+        exist_ty_span: Span,
+    ) -> LoweredNodeId {
+        let exist_ty_item_kind = hir::ItemKind::Existential(exist_ty_item);
+        let exist_ty_id = self.lower_node_id(exist_ty_node_id);
+        // Generate an `existential type Foo: Trait;` declaration.
+        trace!("registering existential type with id {:#?}", exist_ty_id);
+        let exist_ty_item = hir::Item {
+            hir_id: exist_ty_id.hir_id,
+            ident: keywords::Invalid.ident(),
+            attrs: Default::default(),
+            node: exist_ty_item_kind,
+            vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited),
+            span: exist_ty_span,
+        };
+
+        // Insert the item into the global item list. This usually happens
+        // automatically for all AST items. But this existential type item
+        // does not actually exist in the AST.
+        self.insert_item(exist_ty_item);
+        exist_ty_id
+    }
+
     fn lifetimes_from_impl_trait_bounds(
         &mut self,
         exist_ty_id: NodeId,
@@ -1569,9 +1649,6 @@ impl<'a> LoweringContext<'a> {
                         name,
                     }));
 
-                    // We need to manually create the ids here, because the
-                    // definitions will go into the explicit `existential type`
-                    // declaration and thus need to have their owner set to that item
                     let def_node_id = self.context.sess.next_node_id();
                     let LoweredNodeId { node_id: _, hir_id } =
                         self.context.lower_node_id_with_owner(def_node_id, self.exist_ty_id);
@@ -2108,23 +2185,42 @@ impl<'a> LoweringContext<'a> {
         impl_trait_return_allow: bool,
         make_ret_async: Option<NodeId>,
     ) -> P<hir::FnDecl> {
-        let inputs = decl.inputs
-            .iter()
-            .map(|arg| {
-                if let Some((_, ref mut ibty)) = in_band_ty_params {
-                    self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(ibty))
-                } else {
-                    self.lower_ty_direct(&arg.ty, ImplTraitContext::disallowed())
-                }
-            })
-            .collect::<HirVec<_>>();
+        let lt_mode = if make_ret_async.is_some() {
+            // In `async fn`, argument-position elided lifetimes
+            // must be transformed into fresh generic parameters so that
+            // they can be applied to the existential return type.
+            AnonymousLifetimeMode::CreateParameter
+        } else {
+            self.anonymous_lifetime_mode
+        };
+
+        // Remember how many lifetimes were already around so that we can
+        // only look at the lifetime parameters introduced by the arguments.
+        let lifetime_count_before_args = self.lifetimes_to_define.len();
+        let inputs = self.with_anonymous_lifetime_mode(lt_mode, |this| {
+            decl.inputs
+                .iter()
+                .map(|arg| {
+                    if let Some((_, ibty)) = &mut in_band_ty_params {
+                        this.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(ibty))
+                    } else {
+                        this.lower_ty_direct(&arg.ty, ImplTraitContext::disallowed())
+                    }
+                })
+                .collect::<HirVec<_>>()
+        });
 
         let output = if let Some(ret_id) = make_ret_async {
+            // Calculate the `LtReplacement` to use for any return-position elided
+            // lifetimes based on the elided lifetime parameters introduced in the args.
+            let lt_replacement = get_elided_lt_replacement(
+                &self.lifetimes_to_define[lifetime_count_before_args..]
+            );
             self.lower_async_fn_ret_ty(
-                &inputs,
                 &decl.output,
                 in_band_ty_params.expect("make_ret_async but no fn_def_id").0,
                 ret_id,
+                lt_replacement,
             )
         } else {
             match decl.output {
@@ -2173,233 +2269,171 @@ impl<'a> LoweringContext<'a> {
         })
     }
 
-    // Transform `-> T` into `-> impl Future<Output = T>` for `async fn`
+    // Transform `-> T` for `async fn` into -> ExistTy { .. }
+    // combined with the following definition of `ExistTy`:
+    //
+    // existential type ExistTy<generics_from_parent_fn>: Future<Output = T>;
     //
-    // fn_span: the span of the async function declaration. Used for error reporting.
     // inputs: lowered types of arguments to the function. Used to collect lifetimes.
     // output: unlowered output type (`T` in `-> T`)
     // fn_def_id: DefId of the parent function. Used to create child impl trait definition.
+    // exist_ty_node_id: NodeId of the existential type that should be created.
+    // elided_lt_replacement: replacement for elided lifetimes in the return type
     fn lower_async_fn_ret_ty(
         &mut self,
-        inputs: &[hir::Ty],
         output: &FunctionRetTy,
         fn_def_id: DefId,
-        return_impl_trait_id: NodeId,
+        exist_ty_node_id: NodeId,
+        elided_lt_replacement: LtReplacement,
     ) -> hir::FunctionRetTy {
-        // Get lifetimes used in the input arguments to the function. Our output type must also
-        // have the same lifetime.
-        // FIXME(cramertj): multiple different lifetimes are not allowed because
-        // `impl Trait + 'a + 'b` doesn't allow for capture `'a` and `'b` where neither is a subset
-        // of the other. We really want some new lifetime that is a subset of all input lifetimes,
-        // but that doesn't exist at the moment.
-
-        struct AsyncFnLifetimeCollector<'r, 'a: 'r> {
-            context: &'r mut LoweringContext<'a>,
-            // Lifetimes bound by HRTB.
-            currently_bound_lifetimes: Vec<hir::LifetimeName>,
-            // Whether to count elided lifetimes.
-            // Disabled inside of `Fn` or `fn` syntax.
-            collect_elided_lifetimes: bool,
-            // The lifetime found.
-            // Multiple different or elided lifetimes cannot appear in async fn for now.
-            output_lifetime: Option<(hir::LifetimeName, Span)>,
-        }
-
-        impl<'r, 'a: 'r, 'v> hir::intravisit::Visitor<'v> for AsyncFnLifetimeCollector<'r, 'a> {
-            fn nested_visit_map<'this>(
-                &'this mut self,
-            ) -> hir::intravisit::NestedVisitorMap<'this, 'v> {
-                hir::intravisit::NestedVisitorMap::None
-            }
+        let span = output.span();
 
-            fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs) {
-                // Don't collect elided lifetimes used inside of `Fn()` syntax.
-                if parameters.parenthesized {
-                    let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
-                    self.collect_elided_lifetimes = false;
-                    hir::intravisit::walk_generic_args(self, span, parameters);
-                    self.collect_elided_lifetimes = old_collect_elided_lifetimes;
-                } else {
-                    hir::intravisit::walk_generic_args(self, span, parameters);
-                }
-            }
-
-            fn visit_ty(&mut self, t: &'v hir::Ty) {
-                // Don't collect elided lifetimes used inside of `fn()` syntax.
-                if let &hir::TyKind::BareFn(_) = &t.node {
-                    let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
-                    self.collect_elided_lifetimes = false;
-
-                    // Record the "stack height" of `for<'a>` lifetime bindings
-                    // to be able to later fully undo their introduction.
-                    let old_len = self.currently_bound_lifetimes.len();
-                    hir::intravisit::walk_ty(self, t);
-                    self.currently_bound_lifetimes.truncate(old_len);
-
-                    self.collect_elided_lifetimes = old_collect_elided_lifetimes;
-                } else {
-                    hir::intravisit::walk_ty(self, t);
-                }
-            }
+        let exist_ty_span = self.mark_span_with_reason(
+            CompilerDesugaringKind::Async,
+            span,
+            None,
+        );
 
-            fn visit_poly_trait_ref(
-                &mut self,
-                trait_ref: &'v hir::PolyTraitRef,
-                modifier: hir::TraitBoundModifier,
-            ) {
-                // Record the "stack height" of `for<'a>` lifetime bindings
-                // to be able to later fully undo their introduction.
-                let old_len = self.currently_bound_lifetimes.len();
-                hir::intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
-                self.currently_bound_lifetimes.truncate(old_len);
-            }
+        let exist_ty_def_index = self
+            .resolver
+            .definitions()
+            .opt_def_index(exist_ty_node_id)
+            .unwrap();
 
-            fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
-                 // Record the introduction of 'a in `for<'a> ...`
-                if let hir::GenericParamKind::Lifetime { .. } = param.kind {
-                    // Introduce lifetimes one at a time so that we can handle
-                    // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
-                    let lt_name = hir::LifetimeName::Param(param.name);
-                    self.currently_bound_lifetimes.push(lt_name);
-                }
+        self.allocate_hir_id_counter(exist_ty_node_id);
 
-                hir::intravisit::walk_generic_param(self, param);
-            }
+        let (exist_ty_node_id, lifetime_params) = self.with_hir_id_owner(exist_ty_node_id, |this| {
+            let future_bound = this.with_anonymous_lifetime_mode(
+                AnonymousLifetimeMode::Replace(elided_lt_replacement),
+                |this| this.lower_async_fn_output_type_to_future_bound(
+                    output,
+                    fn_def_id,
+                    span,
+                ),
+            );
 
-            fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
-                let name = match lifetime.name {
-                    hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
-                        if self.collect_elided_lifetimes {
-                            // Use `'_` for both implicit and underscore lifetimes in
-                            // `abstract type Foo<'_>: SomeTrait<'_>;`
-                            hir::LifetimeName::Underscore
-                        } else {
-                            return;
-                        }
-                    }
-                    hir::LifetimeName::Param(_) => lifetime.name,
-                    hir::LifetimeName::Error | hir::LifetimeName::Static => return,
-                };
+            // Calculate all the lifetimes that should be captured
+            // by the existential type. This should include all in-scope
+            // lifetime parameters, including those defined in-band.
+            //
+            // Note: this must be done after lowering the output type,
+            // as the output type may introduce new in-band lifetimes.
+            let lifetime_params: Vec<(Span, ParamName)> =
+                this.in_scope_lifetimes
+                    .iter().cloned()
+                    .map(|ident| (ident.span, ParamName::Plain(ident)))
+                    .chain(this.lifetimes_to_define.iter().cloned())
+                    .collect();
 
-                if !self.currently_bound_lifetimes.contains(&name) {
-                    if let Some((current_lt_name, current_lt_span)) = self.output_lifetime {
-                        // We don't currently have a reliable way to desugar `async fn` with
-                        // multiple potentially unrelated input lifetimes into
-                        // `-> impl Trait + 'lt`, so we report an error in this case.
-                        if current_lt_name != name {
-                            struct_span_err!(
-                                self.context.sess,
-                                MultiSpan::from_spans(vec![current_lt_span, lifetime.span]),
-                                E0709,
-                                "multiple different lifetimes used in arguments of `async fn`",
-                            )
-                                .span_label(current_lt_span, "first lifetime here")
-                                .span_label(lifetime.span, "different lifetime here")
-                                .help("`async fn` can only accept borrowed values \
-                                      with identical lifetimes")
-                                .emit()
-                        } else if current_lt_name.is_elided() && name.is_elided() {
-                            struct_span_err!(
-                                self.context.sess,
-                                MultiSpan::from_spans(vec![current_lt_span, lifetime.span]),
-                                E0707,
-                                "multiple elided lifetimes used in arguments of `async fn`",
-                            )
-                                .span_label(current_lt_span, "first lifetime here")
-                                .span_label(lifetime.span, "different lifetime here")
-                                .help("consider giving these arguments named lifetimes")
-                                .emit()
-                        }
-                    } else {
-                        self.output_lifetime = Some((name, lifetime.span));
-                    }
-                }
-            }
-        }
+            let generic_params =
+                lifetime_params
+                    .iter().cloned()
+                    .map(|(span, hir_name)| {
+                        this.lifetime_to_generic_param(span, hir_name, exist_ty_def_index)
+                    })
+                    .collect();
 
-        let bound_lifetime = {
-            let mut lifetime_collector = AsyncFnLifetimeCollector {
-                context: self,
-                currently_bound_lifetimes: Vec::new(),
-                collect_elided_lifetimes: true,
-                output_lifetime: None,
+            let LoweredNodeId { node_id: _, hir_id } = this.next_id();
+            let exist_ty_item = hir::ExistTy {
+                generics: hir::Generics {
+                    params: generic_params,
+                    where_clause: hir::WhereClause {
+                        hir_id,
+                        predicates: hir_vec![],
+                    },
+                    span,
+                },
+                bounds: hir_vec![future_bound],
+                impl_trait_fn: Some(fn_def_id),
+                origin: hir::ExistTyOrigin::AsyncFn,
             };
 
-            for arg in inputs {
-                hir::intravisit::walk_ty(&mut lifetime_collector, arg);
-            }
-            lifetime_collector.output_lifetime
-        };
+            trace!("exist ty from async fn def index: {:#?}", exist_ty_def_index);
+            let exist_ty_id = this.generate_existential_type(
+                exist_ty_node_id,
+                exist_ty_item,
+                span,
+                exist_ty_span,
+            );
 
-        let span = match output {
-            FunctionRetTy::Ty(ty) => ty.span,
-            FunctionRetTy::Default(span) => *span,
-        };
+            (exist_ty_id.node_id, lifetime_params)
+        });
 
-        let impl_trait_ty = self.lower_existential_impl_trait(
-            span, Some(fn_def_id), return_impl_trait_id, |this| {
-            let output_ty = match output {
-                FunctionRetTy::Ty(ty) => {
-                    this.lower_ty(ty, ImplTraitContext::Existential(Some(fn_def_id)))
-                }
-                FunctionRetTy::Default(span) => {
-                    let LoweredNodeId { node_id: _, hir_id } = this.next_id();
-                    P(hir::Ty {
+        let generic_args =
+            lifetime_params
+                .iter().cloned()
+                .map(|(span, hir_name)| {
+                    let LoweredNodeId { node_id: _, hir_id  } = self.next_id();
+                    GenericArg::Lifetime(hir::Lifetime {
                         hir_id,
-                        node: hir::TyKind::Tup(hir_vec![]),
-                        span: *span,
+                        span,
+                        name: hir::LifetimeName::Param(hir_name),
                     })
-                }
-            };
-
-            // "<Output = T>"
-            let LoweredNodeId { node_id: _, hir_id } = this.next_id();
-            let future_params = P(hir::GenericArgs {
-                args: hir_vec![],
-                bindings: hir_vec![hir::TypeBinding {
-                    ident: Ident::from_str(FN_OUTPUT_NAME),
-                    ty: output_ty,
-                    hir_id,
-                    span,
-                }],
-                parenthesized: false,
-            });
+                })
+                .collect();
 
-            let future_path =
-                this.std_path(span, &["future", "Future"], Some(future_params), false);
+        let exist_ty_hir_id = self.lower_node_id(exist_ty_node_id).hir_id;
+        let exist_ty_ref = hir::TyKind::Def(hir::ItemId { id: exist_ty_hir_id }, generic_args);
 
-            let LoweredNodeId { node_id: _, hir_id } = this.next_id();
-            let mut bounds = vec![
-                hir::GenericBound::Trait(
-                    hir::PolyTraitRef {
-                        trait_ref: hir::TraitRef {
-                            path: future_path,
-                            hir_ref_id: hir_id,
-                        },
-                        bound_generic_params: hir_vec![],
-                        span,
-                    },
-                    hir::TraitBoundModifier::None
-                ),
-            ];
+        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
+        hir::FunctionRetTy::Return(P(hir::Ty {
+            node: exist_ty_ref,
+            span,
+            hir_id,
+        }))
+    }
 
-            if let Some((name, span)) = bound_lifetime {
-                let LoweredNodeId { node_id: _, hir_id } = this.next_id();
-                bounds.push(hir::GenericBound::Outlives(
-                    hir::Lifetime { hir_id, name, span }));
+    /// Turns `-> T` into `Future<Output = T>`
+    fn lower_async_fn_output_type_to_future_bound(
+        &mut self,
+        output: &FunctionRetTy,
+        fn_def_id: DefId,
+        span: Span,
+    ) -> hir::GenericBound {
+        // Compute the `T` in `Future<Output = T>` from the return type.
+        let output_ty = match output {
+            FunctionRetTy::Ty(ty) => {
+                self.lower_ty(ty, ImplTraitContext::Existential(Some(fn_def_id)))
             }
+            FunctionRetTy::Default(ret_ty_span) => {
+                let LoweredNodeId { node_id: _, hir_id } = self.next_id();
+                P(hir::Ty {
+                    hir_id,
+                    node: hir::TyKind::Tup(hir_vec![]),
+                    span: *ret_ty_span,
+                })
+            }
+        };
 
-            hir::HirVec::from(bounds)
-        });
-
+        // "<Output = T>"
         let LoweredNodeId { node_id: _, hir_id } = self.next_id();
-        let impl_trait_ty = P(hir::Ty {
-            node: impl_trait_ty,
-            span,
-            hir_id,
+        let future_params = P(hir::GenericArgs {
+            args: hir_vec![],
+            bindings: hir_vec![hir::TypeBinding {
+                ident: Ident::from_str(FN_OUTPUT_NAME),
+                ty: output_ty,
+                hir_id,
+                span,
+            }],
+            parenthesized: false,
         });
 
-        hir::FunctionRetTy::Return(impl_trait_ty)
+        // ::std::future::Future<future_params>
+        let future_path =
+            self.std_path(span, &["future", "Future"], Some(future_params), false);
+
+        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
+        hir::GenericBound::Trait(
+            hir::PolyTraitRef {
+                trait_ref: hir::TraitRef {
+                    path: future_path,
+                    hir_ref_id: hir_id,
+                },
+                bound_generic_params: hir_vec![],
+                span,
+            },
+            hir::TraitBoundModifier::None,
+        )
     }
 
     fn lower_param_bound(
@@ -2437,6 +2471,11 @@ impl<'a> LoweringContext<'a> {
                     }
 
                     AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
+
+                    AnonymousLifetimeMode::Replace(replacement) => {
+                        let LoweredNodeId { node_id: _, hir_id  } = self.lower_node_id(l.id);
+                        self.replace_elided_lifetime(hir_id, span, replacement)
+                    }
                 },
             ident => {
                 self.maybe_collect_in_band_lifetime(ident);
@@ -2461,6 +2500,39 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
+    /// Replace a return-position elided lifetime with the elided lifetime
+    /// from the arguments.
+    fn replace_elided_lifetime(
+        &mut self,
+        hir_id: hir::HirId,
+        span: Span,
+        replacement: LtReplacement,
+    ) -> hir::Lifetime {
+        let multiple_or_none = match replacement {
+            LtReplacement::Some(name) => {
+                return hir::Lifetime {
+                    hir_id,
+                    span,
+                    name: hir::LifetimeName::Param(name),
+                };
+            }
+            LtReplacement::MultipleLifetimes => "multiple",
+            LtReplacement::NoLifetimes => "none",
+        };
+
+        let mut err = crate::middle::resolve_lifetime::report_missing_lifetime_specifiers(
+            self.sess,
+            span,
+            1,
+        );
+        err.note(&format!(
+            "return-position elided lifetimes require exactly one \
+             input-position elided lifetime, found {}.", multiple_or_none));
+        err.emit();
+
+        hir::Lifetime { hir_id, span, name: hir::LifetimeName::Error }
+    }
+
     fn lower_generic_params(
         &mut self,
         params: &[GenericParam],
@@ -2941,6 +3013,7 @@ impl<'a> LoweringContext<'a> {
                 generics: self.lower_generics(generics, ImplTraitContext::disallowed()),
                 bounds: self.lower_param_bounds(b, ImplTraitContext::disallowed()),
                 impl_trait_fn: None,
+                origin: hir::ExistTyOrigin::ExistentialType,
             }),
             ItemKind::Enum(ref enum_definition, ref generics) => hir::ItemKind::Enum(
                 hir::EnumDef {
@@ -5083,7 +5156,8 @@ impl<'a> LoweringContext<'a> {
     /// with no explicit lifetime.
     fn elided_ref_lifetime(&mut self, span: Span) -> hir::Lifetime {
         match self.anonymous_lifetime_mode {
-            // Intercept when we are in an impl header and introduce an in-band lifetime.
+            // Intercept when we are in an impl header or async fn and introduce an in-band
+            // lifetime.
             // Hence `impl Foo for &u32` becomes `impl<'f> Foo for &'f u32` for some fresh
             // `'f`.
             AnonymousLifetimeMode::CreateParameter => {
@@ -5099,6 +5173,10 @@ impl<'a> LoweringContext<'a> {
             AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
 
             AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
+
+            AnonymousLifetimeMode::Replace(replacement) => {
+                self.new_replacement_lifetime(replacement, span)
+            }
         }
     }
 
@@ -5133,6 +5211,12 @@ impl<'a> LoweringContext<'a> {
     /// sorts of cases are deprecated. This may therefore report a warning or an
     /// error, depending on the mode.
     fn elided_path_lifetimes(&mut self, span: Span, count: usize) -> P<[hir::Lifetime]> {
+        (0..count)
+            .map(|_| self.elided_path_lifetime(span))
+            .collect()
+    }
+
+    fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
         match self.anonymous_lifetime_mode {
             // N.B., We intentionally ignore the create-parameter mode here
             // and instead "pass through" to resolve-lifetimes, which will then
@@ -5140,21 +5224,16 @@ impl<'a> LoweringContext<'a> {
             // impl elision for deprecated forms like
             //
             //     impl Foo for std::cell::Ref<u32> // note lack of '_
-            AnonymousLifetimeMode::CreateParameter => {}
+            AnonymousLifetimeMode::CreateParameter |
+            // This is the normal case.
+            AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
 
-            AnonymousLifetimeMode::ReportError => {
-                return (0..count)
-                    .map(|_| self.new_error_lifetime(None, span))
-                    .collect();
+            AnonymousLifetimeMode::Replace(replacement) => {
+                self.new_replacement_lifetime(replacement, span)
             }
 
-            // This is the normal case.
-            AnonymousLifetimeMode::PassThrough => {}
+            AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
         }
-
-        (0..count)
-            .map(|_| self.new_implicit_lifetime(span))
-            .collect()
     }
 
     /// Invoked to create the lifetime argument(s) for an elided trait object
@@ -5184,11 +5263,25 @@ impl<'a> LoweringContext<'a> {
 
             // This is the normal case.
             AnonymousLifetimeMode::PassThrough => {}
+
+            // We don't need to do any replacement here as this lifetime
+            // doesn't refer to an elided lifetime elsewhere in the function
+            // signature.
+            AnonymousLifetimeMode::Replace(_) => {}
         }
 
         self.new_implicit_lifetime(span)
     }
 
+    fn new_replacement_lifetime(
+        &mut self,
+        replacement: LtReplacement,
+        span: Span,
+    ) -> hir::Lifetime {
+        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
+        self.replace_elided_lifetime(hir_id, span, replacement)
+    }
+
     fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {
         let LoweredNodeId { node_id: _, hir_id } = self.next_id();
 
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 8509ddaccf7..58a27d3f78e 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1799,6 +1799,18 @@ pub struct ExistTy {
     pub generics: Generics,
     pub bounds: GenericBounds,
     pub impl_trait_fn: Option<DefId>,
+    pub origin: ExistTyOrigin,
+}
+
+/// Where the existential type came from
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+pub enum ExistTyOrigin {
+    /// `existential type Foo: Trait;`
+    ExistentialType,
+    /// `-> impl Trait`
+    ReturnImplTrait,
+    /// `async fn`
+    AsyncFn,
 }
 
 /// The various kinds of types recognized by the compiler.
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 0a65473de8f..d1020a2d151 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -622,7 +622,7 @@ impl<'a> State<'a> {
             }
             hir::ItemKind::GlobalAsm(ref ga) => {
                 self.head(visibility_qualified(&item.vis, "global asm"))?;
-                self.s.word(ga.asm.as_str().get())?;
+                self.s.word(ga.asm.as_str().to_string())?;
                 self.end()?
             }
             hir::ItemKind::Ty(ref ty, ref generics) => {
@@ -1591,7 +1591,7 @@ impl<'a> State<'a> {
         if ident.is_raw_guess() {
             self.s.word(format!("r#{}", ident.name))?;
         } else {
-            self.s.word(ident.as_str().get())?;
+            self.s.word(ident.as_str().to_string())?;
         }
         self.ann.post(self, AnnNode::Name(&ident.name))
     }
@@ -1998,7 +1998,7 @@ impl<'a> State<'a> {
         self.commasep(Inconsistent, &decl.inputs, |s, ty| {
             s.ibox(indent_unit)?;
             if let Some(arg_name) = arg_names.get(i) {
-                s.s.word(arg_name.as_str().get())?;
+                s.s.word(arg_name.as_str().to_string())?;
                 s.s.word(":")?;
                 s.s.space()?;
             } else if let Some(body_id) = body_id {
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index e60fdd62deb..a8e5db26ead 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -9,7 +9,6 @@ use crate::session::Session;
 
 use std::cmp::Ord;
 use std::hash as std_hash;
-use std::collections::HashMap;
 use std::cell::RefCell;
 
 use syntax::ast;
@@ -394,13 +393,12 @@ impl<'a> HashStable<StableHashingContext<'a>> for DelimSpan {
     }
 }
 
-pub fn hash_stable_trait_impls<'a, 'gcx, W, R>(
+pub fn hash_stable_trait_impls<'a, 'gcx, W>(
     hcx: &mut StableHashingContext<'a>,
     hasher: &mut StableHasher<W>,
     blanket_impls: &[DefId],
-    non_blanket_impls: &HashMap<fast_reject::SimplifiedType, Vec<DefId>, R>)
-    where W: StableHasherResult,
-          R: std_hash::BuildHasher,
+    non_blanket_impls: &FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>)
+    where W: StableHasherResult
 {
     {
         let mut blanket_impls: SmallVec<[_; 8]> = blanket_impls
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 2810b5a8e6a..6b2b0c24c77 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -56,7 +56,7 @@ use crate::hir::Node;
 use crate::middle::region;
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use crate::ty::error::TypeError;
-use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TyKind, TypeFoldable};
+use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
 use std::{cmp, fmt};
 use syntax_pos::{Pos, Span};
@@ -278,7 +278,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn explain_span(self, heading: &str, span: Span) -> (String, Option<Span>) {
-        let lo = self.sess.source_map().lookup_char_pos_adj(span.lo());
+        let lo = self.sess.source_map().lookup_char_pos(span.lo());
         (
             format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1),
             Some(span),
@@ -604,13 +604,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 source,
                 ref prior_arms,
                 last_ty,
+                discrim_hir_id,
                 ..
             } => match source {
                 hir::MatchSource::IfLetDesugar { .. } => {
                     let msg = "`if let` arms have incompatible types";
                     err.span_label(cause.span, msg);
                 }
-                hir::MatchSource::TryDesugar => {}
+                hir::MatchSource::TryDesugar => {
+                    if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
+                        let discrim_expr = self.tcx.hir().expect_expr_by_hir_id(discrim_hir_id);
+                        let discrim_ty = if let hir::ExprKind::Call(_, args) = &discrim_expr.node {
+                            let arg_expr = args.first().expect("try desugaring call w/out arg");
+                            self.in_progress_tables.and_then(|tables| {
+                                tables.borrow().expr_ty_opt(arg_expr)
+                            })
+                        } else {
+                            bug!("try desugaring w/out call expr as discriminant");
+                        };
+
+                        match discrim_ty {
+                            Some(ty) if expected == ty => {
+                                let source_map = self.tcx.sess.source_map();
+                                err.span_suggestion(
+                                    source_map.end_point(cause.span),
+                                    "try removing this `?`",
+                                    "".to_string(),
+                                    Applicability::MachineApplicable,
+                                );
+                            },
+                            _ => {},
+                        }
+                    }
+                }
                 _ => {
                     let msg = "`match` arms have incompatible types";
                     err.span_label(cause.span, msg);
@@ -1094,14 +1120,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 (_, false, _) => {
                     if let Some(exp_found) = exp_found {
                         let (def_id, ret_ty) = match exp_found.found.sty {
-                            TyKind::FnDef(def, _) => {
+                            ty::FnDef(def, _) => {
                                 (Some(def), Some(self.tcx.fn_sig(def).output()))
                             }
                             _ => (None, None),
                         };
 
                         let exp_is_struct = match exp_found.expected.sty {
-                            TyKind::Adt(def, _) => def.is_struct(),
+                            ty::Adt(def, _) => def.is_struct(),
                             _ => false,
                         };
 
@@ -1140,8 +1166,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         diag: &mut DiagnosticBuilder<'tcx>,
     ) {
         match (&exp_found.expected.sty, &exp_found.found.sty) {
-            (TyKind::Adt(exp_def, exp_substs), TyKind::Ref(_, found_ty, _)) => {
-                if let TyKind::Adt(found_def, found_substs) = found_ty.sty {
+            (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) => {
+                if let ty::Adt(found_def, found_substs) = found_ty.sty {
                     let path_str = format!("{:?}", exp_def);
                     if exp_def == &found_def {
                         let opt_msg = "you can convert from `&Option<T>` to `Option<&T>` using \
@@ -1164,17 +1190,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                             let mut show_suggestion = true;
                             for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) {
                                 match exp_ty.sty {
-                                    TyKind::Ref(_, exp_ty, _) => {
+                                    ty::Ref(_, exp_ty, _) => {
                                         match (&exp_ty.sty, &found_ty.sty) {
-                                            (_, TyKind::Param(_)) |
-                                            (_, TyKind::Infer(_)) |
-                                            (TyKind::Param(_), _) |
-                                            (TyKind::Infer(_), _) => {}
+                                            (_, ty::Param(_)) |
+                                            (_, ty::Infer(_)) |
+                                            (ty::Param(_), _) |
+                                            (ty::Infer(_), _) => {}
                                             _ if ty::TyS::same_type(exp_ty, found_ty) => {}
                                             _ => show_suggestion = false,
                                         };
                                     }
-                                    TyKind::Param(_) | TyKind::Infer(_) => {}
+                                    ty::Param(_) | ty::Infer(_) => {}
                                     _ => show_suggestion = false,
                                 }
                             }
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 8bd20843163..be9460ad86f 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -67,6 +67,9 @@ pub struct OpaqueTypeDecl<'tcx> {
     /// the fn body). (Ultimately, writeback is responsible for this
     /// check.)
     pub has_required_region_bounds: bool,
+
+    /// The origin of the existential type
+    pub origin: hir::ExistTyOrigin,
 }
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
@@ -326,14 +329,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                         // There are two regions (`lr` and
                         // `subst_arg`) which are not relatable. We can't
                         // find a best choice.
-                        self.tcx
+                        let context_name = match opaque_defn.origin {
+                            hir::ExistTyOrigin::ExistentialType => "existential type",
+                            hir::ExistTyOrigin::ReturnImplTrait => "impl Trait",
+                            hir::ExistTyOrigin::AsyncFn => "async fn",
+                        };
+                        let msg = format!("ambiguous lifetime bound in `{}`", context_name);
+                        let mut err = self.tcx
                             .sess
-                            .struct_span_err(span, "ambiguous lifetime bound in `impl Trait`")
-                            .span_label(
-                                span,
-                                format!("neither `{}` nor `{}` outlives the other", lr, subst_arg),
-                            )
-                            .emit();
+                            .struct_span_err(span, &msg);
+
+                        let lr_name = lr.to_string();
+                        let subst_arg_name = subst_arg.to_string();
+                        let label_owned;
+                        let label = match (&*lr_name, &*subst_arg_name) {
+                            ("'_", "'_") => "the elided lifetimes here do not outlive one another",
+                            _ => {
+                                label_owned = format!(
+                                    "neither `{}` nor `{}` outlives the other",
+                                    lr_name,
+                                    subst_arg_name,
+                                );
+                                &label_owned
+                            }
+                        };
+                        err.span_label(span, label);
+
+                        if let hir::ExistTyOrigin::AsyncFn = opaque_defn.origin {
+                            err.note("multiple unrelated lifetimes are not allowed in \
+                                     `async fn`.");
+                            err.note("if you're using argument-position elided lifetimes, consider \
+                                switching to a single named lifetime.");
+                        }
+                        err.emit();
 
                         least_region = Some(self.tcx.mk_region(ty::ReEmpty));
                         break;
@@ -692,31 +720,41 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
                             parent_def_id == tcx.hir()
                                                 .local_def_id_from_hir_id(opaque_parent_hir_id)
                         };
-                        let in_definition_scope = match tcx.hir().find_by_hir_id(opaque_hir_id) {
+                        let (in_definition_scope, origin) =
+                            match tcx.hir().find_by_hir_id(opaque_hir_id)
+                        {
                             Some(Node::Item(item)) => match item.node {
                                 // impl trait
                                 hir::ItemKind::Existential(hir::ExistTy {
                                     impl_trait_fn: Some(parent),
+                                    origin,
                                     ..
-                                }) => parent == self.parent_def_id,
+                                }) => (parent == self.parent_def_id, origin),
                                 // named existential types
                                 hir::ItemKind::Existential(hir::ExistTy {
                                     impl_trait_fn: None,
+                                    origin,
                                     ..
-                                }) => may_define_existential_type(
-                                    tcx,
-                                    self.parent_def_id,
-                                    opaque_hir_id,
+                                }) => (
+                                    may_define_existential_type(
+                                        tcx,
+                                        self.parent_def_id,
+                                        opaque_hir_id,
+                                    ),
+                                    origin,
                                 ),
-                                _ => def_scope_default(),
+                                _ => (def_scope_default(), hir::ExistTyOrigin::ExistentialType),
                             },
                             Some(Node::ImplItem(item)) => match item.node {
-                                hir::ImplItemKind::Existential(_) => may_define_existential_type(
-                                    tcx,
-                                    self.parent_def_id,
-                                    opaque_hir_id,
+                                hir::ImplItemKind::Existential(_) => (
+                                    may_define_existential_type(
+                                        tcx,
+                                        self.parent_def_id,
+                                        opaque_hir_id,
+                                    ),
+                                    hir::ExistTyOrigin::ExistentialType,
                                 ),
-                                _ => def_scope_default(),
+                                _ => (def_scope_default(), hir::ExistTyOrigin::ExistentialType),
                             },
                             _ => bug!(
                                 "expected (impl) item, found {}",
@@ -724,7 +762,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
                             ),
                         };
                         if in_definition_scope {
-                            return self.fold_opaque_ty(ty, def_id, substs);
+                            return self.fold_opaque_ty(ty, def_id, substs, origin);
                         }
 
                         debug!(
@@ -746,6 +784,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
         ty: Ty<'tcx>,
         def_id: DefId,
         substs: SubstsRef<'tcx>,
+        origin: hir::ExistTyOrigin,
     ) -> Ty<'tcx> {
         let infcx = self.infcx;
         let tcx = infcx.tcx;
@@ -795,6 +834,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
                 substs,
                 concrete_ty: ty_var,
                 has_required_region_bounds: !required_region_bounds.is_empty(),
+                origin,
             },
         );
         debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index b87343b43c9..c5c2cbfcb89 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -29,6 +29,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(explicit_outlives_requirements)]
 
 #![feature(arbitrary_self_types)]
@@ -39,6 +40,7 @@
 #![cfg_attr(windows, feature(libc))]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
+#![feature(overlapping_marker_traits)]
 #![feature(extern_types)]
 #![feature(nll)]
 #![feature(non_exhaustive)]
@@ -102,6 +104,8 @@ pub mod diagnostics;
 #[macro_use]
 pub mod query;
 
+#[macro_use]
+pub mod arena;
 pub mod cfg;
 pub mod dep_graph;
 pub mod hir;
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 2d8a2c6321f..28a2a1eaf6b 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -352,12 +352,6 @@ declare_lint! {
     "outlives requirements can be inferred"
 }
 
-declare_lint! {
-    pub DUPLICATE_MATCHER_BINDING_NAME,
-    Deny,
-    "duplicate macro matcher binding name"
-}
-
 /// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
 pub mod parser {
     declare_lint! {
@@ -392,81 +386,78 @@ declare_lint! {
     "nested occurrence of `impl Trait` type"
 }
 
-/// Does nothing as a lint pass, but registers some `Lint`s
-/// that are used by other parts of the compiler.
-#[derive(Copy, Clone)]
-pub struct HardwiredLints;
-
-impl LintPass for HardwiredLints {
-    fn name(&self) -> &'static str {
-        "HardwiredLints"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(
-            ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
-            EXCEEDING_BITSHIFTS,
-            UNUSED_IMPORTS,
-            UNUSED_EXTERN_CRATES,
-            UNUSED_QUALIFICATIONS,
-            UNKNOWN_LINTS,
-            UNUSED_VARIABLES,
-            UNUSED_ASSIGNMENTS,
-            DEAD_CODE,
-            UNREACHABLE_CODE,
-            UNREACHABLE_PATTERNS,
-            UNUSED_MACROS,
-            WARNINGS,
-            UNUSED_FEATURES,
-            STABLE_FEATURES,
-            UNKNOWN_CRATE_TYPES,
-            TRIVIAL_CASTS,
-            TRIVIAL_NUMERIC_CASTS,
-            PRIVATE_IN_PUBLIC,
-            EXPORTED_PRIVATE_DEPENDENCIES,
-            PUB_USE_OF_PRIVATE_EXTERN_CRATE,
-            INVALID_TYPE_PARAM_DEFAULT,
-            CONST_ERR,
-            RENAMED_AND_REMOVED_LINTS,
-            SAFE_EXTERN_STATICS,
-            SAFE_PACKED_BORROWS,
-            PATTERNS_IN_FNS_WITHOUT_BODY,
-            LEGACY_DIRECTORY_OWNERSHIP,
-            LEGACY_CONSTRUCTOR_VISIBILITY,
-            MISSING_FRAGMENT_SPECIFIER,
-            PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
-            LATE_BOUND_LIFETIME_ARGUMENTS,
-            INCOHERENT_FUNDAMENTAL_IMPLS,
-            ORDER_DEPENDENT_TRAIT_OBJECTS,
-            DEPRECATED,
-            UNUSED_UNSAFE,
-            UNUSED_MUT,
-            UNCONDITIONAL_RECURSION,
-            SINGLE_USE_LIFETIMES,
-            UNUSED_LIFETIMES,
-            UNUSED_LABELS,
-            TYVAR_BEHIND_RAW_POINTER,
-            ELIDED_LIFETIMES_IN_PATHS,
-            BARE_TRAIT_OBJECTS,
-            ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
-            UNSTABLE_NAME_COLLISIONS,
-            IRREFUTABLE_LET_PATTERNS,
-            DUPLICATE_MACRO_EXPORTS,
-            INTRA_DOC_LINK_RESOLUTION_FAILURE,
-            MISSING_DOC_CODE_EXAMPLES,
-            PRIVATE_DOC_TESTS,
-            WHERE_CLAUSES_OBJECT_SAFETY,
-            PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
-            MACRO_USE_EXTERN_CRATE,
-            MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
-            parser::QUESTION_MARK_MACRO_SEP,
-            parser::ILL_FORMED_ATTRIBUTE_INPUT,
-            DEPRECATED_IN_FUTURE,
-            AMBIGUOUS_ASSOCIATED_ITEMS,
-            NESTED_IMPL_TRAIT,
-            DUPLICATE_MATCHER_BINDING_NAME,
-        )
-    }
+declare_lint! {
+    pub MUTABLE_BORROW_RESERVATION_CONFLICT,
+    Warn,
+    "reservation of a two-phased borrow conflicts with other shared borrows"
+}
+
+declare_lint_pass! {
+    /// Does nothing as a lint pass, but registers some `Lint`s
+    /// that are used by other parts of the compiler.
+    HardwiredLints => [
+        ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+        EXCEEDING_BITSHIFTS,
+        UNUSED_IMPORTS,
+        UNUSED_EXTERN_CRATES,
+        UNUSED_QUALIFICATIONS,
+        UNKNOWN_LINTS,
+        UNUSED_VARIABLES,
+        UNUSED_ASSIGNMENTS,
+        DEAD_CODE,
+        UNREACHABLE_CODE,
+        UNREACHABLE_PATTERNS,
+        UNUSED_MACROS,
+        WARNINGS,
+        UNUSED_FEATURES,
+        STABLE_FEATURES,
+        UNKNOWN_CRATE_TYPES,
+        TRIVIAL_CASTS,
+        TRIVIAL_NUMERIC_CASTS,
+        PRIVATE_IN_PUBLIC,
+        EXPORTED_PRIVATE_DEPENDENCIES,
+        PUB_USE_OF_PRIVATE_EXTERN_CRATE,
+        INVALID_TYPE_PARAM_DEFAULT,
+        CONST_ERR,
+        RENAMED_AND_REMOVED_LINTS,
+        SAFE_EXTERN_STATICS,
+        SAFE_PACKED_BORROWS,
+        PATTERNS_IN_FNS_WITHOUT_BODY,
+        LEGACY_DIRECTORY_OWNERSHIP,
+        LEGACY_CONSTRUCTOR_VISIBILITY,
+        MISSING_FRAGMENT_SPECIFIER,
+        PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+        LATE_BOUND_LIFETIME_ARGUMENTS,
+        INCOHERENT_FUNDAMENTAL_IMPLS,
+        ORDER_DEPENDENT_TRAIT_OBJECTS,
+        DEPRECATED,
+        UNUSED_UNSAFE,
+        UNUSED_MUT,
+        UNCONDITIONAL_RECURSION,
+        SINGLE_USE_LIFETIMES,
+        UNUSED_LIFETIMES,
+        UNUSED_LABELS,
+        TYVAR_BEHIND_RAW_POINTER,
+        ELIDED_LIFETIMES_IN_PATHS,
+        BARE_TRAIT_OBJECTS,
+        ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
+        UNSTABLE_NAME_COLLISIONS,
+        IRREFUTABLE_LET_PATTERNS,
+        DUPLICATE_MACRO_EXPORTS,
+        INTRA_DOC_LINK_RESOLUTION_FAILURE,
+        MISSING_DOC_CODE_EXAMPLES,
+        PRIVATE_DOC_TESTS,
+        WHERE_CLAUSES_OBJECT_SAFETY,
+        PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
+        MACRO_USE_EXTERN_CRATE,
+        MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+        parser::QUESTION_MARK_MACRO_SEP,
+        parser::ILL_FORMED_ATTRIBUTE_INPUT,
+        DEPRECATED_IN_FUTURE,
+        AMBIGUOUS_ASSOCIATED_ITEMS,
+        NESTED_IMPL_TRAIT,
+        MUTABLE_BORROW_RESERVATION_CONFLICT,
+    ]
 }
 
 // this could be a closure, but then implementing derive traits
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index e5eafd768bb..15ea6403e38 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -25,7 +25,7 @@ use crate::lint::levels::{LintLevelSets, LintLevelsBuilder};
 use crate::middle::privacy::AccessLevels;
 use crate::rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
 use crate::session::{config, early_error, Session};
-use crate::ty::{self, TyCtxt, Ty};
+use crate::ty::{self, print::Printer, subst::Kind, TyCtxt, Ty};
 use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
 use crate::util::nodemap::FxHashMap;
 use crate::util::common::time;
@@ -36,9 +36,10 @@ use syntax::edition;
 use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}};
 use errors::DiagnosticBuilder;
 use crate::hir;
-use crate::hir::def_id::{DefId, LOCAL_CRATE};
+use crate::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use crate::hir::intravisit as hir_visit;
 use crate::hir::intravisit::Visitor;
+use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit as ast_visit;
 
@@ -752,6 +753,114 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
     pub fn current_lint_root(&self) -> hir::HirId {
         self.last_node_with_lint_attrs
     }
+
+    /// Check if a `DefId`'s path matches the given absolute type path usage.
+    // Uplifted from rust-lang/rust-clippy
+    pub fn match_path(&self, def_id: DefId, path: &[&str]) -> bool {
+        pub struct AbsolutePathPrinter<'a, 'tcx> {
+            pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        }
+
+        impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> {
+            type Error = !;
+
+            type Path = Vec<LocalInternedString>;
+            type Region = ();
+            type Type = ();
+            type DynExistential = ();
+
+            fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
+                self.tcx
+            }
+
+            fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
+                Ok(())
+            }
+
+            fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+                Ok(())
+            }
+
+            fn print_dyn_existential(
+                self,
+                _predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+                ) -> Result<Self::DynExistential, Self::Error> {
+                Ok(())
+            }
+
+            fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
+                Ok(vec![self.tcx.original_crate_name(cnum).as_str()])
+            }
+
+            fn path_qualified(
+                self,
+                self_ty: Ty<'tcx>,
+                trait_ref: Option<ty::TraitRef<'tcx>>,
+                ) -> Result<Self::Path, Self::Error> {
+                if trait_ref.is_none() {
+                    if let ty::Adt(def, substs) = self_ty.sty {
+                        return self.print_def_path(def.did, substs);
+                    }
+                }
+
+                // This shouldn't ever be needed, but just in case:
+                Ok(vec![match trait_ref {
+                    Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)).as_str(),
+                    None => Symbol::intern(&format!("<{}>", self_ty)).as_str(),
+                }])
+            }
+
+            fn path_append_impl(
+                self,
+                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                _disambiguated_data: &DisambiguatedDefPathData,
+                self_ty: Ty<'tcx>,
+                trait_ref: Option<ty::TraitRef<'tcx>>,
+                ) -> Result<Self::Path, Self::Error> {
+                let mut path = print_prefix(self)?;
+
+                // This shouldn't ever be needed, but just in case:
+                path.push(match trait_ref {
+                    Some(trait_ref) => {
+                        Symbol::intern(&format!("<impl {} for {}>", trait_ref, self_ty)).as_str()
+                    },
+                    None => Symbol::intern(&format!("<impl {}>", self_ty)).as_str(),
+                });
+
+                Ok(path)
+            }
+
+            fn path_append(
+                self,
+                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                disambiguated_data: &DisambiguatedDefPathData,
+                ) -> Result<Self::Path, Self::Error> {
+                let mut path = print_prefix(self)?;
+
+                // Skip `::{{constructor}}` on tuple/unit structs.
+                match disambiguated_data.data {
+                    DefPathData::Ctor => return Ok(path),
+                    _ => {}
+                }
+
+                path.push(disambiguated_data.data.as_interned_str().as_str());
+                Ok(path)
+            }
+
+            fn path_generic_args(
+                self,
+                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                _args: &[Kind<'tcx>],
+                ) -> Result<Self::Path, Self::Error> {
+                print_prefix(self)
+            }
+        }
+
+        let names = AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]).unwrap();
+
+        names.len() == path.len()
+            && names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
+    }
 }
 
 impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> {
diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs
new file mode 100644
index 00000000000..0bafa93011e
--- /dev/null
+++ b/src/librustc/lint/internal.rs
@@ -0,0 +1,109 @@
+//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
+//! Clippy.
+
+use crate::hir::{HirId, Path, PathSegment, QPath, Ty, TyKind};
+use crate::lint::{
+    EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
+};
+use errors::Applicability;
+use rustc_data_structures::fx::FxHashMap;
+use syntax::ast::Ident;
+
+declare_lint! {
+    pub DEFAULT_HASH_TYPES,
+    Allow,
+    "forbid HashMap and HashSet and suggest the FxHash* variants"
+}
+
+pub struct DefaultHashTypes {
+    map: FxHashMap<String, String>,
+}
+
+impl DefaultHashTypes {
+    pub fn new() -> Self {
+        let mut map = FxHashMap::default();
+        map.insert("HashMap".to_string(), "FxHashMap".to_string());
+        map.insert("HashSet".to_string(), "FxHashSet".to_string());
+        Self { map }
+    }
+}
+
+impl_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
+
+impl EarlyLintPass for DefaultHashTypes {
+    fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
+        let ident_string = ident.to_string();
+        if let Some(replace) = self.map.get(&ident_string) {
+            let msg = format!(
+                "Prefer {} over {}, it has better performance",
+                replace, ident_string
+            );
+            let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
+            db.span_suggestion(
+                ident.span,
+                "use",
+                replace.to_string(),
+                Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
+            );
+            db.note(&format!(
+                "a `use rustc_data_structures::fx::{}` may be necessary",
+                replace
+            ))
+            .emit();
+        }
+    }
+}
+
+declare_lint! {
+    pub USAGE_OF_TY_TYKIND,
+    Allow,
+    "Usage of `ty::TyKind` outside of the `ty::sty` module"
+}
+
+declare_lint_pass!(TyKindUsage => [USAGE_OF_TY_TYKIND]);
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
+    fn check_path(&mut self, cx: &LateContext<'_, '_>, path: &'tcx Path, _: HirId) {
+        let segments = path.segments.iter().rev().skip(1).rev();
+
+        if let Some(last) = segments.last() {
+            let span = path.span.with_hi(last.ident.span.hi());
+            if lint_ty_kind_usage(cx, last) {
+                cx.struct_span_lint(USAGE_OF_TY_TYKIND, span, "usage of `ty::TyKind::<kind>`")
+                    .span_suggestion(
+                        span,
+                        "try using ty::<kind> directly",
+                        "ty".to_string(),
+                        Applicability::MaybeIncorrect, // ty maybe needs an import
+                    )
+                    .emit();
+            }
+        }
+    }
+
+    fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) {
+        if let TyKind::Path(qpath) = &ty.node {
+            if let QPath::Resolved(_, path) = qpath {
+                if let Some(last) = path.segments.iter().last() {
+                    if lint_ty_kind_usage(cx, last) {
+                        cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, "usage of `ty::TyKind`")
+                            .help("try using `ty::Ty` instead")
+                            .emit();
+                    }
+                }
+            }
+        }
+    }
+}
+
+fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment) -> bool {
+    if segment.ident.as_str() == "TyKind" {
+        if let Some(def) = segment.def {
+            if let Some(did) = def.opt_def_id() {
+                return cx.match_path(did, &["rustc", "ty", "sty", "TyKind"]);
+            }
+        }
+    }
+
+    false
+}
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index a5506bb8f59..112c247d4d6 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -26,7 +26,7 @@ use rustc_data_structures::sync::{self, Lrc};
 use crate::hir::def_id::{CrateNum, LOCAL_CRATE};
 use crate::hir::intravisit;
 use crate::hir;
-use crate::lint::builtin::{BuiltinLintDiagnostics, DUPLICATE_MATCHER_BINDING_NAME};
+use crate::lint::builtin::BuiltinLintDiagnostics;
 use crate::lint::builtin::parser::{QUESTION_MARK_MACRO_SEP, ILL_FORMED_ATTRIBUTE_INPUT};
 use crate::session::{Session, DiagnosticMessageId};
 use crate::ty::TyCtxt;
@@ -82,7 +82,6 @@ impl Lint {
         match lint_id {
             BufferedEarlyLintId::QuestionMarkMacroSep => QUESTION_MARK_MACRO_SEP,
             BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT,
-            BufferedEarlyLintId::DuplicateMacroMatcherBindingName => DUPLICATE_MATCHER_BINDING_NAME,
         }
     }
 
@@ -181,6 +180,27 @@ pub trait LintPass {
     fn get_lints(&self) -> LintArray;
 }
 
+/// Implements `LintPass for $name` with the given list of `Lint` statics.
+#[macro_export]
+macro_rules! impl_lint_pass {
+    ($name:ident => [$($lint:expr),* $(,)?]) => {
+        impl LintPass for $name {
+            fn name(&self) -> &'static str { stringify!($name) }
+            fn get_lints(&self) -> LintArray { $crate::lint_array!($($lint),*) }
+        }
+    };
+}
+
+/// Declares a type named `$name` which implements `LintPass`.
+/// To the right of `=>` a comma separated list of `Lint` statics is given.
+#[macro_export]
+macro_rules! declare_lint_pass {
+    ($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
+        $(#[$m])* #[derive(Copy, Clone)] pub struct $name;
+        $crate::impl_lint_pass!($name => [$($lint),*]);
+    };
+}
+
 #[macro_export]
 macro_rules! late_lint_methods {
     ($macro:path, $args:tt, [$hir:tt]) => (
@@ -574,6 +594,7 @@ impl_stable_hash_for!(enum self::LintSource {
 pub type LevelSource = (Level, LintSource);
 
 pub mod builtin;
+pub mod internal;
 mod context;
 mod levels;
 
@@ -690,10 +711,14 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
             "this was previously accepted by the compiler but is being phased out; \
              it will become a hard error";
 
-        let explanation = if lint_id == LintId::of(crate::lint::builtin::UNSTABLE_NAME_COLLISIONS) {
+        let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
             "once this method is added to the standard library, \
              the ambiguity may cause an error or change in behavior!"
                 .to_owned()
+        } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) {
+            "this borrowing pattern was not meant to be accepted, \
+             and may become a hard error in the future"
+                .to_owned()
         } else if let Some(edition) = future_incompatible.edition {
             format!("{} in the {} edition!", STANDARD_MESSAGE, edition)
         } else {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 73e232a6a4f..3306bcae212 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -2891,7 +2891,7 @@ fn insert_late_bound_lifetimes(
     }
 }
 
-fn report_missing_lifetime_specifiers(
+pub fn report_missing_lifetime_specifiers(
     sess: &Session,
     span: Span,
     count: usize,
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index fc04c7672db..b9c4d312adb 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -43,7 +43,7 @@ pub type ConstEvalResult<'tcx> = Result<ty::Const<'tcx>, ErrorHandled>;
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct ConstEvalErr<'tcx> {
     pub span: Span,
-    pub error: crate::mir::interpret::EvalErrorKind<'tcx, u64>,
+    pub error: crate::mir::interpret::InterpError<'tcx, u64>,
     pub stacktrace: Vec<FrameInfo<'tcx>>,
 }
 
@@ -65,8 +65,8 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
                 write!(f, "inside call to `{}`", self.instance)?;
             }
             if !self.call_site.is_dummy() {
-                let lo = tcx.sess.source_map().lookup_char_pos_adj(self.call_site.lo());
-                write!(f, " at {}:{}:{}", lo.filename, lo.line, lo.col.to_usize() + 1)?;
+                let lo = tcx.sess.source_map().lookup_char_pos(self.call_site.lo());
+                write!(f, " at {}:{}:{}", lo.file.name, lo.line, lo.col.to_usize() + 1)?;
             }
             Ok(())
         })
@@ -135,10 +135,10 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
         lint_root: Option<hir::HirId>,
     ) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
         match self.error {
-            EvalErrorKind::Layout(LayoutError::Unknown(_)) |
-            EvalErrorKind::TooGeneric => return Err(ErrorHandled::TooGeneric),
-            EvalErrorKind::Layout(LayoutError::SizeOverflow(_)) |
-            EvalErrorKind::TypeckError => return Err(ErrorHandled::Reported),
+            InterpError::Layout(LayoutError::Unknown(_)) |
+            InterpError::TooGeneric => return Err(ErrorHandled::TooGeneric),
+            InterpError::Layout(LayoutError::SizeOverflow(_)) |
+            InterpError::TypeckError => return Err(ErrorHandled::Reported),
             _ => {},
         }
         trace!("reporting const eval failure at {:?}", self.span);
@@ -180,7 +180,7 @@ pub fn struct_error<'a, 'gcx, 'tcx>(
 
 #[derive(Debug, Clone)]
 pub struct EvalError<'tcx> {
-    pub kind: EvalErrorKind<'tcx, u64>,
+    pub kind: InterpError<'tcx, u64>,
     pub backtrace: Option<Box<Backtrace>>,
 }
 
@@ -197,8 +197,8 @@ fn print_backtrace(backtrace: &mut Backtrace) {
     eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
 }
 
-impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
-    fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
+impl<'tcx> From<InterpError<'tcx, u64>> for EvalError<'tcx> {
+    fn from(kind: InterpError<'tcx, u64>) -> Self {
         let backtrace = match env::var("RUST_CTFE_BACKTRACE") {
             // matching RUST_BACKTRACE, we treat "0" the same as "not present".
             Ok(ref val) if val != "0" => {
@@ -221,10 +221,10 @@ impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
     }
 }
 
-pub type AssertMessage<'tcx> = EvalErrorKind<'tcx, mir::Operand<'tcx>>;
+pub type AssertMessage<'tcx> = InterpError<'tcx, mir::Operand<'tcx>>;
 
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub enum EvalErrorKind<'tcx, O> {
+pub enum InterpError<'tcx, O> {
     /// This variant is used by machines to signal their own errors that do not
     /// match an existing variant.
     MachineError(String),
@@ -312,9 +312,9 @@ pub enum EvalErrorKind<'tcx, O> {
 
 pub type EvalResult<'tcx, T = ()> = Result<T, EvalError<'tcx>>;
 
-impl<'tcx, O> EvalErrorKind<'tcx, O> {
+impl<'tcx, O> InterpError<'tcx, O> {
     pub fn description(&self) -> &str {
-        use self::EvalErrorKind::*;
+        use self::InterpError::*;
         match *self {
             MachineError(ref inner) => inner,
             FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionRetMismatch(..)
@@ -450,15 +450,15 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
     }
 }
 
-impl<'tcx> fmt::Display for EvalErrorKind<'tcx, u64> {
+impl<'tcx> fmt::Display for InterpError<'tcx, u64> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self)
     }
 }
 
-impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
+impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use self::EvalErrorKind::*;
+        use self::InterpError::*;
         match *self {
             PointerOutOfBounds { ptr, check, allocation_size } => {
                 write!(f, "Pointer must be in-bounds{} at offset {}, but is outside bounds of \
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 0dd83168527..2c619a7a250 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -2,7 +2,7 @@
 
 #[macro_export]
 macro_rules! err {
-    ($($tt:tt)*) => { Err($crate::mir::interpret::EvalErrorKind::$($tt)*.into()) };
+    ($($tt:tt)*) => { Err($crate::mir::interpret::InterpError::$($tt)*.into()) };
 }
 
 mod error;
@@ -11,7 +11,7 @@ mod allocation;
 mod pointer;
 
 pub use self::error::{
-    EvalError, EvalResult, EvalErrorKind, AssertMessage, ConstEvalErr, struct_error,
+    EvalError, EvalResult, InterpError, AssertMessage, ConstEvalErr, struct_error,
     FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled,
 };
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 7b419e306db..3cab7a3812f 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -4,8 +4,8 @@
 
 use crate::hir::def::{CtorKind, Namespace};
 use crate::hir::def_id::DefId;
-use crate::hir::{self, HirId, InlineAsm};
-use crate::mir::interpret::{ConstValue, EvalErrorKind, Scalar};
+use crate::hir::{self, HirId, InlineAsm as HirInlineAsm};
+use crate::mir::interpret::{ConstValue, InterpError, Scalar};
 use crate::mir::visit::MirVisitable;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
@@ -25,7 +25,7 @@ use std::slice;
 use std::vec::IntoIter;
 use std::{iter, mem, option, u32};
 use syntax::ast::{self, Name};
-use syntax::symbol::InternedString;
+use syntax::symbol::{InternedString, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::subst::{Subst, SubstsRef};
@@ -772,7 +772,7 @@ pub struct LocalDecl<'tcx> {
     /// e.g., via `let x: T`, then we carry that type here. The MIR
     /// borrow checker needs this information since it can affect
     /// region inference.
-    pub user_ty: UserTypeProjections<'tcx>,
+    pub user_ty: UserTypeProjections,
 
     /// Name of the local, used in debuginfo and pretty-printing.
     ///
@@ -1779,12 +1779,9 @@ pub enum StatementKind<'tcx> {
     /// End the current live range for the storage of the local.
     StorageDead(Local),
 
-    /// Executes a piece of inline Assembly.
-    InlineAsm {
-        asm: Box<InlineAsm>,
-        outputs: Box<[Place<'tcx>]>,
-        inputs: Box<[(Span, Operand<'tcx>)]>,
-    },
+    /// Executes a piece of inline Assembly. Stored in a Box to keep the size
+    /// of `StatementKind` low.
+    InlineAsm(Box<InlineAsm<'tcx>>),
 
     /// Retag references in the given place, ensuring they got fresh tags. This is
     /// part of the Stacked Borrows model. These statements are currently only interpreted
@@ -1805,7 +1802,7 @@ pub enum StatementKind<'tcx> {
     /// - `Contravariant` -- requires that `T_y :> T`
     /// - `Invariant` -- requires that `T_y == T`
     /// - `Bivariant` -- no effect
-    AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection<'tcx>>),
+    AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection>),
 
     /// No-op. Useful for deleting instructions without affecting statement indices.
     Nop,
@@ -1858,6 +1855,13 @@ pub enum FakeReadCause {
     ForLet,
 }
 
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct InlineAsm<'tcx> {
+    pub asm: HirInlineAsm,
+    pub outputs: Box<[Place<'tcx>]>,
+    pub inputs: Box<[(Span, Operand<'tcx>)]>,
+}
+
 impl<'tcx> Debug for Statement<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         use self::StatementKind::*;
@@ -1880,11 +1884,8 @@ impl<'tcx> Debug for Statement<'tcx> {
                 ref place,
                 variant_index,
             } => write!(fmt, "discriminant({:?}) = {:?}", place, variant_index),
-            InlineAsm {
-                ref asm,
-                ref outputs,
-                ref inputs,
-            } => write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs),
+            InlineAsm(ref asm) =>
+                write!(fmt, "asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs),
             AscribeUserType(ref place, ref variance, ref c_ty) => {
                 write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
             }
@@ -1939,14 +1940,14 @@ impl_stable_hash_for!(struct Static<'tcx> {
 /// `PlaceProjection` etc below.
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
          Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub struct Projection<'tcx, B, V, T> {
+pub struct Projection<B, V, T> {
     pub base: B,
-    pub elem: ProjectionElem<'tcx, V, T>,
+    pub elem: ProjectionElem<V, T>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
          Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub enum ProjectionElem<'tcx, V, T> {
+pub enum ProjectionElem<V, T> {
     Deref,
     Field(Field, T),
     Index(V),
@@ -1980,16 +1981,18 @@ pub enum ProjectionElem<'tcx, V, T> {
     /// "Downcast" to a variant of an ADT. Currently, we only introduce
     /// this for ADTs with more than one variant. It may be better to
     /// just introduce it always, or always for enums.
-    Downcast(&'tcx AdtDef, VariantIdx),
+    ///
+    /// The included Symbol is the name of the variant, used for printing MIR.
+    Downcast(Option<Symbol>, VariantIdx),
 }
 
 /// Alias for projections as they appear in places, where the base is a place
 /// and the index is a local.
-pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
+pub type PlaceProjection<'tcx> = Projection<Place<'tcx>, Local, Ty<'tcx>>;
 
 /// Alias for projections as they appear in places, where the base is a place
 /// and the index is a local.
-pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
+pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
 
 // at least on 64 bit systems, `PlaceElem` should not be larger than two pointers
 static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
@@ -1998,7 +2001,7 @@ static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
 
 /// Alias for projections as they appear in `UserTypeProjection`, where we
 /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
-pub type ProjectionKind<'tcx> = ProjectionElem<'tcx, (), ()>;
+pub type ProjectionKind = ProjectionElem<(), ()>;
 
 newtype_index! {
     pub struct Field {
@@ -2019,7 +2022,9 @@ impl<'tcx> Place<'tcx> {
     }
 
     pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
-        self.elem(ProjectionElem::Downcast(adt_def, variant_index))
+        self.elem(ProjectionElem::Downcast(
+            Some(adt_def.variants[variant_index].ident.name),
+            variant_index))
     }
 
     pub fn index(self, index: Local) -> Place<'tcx> {
@@ -2080,8 +2085,11 @@ impl<'tcx> Debug for Place<'tcx> {
                 )
             },
             Projection(ref data) => match data.elem {
-                ProjectionElem::Downcast(ref adt_def, index) => {
-                    write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
+                ProjectionElem::Downcast(Some(name), _index) => {
+                    write!(fmt, "({:?} as {})", data.base, name)
+                }
+                ProjectionElem::Downcast(None, index) => {
+                    write!(fmt, "({:?} as variant#{:?})", data.base, index)
                 }
                 ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base),
                 ProjectionElem::Field(field, ty) => {
@@ -2542,36 +2550,36 @@ pub struct Constant<'tcx> {
 /// inferred region `'1`). The second will lead to the constraint `w:
 /// &'static str`.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UserTypeProjections<'tcx> {
-    pub(crate) contents: Vec<(UserTypeProjection<'tcx>, Span)>,
+pub struct UserTypeProjections {
+    pub(crate) contents: Vec<(UserTypeProjection, Span)>,
 }
 
 BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections<'tcx> {
+    impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections {
         contents
     }
 }
 
-impl<'tcx> UserTypeProjections<'tcx> {
+impl<'tcx> UserTypeProjections {
     pub fn none() -> Self {
         UserTypeProjections { contents: vec![] }
     }
 
-    pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection<'tcx>, Span)>) -> Self {
+    pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection, Span)>) -> Self {
         UserTypeProjections { contents: projs.collect() }
     }
 
-    pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection<'tcx>, Span)> {
+    pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection, Span)> {
         self.contents.iter()
     }
 
-    pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
+    pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection> {
         self.contents.iter().map(|&(ref user_type, _span)| user_type)
     }
 
     pub fn push_projection(
         mut self,
-        user_ty: &UserTypeProjection<'tcx>,
+        user_ty: &UserTypeProjection,
         span: Span,
     ) -> Self {
         self.contents.push((user_ty.clone(), span));
@@ -2580,7 +2588,7 @@ impl<'tcx> UserTypeProjections<'tcx> {
 
     fn map_projections(
         mut self,
-        mut f: impl FnMut(UserTypeProjection<'tcx>) -> UserTypeProjection<'tcx>
+        mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection
     ) -> Self {
         self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
         self
@@ -2628,14 +2636,14 @@ impl<'tcx> UserTypeProjections<'tcx> {
 ///   `field[0]` (aka `.0`), indicating that the type of `s` is
 ///   determined by finding the type of the `.0` field from `T`.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UserTypeProjection<'tcx> {
+pub struct UserTypeProjection {
     pub base: UserTypeAnnotationIndex,
-    pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
+    pub projs: Vec<ProjectionElem<(), ()>>,
 }
 
-impl<'tcx> Copy for ProjectionKind<'tcx> { }
+impl Copy for ProjectionKind { }
 
-impl<'tcx> UserTypeProjection<'tcx> {
+impl UserTypeProjection {
     pub(crate) fn index(mut self) -> Self {
         self.projs.push(ProjectionElem::Index(()));
         self
@@ -2662,15 +2670,17 @@ impl<'tcx> UserTypeProjection<'tcx> {
         variant_index: VariantIdx,
         field: Field,
     ) -> Self {
-        self.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
+        self.projs.push(ProjectionElem::Downcast(
+            Some(adt_def.variants[variant_index].ident.name),
+            variant_index));
         self.projs.push(ProjectionElem::Field(field, ()));
         self
     }
 }
 
-CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, }
+CloneTypeFoldableAndLiftImpls! { ProjectionKind, }
 
-impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         use crate::mir::ProjectionElem::*;
 
@@ -3140,13 +3150,21 @@ EnumTypeFoldableImpl! {
         (StatementKind::SetDiscriminant) { place, variant_index },
         (StatementKind::StorageLive)(a),
         (StatementKind::StorageDead)(a),
-        (StatementKind::InlineAsm) { asm, outputs, inputs },
+        (StatementKind::InlineAsm)(a),
         (StatementKind::Retag)(kind, place),
         (StatementKind::AscribeUserType)(a, v, b),
         (StatementKind::Nop),
     }
 }
 
+BraceStructTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for InlineAsm<'tcx> {
+        asm,
+        outputs,
+        inputs,
+    }
+}
+
 EnumTypeFoldableImpl! {
     impl<'tcx, T> TypeFoldable<'tcx> for ClearCrossCrate<T> {
         (ClearCrossCrate::Clear),
@@ -3226,8 +3244,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 target,
                 cleanup,
             } => {
-                let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
-                    EvalErrorKind::BoundsCheck {
+                let msg = if let InterpError::BoundsCheck { ref len, ref index } = *msg {
+                    InterpError::BoundsCheck {
                         len: len.fold_with(folder),
                         index: index.fold_with(folder),
                     }
@@ -3301,7 +3319,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 ref cond, ref msg, ..
             } => {
                 if cond.visit_with(visitor) {
-                    if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
+                    if let InterpError::BoundsCheck { ref len, ref index } = *msg {
                         len.visit_with(visitor) || index.visit_with(visitor)
                     } else {
                         false
@@ -3428,7 +3446,7 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
     }
 }
 
-impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T>
+impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<B, V, T>
 where
     B: TypeFoldable<'tcx>,
     V: TypeFoldable<'tcx>,
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index ac42eacacd7..23be1bbf6c6 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -4,21 +4,17 @@
  */
 
 use crate::mir::*;
-use crate::ty::subst::{Subst, SubstsRef};
-use crate::ty::{self, AdtDef, Ty, TyCtxt};
+use crate::ty::subst::Subst;
+use crate::ty::{self, Ty, TyCtxt};
 use crate::ty::layout::VariantIdx;
 use crate::hir;
 use crate::ty::util::IntTypeExt;
 
 #[derive(Copy, Clone, Debug)]
-pub enum PlaceTy<'tcx> {
-    /// Normal type.
-    Ty { ty: Ty<'tcx> },
-
-    /// Downcast to a particular variant of an enum.
-    Downcast { adt_def: &'tcx AdtDef,
-               substs: SubstsRef<'tcx>,
-               variant_index: VariantIdx },
+pub struct PlaceTy<'tcx> {
+    pub ty: Ty<'tcx>,
+    /// Downcast to a particular variant of an enum, if included.
+    pub variant_index: Option<VariantIdx>,
 }
 
 static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
@@ -27,16 +23,7 @@ static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
 
 impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
-        PlaceTy::Ty { ty }
-    }
-
-    pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        match *self {
-            PlaceTy::Ty { ty } =>
-                ty,
-            PlaceTy::Downcast { adt_def, substs, variant_index: _ } =>
-                tcx.mk_adt(adt_def, substs),
-        }
+        PlaceTy { ty, variant_index: None }
     }
 
     /// `place_ty.field_ty(tcx, f)` computes the type at a given field
@@ -48,21 +35,20 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     /// Note that the resulting type has not been normalized.
     pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
     {
-        // Pass `0` here so it can be used as a "default" variant_index in first arm below
-        let answer = match (self, VariantIdx::new(0)) {
-            (PlaceTy::Ty {
-                ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) |
-            (PlaceTy::Downcast { adt_def, substs, variant_index }, _) => {
-                let variant_def = &adt_def.variants[variant_index];
+        let answer = match self.ty.sty {
+            ty::Adt(adt_def, substs) => {
+                let variant_def = match self.variant_index {
+                    None => adt_def.non_enum_variant(),
+                    Some(variant_index) => {
+                        assert!(adt_def.is_enum());
+                        &adt_def.variants[variant_index]
+                    }
+                };
                 let field_def = &variant_def.fields[f.index()];
                 field_def.ty(tcx, substs)
             }
-            (PlaceTy::Ty { ty }, _) => {
-                match ty.sty {
-                    ty::Tuple(ref tys) => tys[f.index()],
-                    _ => bug!("extracting field of non-tuple non-adt: {:?}", self),
-                }
-            }
+            ty::Tuple(ref tys) => tys[f.index()],
+            _ => bug!("extracting field of non-tuple non-adt: {:?}", self),
         };
         debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
         answer
@@ -86,7 +72,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     pub fn projection_ty_core<V, T>(
         self,
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        elem: &ProjectionElem<'tcx, V, T>,
+        elem: &ProjectionElem<V, T>,
         mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
         -> PlaceTy<'tcx>
     where
@@ -94,62 +80,43 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     {
         let answer = match *elem {
             ProjectionElem::Deref => {
-                let ty = self.to_ty(tcx)
+                let ty = self.ty
                              .builtin_deref(true)
                              .unwrap_or_else(|| {
                                  bug!("deref projection of non-dereferencable ty {:?}", self)
                              })
                              .ty;
-                PlaceTy::Ty {
-                    ty,
-                }
+                PlaceTy::from_ty(ty)
             }
             ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
-                PlaceTy::Ty {
-                    ty: self.to_ty(tcx).builtin_index().unwrap()
-                },
+                PlaceTy::from_ty(self.ty.builtin_index().unwrap()),
             ProjectionElem::Subslice { from, to } => {
-                let ty = self.to_ty(tcx);
-                PlaceTy::Ty {
-                    ty: match ty.sty {
-                        ty::Array(inner, size) => {
-                            let size = size.unwrap_usize(tcx);
-                            let len = size - (from as u64) - (to as u64);
-                            tcx.mk_array(inner, len)
-                        }
-                        ty::Slice(..) => ty,
-                        _ => {
-                            bug!("cannot subslice non-array type: `{:?}`", self)
-                        }
-                    }
-                }
-            }
-            ProjectionElem::Downcast(adt_def1, index) =>
-                match self.to_ty(tcx).sty {
-                    ty::Adt(adt_def, substs) => {
-                        assert!(adt_def.is_enum());
-                        assert!(index.as_usize() < adt_def.variants.len());
-                        assert_eq!(adt_def, adt_def1);
-                        PlaceTy::Downcast { adt_def,
-                                            substs,
-                                            variant_index: index }
+                PlaceTy::from_ty(match self.ty.sty {
+                    ty::Array(inner, size) => {
+                        let size = size.unwrap_usize(tcx);
+                        let len = size - (from as u64) - (to as u64);
+                        tcx.mk_array(inner, len)
                     }
+                    ty::Slice(..) => self.ty,
                     _ => {
-                        bug!("cannot downcast non-ADT type: `{:?}`", self)
+                        bug!("cannot subslice non-array type: `{:?}`", self)
                     }
-                },
+                })
+            }
+            ProjectionElem::Downcast(_name, index) =>
+                PlaceTy { ty: self.ty, variant_index: Some(index) },
             ProjectionElem::Field(ref f, ref fty) =>
-                PlaceTy::Ty { ty: handle_field(&self, f, fty) },
+                PlaceTy::from_ty(handle_field(&self, f, fty)),
         };
         debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
         answer
     }
 }
 
-EnumTypeFoldableImpl! {
+BraceStructTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for PlaceTy<'tcx> {
-        (PlaceTy::Ty) { ty },
-        (PlaceTy::Downcast) { adt_def, substs, variant_index },
+        ty,
+        variant_index,
     }
 }
 
@@ -159,9 +126,9 @@ impl<'tcx> Place<'tcx> {
     {
         match *self {
             Place::Base(PlaceBase::Local(index)) =>
-                PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
+                PlaceTy::from_ty(local_decls.local_decls()[index].ty),
             Place::Base(PlaceBase::Static(ref data)) =>
-                PlaceTy::Ty { ty: data.ty },
+                PlaceTy::from_ty(data.ty),
             Place::Projection(ref proj) =>
                 proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
         }
@@ -186,7 +153,7 @@ impl<'tcx> Place<'tcx> {
         match place {
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Field(field, _ty) => {
-                    let base_ty = proj.base.ty(mir, *tcx).to_ty(*tcx);
+                    let base_ty = proj.base.ty(mir, *tcx).ty;
 
                     if (base_ty.is_closure() || base_ty.is_generator()) &&
                         (!by_ref || mir.upvar_decls[field.index()].by_ref)
@@ -218,7 +185,7 @@ impl<'tcx> Rvalue<'tcx> {
                 tcx.mk_array(operand.ty(local_decls, tcx), count)
             }
             Rvalue::Ref(reg, bk, ref place) => {
-                let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
+                let place_ty = place.ty(local_decls, tcx).ty;
                 tcx.mk_ref(reg,
                     ty::TypeAndMut {
                         ty: place_ty,
@@ -244,7 +211,7 @@ impl<'tcx> Rvalue<'tcx> {
                 operand.ty(local_decls, tcx)
             }
             Rvalue::Discriminant(ref place) => {
-                let ty = place.ty(local_decls, tcx).to_ty(tcx);
+                let ty = place.ty(local_decls, tcx).ty;
                 if let ty::Adt(adt_def, _) = ty.sty {
                     adt_def.repr.discr_type().to_ty(tcx)
                 } else {
@@ -293,7 +260,7 @@ impl<'tcx> Operand<'tcx> {
     {
         match self {
             &Operand::Copy(ref l) |
-            &Operand::Move(ref l) => l.ty(local_decls, tcx).to_ty(tcx),
+            &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
             &Operand::Constant(ref c) => c.ty,
         }
     }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 54e5bfc4397..b04c28cde57 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -137,7 +137,7 @@ macro_rules! make_mir_visitor {
             fn visit_ascribe_user_ty(&mut self,
                                      place: & $($mutability)? Place<'tcx>,
                                      variance: & $($mutability)? ty::Variance,
-                                     user_ty: & $($mutability)? UserTypeProjection<'tcx>,
+                                     user_ty: & $($mutability)? UserTypeProjection,
                                      location: Location) {
                 self.super_ascribe_user_ty(place, variance, user_ty, location);
             }
@@ -205,7 +205,7 @@ macro_rules! make_mir_visitor {
 
             fn visit_user_type_projection(
                 &mut self,
-                ty: & $($mutability)? UserTypeProjection<'tcx>,
+                ty: & $($mutability)? UserTypeProjection,
             ) {
                 self.super_user_type_projection(ty);
             }
@@ -391,15 +391,15 @@ macro_rules! make_mir_visitor {
                             location
                         );
                     }
-                    StatementKind::InlineAsm { outputs, inputs, asm: _ } => {
-                        for output in & $($mutability)? outputs[..] {
+                    StatementKind::InlineAsm(asm) => {
+                        for output in & $($mutability)? asm.outputs[..] {
                             self.visit_place(
                                 output,
                                 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
                                 location
                             );
                         }
-                        for (span, input) in & $($mutability)? inputs[..] {
+                        for (span, input) in & $($mutability)? asm.inputs[..] {
                             self.visit_span(span);
                             self.visit_operand(input, location);
                         }
@@ -560,7 +560,7 @@ macro_rules! make_mir_visitor {
             fn super_assert_message(&mut self,
                                     msg: & $($mutability)? AssertMessage<'tcx>,
                                     location: Location) {
-                use crate::mir::interpret::EvalErrorKind::*;
+                use crate::mir::interpret::InterpError::*;
                 if let BoundsCheck { len, index } = msg {
                     self.visit_operand(len, location);
                     self.visit_operand(index, location);
@@ -700,7 +700,7 @@ macro_rules! make_mir_visitor {
             fn super_ascribe_user_ty(&mut self,
                                      place: & $($mutability)? Place<'tcx>,
                                      _variance: & $($mutability)? ty::Variance,
-                                     user_ty: & $($mutability)? UserTypeProjection<'tcx>,
+                                     user_ty: & $($mutability)? UserTypeProjection,
                                      location: Location) {
                 self.visit_place(
                     place,
@@ -777,7 +777,7 @@ macro_rules! make_mir_visitor {
                                                     min_length: _,
                                                     from_end: _ } => {
                     }
-                    ProjectionElem::Downcast(_adt_def, _variant_index) => {
+                    ProjectionElem::Downcast(_name, _variant_index) => {
                     }
                 }
             }
@@ -851,7 +851,7 @@ macro_rules! make_mir_visitor {
 
             fn super_user_type_projection(
                 &mut self,
-                _ty: & $($mutability)? UserTypeProjection<'tcx>,
+                _ty: & $($mutability)? UserTypeProjection,
             ) {
             }
 
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 8d64818f49b..d0ad2c90668 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -1,10 +1,21 @@
 use crate::ty::query::QueryDescription;
 use crate::ty::query::queries;
-use crate::ty::{self, Ty, TyCtxt};
-use crate::hir::def_id::{DefId, CrateNum};
+use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::subst::SubstsRef;
 use crate::dep_graph::SerializedDepNodeIndex;
+use crate::hir::def_id::{CrateNum, DefId, DefIndex};
+use crate::mir::interpret::GlobalId;
 use crate::traits;
+use crate::traits::query::{
+    CanonicalPredicateGoal, CanonicalProjectionGoal,
+    CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
+    CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal,
+    CanonicalTypeOpNormalizeGoal,
+};
+
 use std::borrow::Cow;
+use syntax_pos::symbol::InternedString;
+
 
 // Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
@@ -73,7 +84,7 @@ rustc_queries! {
         /// Set of all the `DefId`s in this crate that have MIR associated with
         /// them. This includes all the body owners, but also things like struct
         /// constructors.
-        query mir_keys(_: CrateNum) -> Lrc<DefIdSet> {
+        query mir_keys(_: CrateNum) -> &'tcx DefIdSet {
             desc { "getting a list of all mir_keys" }
         }
 
@@ -148,4 +159,909 @@ rustc_queries! {
             desc { "wasm import module map" }
         }
     }
+
+    Other {
+        /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
+        /// predicates (where-clauses) directly defined on it. This is
+        /// equal to the `explicit_predicates_of` predicates plus the
+        /// `inferred_outlives_of` predicates.
+        query predicates_defined_on(_: DefId)
+            -> Lrc<ty::GenericPredicates<'tcx>> {}
+
+        /// Returns the predicates written explicit by the user.
+        query explicit_predicates_of(_: DefId)
+            -> Lrc<ty::GenericPredicates<'tcx>> {}
+
+        /// Returns the inferred outlives predicates (e.g., for `struct
+        /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
+        query inferred_outlives_of(_: DefId) -> Lrc<Vec<ty::Predicate<'tcx>>> {}
+
+        /// Maps from the `DefId` of a trait to the list of
+        /// super-predicates. This is a subset of the full list of
+        /// predicates. We store these in a separate map because we must
+        /// evaluate them even during type conversion, often before the
+        /// full predicates are available (note that supertraits have
+        /// additional acyclicity requirements).
+        query super_predicates_of(key: DefId) -> Lrc<ty::GenericPredicates<'tcx>> {
+            desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) }
+        }
+
+        /// To avoid cycles within the predicates of a single item we compute
+        /// per-type-parameter predicates for resolving `T::AssocTy`.
+        query type_param_predicates(key: (DefId, DefId))
+            -> Lrc<ty::GenericPredicates<'tcx>> {
+            no_force
+            desc { |tcx| "computing the bounds for type parameter `{}`", {
+                let id = tcx.hir().as_local_hir_id(key.1).unwrap();
+                tcx.hir().ty_param_name(id)
+            }}
+        }
+
+        query trait_def(_: DefId) -> &'tcx ty::TraitDef {}
+        query adt_def(_: DefId) -> &'tcx ty::AdtDef {}
+        query adt_destructor(_: DefId) -> Option<ty::Destructor> {}
+
+        // The cycle error here should be reported as an error by `check_representable`.
+        // We consider the type as Sized in the meanwhile to avoid
+        // further errors (done in impl Value for AdtSizedConstraint).
+        // Use `cycle_delay_bug` to delay the cycle error here to be emitted later
+        // in case we accidentally otherwise don't emit an error.
+        query adt_sized_constraint(
+            _: DefId
+        ) -> AdtSizedConstraint<'tcx> {
+            cycle_delay_bug
+        }
+
+        query adt_dtorck_constraint(
+            _: DefId
+        ) -> Result<DtorckConstraint<'tcx>, NoSolution> {}
+
+        /// True if this is a const fn, use the `is_const_fn` to know whether your crate actually
+        /// sees it as const fn (e.g., the const-fn-ness might be unstable and you might not have
+        /// the feature gate active)
+        ///
+        /// **Do not call this function manually.** It is only meant to cache the base data for the
+        /// `is_const_fn` function.
+        query is_const_fn_raw(key: DefId) -> bool {
+            desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) }
+        }
+
+        /// Returns true if calls to the function may be promoted
+        ///
+        /// This is either because the function is e.g., a tuple-struct or tuple-variant
+        /// constructor, or because it has the `#[rustc_promotable]` attribute. The attribute should
+        /// be removed in the future in favour of some form of check which figures out whether the
+        /// function does not inspect the bits of any of its arguments (so is essentially just a
+        /// constructor function).
+        query is_promotable_const_fn(_: DefId) -> bool {}
+
+        /// True if this is a foreign item (i.e., linked via `extern { ... }`).
+        query is_foreign_item(_: DefId) -> bool {}
+
+        /// Get a map with the variance of every item; use `item_variance`
+        /// instead.
+        query crate_variances(_: CrateNum) -> Lrc<ty::CrateVariancesMap> {
+            desc { "computing the variances for items in this crate" }
+        }
+
+        /// Maps from def-id of a type or region parameter to its
+        /// (inferred) variance.
+        query variances_of(_: DefId) -> Lrc<Vec<ty::Variance>> {}
+    }
+
+    TypeChecking {
+        /// Maps from def-id of a type to its (inferred) outlives.
+        query inferred_outlives_crate(_: CrateNum)
+            -> Lrc<ty::CratePredicatesMap<'tcx>> {
+            desc { "computing the inferred outlives predicates for items in this crate" }
+        }
+    }
+
+    Other {
+        /// Maps from an impl/trait def-id to a list of the def-ids of its items
+        query associated_item_def_ids(_: DefId) -> Lrc<Vec<DefId>> {}
+
+        /// Maps from a trait item to the trait item "descriptor"
+        query associated_item(_: DefId) -> ty::AssociatedItem {}
+
+        query impl_trait_ref(_: DefId) -> Option<ty::TraitRef<'tcx>> {}
+        query impl_polarity(_: DefId) -> hir::ImplPolarity {}
+
+        query issue33140_self_ty(_: DefId) -> Option<ty::Ty<'tcx>> {}
+    }
+
+    TypeChecking {
+        /// Maps a DefId of a type to a list of its inherent impls.
+        /// Contains implementations of methods that are inherent to a type.
+        /// Methods in these implementations don't need to be exported.
+        query inherent_impls(_: DefId) -> Lrc<Vec<DefId>> {
+            eval_always
+        }
+    }
+
+    TypeChecking {
+        /// The result of unsafety-checking this `DefId`.
+        query unsafety_check_result(_: DefId) -> mir::UnsafetyCheckResult {}
+
+        /// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error
+        query unsafe_derive_on_repr_packed(_: DefId) -> () {}
+
+        /// The signature of functions and closures.
+        query fn_sig(_: DefId) -> ty::PolyFnSig<'tcx> {}
+    }
+
+    Other {
+        query lint_mod(key: DefId) -> () {
+            desc { |tcx| "linting {}", key.describe_as_module(tcx) }
+        }
+
+        /// Checks the attributes in the module
+        query check_mod_attrs(key: DefId) -> () {
+            desc { |tcx| "checking attributes in {}", key.describe_as_module(tcx) }
+        }
+
+        query check_mod_unstable_api_usage(key: DefId) -> () {
+            desc { |tcx| "checking for unstable API usage in {}", key.describe_as_module(tcx) }
+        }
+
+        /// Checks the loops in the module
+        query check_mod_loops(key: DefId) -> () {
+            desc { |tcx| "checking loops in {}", key.describe_as_module(tcx) }
+        }
+
+        query check_mod_item_types(key: DefId) -> () {
+            desc { |tcx| "checking item types in {}", key.describe_as_module(tcx) }
+        }
+
+        query check_mod_privacy(key: DefId) -> () {
+            desc { |tcx| "checking privacy in {}", key.describe_as_module(tcx) }
+        }
+
+        query check_mod_intrinsics(key: DefId) -> () {
+            desc { |tcx| "checking intrinsics in {}", key.describe_as_module(tcx) }
+        }
+
+        query check_mod_liveness(key: DefId) -> () {
+            desc { |tcx| "checking liveness of variables in {}", key.describe_as_module(tcx) }
+        }
+
+        query check_mod_impl_wf(key: DefId) -> () {
+            desc { |tcx| "checking that impls are well-formed in {}", key.describe_as_module(tcx) }
+        }
+
+        query collect_mod_item_types(key: DefId) -> () {
+            desc { |tcx| "collecting item types in {}", key.describe_as_module(tcx) }
+        }
+
+        /// Caches CoerceUnsized kinds for impls on custom types.
+        query coerce_unsized_info(_: DefId)
+            -> ty::adjustment::CoerceUnsizedInfo {}
+    }
+
+    TypeChecking {
+        query typeck_item_bodies(_: CrateNum) -> () {
+            desc { "type-checking all item bodies" }
+        }
+
+        query typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> {
+            cache { key.is_local() }
+            load_cached(tcx, id) {
+                let typeck_tables: Option<ty::TypeckTables<'tcx>> = tcx
+                    .queries.on_disk_cache
+                    .try_load_query_result(tcx, id);
+
+                typeck_tables.map(|tables| tcx.alloc_tables(tables))
+            }
+        }
+    }
+
+    Other {
+        query used_trait_imports(_: DefId) -> Lrc<DefIdSet> {}
+    }
+
+    TypeChecking {
+        query has_typeck_tables(_: DefId) -> bool {}
+
+        query coherent_trait(def_id: DefId) -> () {
+            desc { |tcx| "coherence checking all impls of trait `{}`", tcx.def_path_str(def_id) }
+        }
+    }
+
+    BorrowChecking {
+        query borrowck(_: DefId) -> Lrc<BorrowCheckResult> {}
+
+        /// Borrow checks the function body. If this is a closure, returns
+        /// additional requirements that the closure's creator must verify.
+        query mir_borrowck(_: DefId) -> mir::BorrowCheckResult<'tcx> {}
+    }
+
+    TypeChecking {
+        /// Gets a complete map from all types to their inherent impls.
+        /// Not meant to be used directly outside of coherence.
+        /// (Defined only for `LOCAL_CRATE`.)
+        query crate_inherent_impls(k: CrateNum)
+            -> Lrc<CrateInherentImpls> {
+            eval_always
+            desc { "all inherent impls defined in crate `{:?}`", k }
+        }
+
+        /// Checks all types in the crate for overlap in their inherent impls. Reports errors.
+        /// Not meant to be used directly outside of coherence.
+        /// (Defined only for `LOCAL_CRATE`.)
+        query crate_inherent_impls_overlap_check(_: CrateNum)
+            -> () {
+            eval_always
+            desc { "check for overlap between inherent impls defined in this crate" }
+        }
+    }
+
+    Other {
+        /// Evaluate a constant without running sanity checks
+        ///
+        /// **Do not use this** outside const eval. Const eval uses this to break query cycles
+        /// during validation. Please add a comment to every use site explaining why using
+        /// `const_eval` isn't sufficient
+        query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
+            -> ConstEvalRawResult<'tcx> {
+            no_force
+            desc { |tcx|
+                "const-evaluating `{}`",
+                tcx.def_path_str(key.value.instance.def.def_id())
+            }
+            cache { true }
+            load_cached(tcx, id) {
+                tcx.queries.on_disk_cache.try_load_query_result(tcx, id).map(Ok)
+            }
+        }
+
+        /// Results of evaluating const items or constants embedded in
+        /// other items (such as enum variant explicit discriminants).
+        query const_eval(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
+            -> ConstEvalResult<'tcx> {
+            no_force
+            desc { |tcx|
+                "const-evaluating + checking `{}`",
+                tcx.def_path_str(key.value.instance.def.def_id())
+            }
+            cache { true }
+            load_cached(tcx, id) {
+                tcx.queries.on_disk_cache.try_load_query_result(tcx, id).map(Ok)
+            }
+        }
+    }
+
+    TypeChecking {
+        query check_match(_: DefId) -> () {}
+
+        /// Performs part of the privacy check and computes "access levels".
+        query privacy_access_levels(_: CrateNum) -> Lrc<AccessLevels> {
+            eval_always
+            desc { "privacy access levels" }
+        }
+        query check_private_in_public(_: CrateNum) -> () {
+            eval_always
+            desc { "checking for private elements in public interfaces" }
+        }
+    }
+
+    Other {
+        query reachable_set(_: CrateNum) -> ReachableSet {
+            desc { "reachability" }
+        }
+
+        /// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body;
+        /// in the case of closures, this will be redirected to the enclosing function.
+        query region_scope_tree(_: DefId) -> Lrc<region::ScopeTree> {}
+
+        query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx> {
+            no_force
+            desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
+        }
+
+        query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName {
+            no_force
+            desc { "computing the symbol for `{}`", key }
+            cache { true }
+        }
+
+        query describe_def(_: DefId) -> Option<Def> {}
+        query def_span(_: DefId) -> Span {
+            // FIXME(mw): DefSpans are not really inputs since they are derived from
+            // HIR. But at the moment HIR hashing still contains some hacks that allow
+            // to make type debuginfo to be source location independent. Declaring
+            // DefSpan an input makes sure that changes to these are always detected
+            // regardless of HIR hashing.
+            eval_always
+        }
+        query lookup_stability(_: DefId) -> Option<&'tcx attr::Stability> {}
+        query lookup_deprecation_entry(_: DefId) -> Option<DeprecationEntry> {}
+        query item_attrs(_: DefId) -> Lrc<[ast::Attribute]> {}
+    }
+
+    Codegen {
+        query codegen_fn_attrs(_: DefId) -> CodegenFnAttrs {}
+    }
+
+    Other {
+        query fn_arg_names(_: DefId) -> Vec<ast::Name> {}
+        /// Gets the rendered value of the specified constant or associated constant.
+        /// Used by rustdoc.
+        query rendered_const(_: DefId) -> String {}
+        query impl_parent(_: DefId) -> Option<DefId> {}
+    }
+
+    TypeChecking {
+        query trait_of_item(_: DefId) -> Option<DefId> {}
+        query const_is_rvalue_promotable_to_static(key: DefId) -> bool {
+            desc { |tcx|
+                "const checking if rvalue is promotable to static `{}`",
+                tcx.def_path_str(key)
+            }
+            cache { true }
+        }
+        query rvalue_promotable_map(key: DefId) -> Lrc<ItemLocalSet> {
+            desc { |tcx|
+                "checking which parts of `{}` are promotable to static",
+                tcx.def_path_str(key)
+            }
+        }
+    }
+
+    Codegen {
+        query is_mir_available(key: DefId) -> bool {
+            desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
+        }
+    }
+
+    Other {
+        query vtable_methods(key: ty::PolyTraitRef<'tcx>)
+                            -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
+            no_force
+            desc { |tcx| "finding all methods for trait {}", tcx.def_path_str(key.def_id()) }
+        }
+    }
+
+    Codegen {
+        query codegen_fulfill_obligation(
+            key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
+        ) -> Vtable<'tcx, ()> {
+            no_force
+            cache { true }
+            desc { |tcx|
+                "checking if `{}` fulfills its obligations",
+                tcx.def_path_str(key.1.def_id())
+            }
+        }
+    }
+
+    TypeChecking {
+        query trait_impls_of(key: DefId) -> Lrc<ty::trait_def::TraitImpls> {
+            desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) }
+        }
+        query specialization_graph_of(_: DefId) -> &'tcx specialization_graph::Graph {}
+        query is_object_safe(key: DefId) -> bool {
+            desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) }
+        }
+
+        /// Gets the ParameterEnvironment for a given item; this environment
+        /// will be in "user-facing" mode, meaning that it is suitabe for
+        /// type-checking etc, and it does not normalize specializable
+        /// associated types. This is almost always what you want,
+        /// unless you are doing MIR optimizations, in which case you
+        /// might want to use `reveal_all()` method to change modes.
+        query param_env(_: DefId) -> ty::ParamEnv<'tcx> {}
+
+        /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
+        /// `ty.is_copy()`, etc, since that will prune the environment where possible.
+        query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+            no_force
+            desc { "computing whether `{}` is `Copy`", env.value }
+        }
+        query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+            no_force
+            desc { "computing whether `{}` is `Sized`", env.value }
+        }
+        query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+            no_force
+            desc { "computing whether `{}` is freeze", env.value }
+        }
+
+        // The cycle error here should be reported as an error by `check_representable`.
+        // We consider the type as not needing drop in the meanwhile to avoid
+        // further errors (done in impl Value for NeedsDrop).
+        // Use `cycle_delay_bug` to delay the cycle error here to be emitted later
+        // in case we accidentally otherwise don't emit an error.
+        query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> NeedsDrop {
+            cycle_delay_bug
+            no_force
+            desc { "computing whether `{}` needs drop", env.value }
+        }
+
+        query layout_raw(
+            env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
+        ) -> Result<&'tcx ty::layout::LayoutDetails, ty::layout::LayoutError<'tcx>> {
+            no_force
+            desc { "computing layout of `{}`", env.value }
+        }
+    }
+
+    Other {
+        query dylib_dependency_formats(_: CrateNum)
+                                        -> Lrc<Vec<(CrateNum, LinkagePreference)>> {
+            desc { "dylib dependency formats of crate" }
+        }
+    }
+
+    Codegen {
+        query is_compiler_builtins(_: CrateNum) -> bool {
+            fatal_cycle
+            desc { "checking if the crate is_compiler_builtins" }
+        }
+        query has_global_allocator(_: CrateNum) -> bool {
+            fatal_cycle
+            desc { "checking if the crate has_global_allocator" }
+        }
+        query has_panic_handler(_: CrateNum) -> bool {
+            fatal_cycle
+            desc { "checking if the crate has_panic_handler" }
+        }
+        query is_sanitizer_runtime(_: CrateNum) -> bool {
+            fatal_cycle
+            desc { "query a crate is #![sanitizer_runtime]" }
+        }
+        query is_profiler_runtime(_: CrateNum) -> bool {
+            fatal_cycle
+            desc { "query a crate is #![profiler_runtime]" }
+        }
+        query panic_strategy(_: CrateNum) -> PanicStrategy {
+            fatal_cycle
+            desc { "query a crate's configured panic strategy" }
+        }
+        query is_no_builtins(_: CrateNum) -> bool {
+            fatal_cycle
+            desc { "test whether a crate has #![no_builtins]" }
+        }
+
+        query extern_crate(_: DefId) -> Lrc<Option<ExternCrate>> {
+            eval_always
+            desc { "getting crate's ExternCrateData" }
+        }
+    }
+
+    TypeChecking {
+        query specializes(_: (DefId, DefId)) -> bool {
+            no_force
+            desc { "computing whether impls specialize one another" }
+        }
+        query in_scope_traits_map(_: DefIndex)
+            -> Option<Lrc<FxHashMap<ItemLocalId, Lrc<StableVec<TraitCandidate>>>>> {
+            eval_always
+            desc { "traits in scope at a block" }
+        }
+    }
+
+    Other {
+        query module_exports(_: DefId) -> Option<Lrc<Vec<Export>>> {
+            eval_always
+        }
+    }
+
+    TypeChecking {
+        query impl_defaultness(_: DefId) -> hir::Defaultness {}
+
+        query check_item_well_formed(_: DefId) -> () {}
+        query check_trait_item_well_formed(_: DefId) -> () {}
+        query check_impl_item_well_formed(_: DefId) -> () {}
+    }
+
+    Linking {
+        // The DefIds of all non-generic functions and statics in the given crate
+        // that can be reached from outside the crate.
+        //
+        // We expect this items to be available for being linked to.
+        //
+        // This query can also be called for LOCAL_CRATE. In this case it will
+        // compute which items will be reachable to other crates, taking into account
+        // the kind of crate that is currently compiled. Crates with only a
+        // C interface have fewer reachable things.
+        //
+        // Does not include external symbols that don't have a corresponding DefId,
+        // like the compiler-generated `main` function and so on.
+        query reachable_non_generics(_: CrateNum)
+            -> Lrc<DefIdMap<SymbolExportLevel>> {
+            desc { "looking up the exported symbols of a crate" }
+        }
+        query is_reachable_non_generic(_: DefId) -> bool {}
+        query is_unreachable_local_definition(_: DefId) -> bool {}
+    }
+
+    Codegen {
+        query upstream_monomorphizations(
+            k: CrateNum
+        ) -> Lrc<DefIdMap<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>> {
+            desc { "collecting available upstream monomorphizations `{:?}`", k }
+        }
+        query upstream_monomorphizations_for(_: DefId)
+            -> Option<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>> {}
+    }
+
+    Other {
+        query foreign_modules(_: CrateNum) -> Lrc<Vec<ForeignModule>> {
+            desc { "looking up the foreign modules of a linked crate" }
+        }
+
+        /// Identifies the entry-point (e.g., the `main` function) for a given
+        /// crate, returning `None` if there is no entry point (such as for library crates).
+        query entry_fn(_: CrateNum) -> Option<(DefId, EntryFnType)> {
+            desc { "looking up the entry function of a crate" }
+        }
+        query plugin_registrar_fn(_: CrateNum) -> Option<DefId> {
+            desc { "looking up the plugin registrar for a crate" }
+        }
+        query proc_macro_decls_static(_: CrateNum) -> Option<DefId> {
+            desc { "looking up the derive registrar for a crate" }
+        }
+        query crate_disambiguator(_: CrateNum) -> CrateDisambiguator {
+            eval_always
+            desc { "looking up the disambiguator a crate" }
+        }
+        query crate_hash(_: CrateNum) -> Svh {
+            eval_always
+            desc { "looking up the hash a crate" }
+        }
+        query original_crate_name(_: CrateNum) -> Symbol {
+            eval_always
+            desc { "looking up the original name a crate" }
+        }
+        query extra_filename(_: CrateNum) -> String {
+            eval_always
+            desc { "looking up the extra filename for a crate" }
+        }
+    }
+
+    TypeChecking {
+        query implementations_of_trait(_: (CrateNum, DefId))
+            -> Lrc<Vec<DefId>> {
+            no_force
+            desc { "looking up implementations of a trait in a crate" }
+        }
+        query all_trait_implementations(_: CrateNum)
+            -> Lrc<Vec<DefId>> {
+            desc { "looking up all (?) trait implementations" }
+        }
+    }
+
+    Other {
+        query dllimport_foreign_items(_: CrateNum)
+            -> Lrc<FxHashSet<DefId>> {
+            desc { "dllimport_foreign_items" }
+        }
+        query is_dllimport_foreign_item(_: DefId) -> bool {}
+        query is_statically_included_foreign_item(_: DefId) -> bool {}
+        query native_library_kind(_: DefId)
+            -> Option<NativeLibraryKind> {}
+    }
+
+    Linking {
+        query link_args(_: CrateNum) -> Lrc<Vec<String>> {
+            eval_always
+            desc { "looking up link arguments for a crate" }
+        }
+    }
+
+    BorrowChecking {
+        // Lifetime resolution. See `middle::resolve_lifetimes`.
+        query resolve_lifetimes(_: CrateNum) -> Lrc<ResolveLifetimes> {
+            desc { "resolving lifetimes" }
+        }
+        query named_region_map(_: DefIndex) ->
+            Option<Lrc<FxHashMap<ItemLocalId, Region>>> {
+            desc { "looking up a named region" }
+        }
+        query is_late_bound_map(_: DefIndex) ->
+            Option<Lrc<FxHashSet<ItemLocalId>>> {
+            desc { "testing if a region is late bound" }
+        }
+        query object_lifetime_defaults_map(_: DefIndex)
+            -> Option<Lrc<FxHashMap<ItemLocalId, Lrc<Vec<ObjectLifetimeDefault>>>>> {
+            desc { "looking up lifetime defaults for a region" }
+        }
+    }
+
+    TypeChecking {
+        query visibility(_: DefId) -> ty::Visibility {}
+    }
+
+    Other {
+        query dep_kind(_: CrateNum) -> DepKind {
+            eval_always
+            desc { "fetching what a dependency looks like" }
+        }
+        query crate_name(_: CrateNum) -> Symbol {
+            eval_always
+            desc { "fetching what a crate is named" }
+        }
+        query item_children(_: DefId) -> Lrc<Vec<Export>> {}
+        query extern_mod_stmt_cnum(_: DefId) -> Option<CrateNum> {}
+
+        query get_lib_features(_: CrateNum) -> Lrc<LibFeatures> {
+            eval_always
+            desc { "calculating the lib features map" }
+        }
+        query defined_lib_features(_: CrateNum)
+            -> Lrc<Vec<(Symbol, Option<Symbol>)>> {
+            desc { "calculating the lib features defined in a crate" }
+        }
+        query get_lang_items(_: CrateNum) -> Lrc<LanguageItems> {
+            eval_always
+            desc { "calculating the lang items map" }
+        }
+        query defined_lang_items(_: CrateNum) -> Lrc<Vec<(DefId, usize)>> {
+            desc { "calculating the lang items defined in a crate" }
+        }
+        query missing_lang_items(_: CrateNum) -> Lrc<Vec<LangItem>> {
+            desc { "calculating the missing lang items in a crate" }
+        }
+        query visible_parent_map(_: CrateNum)
+            -> Lrc<DefIdMap<DefId>> {
+            desc { "calculating the visible parent map" }
+        }
+        query missing_extern_crate_item(_: CrateNum) -> bool {
+            eval_always
+            desc { "seeing if we're missing an `extern crate` item for this crate" }
+        }
+        query used_crate_source(_: CrateNum) -> Lrc<CrateSource> {
+            eval_always
+            desc { "looking at the source for a crate" }
+        }
+        query postorder_cnums(_: CrateNum) -> Lrc<Vec<CrateNum>> {
+            eval_always
+            desc { "generating a postorder list of CrateNums" }
+        }
+
+        query freevars(_: DefId) -> Option<Lrc<Vec<hir::Freevar>>> {
+            eval_always
+        }
+        query maybe_unused_trait_import(_: DefId) -> bool {
+            eval_always
+        }
+        query maybe_unused_extern_crates(_: CrateNum)
+            -> Lrc<Vec<(DefId, Span)>> {
+            eval_always
+            desc { "looking up all possibly unused extern crates" }
+        }
+        query names_imported_by_glob_use(_: DefId)
+            -> Lrc<FxHashSet<ast::Name>> {
+            eval_always
+        }
+
+        query stability_index(_: CrateNum) -> Lrc<stability::Index<'tcx>> {
+            eval_always
+            desc { "calculating the stability index for the local crate" }
+        }
+        query all_crate_nums(_: CrateNum) -> Lrc<Vec<CrateNum>> {
+            eval_always
+            desc { "fetching all foreign CrateNum instances" }
+        }
+
+        /// A vector of every trait accessible in the whole crate
+        /// (i.e., including those from subcrates). This is used only for
+        /// error reporting.
+        query all_traits(_: CrateNum) -> Lrc<Vec<DefId>> {
+            desc { "fetching all foreign and local traits" }
+        }
+    }
+
+    Linking {
+        query exported_symbols(_: CrateNum)
+            -> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>> {
+            desc { "exported_symbols" }
+        }
+    }
+
+    Codegen {
+        query collect_and_partition_mono_items(_: CrateNum)
+            -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>) {
+            eval_always
+            desc { "collect_and_partition_mono_items" }
+        }
+        query is_codegened_item(_: DefId) -> bool {}
+        query codegen_unit(_: InternedString) -> Arc<CodegenUnit<'tcx>> {
+            no_force
+            desc { "codegen_unit" }
+        }
+        query backend_optimization_level(_: CrateNum) -> OptLevel {
+            desc { "optimization level used by backend" }
+        }
+    }
+
+    Other {
+        query output_filenames(_: CrateNum) -> Arc<OutputFilenames> {
+            eval_always
+            desc { "output_filenames" }
+        }
+    }
+
+    TypeChecking {
+        /// Do not call this query directly: invoke `normalize` instead.
+        query normalize_projection_ty(
+            goal: CanonicalProjectionGoal<'tcx>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "normalizing `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: invoke `normalize_erasing_regions` instead.
+        query normalize_ty_after_erasing_regions(
+            goal: ParamEnvAnd<'tcx, Ty<'tcx>>
+        ) -> Ty<'tcx> {
+            no_force
+            desc { "normalizing `{:?}`", goal }
+        }
+
+        query implied_outlives_bounds(
+            goal: CanonicalTyGoal<'tcx>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "computing implied outlives bounds for `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead.
+        query dropck_outlives(
+            goal: CanonicalTyGoal<'tcx>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "computing dropck types for `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or
+        /// `infcx.predicate_must_hold()` instead.
+        query evaluate_obligation(
+            goal: CanonicalPredicateGoal<'tcx>
+        ) -> Result<traits::EvaluationResult, traits::OverflowError> {
+            no_force
+            desc { "evaluating trait selection obligation `{}`", goal.value.value }
+        }
+
+        query evaluate_goal(
+            goal: traits::ChalkCanonicalGoal<'tcx>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
+            NoSolution
+        > {
+            no_force
+            desc { "evaluating trait selection obligation `{}`", goal.value.goal }
+        }
+
+        /// Do not call this query directly: part of the `Eq` type-op
+        query type_op_ascribe_user_type(
+            goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: part of the `Eq` type-op
+        query type_op_eq(
+            goal: CanonicalTypeOpEqGoal<'tcx>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "evaluating `type_op_eq` `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: part of the `Subtype` type-op
+        query type_op_subtype(
+            goal: CanonicalTypeOpSubtypeGoal<'tcx>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "evaluating `type_op_subtype` `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: part of the `ProvePredicate` type-op
+        query type_op_prove_predicate(
+            goal: CanonicalTypeOpProvePredicateGoal<'tcx>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "evaluating `type_op_prove_predicate` `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: part of the `Normalize` type-op
+        query type_op_normalize_ty(
+            goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "normalizing `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: part of the `Normalize` type-op
+        query type_op_normalize_predicate(
+            goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "normalizing `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: part of the `Normalize` type-op
+        query type_op_normalize_poly_fn_sig(
+            goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "normalizing `{:?}`", goal }
+        }
+
+        /// Do not call this query directly: part of the `Normalize` type-op
+        query type_op_normalize_fn_sig(
+            goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>
+        ) -> Result<
+            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>>,
+            NoSolution,
+        > {
+            no_force
+            desc { "normalizing `{:?}`", goal }
+        }
+
+        query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
+            no_force
+            desc { |tcx|
+                "testing substituted normalized predicates:`{}`",
+                tcx.def_path_str(key.0)
+            }
+        }
+
+        query method_autoderef_steps(
+            goal: CanonicalTyGoal<'tcx>
+        ) -> MethodAutoderefStepsResult<'tcx> {
+            no_force
+            desc { "computing autoderef types for `{:?}`", goal }
+        }
+    }
+
+    Other {
+        query target_features_whitelist(_: CrateNum) -> Lrc<FxHashMap<String, Option<String>>> {
+            eval_always
+            desc { "looking up the whitelist of target features" }
+        }
+
+        // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
+        query instance_def_size_estimate(def: ty::InstanceDef<'tcx>)
+            -> usize {
+            no_force
+            desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) }
+        }
+
+        query features_query(_: CrateNum) -> Lrc<feature_gate::Features> {
+            eval_always
+            desc { "looking up enabled feature gates" }
+        }
+    }
 }
diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs
index 730abacf6f6..0f535249b5e 100644
--- a/src/librustc/session/code_stats.rs
+++ b/src/librustc/session/code_stats.rs
@@ -57,7 +57,13 @@ impl CodeStats {
                                          overall_size: Size,
                                          packed: bool,
                                          opt_discr_size: Option<Size>,
-                                         variants: Vec<VariantInfo>) {
+                                         mut variants: Vec<VariantInfo>) {
+        // Sort variants so the largest ones are shown first. A stable sort is
+        // used here so that source code order is preserved for all variants
+        // that have the same size.
+        variants.sort_by(|info1, info2| {
+            info2.size.cmp(&info1.size)
+        });
         let info = TypeSizeInfo {
             kind,
             type_description: type_desc.to_string(),
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 988e4a9ff23..7c0eab26b09 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -113,6 +113,21 @@ impl LinkerPluginLto {
     }
 }
 
+#[derive(Clone, PartialEq, Hash)]
+pub enum PgoGenerate {
+    Enabled(Option<PathBuf>),
+    Disabled,
+}
+
+impl PgoGenerate {
+    pub fn enabled(&self) -> bool {
+        match *self {
+            PgoGenerate::Enabled(_) => true,
+            PgoGenerate::Disabled => false,
+        }
+    }
+}
+
 #[derive(Clone, Copy, PartialEq, Hash)]
 pub enum DebugInfo {
     None,
@@ -826,13 +841,15 @@ macro_rules! options {
         pub const parse_linker_plugin_lto: Option<&str> =
             Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \
                   or the path to the linker plugin");
+        pub const parse_pgo_generate: Option<&str> =
+            Some("an optional path to the profiling data output directory");
         pub const parse_merge_functions: Option<&str> =
             Some("one of: `disabled`, `trampolines`, or `aliases`");
     }
 
     #[allow(dead_code)]
     mod $mod_set {
-        use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto};
+        use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto, PgoGenerate};
         use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
         use std::path::PathBuf;
         use std::str::FromStr;
@@ -1087,6 +1104,14 @@ macro_rules! options {
             true
         }
 
+        fn parse_pgo_generate(slot: &mut PgoGenerate, v: Option<&str>) -> bool {
+            *slot = match v {
+                None => PgoGenerate::Enabled(None),
+                Some(path) => PgoGenerate::Enabled(Some(PathBuf::from(path))),
+            };
+            true
+        }
+
         fn parse_merge_functions(slot: &mut Option<MergeFunctions>, v: Option<&str>) -> bool {
             match v.and_then(|s| MergeFunctions::from_str(s).ok()) {
                 Some(mergefunc) => *slot = Some(mergefunc),
@@ -1363,7 +1388,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "extra arguments to prepend to the linker invocation (space separated)"),
     profile: bool = (false, parse_bool, [TRACKED],
                      "insert profiling code"),
-    pgo_gen: Option<String> = (None, parse_opt_string, [TRACKED],
+    pgo_gen: PgoGenerate = (PgoGenerate::Disabled, parse_pgo_generate, [TRACKED],
         "Generate PGO profile data, to a given file, or to the default location if it's empty."),
     pgo_use: String = (String::new(), parse_string, [TRACKED],
         "Use PGO profile data from the given profile file."),
@@ -1980,7 +2005,7 @@ pub fn build_session_options_and_crate_config(
         );
     }
 
-    if debugging_opts.pgo_gen.is_some() && !debugging_opts.pgo_use.is_empty() {
+    if debugging_opts.pgo_gen.enabled() && !debugging_opts.pgo_use.is_empty() {
         early_error(
             error_format,
             "options `-Z pgo-gen` and `-Z pgo-use` are exclusive",
@@ -2490,7 +2515,7 @@ mod dep_tracking {
     use std::path::PathBuf;
     use std::collections::hash_map::DefaultHasher;
     use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
-                Passes, Sanitizer, LtoCli, LinkerPluginLto};
+                Passes, Sanitizer, LtoCli, LinkerPluginLto, PgoGenerate};
     use syntax::feature_gate::UnstableFeatures;
     use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple};
     use syntax::edition::Edition;
@@ -2558,6 +2583,7 @@ mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(TargetTriple);
     impl_dep_tracking_hash_via_hash!(Edition);
     impl_dep_tracking_hash_via_hash!(LinkerPluginLto);
+    impl_dep_tracking_hash_via_hash!(PgoGenerate);
 
     impl_dep_tracking_hash_for_sortable_vec_of!(String);
     impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
@@ -2625,7 +2651,7 @@ mod tests {
         build_session_options_and_crate_config,
         to_crate_config
     };
-    use crate::session::config::{LtoCli, LinkerPluginLto};
+    use crate::session::config::{LtoCli, LinkerPluginLto, PgoGenerate};
     use crate::session::build_session;
     use crate::session::search_paths::SearchPath;
     use std::collections::{BTreeMap, BTreeSet};
@@ -3124,7 +3150,7 @@ mod tests {
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
         opts = reference.clone();
-        opts.debugging_opts.pgo_gen = Some(String::from("abc"));
+        opts.debugging_opts.pgo_gen = PgoGenerate::Enabled(None);
         assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
         opts = reference.clone();
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 2f3df32945c..a1966c02683 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -46,8 +46,6 @@ use std::path::PathBuf;
 use std::time::Duration;
 use std::sync::{Arc, mpsc};
 
-use parking_lot::Mutex as PlMutex;
-
 mod code_stats;
 pub mod config;
 pub mod filesearch;
@@ -130,7 +128,7 @@ pub struct Session {
     pub profile_channel: Lock<Option<mpsc::Sender<ProfileQueriesMsg>>>,
 
     /// Used by -Z self-profile
-    pub self_profiling: Option<Arc<PlMutex<SelfProfiler>>>,
+    pub self_profiling: Option<Arc<SelfProfiler>>,
 
     /// Some measurements that are being gathered during compilation.
     pub perf_stats: PerfStats,
@@ -166,7 +164,7 @@ pub struct Session {
     pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
 
     /// `Span`s of trait methods that weren't found to avoid emitting object safety errors
-    pub trait_methods_not_found: OneThread<RefCell<FxHashSet<Span>>>,
+    pub trait_methods_not_found: Lock<FxHashSet<Span>>,
 }
 
 pub struct PerfStats {
@@ -838,19 +836,17 @@ impl Session {
 
     #[inline(never)]
     #[cold]
-    fn profiler_active<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
+    fn profiler_active<F: FnOnce(&SelfProfiler) -> ()>(&self, f: F) {
         match &self.self_profiling {
             None => bug!("profiler_active() called but there was no profiler active"),
             Some(profiler) => {
-                let mut p = profiler.lock();
-
-                f(&mut p);
+                f(&profiler);
             }
         }
     }
 
     #[inline(always)]
-    pub fn profiler<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
+    pub fn profiler<F: FnOnce(&SelfProfiler) -> ()>(&self, f: F) {
         if unlikely!(self.self_profiling.is_some()) {
             self.profiler_active(f)
         }
@@ -1138,7 +1134,19 @@ fn build_session_(
     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
 ) -> Session {
     let self_profiler =
-        if sopts.debugging_opts.self_profile { Some(Arc::new(PlMutex::new(SelfProfiler::new()))) }
+        if sopts.debugging_opts.self_profile {
+            let profiler = SelfProfiler::new();
+            match profiler {
+                Ok(profiler) => {
+                    crate::ty::query::QueryName::register_with_profiler(&profiler);
+                    Some(Arc::new(profiler))
+                },
+                Err(e) => {
+                    early_warn(sopts.error_format, &format!("failed to create profiler: {}", e));
+                    None
+                }
+            }
+        }
         else { None };
 
     let host_triple = TargetTriple::from_triple(config::host_triple());
@@ -1236,7 +1244,7 @@ fn build_session_(
         has_global_allocator: Once::new(),
         has_panic_handler: Once::new(),
         driver_lint_caps,
-        trait_methods_not_found: OneThread::new(RefCell::new(Default::default())),
+        trait_methods_not_found: Lock::new(Default::default()),
     };
 
     validate_commandline_args_with_session_available(&sess);
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 78c80b48ee8..b875bfdfa9f 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -26,7 +26,6 @@ use crate::infer::{InferCtxt, SuppressRegionErrors};
 use crate::infer::outlives::env::OutlivesEnvironment;
 use crate::middle::region;
 use crate::mir::interpret::ErrorHandled;
-use rustc_data_structures::sync::Lrc;
 use rustc_macros::HashStable;
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
@@ -227,6 +226,7 @@ pub enum ObligationCauseCode<'tcx> {
         source: hir::MatchSource,
         prior_arms: Vec<Span>,
         last_ty: Ty<'tcx>,
+        discrim_hir_id: hir::HirId,
     },
 
     /// Computing common supertype in the pattern guard for the arms of a match expression
@@ -984,11 +984,11 @@ fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
 fn vtable_methods<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>)
-    -> Lrc<Vec<Option<(DefId, SubstsRef<'tcx>)>>>
+    -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>]
 {
     debug!("vtable_methods({:?})", trait_ref);
 
-    Lrc::new(
+    tcx.arena.alloc_from_iter(
         supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
             let trait_methods = tcx.associated_items(trait_ref.def_id())
                 .filter(|item| item.kind == ty::AssociatedKind::Method);
@@ -1039,7 +1039,7 @@ fn vtable_methods<'a, 'tcx>(
 
                 Some((def_id, substs))
             })
-        }).collect()
+        })
     )
 }
 
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index c576586fcad..384a5862cde 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -16,7 +16,6 @@ use crate::infer::{InferCtxt, InferOk};
 use crate::lint;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::sync::Lrc;
 use syntax_pos::DUMMY_SP;
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::ty::{self, TyCtxt, TypeFoldable};
@@ -289,7 +288,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 pub(super) fn specialization_graph_provider<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     trait_id: DefId,
-) -> Lrc<specialization_graph::Graph> {
+) -> &'tcx specialization_graph::Graph {
     let mut sg = specialization_graph::Graph::new();
 
     let mut trait_impls = tcx.all_impls(trait_id);
@@ -383,7 +382,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
         }
     }
 
-    Lrc::new(sg)
+    tcx.arena.alloc(sg)
 }
 
 /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 561859c7c31..dae1518d722 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -7,7 +7,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
 use crate::traits;
 use crate::ty::{self, TyCtxt, TypeFoldable};
 use crate::ty::fast_reject::{self, SimplifiedType};
-use rustc_data_structures::sync::Lrc;
 use syntax::ast::Ident;
 use crate::util::captures::Captures;
 use crate::util::nodemap::{DefIdMap, FxHashMap};
@@ -439,13 +438,13 @@ impl<'a, 'gcx, 'tcx> Node {
     }
 }
 
-pub struct Ancestors {
+pub struct Ancestors<'tcx> {
     trait_def_id: DefId,
-    specialization_graph: Lrc<Graph>,
+    specialization_graph: &'tcx Graph,
     current_source: Option<Node>,
 }
 
-impl Iterator for Ancestors {
+impl Iterator for Ancestors<'_> {
     type Item = Node;
     fn next(&mut self) -> Option<Node> {
         let cur = self.current_source.take();
@@ -476,7 +475,7 @@ impl<T> NodeItem<T> {
     }
 }
 
-impl<'a, 'gcx, 'tcx> Ancestors {
+impl<'a, 'gcx, 'tcx> Ancestors<'gcx> {
     /// Search the items from the given ancestors, returning each definition
     /// with the given name and the given kind.
     // FIXME(#35870): avoid closures being unexported due to `impl Trait`.
@@ -509,10 +508,10 @@ impl<'a, 'gcx, 'tcx> Ancestors {
 
 /// Walk up the specialization ancestors of a given impl, starting with that
 /// impl itself.
-pub fn ancestors(tcx: TyCtxt<'_, '_, '_>,
+pub fn ancestors(tcx: TyCtxt<'_, 'tcx, '_>,
                  trait_def_id: DefId,
                  start_from_impl: DefId)
-                 -> Ancestors {
+                 -> Ancestors<'tcx> {
     let specialization_graph = tcx.specialization_graph_of(trait_def_id);
     Ancestors {
         trait_def_id,
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index f3a800bf46d..0711f3539e5 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -519,6 +519,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
                 source,
                 ref prior_arms,
                 last_ty,
+                discrim_hir_id,
             } => {
                 tcx.lift(&last_ty).map(|last_ty| {
                     super::MatchExpressionArm {
@@ -526,6 +527,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
                         source,
                         prior_arms: prior_arms.clone(),
                         last_ty,
+                        discrim_hir_id,
                     }
                 })
             }
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
index e7474345c00..a76cc3dfdec 100644
--- a/src/librustc/ty/codec.rs
+++ b/src/librustc/ty/codec.rs
@@ -6,6 +6,7 @@
 // The functionality in here is shared between persisting to crate metadata and
 // persisting to incr. comp. caches.
 
+use crate::arena::ArenaAllocatable;
 use crate::hir::def_id::{DefId, CrateNum};
 use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
 use rustc_data_structures::fx::FxHashMap;
@@ -131,6 +132,26 @@ pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
 }
 
 #[inline]
+pub fn decode_arena_allocable<'a, 'tcx, D, T: ArenaAllocatable + Decodable>(
+    decoder: &mut D
+) -> Result<&'tcx T, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    Ok(decoder.tcx().arena.alloc(Decodable::decode(decoder)?))
+}
+
+#[inline]
+pub fn decode_arena_allocable_slice<'a, 'tcx, D, T: ArenaAllocatable + Decodable>(
+    decoder: &mut D
+) -> Result<&'tcx [T], D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable>::decode(decoder)?))
+}
+
+#[inline]
 pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
     where D: TyDecoder<'a, 'tcx>,
           'tcx: 'a,
@@ -274,6 +295,39 @@ macro_rules! __impl_decoder_methods {
 }
 
 #[macro_export]
+macro_rules! impl_arena_allocatable_decoder {
+    ([]$args:tt) => {};
+    ([decode $(, $attrs:ident)*]
+     [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty], $tcx:lifetime]) => {
+        impl<$($typaram),*> SpecializedDecoder<&$tcx $ty> for $DecoderName<$($typaram),*> {
+            #[inline]
+            fn specialized_decode(&mut self) -> Result<&$tcx $ty, Self::Error> {
+                decode_arena_allocable(self)
+            }
+        }
+
+        impl<$($typaram),*> SpecializedDecoder<&$tcx [$ty]> for $DecoderName<$($typaram),*> {
+            #[inline]
+            fn specialized_decode(&mut self) -> Result<&$tcx [$ty], Self::Error> {
+                decode_arena_allocable_slice(self)
+            }
+        }
+    };
+    ([$ignore:ident $(, $attrs:ident)*]$args:tt) => {
+        impl_arena_allocatable_decoder!([$($attrs),*]$args);
+    };
+}
+
+#[macro_export]
+macro_rules! impl_arena_allocatable_decoders {
+    ($args:tt, [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
+        $(
+            impl_arena_allocatable_decoder!($a [$args, [$name: $ty], $tcx]);
+        )*
+    }
+}
+
+#[macro_export]
 macro_rules! implement_ty_decoder {
     ($DecoderName:ident <$($typaram:tt),*>) => {
         mod __ty_decoder_impl {
@@ -322,6 +376,8 @@ macro_rules! implement_ty_decoder {
             // the caller to pick any lifetime for 'tcx, including 'static,
             // by using the unspecialized proxies to them.
 
+            arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
+
             impl<$($typaram),*> SpecializedDecoder<CrateNum>
             for $DecoderName<$($typaram),*> {
                 fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 77330c7a9d1..7dc4dee3fbf 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1,5 +1,6 @@
 //! Type context book-keeping.
 
+use crate::arena::Arena;
 use crate::dep_graph::DepGraph;
 use crate::dep_graph::{self, DepNode, DepConstructor};
 use crate::session::Session;
@@ -125,7 +126,7 @@ pub struct CtxtInterners<'tcx> {
     clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
     goal: InternedSet<'tcx, GoalKind<'tcx>>,
     goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
-    projs: InternedSet<'tcx, List<ProjectionKind<'tcx>>>,
+    projs: InternedSet<'tcx, List<ProjectionKind>>,
     const_: InternedSet<'tcx, Const<'tcx>>,
 }
 
@@ -219,6 +220,11 @@ pub struct CommonTypes<'tcx> {
     pub never: Ty<'tcx>,
     pub err: Ty<'tcx>,
 
+    /// Dummy type used for the `Self` of a `TraitRef` created for converting
+    /// a trait object, and which gets removed in `ExistentialTraitRef`.
+    /// This type must not appear anywhere in other converted types.
+    pub trait_object_dummy_self: Ty<'tcx>,
+
     pub re_empty: Region<'tcx>,
     pub re_static: Region<'tcx>,
     pub re_erased: Region<'tcx>,
@@ -955,6 +961,8 @@ impl<'tcx> CommonTypes<'tcx> {
             f32: mk(Float(ast::FloatTy::F32)),
             f64: mk(Float(ast::FloatTy::F64)),
 
+            trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
+
             re_empty: mk_region(RegionKind::ReEmpty),
             re_static: mk_region(RegionKind::ReStatic),
             re_erased: mk_region(RegionKind::ReErased),
@@ -996,6 +1004,7 @@ impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> {
 }
 
 pub struct GlobalCtxt<'tcx> {
+    pub arena: WorkerLocal<Arena<'tcx>>,
     global_arenas: &'tcx WorkerLocal<GlobalArenas<'tcx>>,
     global_interners: CtxtInterners<'tcx>,
 
@@ -1255,6 +1264,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         GlobalCtxt {
             sess: s,
             cstore,
+            arena: WorkerLocal::new(|_| Arena::default()),
             global_arenas: &arenas.global,
             global_interners: interners,
             dep_graph,
@@ -1802,7 +1812,7 @@ nop_list_lift!{Ty<'a> => Ty<'tcx>}
 nop_list_lift!{ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
 nop_list_lift!{Predicate<'a> => Predicate<'tcx>}
 nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo}
-nop_list_lift!{ProjectionKind<'a> => ProjectionKind<'tcx>}
+nop_list_lift!{ProjectionKind => ProjectionKind}
 
 // this is the impl for `&'a InternalSubsts<'a>`
 nop_list_lift!{Kind<'a> => Kind<'tcx>}
@@ -2261,9 +2271,9 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[Kind<'lcx>]> for Interned<'tcx, InternalSubsts<'t
     }
 }
 
-impl<'tcx: 'lcx, 'lcx> Borrow<[ProjectionKind<'lcx>]>
-    for Interned<'tcx, List<ProjectionKind<'tcx>>> {
-    fn borrow<'a>(&'a self) -> &'a [ProjectionKind<'lcx>] {
+impl<'tcx> Borrow<[ProjectionKind]>
+    for Interned<'tcx, List<ProjectionKind>> {
+    fn borrow<'a>(&'a self) -> &'a [ProjectionKind] {
         &self.0[..]
     }
 }
@@ -2391,22 +2401,22 @@ direct_interners!('tcx,
 );
 
 macro_rules! slice_interners {
-    ($($field:ident: $method:ident($ty:ident)),+) => (
+    ($($field:ident: $method:ident($ty:ty)),+) => (
         $(intern_method!( 'tcx, $field: $method(
-            &[$ty<'tcx>],
+            &[$ty],
             |a, v| List::from_arena(a, v),
             Deref::deref,
-            |xs: &[$ty<'_>]| xs.iter().any(keep_local)) -> List<$ty<'tcx>>);)+
-    )
+            |xs: &[$ty]| xs.iter().any(keep_local)) -> List<$ty>);)+
+    );
 }
 
 slice_interners!(
-    existential_predicates: _intern_existential_predicates(ExistentialPredicate),
-    predicates: _intern_predicates(Predicate),
-    type_list: _intern_type_list(Ty),
-    substs: _intern_substs(Kind),
-    clauses: _intern_clauses(Clause),
-    goal_list: _intern_goals(Goal),
+    existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>),
+    predicates: _intern_predicates(Predicate<'tcx>),
+    type_list: _intern_type_list(Ty<'tcx>),
+    substs: _intern_substs(Kind<'tcx>),
+    clauses: _intern_clauses(Clause<'tcx>),
+    goal_list: _intern_goals(Goal<'tcx>),
     projs: _intern_projs(ProjectionKind)
 );
 
@@ -2774,7 +2784,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn intern_projs(self, ps: &[ProjectionKind<'tcx>]) -> &'tcx List<ProjectionKind<'tcx>> {
+    pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
         if ps.len() == 0 {
             List::empty()
         } else {
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index e01b50113b9..fd1d3a91ede 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -920,6 +920,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                                         niche_variants,
                                         niche_start,
                                     },
+                                    discr_index: 0,
                                     variants: st,
                                 },
                                 fields: FieldPlacement::Arbitrary {
@@ -1142,6 +1143,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     variants: Variants::Multiple {
                         discr: tag,
                         discr_kind: DiscriminantKind::Tag,
+                        discr_index: 0,
                         variants: layout_variants,
                     },
                     fields: FieldPlacement::Arbitrary {
@@ -1884,10 +1886,12 @@ impl<'a> HashStable<StableHashingContext<'a>> for Variants {
             Multiple {
                 ref discr,
                 ref discr_kind,
+                discr_index,
                 ref variants,
             } => {
                 discr.hash_stable(hcx, hasher);
                 discr_kind.hash_stable(hcx, hasher);
+                discr_index.hash_stable(hcx, hasher);
                 variants.hash_stable(hcx, hasher);
             }
         }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 102057c1380..7d47867cea1 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(stage0), allow(usage_of_ty_tykind))]
+
 pub use self::Variance::*;
 pub use self::AssociatedItemContainer::*;
 pub use self::BorrowKind::*;
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index bc5caffb934..0eda92ea8b8 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -1,17 +1,9 @@
 use crate::dep_graph::SerializedDepNodeIndex;
 use crate::dep_graph::DepNode;
-use crate::hir::def_id::{CrateNum, DefId, DefIndex};
-use crate::mir::interpret::GlobalId;
-use crate::traits;
-use crate::traits::query::{
-    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
-    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
-    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
-};
-use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
-use crate::ty::subst::SubstsRef;
+use crate::hir::def_id::{CrateNum, DefId};
+use crate::ty::TyCtxt;
 use crate::ty::query::queries;
-use crate::ty::query::Query;
+use crate::ty::query::{Query, QueryName};
 use crate::ty::query::QueryCache;
 use crate::ty::query::plumbing::CycleError;
 use crate::util::profiling::ProfileCategory;
@@ -19,7 +11,6 @@ use crate::util::profiling::ProfileCategory;
 use std::borrow::Cow;
 use std::hash::Hash;
 use std::fmt::Debug;
-use syntax_pos::symbol::InternedString;
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::fingerprint::Fingerprint;
 use crate::ich::StableHashingContext;
@@ -27,7 +18,7 @@ use crate::ich::StableHashingContext;
 // Query configuration and description traits.
 
 pub trait QueryConfig<'tcx> {
-    const NAME: &'static str;
+    const NAME: QueryName;
     const CATEGORY: ProfileCategory;
 
     type Key: Eq + Hash + Clone + Debug;
@@ -79,843 +70,12 @@ impl<'tcx, M: QueryAccessors<'tcx, Key=DefId>> QueryDescription<'tcx> for M {
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::check_mod_attrs<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: DefId,
-    ) -> Cow<'static, str> {
-        format!("checking attributes in {}", key.describe_as_module(tcx)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::check_mod_unstable_api_usage<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: DefId,
-    ) -> Cow<'static, str> {
-        format!("checking for unstable API usage in {}", key.describe_as_module(tcx)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::check_mod_loops<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: DefId,
-    ) -> Cow<'static, str> {
-        format!("checking loops in {}", key.describe_as_module(tcx)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::check_mod_item_types<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: DefId,
-    ) -> Cow<'static, str> {
-        format!("checking item types in {}", key.describe_as_module(tcx)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::check_mod_privacy<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: DefId,
-    ) -> Cow<'static, str> {
-        format!("checking privacy in {}", key.describe_as_module(tcx)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::check_mod_intrinsics<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: DefId,
-    ) -> Cow<'static, str> {
-        format!("checking intrinsics in {}", key.describe_as_module(tcx)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::check_mod_liveness<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: DefId,
-    ) -> Cow<'static, str> {
-        format!("checking liveness of variables in {}", key.describe_as_module(tcx)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::check_mod_impl_wf<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: DefId,
-    ) -> Cow<'static, str> {
-        format!("checking that impls are well-formed in {}", key.describe_as_module(tcx)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::collect_mod_item_types<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: DefId,
-    ) -> Cow<'static, str> {
-        format!("collecting item types in {}", key.describe_as_module(tcx)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::normalize_projection_ty<'tcx> {
-    fn describe(
-        _tcx: TyCtxt<'_, '_, '_>,
-        goal: CanonicalProjectionGoal<'tcx>,
-    ) -> Cow<'static, str> {
-        format!("normalizing `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::implied_outlives_bounds<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> Cow<'static, str> {
-        format!("computing implied outlives bounds for `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::dropck_outlives<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> Cow<'static, str> {
-        format!("computing dropck types for `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::normalize_ty_after_erasing_regions<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Cow<'static, str> {
-        format!("normalizing `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::evaluate_obligation<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalPredicateGoal<'tcx>) -> Cow<'static, str> {
-        format!("evaluating trait selection obligation `{}`", goal.value.value).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::evaluate_goal<'tcx> {
-    fn describe(
-        _tcx: TyCtxt<'_, '_, '_>,
-        goal: traits::ChalkCanonicalGoal<'tcx>
-    ) -> Cow<'static, str> {
-        format!("evaluating trait selection obligation `{}`", goal.value.goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type<'tcx> {
-    fn describe(
-        _tcx: TyCtxt<'_, '_, '_>,
-        goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
-    ) -> Cow<'static, str> {
-        format!("evaluating `type_op_ascribe_user_type` `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> Cow<'static, str> {
-        format!("evaluating `type_op_eq` `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::type_op_subtype<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpSubtypeGoal<'tcx>)
-                -> Cow<'static, str> {
-        format!("evaluating `type_op_subtype` `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::type_op_prove_predicate<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpProvePredicateGoal<'tcx>)
-                -> Cow<'static, str> {
-        format!("evaluating `type_op_prove_predicate` `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_ty<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>,
-                goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>) -> Cow<'static, str> {
-        format!("normalizing `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_predicate<'tcx> {
-    fn describe(
-        _tcx: TyCtxt<'_, '_, '_>,
-        goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>,
-    ) -> Cow<'static, str> {
-        format!("normalizing `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_poly_fn_sig<'tcx> {
-    fn describe(
-        _tcx: TyCtxt<'_, '_, '_>,
-        goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>>,
-    ) -> Cow<'static, str> {
-        format!("normalizing `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_fn_sig<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>,
-                goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>) -> Cow<'static, str> {
-        format!("normalizing `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-                -> Cow<'static, str> {
-        format!("computing whether `{}` is `Copy`", env.value).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_sized_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-                -> Cow<'static, str> {
-        format!("computing whether `{}` is `Sized`", env.value).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_freeze_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-                -> Cow<'static, str> {
-        format!("computing whether `{}` is freeze", env.value).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::needs_drop_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-                -> Cow<'static, str> {
-        format!("computing whether `{}` needs drop", env.value).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::layout_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-                -> Cow<'static, str> {
-        format!("computing layout of `{}`", env.value).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("computing the supertraits of `{}`",
-                tcx.def_path_str(def_id)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::type_param_predicates<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, (_, def_id): (DefId, DefId)) -> Cow<'static, str> {
-        let id = tcx.hir().as_local_hir_id(def_id).unwrap();
-        format!("computing the bounds for type parameter `{}`",
-                tcx.hir().ty_param_name(id)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::coherent_trait<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("coherence checking all impls of trait `{}`",
-                tcx.def_path_str(def_id)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::upstream_monomorphizations<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> Cow<'static, str> {
-        format!("collecting available upstream monomorphizations `{:?}`", k).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::crate_inherent_impls<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> Cow<'static, str> {
-        format!("all inherent impls defined in crate `{:?}`", k).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::crate_inherent_impls_overlap_check<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "check for overlap between inherent impls defined in this crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::crate_variances<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "computing the variances for items in this crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::inferred_outlives_crate<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "computing the inferred outlives predicates for items in this crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> {
-        format!("generating MIR shim for `{}`",
-                tcx.def_path_str(def.def_id())).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::privacy_access_levels<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "privacy access levels".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::check_private_in_public<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "checking for private elements in public interfaces".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::typeck_item_bodies<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "type-checking all item bodies".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::reachable_set<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "reachability".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> {
-    fn describe(
-        tcx: TyCtxt<'_, '_, '_>,
-        key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
-    ) -> Cow<'static, str> {
-        format!(
-            "const-evaluating + checking `{}`",
-            tcx.def_path_str(key.value.instance.def.def_id()),
-        ).into()
-    }
-
-    #[inline]
-    fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, _key: Self::Key) -> bool {
-        true
-    }
-
-    #[inline]
-    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: SerializedDepNodeIndex)
-                              -> Option<Self::Value> {
-        tcx.queries.on_disk_cache.try_load_query_result(tcx, id).map(Ok)
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::const_eval_raw<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-        -> Cow<'static, str>
-    {
-        format!("const-evaluating `{}`", tcx.def_path_str(key.value.instance.def.def_id())).into()
-    }
-
-    #[inline]
-    fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, _key: Self::Key) -> bool {
-        true
-    }
-
-    #[inline]
-    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: SerializedDepNodeIndex)
-                              -> Option<Self::Value> {
-        tcx.queries.on_disk_cache.try_load_query_result(tcx, id).map(Ok)
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::symbol_name<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, instance: ty::Instance<'tcx>) -> Cow<'static, str> {
-        format!("computing the symbol for `{}`", instance).into()
-    }
-
-    #[inline]
-    fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, _: Self::Key) -> bool {
-        true
-    }
-
-    #[inline]
-    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: SerializedDepNodeIndex)
-                              -> Option<Self::Value> {
-        tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::describe_def<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        bug!("describe_def")
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::def_span<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        bug!("def_span")
-    }
-}
-
-
-impl<'tcx> QueryDescription<'tcx> for queries::lookup_stability<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        bug!("stability")
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::lookup_deprecation_entry<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        bug!("deprecation")
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::item_attrs<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        bug!("item_attrs")
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_reachable_non_generic<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        bug!("is_reachable_non_generic")
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::fn_arg_names<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        bug!("fn_arg_names")
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::impl_parent<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        bug!("impl_parent")
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::trait_of_item<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        bug!("trait_of_item")
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_static<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("const checking if rvalue is promotable to static `{}`",
-            tcx.def_path_str(def_id)).into()
-    }
-
-    #[inline]
-    fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, _: Self::Key) -> bool {
-        true
-    }
-
-    #[inline]
-    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: SerializedDepNodeIndex)
-                              -> Option<Self::Value> {
-        tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::rvalue_promotable_map<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("checking which parts of `{}` are promotable to static",
-                tcx.def_path_str(def_id)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_mir_available<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("checking if item is mir available: `{}`",
-                tcx.def_path_str(def_id)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::codegen_fulfill_obligation<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>,
-                key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Cow<'static, str> {
-        format!("checking if `{}` fulfills its obligations", tcx.def_path_str(key.1.def_id()))
-            .into()
-    }
-
-    #[inline]
-    fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, _: Self::Key) -> bool {
-        true
-    }
-
-    #[inline]
-    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: SerializedDepNodeIndex)
-                              -> Option<Self::Value> {
-        tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::trait_impls_of<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("trait impls of `{}`", tcx.def_path_str(def_id)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_object_safe<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("determine object safety of trait `{}`", tcx.def_path_str(def_id)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_const_fn_raw<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
-        format!("checking if item is const fn: `{}`", tcx.def_path_str(def_id)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::dylib_dependency_formats<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "dylib dependency formats of crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_compiler_builtins<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "checking if the crate is_compiler_builtins".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::has_global_allocator<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "checking if the crate has_global_allocator".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::has_panic_handler<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "checking if the crate has_panic_handler".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::extern_crate<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        "getting crate's ExternCrateData".into()
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
     fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
         "running analysis passes on this crate".into()
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::specializes<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (DefId, DefId)) -> Cow<'static, str> {
-        "computing whether impls specialize one another".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::in_scope_traits_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> {
-        "traits in scope at a block".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_no_builtins<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "test whether a crate has #![no_builtins]".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::panic_strategy<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "query a crate's configured panic strategy".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_profiler_runtime<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "query a crate is #![profiler_runtime]".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_sanitizer_runtime<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "query a crate is #![sanitizer_runtime]".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::reachable_non_generics<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the exported symbols of a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::foreign_modules<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the foreign modules of a linked crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::entry_fn<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the entry function of a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the plugin registrar for a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::proc_macro_decls_static<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the derive registrar for a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::crate_disambiguator<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the disambiguator a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::crate_hash<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the hash a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::original_crate_name<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the original name a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::extra_filename<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the extra filename for a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::implementations_of_trait<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (CrateNum, DefId)) -> Cow<'static, str> {
-        "looking up implementations of a trait in a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::all_trait_implementations<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up all (?) trait implementations".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::link_args<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up link arguments for a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::resolve_lifetimes<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "resolving lifetimes".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::named_region_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> {
-        "looking up a named region".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::is_late_bound_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> {
-        "testing if a region is late bound".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::object_lifetime_defaults_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> {
-        "looking up lifetime defaults for a region".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::dep_kind<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "fetching what a dependency looks like".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::crate_name<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "fetching what a crate is named".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::get_lib_features<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "calculating the lib features map".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::defined_lib_features<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "calculating the lib features defined in a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::get_lang_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "calculating the lang items map".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::defined_lang_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "calculating the lang items defined in a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::missing_lang_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "calculating the missing lang items in a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::visible_parent_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "calculating the visible parent map".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::missing_extern_crate_item<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "seeing if we're missing an `extern crate` item for this crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::used_crate_source<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking at the source for a crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::postorder_cnums<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "generating a postorder list of CrateNums".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::maybe_unused_extern_crates<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up all possibly unused extern crates".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::stability_index<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "calculating the stability index for the local crate".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::all_traits<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "fetching all foreign and local traits".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::all_crate_nums<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "fetching all foreign CrateNum instances".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::exported_symbols<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "exported_symbols".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::collect_and_partition_mono_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "collect_and_partition_mono_items".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::codegen_unit<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: InternedString) -> Cow<'static, str> {
-        "codegen_unit".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "output_filenames".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::vtable_methods<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::PolyTraitRef<'tcx> ) -> Cow<'static, str> {
-        format!("finding all methods for trait {}", tcx.def_path_str(key.def_id())).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::features_query<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up enabled feature gates".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::typeck_tables_of<'tcx> {
-    #[inline]
-    fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, def_id: Self::Key) -> bool {
-        def_id.is_local()
-    }
-
-    fn try_load_from_disk(tcx: TyCtxt<'_, 'tcx, 'tcx>,
-                          id: SerializedDepNodeIndex)
-                          -> Option<Self::Value> {
-        let typeck_tables: Option<ty::TypeckTables<'tcx>> = tcx
-            .queries.on_disk_cache
-            .try_load_query_result(tcx, id);
-
-        typeck_tables.map(|tables| tcx.alloc_tables(tables))
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, SubstsRef<'tcx>)) -> Cow<'static, str> {
-        format!("testing substituted normalized predicates:`{}`", tcx.def_path_str(key.0)).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::method_autoderef_steps<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> Cow<'static, str> {
-        format!("computing autoderef types for `{:?}`", goal).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::target_features_whitelist<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "looking up the whitelist of target features".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::instance_def_size_estimate<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> {
-        format!("estimating size for `{}`", tcx.def_path_str(def.def_id())).into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::dllimport_foreign_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "dllimport_foreign_items".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::backend_optimization_level<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "optimization level used by backend".into()
-    }
-}
-
 macro_rules! impl_disk_cacheable_query(
     ($query_name:ident, |$tcx:tt, $key:tt| $cond:expr) => {
         impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> {
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index f64156beeaa..cd29ca81890 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -1,4 +1,4 @@
-use crate::dep_graph::{self, DepConstructor, DepNode};
+use crate::dep_graph::{self, DepNode};
 use crate::hir::def_id::{CrateNum, DefId, DefIndex};
 use crate::hir::def::{Def, Export};
 use crate::hir::{self, TraitCandidate, ItemLocalId, CodegenFnAttrs};
@@ -41,7 +41,6 @@ use crate::ty::subst::SubstsRef;
 use crate::util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
 use crate::util::common::{ErrorReported};
 use crate::util::profiling::ProfileCategory::*;
-use crate::session::Session;
 
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::bit_set::BitSet;
@@ -104,738 +103,5 @@ rustc_query_append! { [define_queries!][ <'tcx>
         /// Run analysis passes on the crate
         [] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
 
-        /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
-        /// predicates (where-clauses) directly defined on it. This is
-        /// equal to the `explicit_predicates_of` predicates plus the
-        /// `inferred_outlives_of` predicates.
-        [] fn predicates_defined_on: PredicatesDefinedOnItem(DefId)
-            -> Lrc<ty::GenericPredicates<'tcx>>,
-
-        /// Returns the predicates written explicit by the user.
-        [] fn explicit_predicates_of: ExplicitPredicatesOfItem(DefId)
-            -> Lrc<ty::GenericPredicates<'tcx>>,
-
-        /// Returns the inferred outlives predicates (e.g., for `struct
-        /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
-        [] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
-
-        /// Maps from the `DefId` of a trait to the list of
-        /// super-predicates. This is a subset of the full list of
-        /// predicates. We store these in a separate map because we must
-        /// evaluate them even during type conversion, often before the
-        /// full predicates are available (note that supertraits have
-        /// additional acyclicity requirements).
-        [] fn super_predicates_of: SuperPredicatesOfItem(DefId) -> Lrc<ty::GenericPredicates<'tcx>>,
-
-        /// To avoid cycles within the predicates of a single item we compute
-        /// per-type-parameter predicates for resolving `T::AssocTy`.
-        [] fn type_param_predicates: type_param_predicates((DefId, DefId))
-            -> Lrc<ty::GenericPredicates<'tcx>>,
-
-        [] fn trait_def: TraitDefOfItem(DefId) -> &'tcx ty::TraitDef,
-        [] fn adt_def: AdtDefOfItem(DefId) -> &'tcx ty::AdtDef,
-        [] fn adt_destructor: AdtDestructor(DefId) -> Option<ty::Destructor>,
-
-        // The cycle error here should be reported as an error by `check_representable`.
-        // We consider the type as Sized in the meanwhile to avoid
-        // further errors (done in impl Value for AdtSizedConstraint).
-        // Use `cycle_delay_bug` to delay the cycle error here to be emitted later
-        // in case we accidentally otherwise don't emit an error.
-        [cycle_delay_bug] fn adt_sized_constraint: SizedConstraint(
-            DefId
-        ) -> AdtSizedConstraint<'tcx>,
-
-        [] fn adt_dtorck_constraint: DtorckConstraint(
-            DefId
-        ) -> Result<DtorckConstraint<'tcx>, NoSolution>,
-
-        /// True if this is a const fn, use the `is_const_fn` to know whether your crate actually
-        /// sees it as const fn (e.g., the const-fn-ness might be unstable and you might not have
-        /// the feature gate active)
-        ///
-        /// **Do not call this function manually.** It is only meant to cache the base data for the
-        /// `is_const_fn` function.
-        [] fn is_const_fn_raw: IsConstFn(DefId) -> bool,
-
-
-        /// Returns true if calls to the function may be promoted
-        ///
-        /// This is either because the function is e.g., a tuple-struct or tuple-variant
-        /// constructor, or because it has the `#[rustc_promotable]` attribute. The attribute should
-        /// be removed in the future in favour of some form of check which figures out whether the
-        /// function does not inspect the bits of any of its arguments (so is essentially just a
-        /// constructor function).
-        [] fn is_promotable_const_fn: IsPromotableConstFn(DefId) -> bool,
-
-        /// True if this is a foreign item (i.e., linked via `extern { ... }`).
-        [] fn is_foreign_item: IsForeignItem(DefId) -> bool,
-
-        /// Get a map with the variance of every item; use `item_variance`
-        /// instead.
-        [] fn crate_variances: crate_variances(CrateNum) -> Lrc<ty::CrateVariancesMap>,
-
-        /// Maps from def-id of a type or region parameter to its
-        /// (inferred) variance.
-        [] fn variances_of: ItemVariances(DefId) -> Lrc<Vec<ty::Variance>>,
-    },
-
-    TypeChecking {
-        /// Maps from def-id of a type to its (inferred) outlives.
-        [] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum)
-            -> Lrc<ty::CratePredicatesMap<'tcx>>,
-    },
-
-    Other {
-        /// Maps from an impl/trait def-id to a list of the def-ids of its items
-        [] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Lrc<Vec<DefId>>,
-
-        /// Maps from a trait item to the trait item "descriptor"
-        [] fn associated_item: AssociatedItems(DefId) -> ty::AssociatedItem,
-
-        [] fn impl_trait_ref: ImplTraitRef(DefId) -> Option<ty::TraitRef<'tcx>>,
-        [] fn impl_polarity: ImplPolarity(DefId) -> hir::ImplPolarity,
-
-        [] fn issue33140_self_ty: Issue33140SelfTy(DefId) -> Option<ty::Ty<'tcx>>,
-    },
-
-    TypeChecking {
-        /// Maps a DefId of a type to a list of its inherent impls.
-        /// Contains implementations of methods that are inherent to a type.
-        /// Methods in these implementations don't need to be exported.
-        [] fn inherent_impls: InherentImpls(DefId) -> Lrc<Vec<DefId>>,
-    },
-
-    TypeChecking {
-        /// The result of unsafety-checking this `DefId`.
-        [] fn unsafety_check_result: UnsafetyCheckResult(DefId) -> mir::UnsafetyCheckResult,
-
-        /// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error
-        [] fn unsafe_derive_on_repr_packed: UnsafeDeriveOnReprPacked(DefId) -> (),
-
-        /// The signature of functions and closures.
-        [] fn fn_sig: FnSignature(DefId) -> ty::PolyFnSig<'tcx>,
-    },
-
-    Other {
-        [] fn lint_mod: LintMod(DefId) -> (),
-
-        /// Checks the attributes in the module
-        [] fn check_mod_attrs: CheckModAttrs(DefId) -> (),
-
-        [] fn check_mod_unstable_api_usage: CheckModUnstableApiUsage(DefId) -> (),
-
-        /// Checks the loops in the module
-        [] fn check_mod_loops: CheckModLoops(DefId) -> (),
-
-        [] fn check_mod_item_types: CheckModItemTypes(DefId) -> (),
-
-        [] fn check_mod_privacy: CheckModPrivacy(DefId) -> (),
-
-        [] fn check_mod_intrinsics: CheckModIntrinsics(DefId) -> (),
-
-        [] fn check_mod_liveness: CheckModLiveness(DefId) -> (),
-
-        [] fn check_mod_impl_wf: CheckModImplWf(DefId) -> (),
-
-        [] fn collect_mod_item_types: CollectModItemTypes(DefId) -> (),
-
-        /// Caches CoerceUnsized kinds for impls on custom types.
-        [] fn coerce_unsized_info: CoerceUnsizedInfo(DefId)
-            -> ty::adjustment::CoerceUnsizedInfo,
-    },
-
-    TypeChecking {
-        [] fn typeck_item_bodies:
-                typeck_item_bodies_dep_node(CrateNum) -> (),
-
-        [] fn typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
-    },
-
-    Other {
-        [] fn used_trait_imports: UsedTraitImports(DefId) -> Lrc<DefIdSet>,
-    },
-
-    TypeChecking {
-        [] fn has_typeck_tables: HasTypeckTables(DefId) -> bool,
-
-        [] fn coherent_trait: CoherenceCheckTrait(DefId) -> (),
-    },
-
-    BorrowChecking {
-        [] fn borrowck: BorrowCheck(DefId) -> Lrc<BorrowCheckResult>,
-
-        /// Borrow checks the function body. If this is a closure, returns
-        /// additional requirements that the closure's creator must verify.
-        [] fn mir_borrowck: MirBorrowCheck(DefId) -> mir::BorrowCheckResult<'tcx>,
-    },
-
-    TypeChecking {
-        /// Gets a complete map from all types to their inherent impls.
-        /// Not meant to be used directly outside of coherence.
-        /// (Defined only for `LOCAL_CRATE`.)
-        [] fn crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum)
-            -> Lrc<CrateInherentImpls>,
-
-        /// Checks all types in the crate for overlap in their inherent impls. Reports errors.
-        /// Not meant to be used directly outside of coherence.
-        /// (Defined only for `LOCAL_CRATE`.)
-        [] fn crate_inherent_impls_overlap_check: inherent_impls_overlap_check_dep_node(CrateNum)
-            -> (),
-    },
-
-    Other {
-        /// Evaluate a constant without running sanity checks
-        ///
-        /// **Do not use this** outside const eval. Const eval uses this to break query cycles
-        /// during validation. Please add a comment to every use site explaining why using
-        /// `const_eval` isn't sufficient
-        [] fn const_eval_raw: const_eval_raw_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-            -> ConstEvalRawResult<'tcx>,
-
-        /// Results of evaluating const items or constants embedded in
-        /// other items (such as enum variant explicit discriminants).
-        [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-            -> ConstEvalResult<'tcx>,
-    },
-
-    TypeChecking {
-        [] fn check_match: CheckMatch(DefId) -> (),
-
-        /// Performs part of the privacy check and computes "access levels".
-        [] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Lrc<AccessLevels>,
-        [] fn check_private_in_public: CheckPrivateInPublic(CrateNum) -> (),
-    },
-
-    Other {
-        [] fn reachable_set: reachability_dep_node(CrateNum) -> ReachableSet,
-
-        /// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body;
-        /// in the case of closures, this will be redirected to the enclosing function.
-        [] fn region_scope_tree: RegionScopeTree(DefId) -> Lrc<region::ScopeTree>,
-
-        [] fn mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx>,
-
-        [] fn symbol_name: symbol_name_dep_node(ty::Instance<'tcx>) -> ty::SymbolName,
-
-        [] fn describe_def: DescribeDef(DefId) -> Option<Def>,
-        [] fn def_span: DefSpan(DefId) -> Span,
-        [] fn lookup_stability: LookupStability(DefId) -> Option<&'tcx attr::Stability>,
-        [] fn lookup_deprecation_entry: LookupDeprecationEntry(DefId) -> Option<DeprecationEntry>,
-        [] fn item_attrs: ItemAttrs(DefId) -> Lrc<[ast::Attribute]>,
-    },
-
-    Codegen {
-        [] fn codegen_fn_attrs: codegen_fn_attrs(DefId) -> CodegenFnAttrs,
-    },
-
-    Other {
-        [] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
-        /// Gets the rendered value of the specified constant or associated constant.
-        /// Used by rustdoc.
-        [] fn rendered_const: RenderedConst(DefId) -> String,
-        [] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
-    },
-
-    TypeChecking {
-        [] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
-        [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
-        [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc<ItemLocalSet>,
-    },
-
-    Codegen {
-        [] fn is_mir_available: IsMirAvailable(DefId) -> bool,
-    },
-
-    Other {
-        [] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>)
-                            -> Lrc<Vec<Option<(DefId, SubstsRef<'tcx>)>>>,
-    },
-
-    Codegen {
-        [] fn codegen_fulfill_obligation: fulfill_obligation_dep_node(
-            (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Vtable<'tcx, ()>,
-    },
-
-    TypeChecking {
-        [] fn trait_impls_of: TraitImpls(DefId) -> Lrc<ty::trait_def::TraitImpls>,
-        [] fn specialization_graph_of: SpecializationGraph(DefId)
-            -> Lrc<specialization_graph::Graph>,
-        [] fn is_object_safe: ObjectSafety(DefId) -> bool,
-
-        /// Gets the ParameterEnvironment for a given item; this environment
-        /// will be in "user-facing" mode, meaning that it is suitabe for
-        /// type-checking etc, and it does not normalize specializable
-        /// associated types. This is almost always what you want,
-        /// unless you are doing MIR optimizations, in which case you
-        /// might want to use `reveal_all()` method to change modes.
-        [] fn param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>,
-
-        /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
-        /// `ty.is_copy()`, etc, since that will prune the environment where possible.
-        [] fn is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
-        [] fn is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
-        [] fn is_freeze_raw: is_freeze_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
-
-        // The cycle error here should be reported as an error by `check_representable`.
-        // We consider the type as not needing drop in the meanwhile to avoid
-        // further errors (done in impl Value for NeedsDrop).
-        // Use `cycle_delay_bug` to delay the cycle error here to be emitted later
-        // in case we accidentally otherwise don't emit an error.
-        [cycle_delay_bug] fn needs_drop_raw: needs_drop_dep_node(
-            ty::ParamEnvAnd<'tcx, Ty<'tcx>>
-        ) -> NeedsDrop,
-
-        [] fn layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-                                    -> Result<&'tcx ty::layout::LayoutDetails,
-                                                ty::layout::LayoutError<'tcx>>,
-    },
-
-    Other {
-        [] fn dylib_dependency_formats: DylibDepFormats(CrateNum)
-                                        -> Lrc<Vec<(CrateNum, LinkagePreference)>>,
-    },
-
-    Codegen {
-        [fatal_cycle] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool,
-        [fatal_cycle] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool,
-        [fatal_cycle] fn has_panic_handler: HasPanicHandler(CrateNum) -> bool,
-        [fatal_cycle] fn is_sanitizer_runtime: IsSanitizerRuntime(CrateNum) -> bool,
-        [fatal_cycle] fn is_profiler_runtime: IsProfilerRuntime(CrateNum) -> bool,
-        [fatal_cycle] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy,
-        [fatal_cycle] fn is_no_builtins: IsNoBuiltins(CrateNum) -> bool,
-
-        [] fn extern_crate: ExternCrate(DefId) -> Lrc<Option<ExternCrate>>,
-    },
-
-    TypeChecking {
-        [] fn specializes: specializes_node((DefId, DefId)) -> bool,
-        [] fn in_scope_traits_map: InScopeTraits(DefIndex)
-            -> Option<Lrc<FxHashMap<ItemLocalId, Lrc<StableVec<TraitCandidate>>>>>,
-    },
-
-    Other {
-        [] fn module_exports: ModuleExports(DefId) -> Option<Lrc<Vec<Export>>>,
-    },
-
-    TypeChecking {
-        [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
-
-        [] fn check_item_well_formed: CheckItemWellFormed(DefId) -> (),
-        [] fn check_trait_item_well_formed: CheckTraitItemWellFormed(DefId) -> (),
-        [] fn check_impl_item_well_formed: CheckImplItemWellFormed(DefId) -> (),
-    },
-
-    Linking {
-        // The DefIds of all non-generic functions and statics in the given crate
-        // that can be reached from outside the crate.
-        //
-        // We expect this items to be available for being linked to.
-        //
-        // This query can also be called for LOCAL_CRATE. In this case it will
-        // compute which items will be reachable to other crates, taking into account
-        // the kind of crate that is currently compiled. Crates with only a
-        // C interface have fewer reachable things.
-        //
-        // Does not include external symbols that don't have a corresponding DefId,
-        // like the compiler-generated `main` function and so on.
-        [] fn reachable_non_generics: ReachableNonGenerics(CrateNum)
-            -> Lrc<DefIdMap<SymbolExportLevel>>,
-        [] fn is_reachable_non_generic: IsReachableNonGeneric(DefId) -> bool,
-        [] fn is_unreachable_local_definition: IsUnreachableLocalDefinition(DefId) -> bool,
-    },
-
-    Codegen {
-        [] fn upstream_monomorphizations: UpstreamMonomorphizations(CrateNum)
-            -> Lrc<DefIdMap<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>>,
-        [] fn upstream_monomorphizations_for: UpstreamMonomorphizationsFor(DefId)
-            -> Option<Lrc<FxHashMap<SubstsRef<'tcx>, CrateNum>>>,
-    },
-
-    Other {
-        [] fn foreign_modules: ForeignModules(CrateNum) -> Lrc<Vec<ForeignModule>>,
-
-        /// Identifies the entry-point (e.g., the `main` function) for a given
-        /// crate, returning `None` if there is no entry point (such as for library crates).
-        [] fn entry_fn: EntryFn(CrateNum) -> Option<(DefId, EntryFnType)>,
-        [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
-        [] fn proc_macro_decls_static: ProcMacroDeclsStatic(CrateNum) -> Option<DefId>,
-        [] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator,
-        [] fn crate_hash: CrateHash(CrateNum) -> Svh,
-        [] fn original_crate_name: OriginalCrateName(CrateNum) -> Symbol,
-        [] fn extra_filename: ExtraFileName(CrateNum) -> String,
-    },
-
-    TypeChecking {
-        [] fn implementations_of_trait: implementations_of_trait_node((CrateNum, DefId))
-            -> Lrc<Vec<DefId>>,
-        [] fn all_trait_implementations: AllTraitImplementations(CrateNum)
-            -> Lrc<Vec<DefId>>,
-    },
-
-    Other {
-        [] fn dllimport_foreign_items: DllimportForeignItems(CrateNum)
-            -> Lrc<FxHashSet<DefId>>,
-        [] fn is_dllimport_foreign_item: IsDllimportForeignItem(DefId) -> bool,
-        [] fn is_statically_included_foreign_item: IsStaticallyIncludedForeignItem(DefId) -> bool,
-        [] fn native_library_kind: NativeLibraryKind(DefId)
-            -> Option<NativeLibraryKind>,
-    },
-
-    Linking {
-        [] fn link_args: link_args_node(CrateNum) -> Lrc<Vec<String>>,
-    },
-
-    BorrowChecking {
-        // Lifetime resolution. See `middle::resolve_lifetimes`.
-        [] fn resolve_lifetimes: ResolveLifetimes(CrateNum) -> Lrc<ResolveLifetimes>,
-        [] fn named_region_map: NamedRegion(DefIndex) ->
-            Option<Lrc<FxHashMap<ItemLocalId, Region>>>,
-        [] fn is_late_bound_map: IsLateBound(DefIndex) ->
-            Option<Lrc<FxHashSet<ItemLocalId>>>,
-        [] fn object_lifetime_defaults_map: ObjectLifetimeDefaults(DefIndex)
-            -> Option<Lrc<FxHashMap<ItemLocalId, Lrc<Vec<ObjectLifetimeDefault>>>>>,
-    },
-
-    TypeChecking {
-        [] fn visibility: Visibility(DefId) -> ty::Visibility,
-    },
-
-    Other {
-        [] fn dep_kind: DepKind(CrateNum) -> DepKind,
-        [] fn crate_name: CrateName(CrateNum) -> Symbol,
-        [] fn item_children: ItemChildren(DefId) -> Lrc<Vec<Export>>,
-        [] fn extern_mod_stmt_cnum: ExternModStmtCnum(DefId) -> Option<CrateNum>,
-
-        [] fn get_lib_features: get_lib_features_node(CrateNum) -> Lrc<LibFeatures>,
-        [] fn defined_lib_features: DefinedLibFeatures(CrateNum)
-            -> Lrc<Vec<(Symbol, Option<Symbol>)>>,
-        [] fn get_lang_items: get_lang_items_node(CrateNum) -> Lrc<LanguageItems>,
-        [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Lrc<Vec<(DefId, usize)>>,
-        [] fn missing_lang_items: MissingLangItems(CrateNum) -> Lrc<Vec<LangItem>>,
-        [] fn visible_parent_map: visible_parent_map_node(CrateNum)
-            -> Lrc<DefIdMap<DefId>>,
-        [] fn missing_extern_crate_item: MissingExternCrateItem(CrateNum) -> bool,
-        [] fn used_crate_source: UsedCrateSource(CrateNum) -> Lrc<CrateSource>,
-        [] fn postorder_cnums: postorder_cnums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
-
-        [] fn freevars: Freevars(DefId) -> Option<Lrc<Vec<hir::Freevar>>>,
-        [] fn maybe_unused_trait_import: MaybeUnusedTraitImport(DefId) -> bool,
-        [] fn maybe_unused_extern_crates: maybe_unused_extern_crates_node(CrateNum)
-            -> Lrc<Vec<(DefId, Span)>>,
-        [] fn names_imported_by_glob_use: NamesImportedByGlobUse(DefId)
-            -> Lrc<FxHashSet<ast::Name>>,
-
-        [] fn stability_index: stability_index_node(CrateNum) -> Lrc<stability::Index<'tcx>>,
-        [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
-
-        /// A vector of every trait accessible in the whole crate
-        /// (i.e., including those from subcrates). This is used only for
-        /// error reporting.
-        [] fn all_traits: all_traits_node(CrateNum) -> Lrc<Vec<DefId>>,
-    },
-
-    Linking {
-        [] fn exported_symbols: ExportedSymbols(CrateNum)
-            -> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>>,
-    },
-
-    Codegen {
-        [] fn collect_and_partition_mono_items:
-            collect_and_partition_mono_items_node(CrateNum)
-            -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
-        [] fn is_codegened_item: IsCodegenedItem(DefId) -> bool,
-        [] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
-        [] fn backend_optimization_level: BackendOptimizationLevel(CrateNum) -> OptLevel,
-    },
-
-    Other {
-        [] fn output_filenames: output_filenames_node(CrateNum)
-            -> Arc<OutputFilenames>,
-    },
-
-    TypeChecking {
-        /// Do not call this query directly: invoke `normalize` instead.
-        [] fn normalize_projection_ty: NormalizeProjectionTy(
-            CanonicalProjectionGoal<'tcx>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: invoke `normalize_erasing_regions` instead.
-        [] fn normalize_ty_after_erasing_regions: NormalizeTyAfterErasingRegions(
-            ParamEnvAnd<'tcx, Ty<'tcx>>
-        ) -> Ty<'tcx>,
-
-        [] fn implied_outlives_bounds: ImpliedOutlivesBounds(
-            CanonicalTyGoal<'tcx>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead.
-        [] fn dropck_outlives: DropckOutlives(
-            CanonicalTyGoal<'tcx>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or
-        /// `infcx.predicate_must_hold()` instead.
-        [] fn evaluate_obligation: EvaluateObligation(
-            CanonicalPredicateGoal<'tcx>
-        ) -> Result<traits::EvaluationResult, traits::OverflowError>,
-
-        [] fn evaluate_goal: EvaluateGoal(
-            traits::ChalkCanonicalGoal<'tcx>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
-            NoSolution
-        >,
-
-        /// Do not call this query directly: part of the `Eq` type-op
-        [] fn type_op_ascribe_user_type: TypeOpAscribeUserType(
-            CanonicalTypeOpAscribeUserTypeGoal<'tcx>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: part of the `Eq` type-op
-        [] fn type_op_eq: TypeOpEq(
-            CanonicalTypeOpEqGoal<'tcx>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: part of the `Subtype` type-op
-        [] fn type_op_subtype: TypeOpSubtype(
-            CanonicalTypeOpSubtypeGoal<'tcx>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: part of the `ProvePredicate` type-op
-        [] fn type_op_prove_predicate: TypeOpProvePredicate(
-            CanonicalTypeOpProvePredicateGoal<'tcx>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: part of the `Normalize` type-op
-        [] fn type_op_normalize_ty: TypeOpNormalizeTy(
-            CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: part of the `Normalize` type-op
-        [] fn type_op_normalize_predicate: TypeOpNormalizePredicate(
-            CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: part of the `Normalize` type-op
-        [] fn type_op_normalize_poly_fn_sig: TypeOpNormalizePolyFnSig(
-            CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>>,
-            NoSolution,
-        >,
-
-        /// Do not call this query directly: part of the `Normalize` type-op
-        [] fn type_op_normalize_fn_sig: TypeOpNormalizeFnSig(
-            CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>
-        ) -> Result<
-            Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>>,
-            NoSolution,
-        >,
-
-        [] fn substitute_normalize_and_test_predicates:
-            substitute_normalize_and_test_predicates_node((DefId, SubstsRef<'tcx>)) -> bool,
-
-        [] fn method_autoderef_steps: MethodAutoderefSteps(
-            CanonicalTyGoal<'tcx>
-        ) -> MethodAutoderefStepsResult<'tcx>,
-    },
-
-    Other {
-        [] fn target_features_whitelist:
-            target_features_whitelist_node(CrateNum) -> Lrc<FxHashMap<String, Option<String>>>,
-
-        // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
-        [] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>)
-            -> usize,
-
-        [] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
     },
 ]}
-
-//////////////////////////////////////////////////////////////////////
-// These functions are little shims used to find the dep-node for a
-// given query when there is not a *direct* mapping:
-
-
-fn features_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::Features
-}
-
-fn codegen_fn_attrs<'tcx>(id: DefId) -> DepConstructor<'tcx> {
-    DepConstructor::CodegenFnAttrs { 0: id }
-}
-
-fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
-    DepConstructor::TypeParamPredicates {
-        item_id,
-        param_id
-    }
-}
-
-fn fulfill_obligation_dep_node<'tcx>((param_env, trait_ref):
-    (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> DepConstructor<'tcx> {
-    DepConstructor::FulfillObligation {
-        param_env,
-        trait_ref
-    }
-}
-
-fn crate_inherent_impls_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::Coherence
-}
-
-fn inherent_impls_overlap_check_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::CoherenceInherentImplOverlapCheck
-}
-
-fn reachability_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::Reachability
-}
-
-fn mir_shim_dep_node<'tcx>(instance_def: ty::InstanceDef<'tcx>) -> DepConstructor<'tcx> {
-    DepConstructor::MirShim {
-        instance_def
-    }
-}
-
-fn symbol_name_dep_node<'tcx>(instance: ty::Instance<'tcx>) -> DepConstructor<'tcx> {
-    DepConstructor::SymbolName { instance }
-}
-
-fn typeck_item_bodies_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::TypeckBodiesKrate
-}
-
-fn const_eval_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-                             -> DepConstructor<'tcx> {
-    DepConstructor::ConstEval { param_env }
-}
-fn const_eval_raw_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-                             -> DepConstructor<'tcx> {
-    DepConstructor::ConstEvalRaw { param_env }
-}
-
-fn crate_variances<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::CrateVariances
-}
-
-fn is_copy_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> {
-    DepConstructor::IsCopy { param_env }
-}
-
-fn is_sized_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> {
-    DepConstructor::IsSized { param_env }
-}
-
-fn is_freeze_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> {
-    DepConstructor::IsFreeze { param_env }
-}
-
-fn needs_drop_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> {
-    DepConstructor::NeedsDrop { param_env }
-}
-
-fn layout_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> {
-    DepConstructor::Layout { param_env }
-}
-
-fn specializes_node<'tcx>((a, b): (DefId, DefId)) -> DepConstructor<'tcx> {
-    DepConstructor::Specializes { impl1: a, impl2: b }
-}
-
-fn implementations_of_trait_node<'tcx>((krate, trait_id): (CrateNum, DefId))
-    -> DepConstructor<'tcx>
-{
-    DepConstructor::ImplementationsOfTrait { krate, trait_id }
-}
-
-fn link_args_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::LinkArgs
-}
-
-fn get_lib_features_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::GetLibFeatures
-}
-
-fn get_lang_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::GetLangItems
-}
-
-fn visible_parent_map_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::VisibleParentMap
-}
-
-fn postorder_cnums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::PostorderCnums
-}
-
-fn maybe_unused_extern_crates_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::MaybeUnusedExternCrates
-}
-
-fn stability_index_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::StabilityIndex
-}
-
-fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::AllCrateNums
-}
-
-fn all_traits_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::AllTraits
-}
-
-fn collect_and_partition_mono_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::CollectAndPartitionMonoItems
-}
-
-fn output_filenames_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::OutputFilenames
-}
-
-fn vtable_methods_node<'tcx>(trait_ref: ty::PolyTraitRef<'tcx>) -> DepConstructor<'tcx> {
-    DepConstructor::VtableMethods{ trait_ref }
-}
-
-fn substitute_normalize_and_test_predicates_node<'tcx>(key: (DefId, SubstsRef<'tcx>))
-                                            -> DepConstructor<'tcx> {
-    DepConstructor::SubstituteNormalizeAndTestPredicates { key }
-}
-
-fn target_features_whitelist_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::TargetFeaturesWhitelist
-}
-
-fn instance_def_size_estimate_dep_node<'tcx>(instance_def: ty::InstanceDef<'tcx>)
-                                              -> DepConstructor<'tcx> {
-    DepConstructor::InstanceDefSizeEstimate {
-        instance_def
-    }
-}
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 973291d94ac..d671b58470c 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -114,7 +114,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
             let mut lock = cache.borrow_mut();
             if let Some(value) = lock.results.get(key) {
                 profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
-                tcx.sess.profiler(|p| p.record_query_hit(Q::NAME, Q::CATEGORY));
+                tcx.sess.profiler(|p| p.record_query_hit(Q::NAME));
                 let result = (value.value.clone(), value.index);
                 #[cfg(debug_assertions)]
                 {
@@ -130,7 +130,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
                             //in another thread has completed. Record how long we wait in the
                             //self-profiler
                             #[cfg(parallel_compiler)]
-                            tcx.sess.profiler(|p| p.query_blocked_start(Q::NAME, Q::CATEGORY));
+                            tcx.sess.profiler(|p| p.query_blocked_start(Q::NAME));
 
                             job.clone()
                         },
@@ -172,7 +172,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
             #[cfg(parallel_compiler)]
             {
                 let result = job.r#await(tcx, span);
-                tcx.sess.profiler(|p| p.query_blocked_end(Q::NAME, Q::CATEGORY));
+                tcx.sess.profiler(|p| p.query_blocked_end(Q::NAME));
 
                 if let Err(cycle) = result {
                     return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle));
@@ -358,14 +358,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         key: Q::Key)
     -> Q::Value {
         debug!("ty::query::get_query<{}>(key={:?}, span={:?})",
-               Q::NAME,
+               Q::NAME.as_str(),
                key,
                span);
 
         profq_msg!(self,
             ProfileQueriesMsg::QueryBegin(
                 span.data(),
-                profq_query_msg!(Q::NAME, self, key),
+                profq_query_msg!(Q::NAME.as_str(), self, key),
             )
         );
 
@@ -389,7 +389,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         if dep_node.kind.is_anon() {
             profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
-            self.sess.profiler(|p| p.start_query(Q::NAME, Q::CATEGORY));
+            self.sess.profiler(|p| p.start_query(Q::NAME));
 
             let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
                 self.start_query(job.job.clone(), diagnostics, |tcx| {
@@ -399,7 +399,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 })
             });
 
-            self.sess.profiler(|p| p.end_query(Q::NAME, Q::CATEGORY));
+            self.sess.profiler(|p| p.end_query(Q::NAME));
             profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
 
             self.dep_graph.read_index(dep_node_index);
@@ -474,14 +474,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         let result = if let Some(result) = result {
             profq_msg!(self, ProfileQueriesMsg::CacheHit);
-            self.sess.profiler(|p| p.record_query_hit(Q::NAME, Q::CATEGORY));
+            self.sess.profiler(|p| p.record_query_hit(Q::NAME));
 
             result
         } else {
             // We could not load a result from the on-disk cache, so
             // recompute.
 
-            self.sess.profiler(|p| p.start_query(Q::NAME, Q::CATEGORY));
+            self.sess.profiler(|p| p.start_query(Q::NAME));
 
             // The dep-graph for this computation is already in
             // place
@@ -489,7 +489,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 Q::compute(self, key)
             });
 
-            self.sess.profiler(|p| p.end_query(Q::NAME, Q::CATEGORY));
+            self.sess.profiler(|p| p.end_query(Q::NAME));
             result
         };
 
@@ -552,7 +552,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 key, dep_node);
 
         profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
-        self.sess.profiler(|p| p.start_query(Q::NAME, Q::CATEGORY));
+        self.sess.profiler(|p| p.start_query(Q::NAME));
 
         let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
             self.start_query(job.job.clone(), diagnostics, |tcx| {
@@ -572,7 +572,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             })
         });
 
-        self.sess.profiler(|p| p.end_query(Q::NAME, Q::CATEGORY));
+        self.sess.profiler(|p| p.end_query(Q::NAME));
         profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
 
         if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) {
@@ -619,7 +619,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             let _ = self.get_query::<Q>(DUMMY_SP, key);
         } else {
             profq_msg!(self, ProfileQueriesMsg::CacheHit);
-            self.sess.profiler(|p| p.record_query_hit(Q::NAME, Q::CATEGORY));
+            self.sess.profiler(|p| p.record_query_hit(Q::NAME));
         }
     }
 
@@ -632,7 +632,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     ) {
         profq_msg!(
             self,
-            ProfileQueriesMsg::QueryBegin(span.data(), profq_query_msg!(Q::NAME, self, key))
+            ProfileQueriesMsg::QueryBegin(span.data(),
+                                          profq_query_msg!(Q::NAME.as_str(), self, key))
         );
 
         // We may be concurrently trying both execute and force a query
@@ -725,18 +726,6 @@ macro_rules! define_queries_inner {
                 }
             }
 
-            pub fn record_computed_queries(&self, sess: &Session) {
-                sess.profiler(|p| {
-                    $(
-                        p.record_computed_queries(
-                            <queries::$name<'_> as QueryConfig<'_>>::NAME,
-                            <queries::$name<'_> as QueryConfig<'_>>::CATEGORY,
-                            self.$name.lock().results.len()
-                        );
-                    )*
-                });
-            }
-
             #[cfg(parallel_compiler)]
             pub fn collect_active_jobs(&self) -> Vec<Lrc<QueryJob<$tcx>>> {
                 let mut jobs = Vec::new();
@@ -855,6 +844,24 @@ macro_rules! define_queries_inner {
         }
 
         #[allow(nonstandard_style)]
+        #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+        pub enum QueryName {
+            $($name),*
+        }
+
+        impl QueryName {
+            pub fn register_with_profiler(profiler: &crate::util::profiling::SelfProfiler) {
+                $(profiler.register_query_name(QueryName::$name);)*
+            }
+
+            pub fn as_str(&self) -> &'static str {
+                match self {
+                    $(QueryName::$name => stringify!($name),)*
+                }
+            }
+        }
+
+        #[allow(nonstandard_style)]
         #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
         pub enum Query<$tcx> {
             $($(#[$attr])* $name($K)),*
@@ -894,6 +901,12 @@ macro_rules! define_queries_inner {
                     $(Query::$name(key) => key.default_span(tcx),)*
                 }
             }
+
+            pub fn query_name(&self) -> QueryName {
+                match self {
+                    $(Query::$name(_) => QueryName::$name,)*
+                }
+            }
         }
 
         impl<'a, $tcx> HashStable<StableHashingContext<'a>> for Query<$tcx> {
@@ -930,7 +943,7 @@ macro_rules! define_queries_inner {
             type Key = $K;
             type Value = $V;
 
-            const NAME: &'static str = stringify!($name);
+            const NAME: QueryName = QueryName::$name;
             const CATEGORY: ProfileCategory = $category;
         }
 
@@ -1139,12 +1152,11 @@ pub fn force_from_dep_node<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
     dep_node: &DepNode
 ) -> bool {
-    use crate::hir::def_id::LOCAL_CRATE;
     use crate::dep_graph::RecoverKey;
 
     // We must avoid ever having to call force_from_dep_node() for a
-    // DepNode::CodegenUnit:
-    // Since we cannot reconstruct the query key of a DepNode::CodegenUnit, we
+    // DepNode::codegen_unit:
+    // Since we cannot reconstruct the query key of a DepNode::codegen_unit, we
     // would always end up having to evaluate the first caller of the
     // `codegen_unit` query that *is* reconstructible. This might very well be
     // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
@@ -1155,8 +1167,8 @@ pub fn force_from_dep_node<'tcx>(
     // each CGU, right after partitioning. This way `try_mark_green` will always
     // hit the cache instead of having to go through `force_from_dep_node`.
     // This assertion makes sure, we actually keep applying the solution above.
-    debug_assert!(dep_node.kind != DepKind::CodegenUnit,
-                  "calling force_from_dep_node() on DepKind::CodegenUnit");
+    debug_assert!(dep_node.kind != DepKind::codegen_unit,
+                  "calling force_from_dep_node() on DepKind::codegen_unit");
 
     if !dep_node.kind.can_reconstruct_query_key() {
         return false
@@ -1193,9 +1205,6 @@ pub fn force_from_dep_node<'tcx>(
         ($query:ident, $key:expr) => { force_ex!(tcx, $query, $key) }
     };
 
-    // FIXME(#45015): We should try move this boilerplate code into a macro
-    //                somehow.
-
     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
@@ -1210,223 +1219,11 @@ pub fn force_from_dep_node<'tcx>(
 
         // We don't have enough information to reconstruct the query key of
         // these
-        DepKind::IsCopy |
-        DepKind::IsSized |
-        DepKind::IsFreeze |
-        DepKind::NeedsDrop |
-        DepKind::Layout |
-        DepKind::ConstEval |
-        DepKind::ConstEvalRaw |
-        DepKind::SymbolName |
-        DepKind::MirShim |
-        DepKind::BorrowCheckKrate |
-        DepKind::Specializes |
-        DepKind::ImplementationsOfTrait |
-        DepKind::TypeParamPredicates |
-        DepKind::CodegenUnit |
-        DepKind::CompileCodegenUnit |
-        DepKind::FulfillObligation |
-        DepKind::VtableMethods |
-        DepKind::NormalizeProjectionTy |
-        DepKind::NormalizeTyAfterErasingRegions |
-        DepKind::ImpliedOutlivesBounds |
-        DepKind::DropckOutlives |
-        DepKind::EvaluateObligation |
-        DepKind::EvaluateGoal |
-        DepKind::TypeOpAscribeUserType |
-        DepKind::TypeOpEq |
-        DepKind::TypeOpSubtype |
-        DepKind::TypeOpProvePredicate |
-        DepKind::TypeOpNormalizeTy |
-        DepKind::TypeOpNormalizePredicate |
-        DepKind::TypeOpNormalizePolyFnSig |
-        DepKind::TypeOpNormalizeFnSig |
-        DepKind::SubstituteNormalizeAndTestPredicates |
-        DepKind::MethodAutoderefSteps |
-        DepKind::InstanceDefSizeEstimate => {
+        DepKind::CompileCodegenUnit => {
             bug!("force_from_dep_node() - Encountered {:?}", dep_node)
         }
 
-        // These are not queries
-        DepKind::CoherenceCheckTrait |
-        DepKind::ItemVarianceConstraints => {
-            return false
-        }
-
-        DepKind::RegionScopeTree => { force!(region_scope_tree, def_id!()); }
-
-        DepKind::Coherence => { force!(crate_inherent_impls, LOCAL_CRATE); }
-        DepKind::CoherenceInherentImplOverlapCheck => {
-            force!(crate_inherent_impls_overlap_check, LOCAL_CRATE)
-        },
-        DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
-        DepKind::CheckPrivateInPublic => { force!(check_private_in_public, LOCAL_CRATE); }
-
-        DepKind::BorrowCheck => { force!(borrowck, def_id!()); }
-        DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
-        DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
-        DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); }
-        DepKind::LintMod => { force!(lint_mod, def_id!()); }
-        DepKind::CheckModAttrs => { force!(check_mod_attrs, def_id!()); }
-        DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); }
-        DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); }
-        DepKind::CheckModItemTypes => { force!(check_mod_item_types, def_id!()); }
-        DepKind::CheckModPrivacy => { force!(check_mod_privacy, def_id!()); }
-        DepKind::CheckModIntrinsics => { force!(check_mod_intrinsics, def_id!()); }
-        DepKind::CheckModLiveness => { force!(check_mod_liveness, def_id!()); }
-        DepKind::CheckModImplWf => { force!(check_mod_impl_wf, def_id!()); }
-        DepKind::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); }
-        DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
-        DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
-        DepKind::AssociatedItems => { force!(associated_item, def_id!()); }
-        DepKind::PredicatesDefinedOnItem => { force!(predicates_defined_on, def_id!()); }
-        DepKind::ExplicitPredicatesOfItem => { force!(explicit_predicates_of, def_id!()); }
-        DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
-        DepKind::InferredOutlivesCrate => { force!(inferred_outlives_crate, LOCAL_CRATE); }
-        DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
-        DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
-        DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
-        DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); }
-        DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); }
-        DepKind::Issue33140SelfTy => { force!(issue33140_self_ty, def_id!()); }
-        DepKind::FnSignature => { force!(fn_sig, def_id!()); }
-        DepKind::CoerceUnsizedInfo => { force!(coerce_unsized_info, def_id!()); }
-        DepKind::ItemVariances => { force!(variances_of, def_id!()); }
-        DepKind::IsConstFn => { force!(is_const_fn_raw, def_id!()); }
-        DepKind::IsPromotableConstFn => { force!(is_promotable_const_fn, def_id!()); }
-        DepKind::IsForeignItem => { force!(is_foreign_item, def_id!()); }
-        DepKind::SizedConstraint => { force!(adt_sized_constraint, def_id!()); }
-        DepKind::DtorckConstraint => { force!(adt_dtorck_constraint, def_id!()); }
-        DepKind::AdtDestructor => { force!(adt_destructor, def_id!()); }
-        DepKind::AssociatedItemDefIds => { force!(associated_item_def_ids, def_id!()); }
-        DepKind::InherentImpls => { force!(inherent_impls, def_id!()); }
-        DepKind::TypeckBodiesKrate => { force!(typeck_item_bodies, LOCAL_CRATE); }
-        DepKind::TypeckTables => { force!(typeck_tables_of, def_id!()); }
-        DepKind::UsedTraitImports => { force!(used_trait_imports, def_id!()); }
-        DepKind::HasTypeckTables => { force!(has_typeck_tables, def_id!()); }
-        DepKind::SpecializationGraph => { force!(specialization_graph_of, def_id!()); }
-        DepKind::ObjectSafety => { force!(is_object_safe, def_id!()); }
-        DepKind::TraitImpls => { force!(trait_impls_of, def_id!()); }
-        DepKind::CheckMatch => { force!(check_match, def_id!()); }
-
-        DepKind::ParamEnv => { force!(param_env, def_id!()); }
-        DepKind::DescribeDef => { force!(describe_def, def_id!()); }
-        DepKind::DefSpan => { force!(def_span, def_id!()); }
-        DepKind::LookupStability => { force!(lookup_stability, def_id!()); }
-        DepKind::LookupDeprecationEntry => {
-            force!(lookup_deprecation_entry, def_id!());
-        }
-        DepKind::ConstIsRvaluePromotableToStatic => {
-            force!(const_is_rvalue_promotable_to_static, def_id!());
-        }
-        DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); }
-        DepKind::ImplParent => { force!(impl_parent, def_id!()); }
-        DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
-        DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); }
-        DepKind::IsUnreachableLocalDefinition => {
-            force!(is_unreachable_local_definition, def_id!());
-        }
-        DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
-        DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
-        DepKind::CodegenFnAttrs => { force!(codegen_fn_attrs, def_id!()); }
-        DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
-        DepKind::RenderedConst => { force!(rendered_const, def_id!()); }
-        DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); }
-        DepKind::IsCompilerBuiltins => { force!(is_compiler_builtins, krate!()); }
-        DepKind::HasGlobalAllocator => { force!(has_global_allocator, krate!()); }
-        DepKind::HasPanicHandler => { force!(has_panic_handler, krate!()); }
-        DepKind::ExternCrate => { force!(extern_crate, def_id!()); }
-        DepKind::InScopeTraits => { force!(in_scope_traits_map, def_id!().index); }
-        DepKind::ModuleExports => { force!(module_exports, def_id!()); }
-        DepKind::IsSanitizerRuntime => { force!(is_sanitizer_runtime, krate!()); }
-        DepKind::IsProfilerRuntime => { force!(is_profiler_runtime, krate!()); }
-        DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
-        DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
-        DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
-        DepKind::CheckItemWellFormed => { force!(check_item_well_formed, def_id!()); }
-        DepKind::CheckTraitItemWellFormed => { force!(check_trait_item_well_formed, def_id!()); }
-        DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
-        DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
-        DepKind::EntryFn => { force!(entry_fn, krate!()); }
-        DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
-        DepKind::ProcMacroDeclsStatic => { force!(proc_macro_decls_static, krate!()); }
-        DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); }
-        DepKind::CrateHash => { force!(crate_hash, krate!()); }
-        DepKind::OriginalCrateName => { force!(original_crate_name, krate!()); }
-        DepKind::ExtraFileName => { force!(extra_filename, krate!()); }
         DepKind::Analysis => { force!(analysis, krate!()); }
-
-        DepKind::AllTraitImplementations => {
-            force!(all_trait_implementations, krate!());
-        }
-
-        DepKind::DllimportForeignItems => {
-            force!(dllimport_foreign_items, krate!());
-        }
-        DepKind::IsDllimportForeignItem => {
-            force!(is_dllimport_foreign_item, def_id!());
-        }
-        DepKind::IsStaticallyIncludedForeignItem => {
-            force!(is_statically_included_foreign_item, def_id!());
-        }
-        DepKind::NativeLibraryKind => { force!(native_library_kind, def_id!()); }
-        DepKind::LinkArgs => { force!(link_args, LOCAL_CRATE); }
-
-        DepKind::ResolveLifetimes => { force!(resolve_lifetimes, krate!()); }
-        DepKind::NamedRegion => { force!(named_region_map, def_id!().index); }
-        DepKind::IsLateBound => { force!(is_late_bound_map, def_id!().index); }
-        DepKind::ObjectLifetimeDefaults => {
-            force!(object_lifetime_defaults_map, def_id!().index);
-        }
-
-        DepKind::Visibility => { force!(visibility, def_id!()); }
-        DepKind::DepKind => { force!(dep_kind, krate!()); }
-        DepKind::CrateName => { force!(crate_name, krate!()); }
-        DepKind::ItemChildren => { force!(item_children, def_id!()); }
-        DepKind::ExternModStmtCnum => { force!(extern_mod_stmt_cnum, def_id!()); }
-        DepKind::GetLibFeatures => { force!(get_lib_features, LOCAL_CRATE); }
-        DepKind::DefinedLibFeatures => { force!(defined_lib_features, krate!()); }
-        DepKind::GetLangItems => { force!(get_lang_items, LOCAL_CRATE); }
-        DepKind::DefinedLangItems => { force!(defined_lang_items, krate!()); }
-        DepKind::MissingLangItems => { force!(missing_lang_items, krate!()); }
-        DepKind::VisibleParentMap => { force!(visible_parent_map, LOCAL_CRATE); }
-        DepKind::MissingExternCrateItem => {
-            force!(missing_extern_crate_item, krate!());
-        }
-        DepKind::UsedCrateSource => { force!(used_crate_source, krate!()); }
-        DepKind::PostorderCnums => { force!(postorder_cnums, LOCAL_CRATE); }
-
-        DepKind::Freevars => { force!(freevars, def_id!()); }
-        DepKind::MaybeUnusedTraitImport => {
-            force!(maybe_unused_trait_import, def_id!());
-        }
-        DepKind::NamesImportedByGlobUse => { force!(names_imported_by_glob_use, def_id!()); }
-        DepKind::MaybeUnusedExternCrates => { force!(maybe_unused_extern_crates, LOCAL_CRATE); }
-        DepKind::StabilityIndex => { force!(stability_index, LOCAL_CRATE); }
-        DepKind::AllTraits => { force!(all_traits, LOCAL_CRATE); }
-        DepKind::AllCrateNums => { force!(all_crate_nums, LOCAL_CRATE); }
-        DepKind::ExportedSymbols => { force!(exported_symbols, krate!()); }
-        DepKind::CollectAndPartitionMonoItems => {
-            force!(collect_and_partition_mono_items, LOCAL_CRATE);
-        }
-        DepKind::IsCodegenedItem => { force!(is_codegened_item, def_id!()); }
-        DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
-
-        DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
-
-        DepKind::Features => { force!(features_query, LOCAL_CRATE); }
-
-        DepKind::ForeignModules => { force!(foreign_modules, krate!()); }
-
-        DepKind::UpstreamMonomorphizations => {
-            force!(upstream_monomorphizations, krate!());
-        }
-        DepKind::UpstreamMonomorphizationsFor => {
-            force!(upstream_monomorphizations_for, def_id!());
-        }
-        DepKind::BackendOptimizationLevel => {
-            force!(backend_optimization_level, krate!());
-        }
     );
 
     true
@@ -1479,18 +1276,18 @@ macro_rules! impl_load_from_cache {
 }
 
 impl_load_from_cache!(
-    TypeckTables => typeck_tables_of,
+    typeck_tables_of => typeck_tables_of,
     optimized_mir => optimized_mir,
-    UnsafetyCheckResult => unsafety_check_result,
-    BorrowCheck => borrowck,
-    MirBorrowCheck => mir_borrowck,
+    unsafety_check_result => unsafety_check_result,
+    borrowck => borrowck,
+    mir_borrowck => mir_borrowck,
     mir_const_qualif => mir_const_qualif,
-    ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
-    CheckMatch => check_match,
+    const_is_rvalue_promotable_to_static => const_is_rvalue_promotable_to_static,
+    check_match => check_match,
     type_of => type_of,
     generics_of => generics_of,
     predicates_of => predicates_of,
-    UsedTraitImports => used_trait_imports,
-    CodegenFnAttrs => codegen_fn_attrs,
-    SpecializationGraph => specialization_graph_of,
+    used_trait_imports => used_trait_imports,
+    codegen_fn_attrs => codegen_fn_attrs,
+    specialization_graph_of => specialization_graph_of,
 );
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 4f1fda3f4e5..262dc300334 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -936,7 +936,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind<'tcx>> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
         folder.tcx().intern_projs(&v)
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index 143b5bf3762..58f21893de1 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> TraitDef {
 
     pub fn ancestors(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                      of_impl: DefId)
-                     -> specialization_graph::Ancestors {
+                     -> specialization_graph::Ancestors<'gcx> {
         specialization_graph::ancestors(tcx, self.def_id, of_impl)
     }
 }
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 5622fe43436..26194176350 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -1,11 +1,10 @@
 #![allow(non_camel_case_types)]
 
-use rustc_data_structures::sync::Lock;
+use rustc_data_structures::{fx::FxHashMap, sync::Lock};
 
 use std::cell::{RefCell, Cell};
-use std::collections::HashMap;
 use std::fmt::Debug;
-use std::hash::{Hash, BuildHasher};
+use std::hash::Hash;
 use std::panic;
 use std::env;
 use std::time::{Duration, Instant};
@@ -341,8 +340,8 @@ pub trait MemoizationMap {
         where OP: FnOnce() -> Self::Value;
 }
 
-impl<K, V, S> MemoizationMap for RefCell<HashMap<K,V,S>>
-    where K: Hash+Eq+Clone, V: Clone, S: BuildHasher
+impl<K, V> MemoizationMap for RefCell<FxHashMap<K,V>>
+    where K: Hash+Eq+Clone, V: Clone
 {
     type Key = K;
     type Value = V;
diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs
index 2739a30a291..aabf9a401c6 100644
--- a/src/librustc/util/profiling.rs
+++ b/src/librustc/util/profiling.rs
@@ -1,14 +1,20 @@
 use std::borrow::Cow;
-use std::fs;
-use std::io::{BufWriter, Write};
-use std::mem;
+use std::error::Error;
+use std::mem::{self, Discriminant};
 use std::process;
 use std::thread::ThreadId;
-use std::time::{Duration, Instant, SystemTime};
+use std::u32;
 
-use crate::session::config::Options;
+use crate::ty::query::QueryName;
 
-use rustc_data_structures::fx::FxHashMap;
+use measureme::{StringId, TimestampKind};
+
+/// MmapSerializatioSink is faster on macOS and Linux
+/// but FileSerializationSink is faster on Windows
+#[cfg(not(windows))]
+type Profiler = measureme::Profiler<measureme::MmapSerializationSink>;
+#[cfg(windows)]
+type Profiler = measureme::Profiler<measureme::FileSerializationSink>;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
 pub enum ProfileCategory {
@@ -35,409 +41,129 @@ pub enum ProfilerEvent {
     QueryBlockedEnd { query_name: &'static str, category: ProfileCategory, time: u64 },
 }
 
-impl ProfilerEvent {
-    fn timestamp(&self) -> u64 {
-        use self::ProfilerEvent::*;
-
-        match self {
-            QueryStart { time, .. } |
-            QueryEnd { time, .. } |
-            GenericActivityStart { time, .. } |
-            GenericActivityEnd { time, .. } |
-            QueryCacheHit { time, .. } |
-            QueryCount { time, .. } |
-            IncrementalLoadResultStart { time, .. } |
-            IncrementalLoadResultEnd { time, .. } |
-            QueryBlockedStart { time, .. } |
-            QueryBlockedEnd { time, .. } => *time
-        }
-    }
-}
-
 fn thread_id_to_u64(tid: ThreadId) -> u64 {
     unsafe { mem::transmute::<ThreadId, u64>(tid) }
 }
 
 pub struct SelfProfiler {
-    events: FxHashMap<ThreadId, Vec<ProfilerEvent>>,
-    start_time: SystemTime,
-    start_instant: Instant,
+    profiler: Profiler,
+    query_event_kind: StringId,
+    generic_activity_event_kind: StringId,
+    incremental_load_result_event_kind: StringId,
+    query_blocked_event_kind: StringId,
+    query_cache_hit_event_kind: StringId,
 }
 
 impl SelfProfiler {
-    pub fn new() -> SelfProfiler {
-        let profiler = SelfProfiler {
-            events: Default::default(),
-            start_time: SystemTime::now(),
-            start_instant: Instant::now(),
+    pub fn new() -> Result<SelfProfiler, Box<dyn Error>> {
+        let filename = format!("pid-{}.rustc_profile", process::id());
+        let path = std::path::Path::new(&filename);
+        let profiler = Profiler::new(path)?;
+
+        let query_event_kind = profiler.alloc_string("Query");
+        let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
+        let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult");
+        let query_blocked_event_kind = profiler.alloc_string("QueryBlocked");
+        let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit");
+
+        Ok(SelfProfiler {
+            profiler,
+            query_event_kind,
+            generic_activity_event_kind,
+            incremental_load_result_event_kind,
+            query_blocked_event_kind,
+            query_cache_hit_event_kind,
+        })
+    }
+
+    fn get_query_name_string_id(query_name: QueryName) -> StringId {
+        let discriminant = unsafe {
+            mem::transmute::<Discriminant<QueryName>, u64>(mem::discriminant(&query_name))
         };
 
-        profiler
+        StringId::reserved(discriminant as u32)
+    }
+
+    pub fn register_query_name(&self, query_name: QueryName) {
+        let id = SelfProfiler::get_query_name_string_id(query_name);
+
+        self.profiler.alloc_string_with_reserved_id(id, query_name.as_str());
     }
 
     #[inline]
     pub fn start_activity(
-        &mut self,
-        category: ProfileCategory,
+        &self,
         label: impl Into<Cow<'static, str>>,
     ) {
-        self.record(ProfilerEvent::GenericActivityStart {
-            category,
-            label: label.into(),
-            time: self.get_time_from_start(),
-        })
+        self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::Start);
     }
 
     #[inline]
     pub fn end_activity(
-        &mut self,
-        category: ProfileCategory,
+        &self,
         label: impl Into<Cow<'static, str>>,
     ) {
-        self.record(ProfilerEvent::GenericActivityEnd {
-            category,
-            label: label.into(),
-            time: self.get_time_from_start(),
-        })
+        self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::End);
     }
 
     #[inline]
-    pub fn record_computed_queries(
-        &mut self,
-        query_name: &'static str,
-        category: ProfileCategory,
-        count: usize)
-        {
-        self.record(ProfilerEvent::QueryCount {
-            query_name,
-            category,
-            count,
-            time: self.get_time_from_start(),
-        })
+    pub fn record_query_hit(&self, query_name: QueryName) {
+        self.record_query(query_name, self.query_cache_hit_event_kind, TimestampKind::Instant);
     }
 
     #[inline]
-    pub fn record_query_hit(&mut self, query_name: &'static str, category: ProfileCategory) {
-        self.record(ProfilerEvent::QueryCacheHit {
-            query_name,
-            category,
-            time: self.get_time_from_start(),
-        })
+    pub fn start_query(&self, query_name: QueryName) {
+        self.record_query(query_name, self.query_event_kind, TimestampKind::Start);
     }
 
     #[inline]
-    pub fn start_query(&mut self, query_name: &'static str, category: ProfileCategory) {
-        self.record(ProfilerEvent::QueryStart {
-            query_name,
-            category,
-            time: self.get_time_from_start(),
-        });
+    pub fn end_query(&self, query_name: QueryName) {
+        self.record_query(query_name, self.query_event_kind, TimestampKind::End);
     }
 
     #[inline]
-    pub fn end_query(&mut self, query_name: &'static str, category: ProfileCategory) {
-        self.record(ProfilerEvent::QueryEnd {
+    pub fn incremental_load_result_start(&self, query_name: QueryName) {
+        self.record_query(
             query_name,
-            category,
-            time: self.get_time_from_start(),
-        })
+            self.incremental_load_result_event_kind,
+            TimestampKind::Start
+        );
     }
 
     #[inline]
-    pub fn incremental_load_result_start(&mut self, query_name: &'static str) {
-        self.record(ProfilerEvent::IncrementalLoadResultStart {
-            query_name,
-            time: self.get_time_from_start(),
-        })
+    pub fn incremental_load_result_end(&self, query_name: QueryName) {
+        self.record_query(query_name, self.incremental_load_result_event_kind, TimestampKind::End);
     }
 
     #[inline]
-    pub fn incremental_load_result_end(&mut self, query_name: &'static str) {
-        self.record(ProfilerEvent::IncrementalLoadResultEnd {
-            query_name,
-            time: self.get_time_from_start(),
-        })
-    }
-
-    #[inline]
-    pub fn query_blocked_start(&mut self, query_name: &'static str, category: ProfileCategory) {
-        self.record(ProfilerEvent::QueryBlockedStart {
-            query_name,
-            category,
-            time: self.get_time_from_start(),
-        })
+    pub fn query_blocked_start(&self, query_name: QueryName) {
+        self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::Start);
     }
 
     #[inline]
-    pub fn query_blocked_end(&mut self, query_name: &'static str, category: ProfileCategory) {
-        self.record(ProfilerEvent::QueryBlockedEnd {
-            query_name,
-            category,
-            time: self.get_time_from_start(),
-        })
+    pub fn query_blocked_end(&self, query_name: QueryName) {
+        self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::End);
     }
 
     #[inline]
-    fn record(&mut self, event: ProfilerEvent) {
-        let thread_id = std::thread::current().id();
-        let events = self.events.entry(thread_id).or_default();
+    fn record(&self, event_id: &str, event_kind: StringId, timestamp_kind: TimestampKind) {
+        let thread_id = thread_id_to_u64(std::thread::current().id());
 
-        events.push(event);
+        let event_id = self.profiler.alloc_string(event_id);
+        self.profiler.record_event(event_kind, event_id, thread_id, timestamp_kind);
     }
 
     #[inline]
-    fn get_time_from_start(&self) -> u64 {
-        let duration = Instant::now() - self.start_instant;
-        duration.as_nanos() as u64
-    }
-
-    pub fn dump_raw_events(&self, opts: &Options) {
-        use self::ProfilerEvent::*;
-
-        let pid = process::id();
-
-        let filename =
-            format!("{}.profile_events.json", opts.crate_name.clone().unwrap_or_default());
-
-        let mut file = BufWriter::new(fs::File::create(filename).unwrap());
-
-        let threads: Vec<_> =
-            self.events
-                .keys()
-                .into_iter()
-                .map(|tid| format!("{}", thread_id_to_u64(*tid)))
-                .collect();
-
-        write!(file,
-            "{{\
-                \"processes\": {{\
-                    \"{}\": {{\
-                        \"threads\": [{}],\
-                        \"crate_name\": \"{}\",\
-                        \"opt_level\": \"{:?}\",\
-                        \"incremental\": {}\
-                    }}\
-                }},\
-                \"events\": [\
-             ",
-            pid,
-            threads.join(","),
-            opts.crate_name.clone().unwrap_or_default(),
-            opts.optimize,
-            if opts.incremental.is_some() { "true" } else { "false" },
-        ).unwrap();
-
-        let mut is_first = true;
-        for (thread_id, events) in &self.events {
-            let thread_id = thread_id_to_u64(*thread_id);
-
-            for event in events {
-                if is_first {
-                    is_first = false;
-                } else {
-                    writeln!(file, ",").unwrap();
-                }
-
-                let (secs, nanos) = {
-                    let time = self.start_time + Duration::from_nanos(event.timestamp());
-                    let time_since_unix =
-                        time.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_default();
-                    (time_since_unix.as_secs(), time_since_unix.subsec_nanos())
-                };
+    fn record_query(
+        &self,
+        query_name: QueryName,
+        event_kind: StringId,
+        timestamp_kind: TimestampKind,
+    ) {
+        let dep_node_name = SelfProfiler::get_query_name_string_id(query_name);
 
-                match event {
-                    QueryStart { query_name, category, time: _ } =>
-                        write!(file,
-                            "{{ \
-                                \"QueryStart\": {{ \
-                                    \"query_name\": \"{}\",\
-                                    \"category\": \"{:?}\",\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            query_name,
-                            category,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                    QueryEnd { query_name, category, time: _ } =>
-                        write!(file,
-                            "{{\
-                                \"QueryEnd\": {{\
-                                    \"query_name\": \"{}\",\
-                                    \"category\": \"{:?}\",\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            query_name,
-                            category,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                    GenericActivityStart { category, label, time: _ } =>
-                        write!(file,
-                            "{{
-                                \"GenericActivityStart\": {{\
-                                    \"category\": \"{:?}\",\
-                                    \"label\": \"{}\",\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            category,
-                            label,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                    GenericActivityEnd { category, label, time: _ } =>
-                        write!(file,
-                            "{{\
-                                \"GenericActivityEnd\": {{\
-                                    \"category\": \"{:?}\",\
-                                    \"label\": \"{}\",\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            category,
-                            label,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                    QueryCacheHit { query_name, category, time: _ } =>
-                        write!(file,
-                            "{{\
-                                \"QueryCacheHit\": {{\
-                                    \"query_name\": \"{}\",\
-                                    \"category\": \"{:?}\",\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            query_name,
-                            category,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                    QueryCount { query_name, category, count, time: _ } =>
-                        write!(file,
-                            "{{\
-                                \"QueryCount\": {{\
-                                    \"query_name\": \"{}\",\
-                                    \"category\": \"{:?}\",\
-                                    \"count\": {},\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            query_name,
-                            category,
-                            count,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                    IncrementalLoadResultStart { query_name, time: _ } =>
-                        write!(file,
-                            "{{\
-                                \"IncrementalLoadResultStart\": {{\
-                                    \"query_name\": \"{}\",\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            query_name,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                    IncrementalLoadResultEnd { query_name, time: _ } =>
-                        write!(file,
-                            "{{\
-                                \"IncrementalLoadResultEnd\": {{\
-                                    \"query_name\": \"{}\",\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            query_name,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                    QueryBlockedStart { query_name, category, time: _ } =>
-                        write!(file,
-                            "{{\
-                                \"QueryBlockedStart\": {{\
-                                    \"query_name\": \"{}\",\
-                                    \"category\": \"{:?}\",\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            query_name,
-                            category,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                    QueryBlockedEnd { query_name, category, time: _ } =>
-                        write!(file,
-                            "{{\
-                                \"QueryBlockedEnd\": {{\
-                                    \"query_name\": \"{}\",\
-                                    \"category\": \"{:?}\",\
-                                    \"time\": {{\
-                                        \"secs\": {},\
-                                        \"nanos\": {}\
-                                    }},\
-                                    \"thread_id\": {}\
-                                }}\
-                            }}",
-                            query_name,
-                            category,
-                            secs,
-                            nanos,
-                            thread_id,
-                        ).unwrap(),
-                }
-            }
-        }
+        let thread_id = thread_id_to_u64(std::thread::current().id());
 
-        write!(file, "] }}").unwrap();
+        self.profiler.record_event(event_kind, dep_node_name, thread_id, timestamp_kind);
     }
 }
diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs
index 9d6e728e135..a9e422fb238 100644
--- a/src/librustc_allocator/lib.rs
+++ b/src/librustc_allocator/lib.rs
@@ -2,6 +2,7 @@
 #![feature(rustc_private)]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 pub mod expand;
 
diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml
index 7d9641c83ee..df117de8720 100644
--- a/src/librustc_asan/Cargo.toml
+++ b/src/librustc_asan/Cargo.toml
@@ -12,7 +12,7 @@ test = false
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cmake = "0.1.18"
+cmake = "0.1.38"
 
 [dependencies]
 alloc = { path = "../liballoc" }
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index cf4669db87e..3761a52bccc 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -2,6 +2,7 @@
 
 #![allow(non_camel_case_types)]
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(nll)]
 
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 3a0d9e1334c..348616790b0 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -266,7 +266,8 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
                 OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
             }
             PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => {
-                self.store(bx, next(), dst);
+                let next_arg = next();
+                self.store(bx, next_arg, dst);
             }
         }
     }
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 77fa34e74dd..b15a64c966b 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -104,7 +104,7 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     }
 
     // probestack doesn't play nice either with pgo-gen.
-    if cx.sess().opts.debugging_opts.pgo_gen.is_some() {
+    if cx.sess().opts.debugging_opts.pgo_gen.enabled() {
         return;
     }
 
diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs
index f10bc0516e5..6a3c2adc856 100644
--- a/src/librustc_codegen_llvm/back/link.rs
+++ b/src/librustc_codegen_llvm/back/link.rs
@@ -1014,7 +1014,7 @@ fn link_args(cmd: &mut dyn Linker,
         cmd.build_static_executable();
     }
 
-    if sess.opts.debugging_opts.pgo_gen.is_some() {
+    if sess.opts.debugging_opts.pgo_gen.enabled() {
         cmd.pgo_gen();
     }
 
@@ -1396,10 +1396,6 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
 
     // Same thing as above, but for dynamic crates instead of static crates.
     fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
-        // If we're performing LTO, then it should have been previously required
-        // that all upstream rust dependencies were available in an rlib format.
-        assert!(!are_upstream_rust_objects_already_included(sess));
-
         // Just need to tell the linker about where the library lives and
         // what its name is
         let parent = cratepath.parent();
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 84c652ff238..348f1a12126 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -15,7 +15,6 @@ use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::session::config::{self, Lto};
 use rustc::util::common::time_ext;
-use rustc::util::profiling::ProfileCategory;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
 
@@ -67,8 +66,7 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
         .iter()
         .filter_map(symbol_filter)
         .collect::<Vec<CString>>();
-    let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
-                                       "generate_symbol_white_list_for_thinlto");
+    let _timer = cgcx.profile_activity("generate_symbol_white_list_for_thinlto");
     info!("{} symbols to preserve in this crate", symbol_white_list.len());
 
     // If we're performing LTO for the entire crate graph, then for each of our
@@ -97,8 +95,7 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
         }
 
         for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
-            let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
-                                               format!("load: {}", path.display()));
+            let _timer = cgcx.profile_activity(format!("load: {}", path.display()));
             let exported_symbols = cgcx.exported_symbols
                 .as_ref().expect("needs exported symbols for LTO");
             symbol_white_list.extend(
@@ -727,8 +724,7 @@ pub unsafe fn optimize_thin_module(
         // Like with "fat" LTO, get some better optimizations if landing pads
         // are disabled by removing all landing pads.
         if cgcx.no_landing_pads {
-            let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
-                                               "LLVM_remove_landing_pads");
+            let _timer = cgcx.profile_activity("LLVM_remove_landing_pads");
             llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
             save_temp_bitcode(&cgcx, &module, "thin-lto-after-nounwind");
         }
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 7f259024cee..d803f10746e 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -13,12 +13,11 @@ use crate::LlvmCodegenBackend;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler};
 use rustc_codegen_ssa::traits::*;
-use rustc::session::config::{self, OutputType, Passes, Lto};
+use rustc::session::config::{self, OutputType, Passes, Lto, PgoGenerate};
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_codegen_ssa::{ModuleCodegen, CompiledModule};
 use rustc::util::common::time_ext;
-use rustc::util::profiling::ProfileCategory;
 use rustc_fs_util::{path_to_c_string, link_or_copy};
 use rustc_data_structures::small_c_str::SmallCStr;
 use errors::{Handler, FatalError};
@@ -26,7 +25,7 @@ use errors::{Handler, FatalError};
 use std::ffi::{CString, CStr};
 use std::fs;
 use std::io::{self, Write};
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::str;
 use std::sync::Arc;
 use std::slice;
@@ -73,12 +72,10 @@ pub fn write_output_file(
     unsafe {
         let output_c = path_to_c_string(output);
         let result = llvm::LLVMRustWriteOutputFile(target, pm, m, output_c.as_ptr(), file_type);
-        if result.into_result().is_err() {
+        result.into_result().map_err(|()| {
             let msg = format!("could not write output to {}", output.display());
-            Err(llvm_err(handler, &msg))
-        } else {
-            Ok(())
-        }
+            llvm_err(handler, &msg)
+        })
     }
 }
 
@@ -416,7 +413,7 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
 
         // Finally, run the actual optimization passes
         {
-            let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_function_passes");
+            let _timer = cgcx.profile_activity("LLVM_function_passes");
             time_ext(config.time_passes,
                         None,
                         &format!("llvm function passes [{}]", module_name.unwrap()),
@@ -425,7 +422,7 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
             });
         }
         {
-            let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_module_passes");
+            let _timer = cgcx.profile_activity("LLVM_module_passes");
             time_ext(config.time_passes,
                     None,
                     &format!("llvm module passes [{}]", module_name.unwrap()),
@@ -447,7 +444,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
                   config: &ModuleConfig)
     -> Result<CompiledModule, FatalError>
 {
-    let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "codegen");
+    let _timer = cgcx.profile_activity("codegen");
     {
         let llmod = module.module_llvm.llmod();
         let llcx = &*module.module_llvm.llcx;
@@ -498,29 +495,30 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
 
 
         if write_bc || config.emit_bc_compressed || config.embed_bitcode {
-            let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_make_bitcode");
+            let _timer = cgcx.profile_activity("LLVM_make_bitcode");
             let thin = ThinBuffer::new(llmod);
             let data = thin.data();
 
             if write_bc {
-                let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_bitcode");
+                let _timer = cgcx.profile_activity("LLVM_emit_bitcode");
                 if let Err(e) = fs::write(&bc_out, data) {
-                    diag_handler.err(&format!("failed to write bytecode: {}", e));
+                    let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e);
+                    diag_handler.err(&msg);
                 }
             }
 
             if config.embed_bitcode {
-                let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_embed_bitcode");
+                let _timer = cgcx.profile_activity("LLVM_embed_bitcode");
                 embed_bitcode(cgcx, llcx, llmod, Some(data));
             }
 
             if config.emit_bc_compressed {
-                let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
-                                                   "LLVM_compress_bitcode");
+                let _timer = cgcx.profile_activity("LLVM_compress_bitcode");
                 let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
                 let data = bytecode::encode(&module.name, data);
                 if let Err(e) = fs::write(&dst, data) {
-                    diag_handler.err(&format!("failed to write bytecode: {}", e));
+                    let msg = format!("failed to write bytecode to {}: {}", dst.display(), e);
+                    diag_handler.err(&msg);
                 }
             }
         } else if config.embed_bitcode_marker {
@@ -530,9 +528,9 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
         time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
             || -> Result<(), FatalError> {
             if config.emit_ir {
-                let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_ir");
+                let _timer = cgcx.profile_activity("LLVM_emit_ir");
                 let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
-                let out = path_to_c_string(&out);
+                let out_c = path_to_c_string(&out);
 
                 extern "C" fn demangle_callback(input_ptr: *const c_char,
                                                 input_len: size_t,
@@ -566,13 +564,18 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
                 }
 
                 with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                    llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
+                    let result =
+                        llvm::LLVMRustPrintModule(cpm, llmod, out_c.as_ptr(), demangle_callback);
                     llvm::LLVMDisposePassManager(cpm);
-                });
+                    result.into_result().map_err(|()| {
+                        let msg = format!("failed to write LLVM IR to {}", out.display());
+                        llvm_err(diag_handler, &msg)
+                    })
+                })?;
             }
 
             if config.emit_asm || asm_to_obj {
-                let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_asm");
+                let _timer = cgcx.profile_activity("LLVM_emit_asm");
                 let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
 
                 // We can't use the same module for asm and binary output, because that triggers
@@ -590,13 +593,13 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
             }
 
             if write_obj {
-                let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_obj");
+                let _timer = cgcx.profile_activity("LLVM_emit_obj");
                 with_codegen(tm, llmod, config.no_builtins, |cpm| {
                     write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
                                       llvm::FileType::ObjectFile)
                 })?;
             } else if asm_to_obj {
-                let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_asm_to_obj");
+                let _timer = cgcx.profile_activity("LLVM_asm_to_obj");
                 let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
                 run_assembler(cgcx, diag_handler, &assembly, &obj_out);
 
@@ -703,10 +706,20 @@ pub unsafe fn with_llvm_pmb(llmod: &llvm::Module,
         .unwrap_or(llvm::CodeGenOptSizeNone);
     let inline_threshold = config.inline_threshold;
 
-    let pgo_gen_path = config.pgo_gen.as_ref().map(|s| {
-        let s = if s.is_empty() { "default_%m.profraw" } else { s };
-        CString::new(s.as_bytes()).unwrap()
-    });
+    let pgo_gen_path = match config.pgo_gen {
+        PgoGenerate::Enabled(ref opt_dir_path) => {
+            let path = if let Some(dir_path) = opt_dir_path {
+                dir_path.join("default_%m.profraw")
+            } else {
+                PathBuf::from("default_%m.profraw")
+            };
+
+            Some(CString::new(format!("{}", path.display())).unwrap())
+        }
+        PgoGenerate::Disabled => {
+            None
+        }
+    };
 
     let pgo_use_path = if config.pgo_use.is_empty() {
         None
@@ -790,6 +803,7 @@ fn create_msvc_imps(
     } else {
         "\x01__imp_"
     };
+
     unsafe {
         let i8p_ty = Type::i8p_llcx(llcx);
         let globals = base::iter_globals(llmod)
@@ -797,14 +811,23 @@ fn create_msvc_imps(
                 llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage &&
                     llvm::LLVMIsDeclaration(val) == 0
             })
-            .map(move |val| {
+            .filter_map(|val| {
+                // Exclude some symbols that we know are not Rust symbols.
                 let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
+                if ignored(name.to_bytes()) {
+                    None
+                } else {
+                    Some((val, name))
+                }
+            })
+            .map(move |(val, name)| {
                 let mut imp_name = prefix.as_bytes().to_vec();
                 imp_name.extend(name.to_bytes());
                 let imp_name = CString::new(imp_name).unwrap();
                 (imp_name, val)
             })
             .collect::<Vec<_>>();
+
         for (imp_name, val) in globals {
             let imp = llvm::LLVMAddGlobal(llmod,
                                           i8p_ty,
@@ -813,4 +836,10 @@ fn create_msvc_imps(
             llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
         }
     }
+
+    // Use this function to exclude certain symbols from `__imp` generation.
+    fn ignored(symbol_name: &[u8]) -> bool {
+        // These are symbols generated by LLVM's profiling instrumentation
+        symbol_name.starts_with(b"__llvm_profile_")
+    }
 }
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index e549b120da9..6560ed0a8e6 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -22,6 +22,7 @@ use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def::CtorKind;
 use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
 use rustc::ich::NodeIdHashingMode;
+use rustc::mir::Field;
 use rustc::mir::interpret::truncate;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc::ty::Instance;
@@ -117,6 +118,32 @@ impl TypeMap<'ll, 'tcx> {
         }
     }
 
+    // Removes a Ty to metadata mapping
+    // This is useful when computing the metadata for a potentially
+    // recursive type (e.g. a function ptr of the form:
+    //
+    // fn foo() -> impl Copy { foo }
+    //
+    // This kind of type cannot be properly represented
+    // via LLVM debuginfo. As a workaround,
+    // we register a temporary Ty to metadata mapping
+    // for the function before we compute its actual metadata.
+    // If the metadata computation ends up recursing back to the
+    // original function, it will use the temporary mapping
+    // for the inner self-reference, preventing us from
+    // recursing forever.
+    //
+    // This function is used to remove the temporary metadata
+    // mapping after we've computed the actual metadata
+    fn remove_type(
+        &mut self,
+        type_: Ty<'tcx>,
+    ) {
+        if self.type_to_metadata.remove(type_).is_none() {
+            bug!("Type metadata Ty '{}' is not in the TypeMap!", type_);
+        }
+    }
+
     // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
     // fail if the mapping already exists.
     fn register_unique_id_with_metadata(
@@ -608,10 +635,7 @@ pub fn type_metadata(
             }
         }
         ty::FnDef(..) | ty::FnPtr(_) => {
-            let fn_metadata = subroutine_type_metadata(cx,
-                                                       unique_type_id,
-                                                       t.fn_sig(cx.tcx),
-                                                       usage_site_span).metadata;
+
             if let Some(metadata) = debug_context(cx).type_map
                .borrow()
                .find_metadata_for_unique_id(unique_type_id)
@@ -619,6 +643,41 @@ pub fn type_metadata(
                 return metadata;
             }
 
+            // It's possible to create a self-referential
+            // type in Rust by using 'impl trait':
+            //
+            // fn foo() -> impl Copy { foo }
+            //
+            // See TypeMap::remove_type for more detals
+            // about the workaround
+
+            let temp_type = {
+                unsafe {
+                    // The choice of type here is pretty arbitrary -
+                    // anything reading the debuginfo for a recursive
+                    // type is going to see *somthing* weird - the only
+                    // question is what exactly it will see
+                    let (size, align) = cx.size_and_align_of(t);
+                    llvm::LLVMRustDIBuilderCreateBasicType(
+                        DIB(cx),
+                        SmallCStr::new("<recur_type>").as_ptr(),
+                        size.bits(),
+                        align.bits() as u32,
+                        DW_ATE_unsigned)
+                }
+            };
+
+            let type_map = &debug_context(cx).type_map;
+            type_map.borrow_mut().register_type_with_metadata(t, temp_type);
+
+            let fn_metadata = subroutine_type_metadata(cx,
+                                                       unique_type_id,
+                                                       t.fn_sig(cx.tcx),
+                                                       usage_site_span).metadata;
+
+            type_map.borrow_mut().remove_type(t);
+
+
             // This is actually a function pointer, so wrap it in pointer DI
             MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
 
@@ -1248,12 +1307,15 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
             }
             layout::Variants::Multiple {
                 discr_kind: layout::DiscriminantKind::Tag,
+                discr_index,
                 ref variants,
                 ..
             } => {
                 let discriminant_info = if fallback {
-                    RegularDiscriminant(self.discriminant_type_metadata
-                                        .expect(""))
+                    RegularDiscriminant {
+                        discr_field: Field::from(discr_index),
+                        discr_type_metadata: self.discriminant_type_metadata.unwrap()
+                    }
                 } else {
                     // This doesn't matter in this case.
                     NoDiscriminant
@@ -1300,6 +1362,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                 },
                 ref discr,
                 ref variants,
+                discr_index,
             } => {
                 if fallback {
                     let variant = self.layout.for_variant(cx, dataful_variant);
@@ -1345,8 +1408,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                     }
                     compute_field_path(cx, &mut name,
                                        self.layout,
-                                       self.layout.fields.offset(0),
-                                       self.layout.field(cx, 0).size);
+                                       self.layout.fields.offset(discr_index),
+                                       self.layout.field(cx, discr_index).size);
                     name.push_str(&adt.variants[*niche_variants.start()].ident.as_str());
 
                     // Create the (singleton) list of descriptions of union members.
@@ -1428,6 +1491,8 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
                 name: name.to_string(),
                 type_metadata: if use_enum_fallback(cx) {
                     match self.discriminant_type_metadata {
+                        // Discriminant is always the first field of our variant
+                        // when using the enum fallback.
                         Some(metadata) if i == 0 => metadata,
                         _ => type_metadata(cx, ty, self.span)
                     }
@@ -1446,7 +1511,7 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
 
 #[derive(Copy, Clone)]
 enum EnumDiscriminantInfo<'ll> {
-    RegularDiscriminant(&'ll DIType),
+    RegularDiscriminant{ discr_field: Field, discr_type_metadata: &'ll DIType },
     OptimizedDiscriminant,
     NoDiscriminant
 }
@@ -1477,15 +1542,26 @@ fn describe_enum_variant(
                                            unique_type_id,
                                            Some(containing_scope));
 
+    let arg_name = |i: usize| {
+        if variant.ctor_kind == CtorKind::Fn {
+            format!("__{}", i)
+        } else {
+            variant.fields[i].ident.to_string()
+        }
+    };
+
     // Build an array of (field name, field type) pairs to be captured in the factory closure.
     let (offsets, args) = if use_enum_fallback(cx) {
         // If this is not a univariant enum, there is also the discriminant field.
         let (discr_offset, discr_arg) = match discriminant_info {
-            RegularDiscriminant(_) => {
+            RegularDiscriminant { discr_field, .. } => {
                 // We have the layout of an enum variant, we need the layout of the outer enum
                 let enum_layout = cx.layout_of(layout.ty);
-                (Some(enum_layout.fields.offset(0)),
-                 Some(("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, 0).ty)))
+                let offset = enum_layout.fields.offset(discr_field.as_usize());
+                let args = (
+                    "RUST$ENUM$DISR".to_owned(),
+                    enum_layout.field(cx, discr_field.as_usize()).ty);
+                (Some(offset), Some(args))
             }
             _ => (None, None),
         };
@@ -1494,12 +1570,7 @@ fn describe_enum_variant(
                 layout.fields.offset(i)
             })).collect(),
             discr_arg.into_iter().chain((0..layout.fields.count()).map(|i| {
-                let name = if variant.ctor_kind == CtorKind::Fn {
-                    format!("__{}", i)
-                } else {
-                    variant.fields[i].ident.to_string()
-                };
-                (name, layout.field(cx, i).ty)
+                (arg_name(i), layout.field(cx, i).ty)
             })).collect()
         )
     } else {
@@ -1508,12 +1579,7 @@ fn describe_enum_variant(
                 layout.fields.offset(i)
             }).collect(),
             (0..layout.fields.count()).map(|i| {
-                let name = if variant.ctor_kind == CtorKind::Fn {
-                    format!("__{}", i)
-                } else {
-                    variant.fields[i].ident.to_string()
-                };
-                (name, layout.field(cx, i).ty)
+                (arg_name(i), layout.field(cx, i).ty)
             }).collect()
         )
     };
@@ -1523,8 +1589,8 @@ fn describe_enum_variant(
             offsets,
             args,
             discriminant_type_metadata: match discriminant_info {
-                RegularDiscriminant(discriminant_type_metadata) => {
-                    Some(discriminant_type_metadata)
+                RegularDiscriminant { discr_type_metadata, .. } => {
+                    Some(discr_type_metadata)
                 }
                 _ => None
             },
@@ -1674,6 +1740,7 @@ fn prepare_enum_metadata(
         layout::Variants::Multiple {
             discr_kind: layout::DiscriminantKind::Niche { .. },
             ref discr,
+            discr_index,
             ..
         } => {
             // Find the integer type of the correct size.
@@ -1697,7 +1764,7 @@ fn prepare_enum_metadata(
                     UNKNOWN_LINE_NUMBER,
                     size.bits(),
                     align.abi.bits() as u32,
-                    layout.fields.offset(0).bits(),
+                    layout.fields.offset(discr_index).bits(),
                     DIFlags::FlagArtificial,
                     discr_metadata))
             }
@@ -1706,6 +1773,7 @@ fn prepare_enum_metadata(
         layout::Variants::Multiple {
             discr_kind: layout::DiscriminantKind::Tag,
             ref discr,
+            discr_index,
             ..
         } => {
             let discr_type = discr.value.to_ty(cx.tcx);
@@ -1721,7 +1789,7 @@ fn prepare_enum_metadata(
                     UNKNOWN_LINE_NUMBER,
                     size.bits(),
                     align.bits() as u32,
-                    layout.fields.offset(0).bits(),
+                    layout.fields.offset(discr_index).bits(),
                     DIFlags::FlagArtificial,
                     discr_metadata))
             }
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 6abbcd9feba..57e4ac07d5e 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -296,12 +296,6 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
         let mut flags = DIFlags::FlagPrototyped;
 
-        if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
-            if id == def_id {
-                flags |= DIFlags::FlagMainSubprogram;
-            }
-        }
-
         if self.layout_of(sig.output()).abi.is_uninhabited() {
             flags |= DIFlags::FlagNoReturn;
         }
@@ -313,6 +307,11 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         if self.sess().opts.optimize != config::OptLevel::No {
             spflags |= DISPFlags::SPFlagOptimized;
         }
+        if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
+            if id == def_id {
+                spflags |= DISPFlags::SPFlagMainSubprogram;
+            }
+        }
 
         let fn_metadata = unsafe {
             llvm::LLVMRustDIBuilderCreateFunction(
diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs
index 8b218ab39d9..eff7cd1bc8a 100644
--- a/src/librustc_codegen_llvm/debuginfo/type_names.rs
+++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs
@@ -5,6 +5,7 @@ use rustc::hir::def_id::DefId;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty};
 use rustc_codegen_ssa::traits::*;
+use rustc_data_structures::fx::FxHashSet;
 
 use rustc::hir;
 
@@ -17,7 +18,8 @@ pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                              qualified: bool)
                                              -> String {
     let mut result = String::with_capacity(64);
-    push_debuginfo_type_name(cx, t, qualified, &mut result);
+    let mut visited = FxHashSet::default();
+    push_debuginfo_type_name(cx, t, qualified, &mut result, &mut visited);
     result
 }
 
@@ -26,7 +28,9 @@ pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                           t: Ty<'tcx>,
                                           qualified: bool,
-                                          output: &mut String) {
+                                          output: &mut String,
+                                          visited: &mut FxHashSet<Ty<'tcx>>) {
+
     // When targeting MSVC, emit C++ style type names for compatibility with
     // .natvis visualizers (and perhaps other existing native debuggers?)
     let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
@@ -42,12 +46,12 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::Foreign(def_id) => push_item_name(cx, def_id, qualified, output),
         ty::Adt(def, substs) => {
             push_item_name(cx, def.did, qualified, output);
-            push_type_params(cx, substs, output);
+            push_type_params(cx, substs, output, visited);
         },
         ty::Tuple(component_types) => {
             output.push('(');
             for &component_type in component_types {
-                push_debuginfo_type_name(cx, component_type, true, output);
+                push_debuginfo_type_name(cx, component_type, true, output, visited);
                 output.push_str(", ");
             }
             if !component_types.is_empty() {
@@ -65,7 +69,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 hir::MutMutable => output.push_str("mut "),
             }
 
-            push_debuginfo_type_name(cx, inner_type, true, output);
+            push_debuginfo_type_name(cx, inner_type, true, output, visited);
 
             if cpp_like_names {
                 output.push('*');
@@ -79,7 +83,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 output.push_str("mut ");
             }
 
-            push_debuginfo_type_name(cx, inner_type, true, output);
+            push_debuginfo_type_name(cx, inner_type, true, output, visited);
 
             if cpp_like_names {
                 output.push('*');
@@ -87,7 +91,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         },
         ty::Array(inner_type, len) => {
             output.push('[');
-            push_debuginfo_type_name(cx, inner_type, true, output);
+            push_debuginfo_type_name(cx, inner_type, true, output, visited);
             output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
             output.push(']');
         },
@@ -98,7 +102,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 output.push('[');
             }
 
-            push_debuginfo_type_name(cx, inner_type, true, output);
+            push_debuginfo_type_name(cx, inner_type, true, output, visited);
 
             if cpp_like_names {
                 output.push('>');
@@ -113,12 +117,31 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                     &principal,
                 );
                 push_item_name(cx, principal.def_id, false, output);
-                push_type_params(cx, principal.substs, output);
+                push_type_params(cx, principal.substs, output, visited);
             } else {
                 output.push_str("dyn '_");
             }
         },
         ty::FnDef(..) | ty::FnPtr(_) => {
+            // We've encountered a weird 'recursive type'
+            // Currently, the only way to generate such a type
+            // is by using 'impl trait':
+            //
+            // fn foo() -> impl Copy { foo }
+            //
+            // There's not really a sensible name we can generate,
+            // since we don't include 'impl trait' types (e.g. ty::Opaque)
+            // in the output
+            //
+            // Since we need to generate *something*, we just
+            // use a dummy string that should make it clear
+            // that something unusual is going on
+            if !visited.insert(t) {
+                output.push_str("<recursive_type>");
+                return;
+            }
+
+
             let sig = t.fn_sig(cx.tcx);
             if sig.unsafety() == hir::Unsafety::Unsafe {
                 output.push_str("unsafe ");
@@ -136,7 +159,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
             if !sig.inputs().is_empty() {
                 for &parameter_type in sig.inputs() {
-                    push_debuginfo_type_name(cx, parameter_type, true, output);
+                    push_debuginfo_type_name(cx, parameter_type, true, output, visited);
                     output.push_str(", ");
                 }
                 output.pop();
@@ -155,8 +178,20 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
             if !sig.output().is_unit() {
                 output.push_str(" -> ");
-                push_debuginfo_type_name(cx, sig.output(), true, output);
+                push_debuginfo_type_name(cx, sig.output(), true, output, visited);
             }
+
+
+            // We only keep the type in 'visited'
+            // for the duration of the body of this method.
+            // It's fine for a particular function type
+            // to show up multiple times in one overall type
+            // (e.g. MyType<fn() -> u8, fn() -> u8>
+            //
+            // We only care about avoiding recursing
+            // directly back to the type we're currently
+            // processing
+            visited.remove(t);
         },
         ty::Closure(..) => {
             output.push_str("closure");
@@ -200,7 +235,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     // common denominator - otherwise we would run into conflicts.
     fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                   substs: SubstsRef<'tcx>,
-                                  output: &mut String) {
+                                  output: &mut String,
+                                  visited: &mut FxHashSet<Ty<'tcx>>) {
         if substs.types().next().is_none() {
             return;
         }
@@ -208,7 +244,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         output.push('<');
 
         for type_parameter in substs.types() {
-            push_debuginfo_type_name(cx, type_parameter, true, output);
+            push_debuginfo_type_name(cx, type_parameter, true, output, visited);
             output.push_str(", ");
         }
 
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 0aae6b46e3d..da91217e95e 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -65,7 +65,6 @@ use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
 use rustc::session::Session;
 use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel};
 use rustc::ty::{self, TyCtxt};
-use rustc::util::profiling::ProfileCategory;
 use rustc::util::common::ErrorReported;
 use rustc_mir::monomorphize;
 use rustc_codegen_ssa::ModuleCodegen;
@@ -330,12 +329,12 @@ impl CodegenBackend for LlvmCodegenBackend {
 
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
-        sess.profiler(|p| p.start_activity(ProfileCategory::Linking, "link_crate"));
+        sess.profiler(|p| p.start_activity("link_crate"));
         time(sess, "linking", || {
             back::link::link_binary(sess, &codegen_results,
                                     outputs, &codegen_results.crate_name.as_str());
         });
-        sess.profiler(|p| p.end_activity(ProfileCategory::Linking, "link_crate"));
+        sess.profiler(|p| p.end_activity("link_crate"));
 
         // Now that we won't touch anything in the incremental compilation directory
         // any more, we can finalize it (which involves renaming it)
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 2ad6d9c053a..f6ee8bec16a 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -588,7 +588,6 @@ pub mod debuginfo {
             const FlagIntroducedVirtual   = (1 << 18);
             const FlagBitField            = (1 << 19);
             const FlagNoReturn            = (1 << 20);
-            const FlagMainSubprogram      = (1 << 21);
         }
     }
 
@@ -603,6 +602,7 @@ pub mod debuginfo {
             const SPFlagLocalToUnit       = (1 << 2);
             const SPFlagDefinition        = (1 << 3);
             const SPFlagOptimized         = (1 << 4);
+            const SPFlagMainSubprogram    = (1 << 5);
         }
     }
 
@@ -1687,7 +1687,8 @@ extern "C" {
                                Demangle: extern fn(*const c_char,
                                                    size_t,
                                                    *mut c_char,
-                                                   size_t) -> size_t);
+                                                   size_t) -> size_t,
+                               ) -> LLVMRustResult;
     pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
     pub fn LLVMRustPrintPasses();
     pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs
index 020447608ee..d42fa829161 100644
--- a/src/librustc_codegen_llvm/type_of.rs
+++ b/src/librustc_codegen_llvm/type_of.rs
@@ -452,31 +452,27 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
 
             _ => {
                 let mut data_variant = match self.variants {
+                    // Within the discriminant field, only the niche itself is
+                    // always initialized, so we only check for a pointer at its
+                    // offset.
+                    //
+                    // If the niche is a pointer, it's either valid (according
+                    // to its type), or null (which the niche field's scalar
+                    // validity range encodes).  This allows using
+                    // `dereferenceable_or_null` for e.g., `Option<&T>`, and
+                    // this will continue to work as long as we don't start
+                    // using more niches than just null (e.g., the first page of
+                    // the address space, or unaligned pointers).
                     layout::Variants::Multiple {
                         discr_kind: layout::DiscriminantKind::Niche {
                             dataful_variant,
                             ..
                         },
+                        discr_index,
                         ..
-                    } => {
-                        // Only the niche itself is always initialized,
-                        // so only check for a pointer at its offset.
-                        //
-                        // If the niche is a pointer, it's either valid
-                        // (according to its type), or null (which the
-                        // niche field's scalar validity range encodes).
-                        // This allows using `dereferenceable_or_null`
-                        // for e.g., `Option<&T>`, and this will continue
-                        // to work as long as we don't start using more
-                        // niches than just null (e.g., the first page
-                        // of the address space, or unaligned pointers).
-                        if self.fields.offset(0) == offset {
-                            Some(self.for_variant(cx, dataful_variant))
-                        } else {
-                            None
-                        }
-                    }
-                    _ => Some(*self)
+                    } if self.fields.offset(discr_index) == offset =>
+                        Some(self.for_variant(cx, dataful_variant)),
+                    _ => Some(*self),
                 };
 
                 if let Some(variant) = data_variant {
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 336f41b784a..a55f783df43 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -209,7 +209,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
-    if tcx.sess.opts.debugging_opts.pgo_gen.is_some() {
+    if tcx.sess.opts.debugging_opts.pgo_gen.enabled() {
         // These are weak symbols that point to the profile version and the
         // profile name, which need to be treated as exported so LTO doesn't nix
         // them.
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index fa8c4177eaf..4b02425d40d 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -12,13 +12,14 @@ use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir,
 use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind};
 use rustc::dep_graph::cgu_reuse_tracker::CguReuseTracker;
 use rustc::middle::cstore::EncodedMetadata;
-use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto};
+use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Lto,
+                             Sanitizer, PgoGenerate};
 use rustc::session::Session;
 use rustc::util::nodemap::FxHashMap;
 use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc::ty::TyCtxt;
 use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry};
-use rustc::util::profiling::{ProfileCategory, SelfProfiler};
+use rustc::util::profiling::SelfProfiler;
 use rustc_fs_util::link_or_copy;
 use rustc_data_structures::svh::Svh;
 use rustc_errors::{Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
@@ -29,7 +30,6 @@ use syntax::ext::hygiene::Mark;
 use syntax_pos::MultiSpan;
 use syntax_pos::symbol::Symbol;
 use jobserver::{Client, Acquired};
-use parking_lot::Mutex as PlMutex;
 
 use std::any::Any;
 use std::borrow::Cow;
@@ -56,7 +56,7 @@ pub struct ModuleConfig {
     /// Some(level) to optimize binary size, or None to not affect program size.
     pub opt_size: Option<config::OptLevel>,
 
-    pub pgo_gen: Option<String>,
+    pub pgo_gen: PgoGenerate,
     pub pgo_use: String,
 
     // Flags indicating which outputs to produce.
@@ -94,7 +94,7 @@ impl ModuleConfig {
             opt_level: None,
             opt_size: None,
 
-            pgo_gen: None,
+            pgo_gen: PgoGenerate::Disabled,
             pgo_use: String::new(),
 
             emit_no_opt_bc: false,
@@ -198,25 +198,21 @@ impl<B: WriteBackendMethods> Clone for TargetMachineFactory<B> {
 }
 
 pub struct ProfileGenericActivityTimer {
-    profiler: Option<Arc<PlMutex<SelfProfiler>>>,
-    category: ProfileCategory,
+    profiler: Option<Arc<SelfProfiler>>,
     label: Cow<'static, str>,
 }
 
 impl ProfileGenericActivityTimer {
     pub fn start(
-        profiler: Option<Arc<PlMutex<SelfProfiler>>>,
-        category: ProfileCategory,
+        profiler: Option<Arc<SelfProfiler>>,
         label: Cow<'static, str>,
     ) -> ProfileGenericActivityTimer {
         if let Some(profiler) = &profiler {
-            let mut p = profiler.lock();
-            p.start_activity(category, label.clone());
+            profiler.start_activity(label.clone());
         }
 
         ProfileGenericActivityTimer {
             profiler,
-            category,
             label,
         }
     }
@@ -225,8 +221,7 @@ impl ProfileGenericActivityTimer {
 impl Drop for ProfileGenericActivityTimer {
     fn drop(&mut self) {
         if let Some(profiler) = &self.profiler {
-            let mut p = profiler.lock();
-            p.end_activity(self.category, self.label.clone());
+            profiler.end_activity(self.label.clone());
         }
     }
 }
@@ -237,7 +232,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     // Resources needed when running LTO
     pub backend: B,
     pub time_passes: bool,
-    pub profiler: Option<Arc<PlMutex<SelfProfiler>>>,
+    pub profiler: Option<Arc<SelfProfiler>>,
     pub lto: Lto,
     pub no_landing_pads: bool,
     pub save_temps: bool,
@@ -291,19 +286,17 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
 
     #[inline(never)]
     #[cold]
-    fn profiler_active<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
+    fn profiler_active<F: FnOnce(&SelfProfiler) -> ()>(&self, f: F) {
         match &self.profiler {
             None => bug!("profiler_active() called but there was no profiler active"),
             Some(profiler) => {
-                let mut p = profiler.lock();
-
-                f(&mut p);
+                f(&*profiler);
             }
         }
     }
 
     #[inline(always)]
-    pub fn profile<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
+    pub fn profile<F: FnOnce(&SelfProfiler) -> ()>(&self, f: F) {
         if unlikely!(self.profiler.is_some()) {
             self.profiler_active(f)
         }
@@ -311,10 +304,9 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
 
     pub fn profile_activity(
         &self,
-        category: ProfileCategory,
         label: impl Into<Cow<'static, str>>,
     ) -> ProfileGenericActivityTimer {
-        ProfileGenericActivityTimer::start(self.profiler.clone(), category, label.into())
+        ProfileGenericActivityTimer::start(self.profiler.clone(), label.into())
     }
 }
 
@@ -324,7 +316,7 @@ fn generate_lto_work<B: ExtraBackendMethods>(
     needs_thin_lto: Vec<(String, B::ThinBuffer)>,
     import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>
 ) -> Vec<(WorkItem<B>, u64)> {
-    cgcx.profile(|p| p.start_activity(ProfileCategory::Linking, "codegen_run_lto"));
+    cgcx.profile(|p| p.start_activity("codegen_run_lto"));
 
     let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() {
         assert!(needs_thin_lto.is_empty());
@@ -351,7 +343,7 @@ fn generate_lto_work<B: ExtraBackendMethods>(
         }), 0)
     })).collect();
 
-    cgcx.profile(|p| p.end_activity(ProfileCategory::Linking, "codegen_run_lto"));
+    cgcx.profile(|p| p.end_activity("codegen_run_lto"));
 
     result
 }
@@ -1655,9 +1647,9 @@ fn spawn_work<B: ExtraBackendMethods>(
         // surface that there was an error in this worker.
         bomb.result = {
             let label = work.name();
-            cgcx.profile(|p| p.start_activity(ProfileCategory::Codegen, label.clone()));
+            cgcx.profile(|p| p.start_activity(label.clone()));
             let result = execute_work_item(&cgcx, work).ok();
-            cgcx.profile(|p| p.end_activity(ProfileCategory::Codegen, label));
+            cgcx.profile(|p| p.end_activity(label));
 
             result
         };
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 27e3e306699..6cb54831a07 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -25,7 +25,6 @@ use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
 use rustc::ty::query::Providers;
 use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::util::common::{time, print_time_passes_entry};
-use rustc::util::profiling::ProfileCategory;
 use rustc::session::config::{self, EntryFnType, Lto};
 use rustc::session::Session;
 use rustc_mir::monomorphize::item::DefPathBasedNames;
@@ -539,7 +538,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
 
     // Codegen the metadata.
-    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen, "codegen crate metadata"));
+    tcx.sess.profiler(|p| p.start_activity("codegen crate metadata"));
 
     let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE,
                                                             &["crate"],
@@ -549,7 +548,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     let metadata = time(tcx.sess, "write metadata", || {
         backend.write_metadata(tcx, &mut metadata_llvm_module)
     });
-    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen, "codegen crate metadata"));
+    tcx.sess.profiler(|p| p.end_activity("codegen crate metadata"));
 
     let metadata_module = ModuleCodegen {
         name: metadata_cgu_name,
@@ -662,14 +661,12 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
 
         match cgu_reuse {
             CguReuse::No => {
-                tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen,
-                                                       format!("codegen {}", cgu.name())));
+                tcx.sess.profiler(|p| p.start_activity(format!("codegen {}", cgu.name())));
                 let start_time = Instant::now();
                 let stats = backend.compile_codegen_unit(tcx, *cgu.name());
                 all_stats.extend(stats);
                 total_codegen_time += start_time.elapsed();
-                tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen,
-                                                     format!("codegen {}", cgu.name())));
+                tcx.sess.profiler(|p| p.end_activity(format!("codegen {}", cgu.name())));
                 false
             }
             CguReuse::PreLto => {
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 1e898ced7a6..e2917578c0e 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -14,6 +14,7 @@
 #![allow(unused_attributes)]
 #![allow(dead_code)]
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(explicit_outlives_requirements)]
 
 #![recursion_limit="256"]
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index facae9a9797..8253a167245 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -172,14 +172,14 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
                 // ZSTs don't require any actual memory access.
                 let elem_ty = base_ty
                     .projection_ty(cx.tcx(), &proj.elem)
-                    .to_ty(cx.tcx());
+                    .ty;
                 let elem_ty = self.fx.monomorphize(&elem_ty);
                 if cx.layout_of(elem_ty).is_zst() {
                     return;
                 }
 
                 if let mir::ProjectionElem::Field(..) = proj.elem {
-                    let layout = cx.layout_of(base_ty.to_ty(cx.tcx()));
+                    let layout = cx.layout_of(base_ty.ty);
                     if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
                         // Recurse with the same context, instead of `Projection`,
                         // potentially stopping at non-operand projections,
@@ -247,7 +247,7 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
             PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
                 let ty = mir::Place::Base(mir::PlaceBase::Local(local)).ty(self.fx.mir,
                                                                            self.fx.cx.tcx());
-                let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx()));
+                let ty = self.fx.monomorphize(&ty.ty);
 
                 // Only need the place if we're actually dropping it.
                 if self.fx.cx.type_needs_drop(ty) {
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 26442faa321..e64c847db65 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -2,7 +2,7 @@ use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
 use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
-use rustc::mir::interpret::EvalErrorKind;
+use rustc::mir::interpret::InterpError;
 use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
 use rustc_target::spec::abi::Abi;
 use rustc_mir::monomorphize;
@@ -238,6 +238,13 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
         }
+        if self.fn_ty.ret.layout.abi.is_uninhabited() {
+            // Functions with uninhabited return values are marked `noreturn`,
+            // so we should make sure that we never actually do.
+            bx.abort();
+            bx.unreachable();
+            return;
+        }
         let llval = match self.fn_ty.ret.mode {
             PassMode::Ignore(IgnoreMode::Zst) | PassMode::Indirect(..) => {
                 bx.ret_void();
@@ -301,7 +308,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         target: mir::BasicBlock,
         unwind: Option<mir::BasicBlock>,
     ) {
-        let ty = location.ty(self.mir, bx.tcx()).to_ty(bx.tcx());
+        let ty = location.ty(self.mir, bx.tcx()).ty;
         let ty = self.monomorphize(&ty);
         let drop_fn = monomorphize::resolve_drop_in_place(bx.tcx(), ty);
 
@@ -365,7 +372,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // checked operation, just a comparison with the minimum
         // value, so we have to check for the assert message.
         if !bx.check_overflow() {
-            if let mir::interpret::EvalErrorKind::OverflowNeg = *msg {
+            if let mir::interpret::InterpError::OverflowNeg = *msg {
                 const_cond = Some(expected);
             }
         }
@@ -400,7 +407,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         // Put together the arguments to the panic entry point.
         let (lang_item, args) = match *msg {
-            EvalErrorKind::BoundsCheck { ref len, ref index } => {
+            InterpError::BoundsCheck { ref len, ref index } => {
                 let len = self.codegen_operand(&mut bx, len).immediate();
                 let index = self.codegen_operand(&mut bx, index).immediate();
 
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 9ed7e26729f..1134707f96c 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -216,19 +216,19 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
         if self.layout.abi.is_uninhabited() {
             return bx.cx().const_undef(cast_to);
         }
-        let (discr_scalar, discr_kind) = match self.layout.variants {
+        let (discr_scalar, discr_kind, discr_index) = match self.layout.variants {
             layout::Variants::Single { index } => {
                 let discr_val = self.layout.ty.ty_adt_def().map_or(
                     index.as_u32() as u128,
                     |def| def.discriminant_for_variant(bx.cx().tcx(), index).val);
                 return bx.cx().const_uint_big(cast_to, discr_val);
             }
-            layout::Variants::Multiple { ref discr, ref discr_kind, .. } => {
-                (discr, discr_kind)
+            layout::Variants::Multiple { ref discr, ref discr_kind, discr_index, .. } => {
+                (discr, discr_kind, discr_index)
             }
         };
 
-        let discr = self.project_field(bx, 0);
+        let discr = self.project_field(bx, discr_index);
         let lldiscr = bx.load_operand(discr).immediate();
         match *discr_kind {
             layout::DiscriminantKind::Tag => {
@@ -292,9 +292,10 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
             }
             layout::Variants::Multiple {
                 discr_kind: layout::DiscriminantKind::Tag,
+                discr_index,
                 ..
             } => {
-                let ptr = self.project_field(bx, 0);
+                let ptr = self.project_field(bx, discr_index);
                 let to = self.layout.ty.ty_adt_def().unwrap()
                     .discriminant_for_variant(bx.tcx(), variant_index)
                     .val;
@@ -309,6 +310,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
                     ref niche_variants,
                     niche_start,
                 },
+                discr_index,
                 ..
             } => {
                 if variant_index != dataful_variant {
@@ -321,7 +323,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
                         bx.memset(self.llval, fill_byte, size, self.align, MemFlags::empty());
                     }
 
-                    let niche = self.project_field(bx, 0);
+                    let niche = self.project_field(bx, discr_index);
                     let niche_llty = bx.cx().immediate_backend_type(niche.layout);
                     let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
                     let niche_value = (niche_value as u128)
@@ -494,8 +496,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     mir::ProjectionElem::Subslice { from, to } => {
                         let mut subslice = cg_base.project_index(bx,
                             bx.cx().const_usize(from as u64));
-                        let projected_ty = PlaceTy::Ty { ty: cg_base.layout.ty }
-                            .projection_ty(tcx, &projection.elem).to_ty(tcx);
+                        let projected_ty = PlaceTy::from_ty(cg_base.layout.ty)
+                            .projection_ty(tcx, &projection.elem).ty;
                         subslice.layout = bx.cx().layout_of(self.monomorphize(&projected_ty));
 
                         if subslice.layout.is_unsized() {
@@ -523,6 +525,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn monomorphized_place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
         let tcx = self.cx.tcx();
         let place_ty = place.ty(self.mir, tcx);
-        self.monomorphize(&place_ty.to_ty(tcx))
+        self.monomorphize(&place_ty.ty)
     }
 }
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index 97729e8aeb3..618d05245d2 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -68,13 +68,13 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
                 bx
             }
-            mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
-                let outputs = outputs.iter().map(|output| {
+            mir::StatementKind::InlineAsm(ref asm) => {
+                let outputs = asm.outputs.iter().map(|output| {
                     self.codegen_place(&mut bx, output)
                 }).collect();
 
-                let input_vals = inputs.iter()
-                    .fold(Vec::with_capacity(inputs.len()), |mut acc, (span, input)| {
+                let input_vals = asm.inputs.iter()
+                    .fold(Vec::with_capacity(asm.inputs.len()), |mut acc, (span, input)| {
                         let op = self.codegen_operand(&mut bx, input);
                         if let OperandValue::Immediate(_) = op.val {
                             acc.push(op.immediate());
@@ -85,8 +85,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         acc
                 });
 
-                if input_vals.len() == inputs.len() {
-                    let res = bx.codegen_inline_asm(asm, outputs, input_vals);
+                if input_vals.len() == asm.inputs.len() {
+                    let res = bx.codegen_inline_asm(&asm.asm, outputs, input_vals);
                     if !res {
                         span_err!(bx.sess(), statement.source_info.span, E0668,
                                   "malformed inline assembly");
diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs
index 1a3914e6ef4..330cfe154e3 100644
--- a/src/librustc_codegen_utils/lib.rs
+++ b/src/librustc_codegen_utils/lib.rs
@@ -16,6 +16,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use]
 extern crate rustc;
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 63e44d82a28..d586b376d45 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -12,7 +12,7 @@ crate-type = ["dylib"]
 [dependencies]
 ena = "0.13"
 log = "0.4"
-jobserver_crate = { version = "0.1", package = "jobserver" }
+jobserver_crate = { version = "0.1.13", package = "jobserver" }
 lazy_static = "1"
 rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 serialize = { path = "../libserialize" }
diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs
index aaed41d9fa3..93a2a261c6f 100644
--- a/src/librustc_data_structures/graph/dominators/mod.rs
+++ b/src/librustc_data_structures/graph/dominators/mod.rs
@@ -8,8 +8,6 @@ use super::super::indexed_vec::{Idx, IndexVec};
 use super::iterate::reverse_post_order;
 use super::ControlFlowGraph;
 
-use std::fmt;
-
 #[cfg(test)]
 mod test;
 
@@ -158,48 +156,3 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
         }
     }
 }
-
-pub struct DominatorTree<N: Idx> {
-    root: N,
-    children: IndexVec<N, Vec<N>>,
-}
-
-impl<Node: Idx> DominatorTree<Node> {
-    pub fn children(&self, node: Node) -> &[Node] {
-        &self.children[node]
-    }
-}
-
-impl<Node: Idx> fmt::Debug for DominatorTree<Node> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(
-            &DominatorTreeNode {
-                tree: self,
-                node: self.root,
-            },
-            fmt,
-        )
-    }
-}
-
-struct DominatorTreeNode<'tree, Node: Idx> {
-    tree: &'tree DominatorTree<Node>,
-    node: Node,
-}
-
-impl<'tree, Node: Idx> fmt::Debug for DominatorTreeNode<'tree, Node> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let subtrees: Vec<_> = self.tree
-            .children(self.node)
-            .iter()
-            .map(|&child| DominatorTreeNode {
-                tree: self.tree,
-                node: child,
-            })
-            .collect();
-        fmt.debug_tuple("")
-            .field(&self.node)
-            .field(&subtrees)
-            .finish()
-    }
-}
diff --git a/src/librustc_data_structures/jobserver.rs b/src/librustc_data_structures/jobserver.rs
index 48ac8125a0d..b42ccb932b9 100644
--- a/src/librustc_data_structures/jobserver.rs
+++ b/src/librustc_data_structures/jobserver.rs
@@ -1,89 +1,5 @@
-use jobserver_crate::{Client, HelperThread, Acquired};
+use jobserver_crate::Client;
 use lazy_static::lazy_static;
-use std::sync::{Condvar, Arc, Mutex};
-use std::mem;
-
-#[derive(Default)]
-struct LockedProxyData {
-    /// The number of free thread tokens, this may include the implicit token given to the process
-    free: usize,
-
-    /// The number of threads waiting for a token
-    waiters: usize,
-
-    /// The number of tokens we requested from the server
-    requested: usize,
-
-    /// Stored tokens which will be dropped when we no longer need them
-    tokens: Vec<Acquired>,
-}
-
-impl LockedProxyData {
-    fn request_token(&mut self, thread: &Mutex<HelperThread>) {
-        self.requested += 1;
-        thread.lock().unwrap().request_token();
-    }
-
-    fn release_token(&mut self, cond_var: &Condvar) {
-        if self.waiters > 0 {
-            self.free += 1;
-            cond_var.notify_one();
-        } else {
-            if self.tokens.is_empty() {
-                // We are returning the implicit token
-                self.free += 1;
-            } else {
-                // Return a real token to the server
-                self.tokens.pop().unwrap();
-            }
-        }
-    }
-
-    fn take_token(&mut self, thread: &Mutex<HelperThread>) -> bool {
-        if self.free > 0 {
-            self.free -= 1;
-            self.waiters -= 1;
-
-            // We stole some token reqested by someone else
-            // Request another one
-            if self.requested + self.free < self.waiters {
-                self.request_token(thread);
-            }
-
-            true
-        } else {
-            false
-        }
-    }
-
-    fn new_requested_token(&mut self, token: Acquired, cond_var: &Condvar) {
-        self.requested -= 1;
-
-        // Does anything need this token?
-        if self.waiters > 0 {
-            self.free += 1;
-            self.tokens.push(token);
-            cond_var.notify_one();
-        } else {
-            // Otherwise we'll just drop it
-            mem::drop(token);
-        }
-    }
-}
-
-#[derive(Default)]
-struct ProxyData {
-    lock: Mutex<LockedProxyData>,
-    cond_var: Condvar,
-}
-
-/// A helper type which makes managing jobserver tokens easier.
-/// It also allows you to treat the implicit token given to the process
-/// in the same manner as requested tokens.
-struct Proxy {
-    thread: Mutex<HelperThread>,
-    data: Arc<ProxyData>,
-}
 
 lazy_static! {
     // We can only call `from_env` once per process
@@ -105,20 +21,12 @@ lazy_static! {
     // per-process.
     static ref GLOBAL_CLIENT: Client = unsafe {
         Client::from_env().unwrap_or_else(|| {
-            Client::new(32).expect("failed to create jobserver")
+            let client = Client::new(32).expect("failed to create jobserver");
+            // Acquire a token for the main thread which we can release later
+            client.acquire_raw().ok();
+            client
         })
     };
-
-    static ref GLOBAL_PROXY: Proxy = {
-        let data = Arc::new(ProxyData::default());
-
-        Proxy {
-            data: data.clone(),
-            thread: Mutex::new(client().into_helper_thread(move |token| {
-                data.lock.lock().unwrap().new_requested_token(token.unwrap(), &data.cond_var);
-            }).unwrap()),
-        }
-    };
 }
 
 pub fn client() -> Client {
@@ -126,31 +34,9 @@ pub fn client() -> Client {
 }
 
 pub fn acquire_thread() {
-    GLOBAL_PROXY.acquire_token();
+    GLOBAL_CLIENT.acquire_raw().ok();
 }
 
 pub fn release_thread() {
-    GLOBAL_PROXY.release_token();
-}
-
-impl Proxy {
-    fn release_token(&self) {
-        self.data.lock.lock().unwrap().release_token(&self.data.cond_var);
-    }
-
-    fn acquire_token(&self) {
-        let mut data = self.data.lock.lock().unwrap();
-        data.waiters += 1;
-        if data.take_token(&self.thread) {
-            return;
-        }
-        // Request a token for us
-        data.request_token(&self.thread);
-        loop {
-            data = self.data.cond_var.wait(data).unwrap();
-            if data.take_token(&self.thread) {
-                return;
-            }
-        }
-    }
+    GLOBAL_CLIENT.release_raw().ok();
 }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 4b7cffaad55..66c7c9d0eae 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -17,6 +17,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 pub extern crate getopts;
 #[cfg(unix)]
@@ -743,7 +744,7 @@ fn usage(verbose: bool, include_unstable_options: bool) {
     }
     let message = "Usage: rustc [OPTIONS] INPUT";
     let nightly_help = if nightly_options::is_nightly_build() {
-        "\n    -Z help             Print internal options for debugging rustc"
+        "\n    -Z help             Print unstable compiler options"
     } else {
         ""
     };
@@ -891,7 +892,7 @@ Available lint options:
 }
 
 fn describe_debug_flags() {
-    println!("\nAvailable debug options:\n");
+    println!("\nAvailable options:\n");
     print_flag_list("-Z", config::DB_OPTIONS);
 }
 
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index ebbc5a3d3a3..71bef54cd17 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -6,6 +6,7 @@
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[allow(unused_extern_crates)]
 extern crate serialize as rustc_serialize; // used by deriving
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index fe75bbc36c3..d7db324f346 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -8,6 +8,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use] extern crate rustc;
 #[allow(unused_extern_crates)]
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 46e2582ac3b..5c4fd9dba7a 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -3,9 +3,9 @@
 //! we will compare the fingerprint from the current and from the previous
 //! compilation session as appropriate:
 //!
-//! - `#[rustc_clean(cfg="rev2", except="TypeckTables")]` if we are
+//! - `#[rustc_clean(cfg="rev2", except="typeck_tables_of")]` if we are
 //!   in `#[cfg(rev2)]`, then the fingerprints associated with
-//!   `DepNode::TypeckTables(X)` must be DIFFERENT (`X` is the `DefId` of the
+//!   `DepNode::typeck_tables_of(X)` must be DIFFERENT (`X` is the `DefId` of the
 //!   current node).
 //! - `#[rustc_clean(cfg="rev2")]` same as above, except that the
 //!   fingerprints must be the SAME (along with all other fingerprints).
@@ -42,14 +42,14 @@ const BASE_CONST: &[&str] = &[
 /// DepNodes for functions + methods
 const BASE_FN: &[&str] = &[
     // Callers will depend on the signature of these items, so we better test
-    label_strs::FnSignature,
+    label_strs::fn_sig,
     label_strs::generics_of,
     label_strs::predicates_of,
     label_strs::type_of,
 
     // And a big part of compilation (that we eventually want to cache) is type inference
     // information:
-    label_strs::TypeckTables,
+    label_strs::typeck_tables_of,
 ];
 
 /// DepNodes for Hir, which is pretty much everything
@@ -61,9 +61,9 @@ const BASE_HIR: &[&str] = &[
 
 /// `impl` implementation of struct/trait
 const BASE_IMPL: &[&str] = &[
-    label_strs::AssociatedItemDefIds,
+    label_strs::associated_item_def_ids,
     label_strs::generics_of,
-    label_strs::ImplTraitRef,
+    label_strs::impl_trait_ref,
 ];
 
 /// DepNodes for mir_built/Optimized, which is relevant in "executable"
@@ -85,22 +85,22 @@ const BASE_STRUCT: &[&str] = &[
 
 /// Trait definition `DepNode`s.
 const BASE_TRAIT_DEF: &[&str] = &[
-    label_strs::AssociatedItemDefIds,
+    label_strs::associated_item_def_ids,
     label_strs::generics_of,
-    label_strs::ObjectSafety,
+    label_strs::is_object_safe,
     label_strs::predicates_of,
-    label_strs::SpecializationGraph,
-    label_strs::TraitDefOfItem,
-    label_strs::TraitImpls,
+    label_strs::specialization_graph_of,
+    label_strs::trait_def,
+    label_strs::trait_impls_of,
 ];
 
 /// Extra `DepNode`s for functions and methods.
 const EXTRA_ASSOCIATED: &[&str] = &[
-    label_strs::AssociatedItems,
+    label_strs::associated_item,
 ];
 
 const EXTRA_TRAIT: &[&str] = &[
-    label_strs::TraitOfItem,
+    label_strs::trait_of_item,
 ];
 
 // Fully Built Labels
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index 245a2bf92d5..23575e51dfc 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -12,7 +12,6 @@ use rustc_data_structures::OnDrop;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc_metadata::cstore::CStore;
-use std::collections::HashSet;
 use std::io::Write;
 use std::path::PathBuf;
 use std::result;
@@ -124,10 +123,6 @@ where
         profile::dump(&compiler.sess, "profile_queries".to_string())
     }
 
-    if compiler.sess.opts.debugging_opts.self_profile {
-        compiler.sess.profiler(|p| p.dump_raw_events(&compiler.sess.opts));
-    }
-
     r
 }
 
diff --git a/src/librustc_interface/lib.rs b/src/librustc_interface/lib.rs
index 3314681b698..353ff6a57a5 100644
--- a/src/librustc_interface/lib.rs
+++ b/src/librustc_interface/lib.rs
@@ -7,6 +7,7 @@
 #![cfg_attr(unix, feature(libc))]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![allow(unused_imports)]
 
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 1547e15fd48..3fd684f5d97 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -69,7 +69,7 @@ pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
         .set_continue_after_error(sess.opts.debugging_opts.continue_parse_after_error);
     hygiene::set_default_edition(sess.edition());
 
-    sess.profiler(|p| p.start_activity(ProfileCategory::Parsing, "parsing"));
+    sess.profiler(|p| p.start_activity("parsing"));
     let krate = time(sess, "parsing", || match *input {
         Input::File(ref file) => parse::parse_crate_from_file(file, &sess.parse_sess),
         Input::Str {
@@ -77,7 +77,7 @@ pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
             ref name,
         } => parse::parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess),
     })?;
-    sess.profiler(|p| p.end_activity(ProfileCategory::Parsing, "parsing"));
+    sess.profiler(|p| p.end_activity("parsing"));
 
     sess.diagnostic().set_continue_after_error(true);
 
@@ -375,7 +375,7 @@ fn configure_and_expand_inner<'a>(
     syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts);
 
     // Expand all macros
-    sess.profiler(|p| p.start_activity(ProfileCategory::Expansion, "macro expansion"));
+    sess.profiler(|p| p.start_activity("macro expansion"));
     krate = time(sess, "expansion", || {
         // Windows dlls do not have rpaths, so they don't know how to find their
         // dependencies. It's up to us to tell the system where to find all the
@@ -450,7 +450,7 @@ fn configure_and_expand_inner<'a>(
         }
         krate
     });
-    sess.profiler(|p| p.end_activity(ProfileCategory::Expansion, "macro expansion"));
+    sess.profiler(|p| p.end_activity("macro expansion"));
 
     time(sess, "maybe building test harness", || {
         syntax::test::modify_for_testing(
@@ -869,8 +869,6 @@ pub fn create_global_ctxt(
         yield BoxedGlobalCtxt::initial_yield(());
         box_region_allow_access!(for('gcx), (&'gcx GlobalCtxt<'gcx>), (gcx));
 
-        gcx.queries.record_computed_queries(sess);
-
         if sess.opts.debugging_opts.query_stats {
             gcx.queries.print_stats();
         }
@@ -1022,9 +1020,9 @@ pub fn start_codegen<'tcx>(
         ::rustc::middle::dependency_format::calculate(tcx)
     });
 
-    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen, "codegen crate"));
+    tcx.sess.profiler(|p| p.start_activity("codegen crate"));
     let codegen = time(tcx.sess, "codegen", move || codegen_backend.codegen_crate(tcx, rx));
-    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen, "codegen crate"));
+    tcx.sess.profiler(|p| p.end_activity("codegen crate"));
 
     if log_enabled!(::log::Level::Info) {
         println!("Post-codegen");
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 6e4f2bf24e3..17523aedffb 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -21,7 +21,6 @@ use rustc_plugin;
 use rustc_privacy;
 use rustc_resolve;
 use rustc_typeck;
-use std::collections::HashSet;
 use std::env;
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::io::{self, Write};
@@ -109,6 +108,9 @@ pub fn create_session(
     let codegen_backend = get_codegen_backend(&sess);
 
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
+    if sess.unstable_options() {
+        rustc_lint::register_internals(&mut sess.lint_store.borrow_mut(), Some(&sess));
+    }
 
     let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
     add_configuration(&mut cfg, &sess, &*codegen_backend);
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 1fae931e9f1..7fe047ec2c6 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -63,18 +63,7 @@ declare_lint! {
     "suggest using `loop { }` instead of `while true { }`"
 }
 
-#[derive(Copy, Clone)]
-pub struct WhileTrue;
-
-impl LintPass for WhileTrue {
-    fn name(&self) -> &'static str {
-        "WhileTrue"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(WHILE_TRUE)
-    }
-}
+declare_lint_pass!(WhileTrue => [WHILE_TRUE]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WhileTrue {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) {
@@ -105,8 +94,7 @@ declare_lint! {
     "use of owned (Box type) heap memory"
 }
 
-#[derive(Copy, Clone)]
-pub struct BoxPointers;
+declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
 
 impl BoxPointers {
     fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'_, '_>, span: Span, ty: Ty<'_>) {
@@ -119,16 +107,6 @@ impl BoxPointers {
     }
 }
 
-impl LintPass for BoxPointers {
-    fn name(&self) -> &'static str {
-        "BoxPointers"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(BOX_POINTERS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
         match it.node {
@@ -169,18 +147,7 @@ declare_lint! {
     "using `Struct { x: x }` instead of `Struct { x }` in a pattern"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonShorthandFieldPatterns;
-
-impl LintPass for NonShorthandFieldPatterns {
-    fn name(&self) -> &'static str {
-        "NonShorthandFieldPatterns"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SHORTHAND_FIELD_PATTERNS)
-    }
-}
+declare_lint_pass!(NonShorthandFieldPatterns => [NON_SHORTHAND_FIELD_PATTERNS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
     fn check_pat(&mut self, cx: &LateContext<'_, '_>, pat: &hir::Pat) {
@@ -226,18 +193,7 @@ declare_lint! {
     "usage of `unsafe` code"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnsafeCode;
-
-impl LintPass for UnsafeCode {
-    fn name(&self) -> &'static str {
-        "UnsafeCode"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNSAFE_CODE)
-    }
-}
+declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);
 
 impl UnsafeCode {
     fn report_unsafe(&self, cx: &EarlyContext<'_>, span: Span, desc: &'static str) {
@@ -327,6 +283,8 @@ pub struct MissingDoc {
     private_traits: FxHashSet<hir::HirId>,
 }
 
+impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
+
 fn has_doc(attr: &ast::Attribute) -> bool {
     if !attr.check_name("doc") {
         return false;
@@ -394,16 +352,6 @@ impl MissingDoc {
     }
 }
 
-impl LintPass for MissingDoc {
-    fn name(&self) -> &'static str {
-        "MissingDoc"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_DOCS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
     fn enter_lint_attrs(&mut self, _: &LateContext<'_, '_>, attrs: &[ast::Attribute]) {
         let doc_hidden = self.doc_hidden() ||
@@ -541,18 +489,7 @@ declare_lint! {
     "detects potentially-forgotten implementations of `Copy`"
 }
 
-#[derive(Copy, Clone)]
-pub struct MissingCopyImplementations;
-
-impl LintPass for MissingCopyImplementations {
-    fn name(&self) -> &'static str {
-        "MissingCopyImplementations"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_COPY_IMPLEMENTATIONS)
-    }
-}
+declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
@@ -609,22 +546,14 @@ pub struct MissingDebugImplementations {
     impling_types: Option<HirIdSet>,
 }
 
+impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
+
 impl MissingDebugImplementations {
     pub fn new() -> MissingDebugImplementations {
         MissingDebugImplementations { impling_types: None }
     }
 }
 
-impl LintPass for MissingDebugImplementations {
-    fn name(&self) -> &'static str {
-        "MissingDebugImplementations"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_DEBUG_IMPLEMENTATIONS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
         if !cx.access_levels.is_reachable(item.hir_id) {
@@ -672,19 +601,10 @@ declare_lint! {
     "detects anonymous parameters"
 }
 
-/// Checks for use of anonymous parameters (RFC 1685).
-#[derive(Copy, Clone)]
-pub struct AnonymousParameters;
-
-impl LintPass for AnonymousParameters {
-    fn name(&self) -> &'static str {
-        "AnonymousParameters"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(ANONYMOUS_PARAMETERS)
-    }
-}
+declare_lint_pass!(
+    /// Checks for use of anonymous parameters (RFC 1685).
+    AnonymousParameters => [ANONYMOUS_PARAMETERS]
+);
 
 impl EarlyLintPass for AnonymousParameters {
     fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::TraitItem) {
@@ -736,6 +656,8 @@ pub struct DeprecatedAttr {
     depr_attrs: Vec<&'static (&'static str, AttributeType, AttributeTemplate, AttributeGate)>,
 }
 
+impl_lint_pass!(DeprecatedAttr => []);
+
 impl DeprecatedAttr {
     pub fn new() -> DeprecatedAttr {
         DeprecatedAttr {
@@ -744,16 +666,6 @@ impl DeprecatedAttr {
     }
 }
 
-impl LintPass for DeprecatedAttr {
-    fn name(&self) -> &'static str {
-        "DeprecatedAttr"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!()
-    }
-}
-
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
         let name = attr.name_or_empty();
@@ -786,18 +698,7 @@ declare_lint! {
     "detects doc comments that aren't used by rustdoc"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedDocComment;
-
-impl LintPass for UnusedDocComment {
-    fn name(&self) -> &'static str {
-        "UnusedDocComment"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array![UNUSED_DOC_COMMENTS]
-    }
-}
+declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]);
 
 impl UnusedDocComment {
     fn warn_if_doc(
@@ -884,18 +785,7 @@ declare_lint! {
     "compiler plugin used as ordinary library in non-plugin crate"
 }
 
-#[derive(Copy, Clone)]
-pub struct PluginAsLibrary;
-
-impl LintPass for PluginAsLibrary {
-    fn name(&self) -> &'static str {
-        "PluginAsLibrary"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array![PLUGIN_AS_LIBRARY]
-    }
-}
+declare_lint_pass!(PluginAsLibrary => [PLUGIN_AS_LIBRARY]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PluginAsLibrary {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
@@ -940,19 +830,7 @@ declare_lint! {
     "generic items must be mangled"
 }
 
-#[derive(Copy, Clone)]
-pub struct InvalidNoMangleItems;
-
-impl LintPass for InvalidNoMangleItems {
-    fn name(&self) -> &'static str {
-        "InvalidNoMangleItems"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NO_MANGLE_CONST_ITEMS,
-                    NO_MANGLE_GENERIC_ITEMS)
-    }
-}
+declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GENERIC_ITEMS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
@@ -1011,24 +889,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
     }
 }
 
-#[derive(Clone, Copy)]
-pub struct MutableTransmutes;
-
 declare_lint! {
     MUTABLE_TRANSMUTES,
     Deny,
     "mutating transmuted &mut T from &T may cause undefined behavior"
 }
 
-impl LintPass for MutableTransmutes {
-    fn name(&self) -> &'static str {
-        "MutableTransmutes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MUTABLE_TRANSMUTES)
-    }
-}
+declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &hir::Expr) {
@@ -1036,7 +903,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
 
         let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \
                    consider instead using an UnsafeCell";
-        match get_transmute_from_to(cx, expr) {
+        match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.sty, &ty2.sty)) {
             Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => {
                 if to_mt == hir::Mutability::MutMutable &&
                    from_mt == hir::Mutability::MutImmutable {
@@ -1049,7 +916,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
         fn get_transmute_from_to<'a, 'tcx>
             (cx: &LateContext<'a, 'tcx>,
              expr: &hir::Expr)
-             -> Option<(&'tcx ty::TyKind<'tcx>, &'tcx ty::TyKind<'tcx>)> {
+             -> Option<(Ty<'tcx>, Ty<'tcx>)> {
             let def = if let hir::ExprKind::Path(ref qpath) = expr.node {
                 cx.tables.qpath_def(qpath, expr.hir_id)
             } else {
@@ -1062,7 +929,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
                 let sig = cx.tables.node_type(expr.hir_id).fn_sig(cx.tcx);
                 let from = sig.inputs().skip_binder()[0];
                 let to = *sig.output().skip_binder();
-                return Some((&from.sty, &to.sty));
+                return Some((from, to));
             }
             None
         }
@@ -1074,25 +941,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
     }
 }
 
-/// Forbids using the `#[feature(...)]` attribute
-#[derive(Copy, Clone)]
-pub struct UnstableFeatures;
-
 declare_lint! {
     UNSTABLE_FEATURES,
     Allow,
     "enabling unstable features (deprecated. do not use)"
 }
 
-impl LintPass for UnstableFeatures {
-    fn name(&self) -> &'static str {
-        "UnstableFeatures"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNSTABLE_FEATURES)
-    }
-}
+declare_lint_pass!(
+    /// Forbids using the `#[feature(...)]` attribute
+    UnstableFeatures => [UNSTABLE_FEATURES]
+);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures {
     fn check_attribute(&mut self, ctx: &LateContext<'_, '_>, attr: &ast::Attribute) {
@@ -1106,24 +964,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures {
     }
 }
 
-/// Lint for unions that contain fields with possibly non-trivial destructors.
-pub struct UnionsWithDropFields;
-
 declare_lint! {
     UNIONS_WITH_DROP_FIELDS,
     Warn,
     "use of unions that contain fields with possibly non-trivial drop code"
 }
 
-impl LintPass for UnionsWithDropFields {
-    fn name(&self) -> &'static str {
-        "UnionsWithDropFields"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNIONS_WITH_DROP_FIELDS)
-    }
-}
+declare_lint_pass!(
+    /// Lint for unions that contain fields with possibly non-trivial destructors.
+    UnionsWithDropFields => [UNIONS_WITH_DROP_FIELDS]
+);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     fn check_item(&mut self, ctx: &LateContext<'_, '_>, item: &hir::Item) {
@@ -1143,25 +993,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     }
 }
 
-/// Lint for items marked `pub` that aren't reachable from other crates.
-#[derive(Copy, Clone)]
-pub struct UnreachablePub;
-
 declare_lint! {
     pub UNREACHABLE_PUB,
     Allow,
     "`pub` items not reachable from crate root"
 }
 
-impl LintPass for UnreachablePub {
-    fn name(&self) -> &'static str {
-        "UnreachablePub"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNREACHABLE_PUB)
-    }
-}
+declare_lint_pass!(
+    /// Lint for items marked `pub` that aren't reachable from other crates.
+    UnreachablePub => [UNREACHABLE_PUB]
+);
 
 impl UnreachablePub {
     fn perform_lint(&self, cx: &LateContext<'_, '_>, what: &str, id: hir::HirId,
@@ -1197,7 +1038,6 @@ impl UnreachablePub {
     }
 }
 
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
         self.perform_lint(cx, "item", item.hir_id, &item.vis, item.span, true);
@@ -1217,27 +1057,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
     }
 }
 
-/// Lint for trait and lifetime bounds in type aliases being mostly ignored.
-/// They are relevant when using associated types, but otherwise neither checked
-/// at definition site nor enforced at use site.
-
-pub struct TypeAliasBounds;
-
 declare_lint! {
     TYPE_ALIAS_BOUNDS,
     Warn,
     "bounds in type aliases are not enforced"
 }
 
-impl LintPass for TypeAliasBounds {
-    fn name(&self) -> &'static str {
-        "TypeAliasBounds"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TYPE_ALIAS_BOUNDS)
-    }
-}
+declare_lint_pass!(
+    /// Lint for trait and lifetime bounds in type aliases being mostly ignored.
+    /// They are relevant when using associated types, but otherwise neither checked
+    /// at definition site nor enforced at use site.
+    TypeAliasBounds => [TYPE_ALIAS_BOUNDS]
+);
 
 impl TypeAliasBounds {
     fn is_type_variable_assoc(qpath: &hir::QPath) -> bool {
@@ -1331,21 +1162,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds {
     }
 }
 
-/// Lint constants that are erroneous.
-/// Without this lint, we might not get any diagnostic if the constant is
-/// unused within this crate, even though downstream crates can't use it
-/// without producing an error.
-pub struct UnusedBrokenConst;
-
-impl LintPass for UnusedBrokenConst {
-    fn name(&self) -> &'static str {
-        "UnusedBrokenConst"
-    }
+declare_lint_pass!(
+    /// Lint constants that are erroneous.
+    /// Without this lint, we might not get any diagnostic if the constant is
+    /// unused within this crate, even though downstream crates can't use it
+    /// without producing an error.
+    UnusedBrokenConst => []
+);
 
-    fn get_lints(&self) -> LintArray {
-        lint_array!()
-    }
-}
 fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) {
     let def_id = cx.tcx.hir().body_owner_def_id(body_id);
     let is_static = cx.tcx.is_static(def_id).is_some();
@@ -1378,25 +1202,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
     }
 }
 
-/// Lint for trait and lifetime bounds that don't depend on type parameters
-/// which either do nothing, or stop the item from being used.
-pub struct TrivialConstraints;
-
 declare_lint! {
     TRIVIAL_BOUNDS,
     Warn,
     "these bounds don't depend on an type parameters"
 }
 
-impl LintPass for TrivialConstraints {
-    fn name(&self) -> &'static str {
-        "TrivialConstraints"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TRIVIAL_BOUNDS)
-    }
-}
+declare_lint_pass!(
+    /// Lint for trait and lifetime bounds that don't depend on type parameters
+    /// which either do nothing, or stop the item from being used.
+    TrivialConstraints => [TRIVIAL_BOUNDS]
+);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
     fn check_item(
@@ -1440,40 +1256,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
     }
 }
 
-
-/// Does nothing as a lint pass, but registers some `Lint`s
-/// which are used by other parts of the compiler.
-#[derive(Copy, Clone)]
-pub struct SoftLints;
-
-impl LintPass for SoftLints {
-    fn name(&self) -> &'static str {
-        "SoftLints"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(
-            WHILE_TRUE,
-            BOX_POINTERS,
-            NON_SHORTHAND_FIELD_PATTERNS,
-            UNSAFE_CODE,
-            MISSING_DOCS,
-            MISSING_COPY_IMPLEMENTATIONS,
-            MISSING_DEBUG_IMPLEMENTATIONS,
-            ANONYMOUS_PARAMETERS,
-            UNUSED_DOC_COMMENTS,
-            PLUGIN_AS_LIBRARY,
-            NO_MANGLE_CONST_ITEMS,
-            NO_MANGLE_GENERIC_ITEMS,
-            MUTABLE_TRANSMUTES,
-            UNSTABLE_FEATURES,
-            UNIONS_WITH_DROP_FIELDS,
-            UNREACHABLE_PUB,
-            TYPE_ALIAS_BOUNDS,
-            TRIVIAL_BOUNDS
-        )
-    }
-}
+declare_lint_pass!(
+    /// Does nothing as a lint pass, but registers some `Lint`s
+    /// which are used by other parts of the compiler.
+    SoftLints => [
+        WHILE_TRUE,
+        BOX_POINTERS,
+        NON_SHORTHAND_FIELD_PATTERNS,
+        UNSAFE_CODE,
+        MISSING_DOCS,
+        MISSING_COPY_IMPLEMENTATIONS,
+        MISSING_DEBUG_IMPLEMENTATIONS,
+        ANONYMOUS_PARAMETERS,
+        UNUSED_DOC_COMMENTS,
+        PLUGIN_AS_LIBRARY,
+        NO_MANGLE_CONST_ITEMS,
+        NO_MANGLE_GENERIC_ITEMS,
+        MUTABLE_TRANSMUTES,
+        UNSTABLE_FEATURES,
+        UNIONS_WITH_DROP_FIELDS,
+        UNREACHABLE_PUB,
+        TYPE_ALIAS_BOUNDS,
+        TRIVIAL_BOUNDS
+    ]
+);
 
 declare_lint! {
     pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
@@ -1481,18 +1287,7 @@ declare_lint! {
     "`...` range patterns are deprecated"
 }
 
-
-pub struct EllipsisInclusiveRangePatterns;
-
-impl LintPass for EllipsisInclusiveRangePatterns {
-    fn name(&self) -> &'static str {
-        "EllipsisInclusiveRangePatterns"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS)
-    }
-}
+declare_lint_pass!(EllipsisInclusiveRangePatterns => [ELLIPSIS_INCLUSIVE_RANGE_PATTERNS]);
 
 impl EarlyLintPass for EllipsisInclusiveRangePatterns {
     fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &ast::Pat, visit_subpats: &mut bool) {
@@ -1553,6 +1348,8 @@ pub struct UnnameableTestItems {
     items_nameable: bool,
 }
 
+impl_lint_pass!(UnnameableTestItems => [UNNAMEABLE_TEST_ITEMS]);
+
 impl UnnameableTestItems {
     pub fn new() -> Self {
         Self {
@@ -1562,16 +1359,6 @@ impl UnnameableTestItems {
     }
 }
 
-impl LintPass for UnnameableTestItems {
-    fn name(&self) -> &'static str {
-        "UnnameableTestItems"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNNAMEABLE_TEST_ITEMS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
         if self.items_nameable {
@@ -1605,19 +1392,10 @@ declare_lint! {
     "detects edition keywords being used as an identifier"
 }
 
-/// Check for uses of edition keywords used as an identifier.
-#[derive(Copy, Clone)]
-pub struct KeywordIdents;
-
-impl LintPass for KeywordIdents {
-    fn name(&self) -> &'static str {
-        "KeywordIdents"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(KEYWORD_IDENTS)
-    }
-}
+declare_lint_pass!(
+    /// Check for uses of edition keywords used as an identifier.
+    KeywordIdents => [KEYWORD_IDENTS]
+);
 
 struct UnderMacro(bool);
 
@@ -1740,18 +1518,7 @@ impl EarlyLintPass for KeywordIdents {
     }
 }
 
-
-pub struct ExplicitOutlivesRequirements;
-
-impl LintPass for ExplicitOutlivesRequirements {
-    fn name(&self) -> &'static str {
-        "ExplicitOutlivesRequirements"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array![EXPLICIT_OUTLIVES_REQUIREMENTS]
-    }
-}
+declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMENTS]);
 
 impl ExplicitOutlivesRequirements {
     fn collect_outlives_bound_spans(
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index c9301a32d83..4a2d6dc68ae 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -20,6 +20,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use]
 extern crate rustc;
@@ -61,6 +62,7 @@ use nonstandard_style::*;
 use builtin::*;
 use types::*;
 use unused::*;
+use rustc::lint::internal::*;
 
 /// Useful for other parts of the compiler.
 pub use builtin::SoftLints;
@@ -427,15 +429,15 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             edition: None,
         },
         FutureIncompatibleInfo {
-            id: LintId::of(DUPLICATE_MATCHER_BINDING_NAME),
-            reference: "issue #57593 <https://github.com/rust-lang/rust/issues/57593>",
-            edition: None,
-        },
-        FutureIncompatibleInfo {
             id: LintId::of(NESTED_IMPL_TRAIT),
             reference: "issue #59014 <https://github.com/rust-lang/rust/issues/59014>",
             edition: None,
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(MUTABLE_BORROW_RESERVATION_CONFLICT),
+            reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>",
+            edition: None,
+        }
         ]);
 
     // Register renamed and removed lints.
@@ -487,4 +489,21 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
         "no longer a warning, #[no_mangle] statics always exported");
     store.register_removed("bad_repr",
         "replaced with a generic attribute input check");
+    store.register_removed("duplicate_matcher_binding_name",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/57742");
+}
+
+pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
+    store.register_early_pass(sess, false, false, box DefaultHashTypes::new());
+    store.register_late_pass(sess, false, false, false, box TyKindUsage);
+    store.register_group(
+        sess,
+        false,
+        "internal",
+        None,
+        vec![
+            LintId::of(DEFAULT_HASH_TYPES),
+            LintId::of(USAGE_OF_TY_TYKIND),
+        ],
+    );
 }
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index 7a164dbcdf1..1d8979f7d1c 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -38,6 +38,8 @@ declare_lint! {
     "types, variants, traits and type parameters should have camel case names"
 }
 
+declare_lint_pass!(NonCamelCaseTypes => [NON_CAMEL_CASE_TYPES]);
+
 fn char_has_case(c: char) -> bool {
     c.is_lowercase() || c.is_uppercase()
 }
@@ -105,9 +107,6 @@ fn to_camel_case(s: &str) -> String {
         .0
 }
 
-#[derive(Copy, Clone)]
-pub struct NonCamelCaseTypes;
-
 impl NonCamelCaseTypes {
     fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) {
         let name = &ident.name.as_str();
@@ -126,16 +125,6 @@ impl NonCamelCaseTypes {
     }
 }
 
-impl LintPass for NonCamelCaseTypes {
-    fn name(&self) -> &'static str {
-        "NonCamelCaseTypes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_CAMEL_CASE_TYPES)
-    }
-}
-
 impl EarlyLintPass for NonCamelCaseTypes {
     fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
         let has_repr_c = it.attrs
@@ -173,8 +162,7 @@ declare_lint! {
     "variables, methods, functions, lifetime parameters and modules should have snake case names"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonSnakeCase;
+declare_lint_pass!(NonSnakeCase => [NON_SNAKE_CASE]);
 
 impl NonSnakeCase {
     fn to_snake_case(mut str: &str) -> String {
@@ -256,16 +244,6 @@ impl NonSnakeCase {
     }
 }
 
-impl LintPass for NonSnakeCase {
-    fn name(&self) -> &'static str {
-        "NonSnakeCase"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SNAKE_CASE)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
     fn check_mod(&mut self, cx: &LateContext<'_, '_>, _: &'tcx hir::Mod, _: Span, id: hir::HirId) {
         if id != hir::CRATE_HIR_ID {
@@ -387,8 +365,7 @@ declare_lint! {
     "static constants should have uppercase identifiers"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonUpperCaseGlobals;
+declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]);
 
 impl NonUpperCaseGlobals {
     fn check_upper_case(cx: &LateContext<'_, '_>, sort: &str, ident: &Ident) {
@@ -410,16 +387,6 @@ impl NonUpperCaseGlobals {
     }
 }
 
-impl LintPass for NonUpperCaseGlobals {
-    fn name(&self) -> &'static str {
-        "NonUpperCaseGlobals"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_UPPER_CASE_GLOBALS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
         match it.node {
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 494a9bb73ed..d3223c6edb8 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -49,23 +49,14 @@ pub struct TypeLimits {
     negated_expr_id: hir::HirId,
 }
 
+impl_lint_pass!(TypeLimits => [UNUSED_COMPARISONS, OVERFLOWING_LITERALS]);
+
 impl TypeLimits {
     pub fn new() -> TypeLimits {
         TypeLimits { negated_expr_id: hir::DUMMY_HIR_ID }
     }
 }
 
-impl LintPass for TypeLimits {
-    fn name(&self) -> &'static str {
-        "TypeLimits"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_COMPARISONS,
-                    OVERFLOWING_LITERALS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
         match e.node {
@@ -104,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                                         report_bin_hex_error(
                                             cx,
                                             e,
-                                            ty::Int(t),
+                                            attr::IntType::SignedInt(t),
                                             repr_str,
                                             v,
                                             negative,
@@ -159,7 +150,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                                 report_bin_hex_error(
                                     cx,
                                     e,
-                                    ty::Uint(t),
+                                    attr::IntType::UnsignedInt(t),
                                     repr_str,
                                     lit_val,
                                     false,
@@ -321,7 +312,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
         //
         // No suggestion for: `isize`, `usize`.
         fn get_type_suggestion<'a>(
-            t: &ty::TyKind<'_>,
+            t: Ty<'_>,
             val: u128,
             negative: bool,
         ) -> Option<String> {
@@ -347,14 +338,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                     }
                 }
             }
-            match t {
-                &ty::Int(i) => find_fit!(i, val, negative,
+            match t.sty {
+                ty::Int(i) => find_fit!(i, val, negative,
                               I8 => [U8] => [I16, I32, I64, I128],
                               I16 => [U16] => [I32, I64, I128],
                               I32 => [U32] => [I64, I128],
                               I64 => [U64] => [I128],
                               I128 => [U128] => []),
-                &ty::Uint(u) => find_fit!(u, val, negative,
+                ty::Uint(u) => find_fit!(u, val, negative,
                               U8 => [U8, U16, U32, U64, U128] => [],
                               U16 => [U16, U32, U64, U128] => [],
                               U32 => [U32, U64, U128] => [],
@@ -367,25 +358,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
         fn report_bin_hex_error(
             cx: &LateContext<'_, '_>,
             expr: &hir::Expr,
-            ty: ty::TyKind<'_>,
+            ty: attr::IntType,
             repr_str: String,
             val: u128,
             negative: bool,
         ) {
+            let size = layout::Integer::from_attr(&cx.tcx, ty).size();
             let (t, actually) = match ty {
-                ty::Int(t) => {
-                    let ity = attr::IntType::SignedInt(t);
-                    let size = layout::Integer::from_attr(&cx.tcx, ity).size();
+                attr::IntType::SignedInt(t) => {
                     let actually = sign_extend(val, size) as i128;
                     (format!("{:?}", t), actually.to_string())
                 }
-                ty::Uint(t) => {
-                    let ity = attr::IntType::UnsignedInt(t);
-                    let size = layout::Integer::from_attr(&cx.tcx, ity).size();
+                attr::IntType::UnsignedInt(t) => {
                     let actually = truncate(val, size);
                     (format!("{:?}", t), actually.to_string())
                 }
-                _ => bug!(),
             };
             let mut err = cx.struct_span_lint(
                 OVERFLOWING_LITERALS,
@@ -398,7 +385,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                 repr_str, val, t, actually, t
             ));
             if let Some(sugg_ty) =
-                get_type_suggestion(&cx.tables.node_type(expr.hir_id).sty, val, negative)
+                get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative)
             {
                 if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
                     let (sans_suffix, _) = repr_str.split_at(pos);
@@ -424,6 +411,8 @@ declare_lint! {
     "proper use of libc types in foreign modules"
 }
 
+declare_lint_pass!(ImproperCTypes => [IMPROPER_CTYPES]);
+
 struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
     cx: &'a LateContext<'a, 'tcx>,
 }
@@ -793,19 +782,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     }
 }
 
-#[derive(Copy, Clone)]
-pub struct ImproperCTypes;
-
-impl LintPass for ImproperCTypes {
-    fn name(&self) -> &'static str {
-        "ImproperCTypes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(IMPROPER_CTYPES)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
     fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem) {
         let mut vis = ImproperCTypesVisitor { cx };
@@ -824,17 +800,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
     }
 }
 
-pub struct VariantSizeDifferences;
-
-impl LintPass for VariantSizeDifferences {
-    fn name(&self) -> &'static str {
-        "VariantSizeDifferences"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(VARIANT_SIZE_DIFFERENCES)
-    }
-}
+declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
@@ -854,6 +820,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
                     discr_kind: layout::DiscriminantKind::Tag,
                     ref discr,
                     ref variants,
+                    ..
                 } => (variants, discr),
                 _ => return,
             };
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 37c147d93d8..d41d97f58bc 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -32,18 +32,7 @@ declare_lint! {
     "unused result of an expression in a statement"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedResults;
-
-impl LintPass for UnusedResults {
-    fn name(&self) -> &'static str {
-        "UnusedResults"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS)
-    }
-}
+declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
     fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
@@ -203,18 +192,7 @@ declare_lint! {
     "path statements with no effect"
 }
 
-#[derive(Copy, Clone)]
-pub struct PathStatements;
-
-impl LintPass for PathStatements {
-    fn name(&self) -> &'static str {
-        "PathStatements"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(PATH_STATEMENTS)
-    }
-}
+declare_lint_pass!(PathStatements => [PATH_STATEMENTS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements {
     fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
@@ -232,18 +210,7 @@ declare_lint! {
     "detects attributes that were not used by the compiler"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedAttributes;
-
-impl LintPass for UnusedAttributes {
-    fn name(&self) -> &'static str {
-        "UnusedAttributes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ATTRIBUTES)
-    }
-}
+declare_lint_pass!(UnusedAttributes => [UNUSED_ATTRIBUTES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
     fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) {
@@ -305,8 +272,7 @@ declare_lint! {
     "`if`, `match`, `while` and `return` do not need parentheses"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedParens;
+declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
 
 impl UnusedParens {
     fn check_unused_parens_expr(&self,
@@ -383,16 +349,6 @@ impl UnusedParens {
     }
 }
 
-impl LintPass for UnusedParens {
-    fn name(&self) -> &'static str {
-        "UnusedParens"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_PARENS)
-    }
-}
-
 impl EarlyLintPass for UnusedParens {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         use syntax::ast::ExprKind::*;
@@ -465,8 +421,7 @@ declare_lint! {
     "unnecessary braces around an imported item"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedImportBraces;
+declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);
 
 impl UnusedImportBraces {
     fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
@@ -505,16 +460,6 @@ impl UnusedImportBraces {
     }
 }
 
-impl LintPass for UnusedImportBraces {
-    fn name(&self) -> &'static str {
-        "UnusedImportBraces"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_IMPORT_BRACES)
-    }
-}
-
 impl EarlyLintPass for UnusedImportBraces {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
         if let ast::ItemKind::Use(ref use_tree) = item.node {
@@ -529,18 +474,7 @@ declare_lint! {
     "detects unnecessary allocations that can be eliminated"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedAllocation;
-
-impl LintPass for UnusedAllocation {
-    fn name(&self) -> &'static str {
-        "UnusedAllocation"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ALLOCATION)
-    }
-}
+declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) {
diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml
index 9ad53ee6d09..9a24361f44e 100644
--- a/src/librustc_lsan/Cargo.toml
+++ b/src/librustc_lsan/Cargo.toml
@@ -12,7 +12,7 @@ test = false
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cmake = "0.1.18"
+cmake = "0.1.38"
 
 [dependencies]
 alloc = { path = "../liballoc" }
diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs
index bd5be831ff6..e4a6dfcd4e8 100644
--- a/src/librustc_macros/src/query.rs
+++ b/src/librustc_macros/src/query.rs
@@ -43,6 +43,9 @@ enum QueryModifier {
     /// A cycle error for this query aborting the compilation with a fatal error.
     FatalCycle,
 
+    /// A cycle error results in a delay_bug call
+    CycleDelayBug,
+
     /// Don't hash the result, instead just mark a query red if it runs
     NoHash,
 
@@ -101,6 +104,8 @@ impl Parse for QueryModifier {
             Ok(QueryModifier::LoadCached(tcx, id, block))
         } else if modifier == "fatal_cycle" {
             Ok(QueryModifier::FatalCycle)
+        } else if modifier == "cycle_delay_bug" {
+            Ok(QueryModifier::CycleDelayBug)
         } else if modifier == "no_hash" {
             Ok(QueryModifier::NoHash)
         } else if modifier == "no_force" {
@@ -207,6 +212,9 @@ struct QueryModifiers {
     /// A cycle error for this query aborting the compilation with a fatal error.
     fatal_cycle: bool,
 
+    /// A cycle error results in a delay_bug call
+    cycle_delay_bug: bool,
+
     /// Don't hash the result, instead just mark a query red if it runs
     no_hash: bool,
 
@@ -226,6 +234,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
     let mut cache = None;
     let mut desc = None;
     let mut fatal_cycle = false;
+    let mut cycle_delay_bug = false;
     let mut no_hash = false;
     let mut no_force = false;
     let mut anon = false;
@@ -256,6 +265,12 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
                 }
                 fatal_cycle = true;
             }
+            QueryModifier::CycleDelayBug => {
+                if cycle_delay_bug {
+                    panic!("duplicate modifier `cycle_delay_bug` for query `{}`", query.name);
+                }
+                cycle_delay_bug = true;
+            }
             QueryModifier::NoHash => {
                 if no_hash {
                     panic!("duplicate modifier `no_hash` for query `{}`", query.name);
@@ -287,6 +302,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
         cache,
         desc,
         fatal_cycle,
+        cycle_delay_bug,
         no_hash,
         no_force,
         anon,
@@ -333,6 +349,7 @@ fn add_query_description_impl(
         let tcx = tcx.as_ref().map(|t| quote! { #t }).unwrap_or(quote! { _ });
         quote! {
             #[inline]
+            #[allow(unused_variables)]
             fn cache_on_disk(#tcx: TyCtxt<'_, 'tcx, 'tcx>, #key: Self::Key) -> bool {
                 #expr
             }
@@ -348,6 +365,7 @@ fn add_query_description_impl(
     let desc = modifiers.desc.as_ref().map(|(tcx, desc)| {
         let tcx = tcx.as_ref().map(|t| quote! { #t }).unwrap_or(quote! { _ });
         quote! {
+            #[allow(unused_variables)]
             fn describe(
                 #tcx: TyCtxt<'_, '_, '_>,
                 #key: #arg,
@@ -397,6 +415,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             if modifiers.fatal_cycle {
                 attributes.push(quote! { fatal_cycle });
             };
+            // Pass on the cycle_delay_bug modifier
+            if modifiers.cycle_delay_bug {
+                attributes.push(quote! { cycle_delay_bug });
+            };
             // Pass on the no_hash modifier
             if modifiers.no_hash {
                 attributes.push(quote! { no_hash });
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 36d9bf9f50d..66daa4518be 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -862,7 +862,7 @@ impl<'a> CrateLoader<'a> {
 
     fn inject_profiler_runtime(&mut self) {
         if self.sess.opts.debugging_opts.profile ||
-            self.sess.opts.debugging_opts.pgo_gen.is_some()
+            self.sess.opts.debugging_opts.pgo_gen.enabled()
         {
             info!("loading profiler");
 
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 14416b5ce07..4078171733f 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -14,6 +14,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 extern crate libc;
 #[allow(unused_extern_crates)]
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index cbef7a7f6c4..c81da66672f 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -52,7 +52,7 @@ crate enum TwoPhaseActivation {
     ActivatedAt(Location),
 }
 
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 crate struct BorrowData<'tcx> {
     /// Location where the borrow reservation starts.
     /// In many cases, this will be equal to the activation location but not always.
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 95701204cab..e6d818152f5 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -13,6 +13,7 @@ use rustc::mir::{
     Static, StaticKind, TerminatorKind, VarBindingForm,
 };
 use rustc::ty::{self, DefIdTree};
+use rustc::ty::layout::VariantIdx;
 use rustc::ty::print::Print;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
@@ -25,8 +26,7 @@ use super::borrow_set::BorrowData;
 use super::{Context, MirBorrowckCtxt};
 use super::{InitializationRequiringAction, PrefixSet};
 use crate::dataflow::drop_flag_effects;
-use crate::dataflow::move_paths::indexes::MoveOutIndex;
-use crate::dataflow::move_paths::MovePathIndex;
+use crate::dataflow::indexes::{MovePathIndex, MoveOutIndex};
 use crate::util::borrowck_errors::{BorrowckErrors, Origin};
 
 #[derive(Debug)]
@@ -201,7 +201,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 );
             }
 
-            let ty = used_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+            let ty = used_place.ty(self.mir, self.infcx.tcx).ty;
             let needs_note = match ty.sty {
                 ty::Closure(id, _) => {
                     let tables = self.infcx.tcx.typeck_tables_of(id);
@@ -216,13 +216,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 let mpi = self.move_data.moves[move_out_indices[0]].path;
                 let place = &self.move_data.move_paths[mpi].place;
 
-                let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                let ty = place.ty(self.mir, self.infcx.tcx).ty;
                 let opt_name = self.describe_place_with_options(place, IncludingDowncast(true));
                 let note_msg = match opt_name {
                     Some(ref name) => format!("`{}`", name),
                     None => "value".to_owned(),
                 };
-                if let ty::TyKind::Param(param_ty) = ty.sty {
+                if let ty::Param(param_ty) = ty.sty {
                     let tcx = self.infcx.tcx;
                     let generics = tcx.generics_of(self.mir_def_id);
                     let def_id = generics.type_param(&param_ty, tcx).def_id;
@@ -317,7 +317,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         context: Context,
         (place, _span): (&Place<'tcx>, Span),
         borrow: &BorrowData<'tcx>,
-    ) {
+    ) -> DiagnosticBuilder<'cx> {
         let tcx = self.infcx.tcx;
 
         let borrow_spans = self.retrieve_borrow_spans(borrow);
@@ -346,7 +346,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
         self.explain_why_borrow_contains_point(context, borrow, None)
             .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None);
-        err.buffer(&mut self.errors_buffer);
+        err
     }
 
     pub(super) fn report_conflicting_borrow(
@@ -355,7 +355,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         (place, span): (&Place<'tcx>, Span),
         gen_borrow_kind: BorrowKind,
         issued_borrow: &BorrowData<'tcx>,
-    ) {
+    ) -> DiagnosticBuilder<'cx> {
         let issued_spans = self.retrieve_borrow_spans(issued_borrow);
         let issued_span = issued_spans.args_or_use();
 
@@ -459,9 +459,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         "borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe()
                     ),
                 );
-                err.buffer(&mut self.errors_buffer);
 
-                return;
+                return err;
             }
 
             (BorrowKind::Unique, _, _, _, _, _) => {
@@ -511,14 +510,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 )
             }
 
-            (BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _)
-            | (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _) => {
-                // Shallow borrows are uses from the user's point of view.
-                self.report_use_while_mutably_borrowed(context, (place, span), issued_borrow);
-                return;
-            }
             (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _)
             | (BorrowKind::Shared, _, _, BorrowKind::Shallow, _, _)
+            | (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _)
+            | (BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _)
             | (BorrowKind::Shallow, _, _, BorrowKind::Shared, _, _)
             | (BorrowKind::Shallow, _, _, BorrowKind::Shallow, _, _) => unreachable!(),
         };
@@ -566,7 +561,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             None,
         );
 
-        err.buffer(&mut self.errors_buffer);
+        err
     }
 
     /// Returns the description of the root place for a conflicting borrow and the full
@@ -600,8 +595,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         // Define a small closure that we can use to check if the type of a place
         // is a union.
         let is_union = |place: &Place<'tcx>| -> bool {
-            place.ty(self.mir, self.infcx.tcx)
-                .to_ty(self.infcx.tcx)
+            place.ty(self.mir, self.infcx.tcx).ty
                 .ty_adt_def()
                 .map(|adt| adt.is_union())
                 .unwrap_or(false)
@@ -650,7 +644,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                             // Also compute the name of the union type, eg. `Foo` so we
                             // can add a helpful note with it.
-                            let ty = base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                            let ty = base.ty(self.mir, self.infcx.tcx).ty;
 
                             return Some((desc_base, desc_first, desc_second, ty.to_string()));
                         },
@@ -1533,7 +1527,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         if let TerminatorKind::Call {
             func: Operand::Constant(box Constant {
                 literal: ty::Const {
-                    ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), ..  },
+                    ty: &ty::TyS { sty: ty::FnDef(id, _), ..  },
                     ..
                 },
                 ..
@@ -1551,7 +1545,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 };
 
                 debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
-                if let ty::TyKind::Closure(did, _) = self.mir.local_decls[closure].ty.sty {
+                if let ty::Closure(did, _) = self.mir.local_decls[closure].ty.sty {
                     let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap();
 
                     if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did)
@@ -1574,7 +1568,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
         // Check if we are just moving a closure after it has been invoked.
         if let Some(target) = target {
-            if let ty::TyKind::Closure(did, _) = self.mir.local_decls[target].ty.sty {
+            if let ty::Closure(did, _) = self.mir.local_decls[target].ty.sty {
                 let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap();
 
                 if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did)
@@ -1765,20 +1759,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     }
 
     /// End-user visible description of the `field`nth field of `base`
-    fn describe_field(&self, base: &Place<'_>, field: Field) -> String {
+    fn describe_field(&self, base: &Place<'tcx>, field: Field) -> String {
         match *base {
             Place::Base(PlaceBase::Local(local)) => {
                 let local = &self.mir.local_decls[local];
-                self.describe_field_from_ty(&local.ty, field)
+                self.describe_field_from_ty(&local.ty, field, None)
             }
             Place::Base(PlaceBase::Static(ref static_)) =>
-                self.describe_field_from_ty(&static_.ty, field),
+                self.describe_field_from_ty(&static_.ty, field, None),
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Deref => self.describe_field(&proj.base, field),
-                ProjectionElem::Downcast(def, variant_index) =>
-                    def.variants[variant_index].fields[field.index()].ident.to_string(),
+                ProjectionElem::Downcast(_, variant_index) => {
+                    let base_ty = base.ty(self.mir, self.infcx.tcx).ty;
+                    self.describe_field_from_ty(&base_ty, field, Some(variant_index))
+                }
                 ProjectionElem::Field(_, field_type) => {
-                    self.describe_field_from_ty(&field_type, field)
+                    self.describe_field_from_ty(&field_type, field, None)
                 }
                 ProjectionElem::Index(..)
                 | ProjectionElem::ConstantIndex { .. }
@@ -1790,24 +1786,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     }
 
     /// End-user visible description of the `field_index`nth field of `ty`
-    fn describe_field_from_ty(&self, ty: &ty::Ty<'_>, field: Field) -> String {
+    fn describe_field_from_ty(
+        &self,
+        ty: &ty::Ty<'_>,
+        field: Field,
+        variant_index: Option<VariantIdx>
+    ) -> String {
         if ty.is_box() {
             // If the type is a box, the field is described from the boxed type
-            self.describe_field_from_ty(&ty.boxed_ty(), field)
+            self.describe_field_from_ty(&ty.boxed_ty(), field, variant_index)
         } else {
             match ty.sty {
-                ty::Adt(def, _) => if def.is_enum() {
-                    field.index().to_string()
-                } else {
-                    def.non_enum_variant().fields[field.index()]
+                ty::Adt(def, _) => {
+                    let variant = if let Some(idx) = variant_index {
+                        assert!(def.is_enum());
+                        &def.variants[idx]
+                    } else {
+                        def.non_enum_variant()
+                    };
+                    variant.fields[field.index()]
                         .ident
                         .to_string()
                 },
                 ty::Tuple(_) => field.index().to_string(),
                 ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
-                    self.describe_field_from_ty(&ty, field)
+                    self.describe_field_from_ty(&ty, field, variant_index)
                 }
-                ty::Array(ty, _) | ty::Slice(ty) => self.describe_field_from_ty(&ty, field),
+                ty::Array(ty, _) | ty::Slice(ty) =>
+                    self.describe_field_from_ty(&ty, field, variant_index),
                 ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
                     // Convert the def-id into a node-id. node-ids are only valid for
                     // the local code in the current crate, so this returns an `Option` in case
@@ -1865,7 +1871,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         StorageDeadOrDrop::LocalStorageDead
                         | StorageDeadOrDrop::BoxedStorageDead => {
                             assert!(
-                                base.ty(self.mir, tcx).to_ty(tcx).is_box(),
+                                base.ty(self.mir, tcx).ty.is_box(),
                                 "Drop of value behind a reference or raw pointer"
                             );
                             StorageDeadOrDrop::BoxedStorageDead
@@ -1873,7 +1879,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         StorageDeadOrDrop::Destructor(_) => base_access,
                     },
                     ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
-                        let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
+                        let base_ty = base.ty(self.mir, tcx).ty;
                         match base_ty.sty {
                             ty::Adt(def, _) if def.has_dtor(tcx) => {
                                 // Report the outermost adt with a destructor
@@ -1911,7 +1917,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             } else {
                 let ty = self.infcx.tcx.type_of(self.mir_def_id);
                 match ty.sty {
-                    ty::TyKind::FnDef(_, _) | ty::TyKind::FnPtr(_) => self.annotate_fn_sig(
+                    ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig(
                         self.mir_def_id,
                         self.infcx.tcx.fn_sig(self.mir_def_id),
                     ),
@@ -2156,12 +2162,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         //    anything.
         let return_ty = sig.output();
         match return_ty.skip_binder().sty {
-            ty::TyKind::Ref(return_region, _, _) if return_region.has_name() && !is_closure => {
+            ty::Ref(return_region, _, _) if return_region.has_name() && !is_closure => {
                 // This is case 1 from above, return type is a named reference so we need to
                 // search for relevant arguments.
                 let mut arguments = Vec::new();
                 for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
-                    if let ty::TyKind::Ref(argument_region, _, _) = argument.sty {
+                    if let ty::Ref(argument_region, _, _) = argument.sty {
                         if argument_region == return_region {
                             // Need to use the `rustc::ty` types to compare against the
                             // `return_region`. Then use the `rustc::hir` type to get only
@@ -2198,7 +2204,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     return_span,
                 })
             }
-            ty::TyKind::Ref(_, _, _) if is_closure => {
+            ty::Ref(_, _, _) if is_closure => {
                 // This is case 2 from above but only for closures, return type is anonymous
                 // reference so we select
                 // the first argument.
@@ -2207,9 +2213,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                 // Closure arguments are wrapped in a tuple, so we need to get the first
                 // from that.
-                if let ty::TyKind::Tuple(elems) = argument_ty.sty {
+                if let ty::Tuple(elems) = argument_ty.sty {
                     let argument_ty = elems.first()?;
-                    if let ty::TyKind::Ref(_, _, _) = argument_ty.sty {
+                    if let ty::Ref(_, _, _) = argument_ty.sty {
                         return Some(AnnotatedBorrowFnSignature::Closure {
                             argument_ty,
                             argument_span,
@@ -2219,7 +2225,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                 None
             }
-            ty::TyKind::Ref(_, _, _) => {
+            ty::Ref(_, _, _) => {
                 // This is also case 2 from above but for functions, return type is still an
                 // anonymous reference so we select the first argument.
                 let argument_span = fn_decl.inputs.first()?.span;
@@ -2230,7 +2236,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                 // We expect the first argument to be a reference.
                 match argument_ty.sty {
-                    ty::TyKind::Ref(_, _, _) => {}
+                    ty::Ref(_, _, _) => {}
                     _ => return None,
                 }
 
@@ -2358,8 +2364,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         // this by hooking into the pretty printer and telling it to label the
         // lifetimes without names with the value `'0`.
         match ty.sty {
-            ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
-            | ty::TyKind::Ref(
+            ty::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
+            | ty::Ref(
                 ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
                 _,
                 _,
@@ -2378,7 +2384,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS);
 
         let region = match ty.sty {
-            ty::TyKind::Ref(region, _, _) => {
+            ty::Ref(region, _, _) => {
                 match region {
                     ty::RegionKind::ReLateBound(_, br)
                     | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs
index 8de39f0efc1..c0b199f1798 100644
--- a/src/librustc_mir/borrow_check/flows.rs
+++ b/src/librustc_mir/borrow_check/flows.rs
@@ -11,7 +11,7 @@ use crate::borrow_check::location::LocationIndex;
 
 use polonius_engine::Output;
 
-use crate::dataflow::move_paths::indexes::BorrowIndex;
+use crate::dataflow::indexes::BorrowIndex;
 use crate::dataflow::move_paths::HasMoveData;
 use crate::dataflow::Borrows;
 use crate::dataflow::EverInitializedPlaces;
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 5c159cda141..0b2c90b9160 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -6,6 +6,7 @@ use rustc::hir::Node;
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
 use rustc::lint::builtin::UNUSED_MUT;
+use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT};
 use rustc::middle::borrowck::SignalledError;
 use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc::mir::{
@@ -18,17 +19,18 @@ use rustc::ty::{self, TyCtxt};
 
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level};
 use rustc_data_structures::bit_set::BitSet;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
 use smallvec::SmallVec;
 
-use std::rc::Rc;
 use std::collections::BTreeMap;
+use std::mem;
+use std::rc::Rc;
 
-use syntax_pos::Span;
+use syntax_pos::{Span, DUMMY_SP};
 
 use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex};
-use crate::dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MoveError};
+use crate::dataflow::move_paths::{HasMoveData, InitLocation, LookupResult, MoveData, MoveError};
 use crate::dataflow::Borrows;
 use crate::dataflow::DataflowResultsConsumer;
 use crate::dataflow::FlowAtLocation;
@@ -238,6 +240,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         locals_are_invalidated_at_exit,
         access_place_error_reported: Default::default(),
         reservation_error_reported: Default::default(),
+        reservation_warnings: Default::default(),
         move_error_reported: BTreeMap::new(),
         uninitialized_error_reported: Default::default(),
         errors_buffer,
@@ -260,6 +263,29 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     }
     mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
 
+    // Convert any reservation warnings into lints.
+    let reservation_warnings = mem::replace(&mut mbcx.reservation_warnings, Default::default());
+    for (_, (place, span, context, bk, borrow)) in reservation_warnings {
+        let mut initial_diag = mbcx.report_conflicting_borrow(context, (&place, span), bk, &borrow);
+
+        let lint_root = if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.source_scope_local_data {
+            let scope = mbcx.mir.source_info(context.loc).scope;
+            vsi[scope].lint_root
+        } else {
+            id
+        };
+
+        // Span and message don't matter; we overwrite them below anyway
+        let mut diag = mbcx.infcx.tcx.struct_span_lint_hir(
+            MUTABLE_BORROW_RESERVATION_CONFLICT, lint_root, DUMMY_SP, "");
+
+        diag.message = initial_diag.styled_message().clone();
+        diag.span = initial_diag.span.clone();
+
+        initial_diag.cancel();
+        diag.buffer(&mut mbcx.errors_buffer);
+    }
+
     // For each non-user used mutable variable, check if it's been assigned from
     // a user-declared local. If so, then put that local into the used_mut set.
     // Note that this set is expected to be small - only upvars from closures
@@ -341,18 +367,9 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
                     // if AST-borrowck signalled no errors, then
                     // downgrade all the buffered MIR-borrowck errors
                     // to warnings.
-                    for err in &mut mbcx.errors_buffer {
-                        if err.is_error() {
-                            err.level = Level::Warning;
-                            err.warn(
-                                "this error has been downgraded to a warning for backwards \
-                                 compatibility with previous releases",
-                            );
-                            err.warn(
-                                "this represents potential undefined behavior in your code and \
-                                 this warning will become a hard error in the future",
-                            );
-                        }
+
+                    for err in mbcx.errors_buffer.iter_mut() {
+                        downgrade_if_error(err);
                     }
                 }
                 SignalledError::SawSomeError => {
@@ -378,6 +395,20 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     result
 }
 
+fn downgrade_if_error(diag: &mut Diagnostic) {
+    if diag.is_error() {
+        diag.level = Level::Warning;
+        diag.warn(
+            "this error has been downgraded to a warning for backwards \
+            compatibility with previous releases",
+        );
+        diag.warn(
+            "this represents potential undefined behavior in your code and \
+            this warning will become a hard error in the future",
+        );
+    }
+}
+
 pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
     mir: &'cx Mir<'tcx>,
@@ -410,6 +441,13 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     // but it is currently inconvenient to track down the `BorrowIndex`
     // at the time we detect and report a reservation error.
     reservation_error_reported: FxHashSet<Place<'tcx>>,
+    /// Migration warnings to be reported for #56254. We delay reporting these
+    /// so that we can suppress the warning if there's a corresponding error
+    /// for the activation of the borrow.
+    reservation_warnings: FxHashMap<
+        BorrowIndex,
+        (Place<'tcx>, Span, Context, BorrowKind, BorrowData<'tcx>)
+    >,
     /// This field keeps track of move errors that are to be reported for given move indicies.
     ///
     /// There are situations where many errors can be reported for a single move out (see #53807)
@@ -525,16 +563,12 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                     flow_state,
                 );
             }
-            StatementKind::InlineAsm {
-                ref asm,
-                ref outputs,
-                ref inputs,
-            } => {
+            StatementKind::InlineAsm(ref asm) => {
                 let context = ContextKind::InlineAsm.new(location);
-                for (o, output) in asm.outputs.iter().zip(outputs.iter()) {
+                for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
                     if o.is_indirect {
                         // FIXME(eddyb) indirect inline asm outputs should
-                        // be encoeded through MIR place derefs instead.
+                        // be encoded through MIR place derefs instead.
                         self.access_place(
                             context,
                             (output, o.span),
@@ -558,7 +592,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                         );
                     }
                 }
-                for (_, input) in inputs.iter() {
+                for (_, input) in asm.inputs.iter() {
                     self.consume_operand(context, (input, span), flow_state);
                 }
             }
@@ -616,8 +650,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                 let drop_place_ty = drop_place.ty(self.mir, self.infcx.tcx);
 
                 // Erase the regions.
-                let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty)
-                    .to_ty(self.infcx.tcx);
+                let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty;
 
                 // "Lift" into the gcx -- once regions are erased, this type should be in the
                 // global arenas; this "lift" operation basically just asserts that is true, but
@@ -688,7 +721,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                 cleanup: _,
             } => {
                 self.consume_operand(ContextKind::Assert.new(loc), (cond, span), flow_state);
-                use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
+                use rustc::mir::interpret::InterpError::BoundsCheck;
                 if let BoundsCheck { ref len, ref index } = *msg {
                     self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state);
                     self.consume_operand(ContextKind::Assert.new(loc), (index, span), flow_state);
@@ -926,11 +959,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let conflict_error =
             self.check_access_for_conflict(context, place_span, sd, rw, flow_state);
 
+        if let (Activation(_, borrow_idx), true) = (kind.1, conflict_error) {
+            // Suppress this warning when there's an error being emited for the
+            // same borrow: fixing the error is likely to fix the warning.
+            self.reservation_warnings.remove(&borrow_idx);
+        }
+
         if conflict_error || mutability_error {
             debug!(
                 "access_place: logging error place_span=`{:?}` kind=`{:?}`",
                 place_span, kind
             );
+
             self.access_place_error_reported
                 .insert((place_span.0.clone(), place_span.1));
         }
@@ -981,8 +1021,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     Control::Continue
                 }
 
-                (Read(_), BorrowKind::Shared) | (Reservation(..), BorrowKind::Shared)
-                | (Read(_), BorrowKind::Shallow) | (Reservation(..), BorrowKind::Shallow)
+                (Read(_), BorrowKind::Shared)
+                | (Read(_), BorrowKind::Shallow)
                 | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Unique)
                 | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
                     Control::Continue
@@ -996,7 +1036,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => {
                     // Reading from mere reservations of mutable-borrows is OK.
                     if !is_active(&this.dominators, borrow, context.loc) {
-                        assert!(allow_two_phase_borrow(&this.infcx.tcx, borrow.kind));
+                        assert!(allow_two_phase_borrow(&tcx, borrow.kind));
                         return Control::Continue;
                     }
 
@@ -1004,20 +1044,45 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     match kind {
                         ReadKind::Copy  => {
                             this.report_use_while_mutably_borrowed(context, place_span, borrow)
+                                .buffer(&mut this.errors_buffer);
                         }
                         ReadKind::Borrow(bk) => {
-                            this.report_conflicting_borrow(context, place_span, bk, &borrow)
+                            this.report_conflicting_borrow(context, place_span, bk, borrow)
+                                .buffer(&mut this.errors_buffer);
                         }
                     }
                     Control::Break
                 }
 
-                (Reservation(kind), BorrowKind::Unique)
-                | (Reservation(kind), BorrowKind::Mut { .. })
+                (Reservation(WriteKind::MutableBorrow(bk)), BorrowKind::Shallow)
+                | (Reservation(WriteKind::MutableBorrow(bk)), BorrowKind::Shared) if {
+                    tcx.migrate_borrowck()
+                } => {
+                    let bi = this.borrow_set.location_map[&context.loc];
+                    debug!(
+                        "recording invalid reservation of place: {:?} with \
+                         borrow index {:?} as warning",
+                        place_span.0,
+                        bi,
+                    );
+                    // rust-lang/rust#56254 - This was previously permitted on
+                    // the 2018 edition so we emit it as a warning. We buffer
+                    // these sepately so that we only emit a warning if borrow
+                    // checking was otherwise successful.
+                    this.reservation_warnings.insert(
+                        bi,
+                        (place_span.0.clone(), place_span.1, context, bk, borrow.clone()),
+                    );
+
+                    // Don't suppress actual errors.
+                    Control::Continue
+                }
+
+                (Reservation(kind), _)
                 | (Activation(kind, _), _)
                 | (Write(kind), _) => {
                     match rw {
-                        Reservation(_) => {
+                        Reservation(..) => {
                             debug!(
                                 "recording invalid reservation of \
                                  place: {:?}",
@@ -1038,7 +1103,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     error_reported = true;
                     match kind {
                         WriteKind::MutableBorrow(bk) => {
-                            this.report_conflicting_borrow(context, place_span, bk, &borrow)
+                            this.report_conflicting_borrow(context, place_span, bk, borrow)
+                                .buffer(&mut this.errors_buffer);
                         }
                         WriteKind::StorageDeadOrDrop => {
                             this.report_borrowed_value_does_not_live_long_enough(
@@ -1051,7 +1117,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             this.report_illegal_mutation_of_borrowed(context, place_span, borrow)
                         }
                         WriteKind::Move => {
-                            this.report_move_out_while_borrowed(context, place_span, &borrow)
+                            this.report_move_out_while_borrowed(context, place_span, borrow)
                         }
                     }
                     Control::Break
@@ -1211,25 +1277,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         } = self.infcx.tcx.mir_borrowck(def_id);
                         debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
                         for field in used_mut_upvars {
-                            // This relies on the current way that by-value
-                            // captures of a closure are copied/moved directly
-                            // when generating MIR.
-                            match operands[field.index()] {
-                                Operand::Move(Place::Base(PlaceBase::Local(local)))
-                                | Operand::Copy(Place::Base(PlaceBase::Local(local))) => {
-                                    self.used_mut.insert(local);
-                                }
-                                Operand::Move(ref place @ Place::Projection(_))
-                                | Operand::Copy(ref place @ Place::Projection(_)) => {
-                                    if let Some(field) = place.is_upvar_field_projection(
-                                            self.mir, &self.infcx.tcx) {
-                                        self.used_mut_upvars.push(field);
-                                    }
-                                }
-                                Operand::Move(Place::Base(PlaceBase::Static(..)))
-                                | Operand::Copy(Place::Base(PlaceBase::Static(..)))
-                                | Operand::Constant(..) => {}
-                            }
+                            self.propagate_closure_used_mut_upvar(&operands[field.index()]);
                         }
                     }
                     AggregateKind::Adt(..)
@@ -1244,6 +1292,80 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         }
     }
 
+    fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) {
+        let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| {
+            match *place {
+                Place::Projection { .. } => {
+                    if let Some(field) = place.is_upvar_field_projection(
+                            this.mir, &this.infcx.tcx) {
+                        this.used_mut_upvars.push(field);
+                    }
+                }
+                Place::Base(PlaceBase::Local(local)) => {
+                    this.used_mut.insert(local);
+                }
+                Place::Base(PlaceBase::Static(_)) => {}
+            }
+        };
+
+        // This relies on the current way that by-value
+        // captures of a closure are copied/moved directly
+        // when generating MIR.
+        match *operand {
+            Operand::Move(Place::Base(PlaceBase::Local(local)))
+            | Operand::Copy(Place::Base(PlaceBase::Local(local)))
+                if self.mir.local_decls[local].is_user_variable.is_none() =>
+            {
+                if self.mir.local_decls[local].ty.is_mutable_pointer() {
+                    // The variable will be marked as mutable by the borrow.
+                    return;
+                }
+                // This is an edge case where we have a `move` closure
+                // inside a non-move closure, and the inner closure
+                // contains a mutation:
+                //
+                // let mut i = 0;
+                // || { move || { i += 1; }; };
+                //
+                // In this case our usual strategy of assuming that the
+                // variable will be captured by mutable reference is
+                // wrong, since `i` can be copied into the inner
+                // closure from a shared reference.
+                //
+                // As such we have to search for the local that this
+                // capture comes from and mark it as being used as mut.
+
+                let temp_mpi = self.move_data.rev_lookup.find_local(local);
+                let init = if let [init_index] = *self.move_data.init_path_map[temp_mpi] {
+                    &self.move_data.inits[init_index]
+                } else {
+                    bug!("temporary should be initialized exactly once")
+                };
+
+                let loc = match init.location {
+                    InitLocation::Statement(stmt) => stmt,
+                    _ => bug!("temporary initialized in arguments"),
+                };
+
+                let bbd = &self.mir[loc.block];
+                let stmt = &bbd.statements[loc.statement_index];
+                debug!("temporary assigned in: stmt={:?}", stmt);
+
+                if let StatementKind::Assign(_, box Rvalue::Ref(_, _, ref source)) = stmt.kind {
+                    propagate_closure_used_mut_place(self, source);
+                } else {
+                    bug!("closures should only capture user variables \
+                        or references to user variables");
+                }
+            }
+            Operand::Move(ref place)
+            | Operand::Copy(ref place) => {
+                propagate_closure_used_mut_place(self, place);
+            }
+            Operand::Constant(..) => {}
+        }
+    }
+
     fn consume_operand(
         &mut self,
         context: Context,
@@ -1641,7 +1763,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             // assigning to `P.f` requires `P` itself
                             // be already initialized
                             let tcx = self.infcx.tcx;
-                            match base.ty(self.mir, tcx).to_ty(tcx).sty {
+                            match base.ty(self.mir, tcx).ty.sty {
                                 ty::Adt(def, _) if def.has_dtor(tcx) => {
                                     self.check_if_path_or_subpath_is_moved(
                                         context, InitializationRequiringAction::Assignment,
@@ -1746,7 +1868,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // no move out from an earlier location) then this is an attempt at initialization
                 // of the union - we should error in that case.
                 let tcx = this.infcx.tcx;
-                if let ty::TyKind::Adt(def, _) = base.ty(this.mir, tcx).to_ty(tcx).sty {
+                if let ty::Adt(def, _) = base.ty(this.mir, tcx).ty.sty {
                     if def.is_union() {
                         if this.move_data.path_map[mpi].iter().any(|moi| {
                             this.move_data.moves[*moi].source.is_predecessor_of(
@@ -2007,7 +2129,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             Place::Projection(ref proj) => {
                 match proj.elem {
                     ProjectionElem::Deref => {
-                        let base_ty = proj.base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let base_ty = proj.base.ty(self.mir, self.infcx.tcx).ty;
 
                         // Check the kind of deref to decide
                         match base_ty.sty {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index bd4bf67d0b1..7efe1d83c2e 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -266,7 +266,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         // Inspect the type of the content behind the
                         // borrow to provide feedback about why this
                         // was a move rather than a copy.
-                        let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let ty = place.ty(self.mir, self.infcx.tcx).ty;
                         let is_upvar_field_projection =
                             self.prefixes(&original_path, PrefixSet::All)
                             .any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
@@ -530,9 +530,9 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                     // We're only interested in assignments (in particular, where the
                     // assignment came from - was it an `Rc` or `Arc`?).
                     if let StatementKind::Assign(_, box Rvalue::Ref(_, _, source)) = &stmt.kind {
-                        let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let ty = source.ty(self.mir, self.infcx.tcx).ty;
                         let ty = match ty.sty {
-                            ty::TyKind::Ref(_, ty, _) => ty,
+                            ty::Ref(_, ty, _) => ty,
                             _ => ty,
                         };
                         debug!("borrowed_content_source: ty={:?}", ty);
@@ -555,9 +555,9 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                             _ => continue,
                         };
 
-                        let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let ty = source.ty(self.mir, self.infcx.tcx).ty;
                         let ty = match ty.sty {
-                            ty::TyKind::Ref(_, ty, _) => ty,
+                            ty::Ref(_, ty, _) => ty,
                             _ => ty,
                         };
                         debug!("borrowed_content_source: ty={:?}", ty);
@@ -581,7 +581,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             base,
             elem: ProjectionElem::Deref,
         }) = place {
-            if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_unsafe_ptr() {
+            if base.ty(self.mir, self.infcx.tcx).ty.is_unsafe_ptr() {
                 return BorrowedContentSource::DerefRawPointer;
             }
         }
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index f351212e9d5..b780511315d 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -5,7 +5,7 @@ use rustc::mir::{
     Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind,
 };
 use rustc::mir::{Terminator, TerminatorKind};
-use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
+use rustc::ty::{self, Const, DefIdTree, TyS, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 use syntax_pos::symbol::keywords;
@@ -64,7 +64,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 elem: ProjectionElem::Field(upvar_index, _),
             }) => {
                 debug_assert!(is_closure_or_generator(
-                    base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx)
+                    base.ty(self.mir, self.infcx.tcx).ty
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
@@ -85,7 +85,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                     item_msg = format!("`{}`", access_place_desc.unwrap());
                     debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
                     debug_assert!(is_closure_or_generator(
-                        the_place_err.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx)
+                        the_place_err.ty(self.mir, self.infcx.tcx).ty
                     ));
 
                     reason = if access_place.is_upvar_field_projection(self.mir,
@@ -110,7 +110,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                     reason = ", as it is immutable for the pattern guard".to_string();
                 } else {
                     let pointer_type =
-                        if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_region_ptr() {
+                        if base.ty(self.mir, self.infcx.tcx).ty.is_region_ptr() {
                             "`&` reference"
                         } else {
                             "`*const` pointer"
@@ -232,7 +232,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
 
                 if let Some((span, message)) = annotate_struct_field(
                     self.infcx.tcx,
-                    base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx),
+                    base.ty(self.mir, self.infcx.tcx).ty,
                     field,
                 ) {
                     err.span_suggestion(
@@ -261,7 +261,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                             // Otherwise, check if the name is the self kewyord - in which case
                             // we have an explicit self. Do the same thing in this case and check
                             // for a `self: &mut Self` to suggest removing the `&mut`.
-                            if let ty::TyKind::Ref(
+                            if let ty::Ref(
                                 _, _, hir::Mutability::MutMutable
                             ) = local_decl.ty.sty {
                                 true
@@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 elem: ProjectionElem::Field(upvar_index, _),
             }) => {
                 debug_assert!(is_closure_or_generator(
-                    base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx)
+                    base.ty(self.mir, self.infcx.tcx).ty
                 ));
 
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
@@ -476,7 +476,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                                     func: Operand::Constant(box Constant {
                                         literal: Const {
                                             ty: &TyS {
-                                                sty: TyKind::FnDef(id, substs),
+                                                sty: ty::FnDef(id, substs),
                                                 ..
                                             },
                                             ..
@@ -633,8 +633,8 @@ fn annotate_struct_field(
     field: &mir::Field,
 ) -> Option<(Span, String)> {
     // Expect our local to be a reference to a struct of some kind.
-    if let ty::TyKind::Ref(_, ty, _) = ty.sty {
-        if let ty::TyKind::Adt(def, _) = ty.sty {
+    if let ty::Ref(_, ty, _) = ty.sty {
+        if let ty::Adt(def, _) = ty.sty {
             let field = def.all_fields().nth(field.index())?;
             // Use the HIR types to construct the diagnostic message.
             let hir_id = tcx.hir().as_local_hir_id(field.did)?;
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index 375dd6e97f1..bf9cff1e4ae 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -174,7 +174,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
         &mut self,
         _place: &Place<'tcx>,
         _variance: &ty::Variance,
-        _user_ty: &UserTypeProjection<'tcx>,
+        _user_ty: &UserTypeProjection,
         _location: Location,
     ) {
     }
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 67b77605f3c..e30938bc326 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -589,7 +589,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                 // Check the type for a trait object.
                                 return match ty.sty {
                                     // `&dyn Trait`
-                                    ty::TyKind::Ref(_, ty, _) if ty.is_trait() => true,
+                                    ty::Ref(_, ty, _) if ty.is_trait() => true,
                                     // `Box<dyn Trait>`
                                     _ if ty.is_box() && ty.boxed_ty().is_trait() => true,
                                     // `dyn Trait`
diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs
index 9714398d9d6..926f52b7cfc 100644
--- a/src/librustc_mir/borrow_check/nll/facts.rs
+++ b/src/librustc_mir/borrow_check/nll/facts.rs
@@ -72,18 +72,6 @@ impl Atom for BorrowIndex {
     }
 }
 
-impl From<usize> for BorrowIndex {
-    fn from(i: usize) -> BorrowIndex {
-        BorrowIndex::new(i)
-    }
-}
-
-impl From<BorrowIndex> for usize {
-    fn from(vid: BorrowIndex) -> usize {
-        Idx::index(vid)
-    }
-}
-
 impl Atom for LocationIndex {
     fn index(self) -> usize {
         Idx::index(self)
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index aafbff35776..36d3a03cdfd 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -9,7 +9,7 @@ use crate::borrow_check::ArtificialField;
 use crate::borrow_check::{ReadKind, WriteKind};
 use crate::borrow_check::nll::facts::AllFacts;
 use crate::borrow_check::path_utils::*;
-use crate::dataflow::move_paths::indexes::BorrowIndex;
+use crate::dataflow::indexes::BorrowIndex;
 use rustc::ty::TyCtxt;
 use rustc::mir::visit::Visitor;
 use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase, Rvalue};
@@ -92,16 +92,12 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
                     JustWrite,
                 );
             }
-            StatementKind::InlineAsm {
-                ref asm,
-                ref outputs,
-                ref inputs,
-            } => {
+            StatementKind::InlineAsm(ref asm) => {
                 let context = ContextKind::InlineAsm.new(location);
-                for (o, output) in asm.outputs.iter().zip(outputs.iter()) {
+                for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
                     if o.is_indirect {
                         // FIXME(eddyb) indirect inline asm outputs should
-                        // be encoeded through MIR place derefs instead.
+                        // be encoded through MIR place derefs instead.
                         self.access_place(
                             context,
                             output,
@@ -117,7 +113,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
                         );
                     }
                 }
-                for (_, input) in inputs.iter() {
+                for (_, input) in asm.inputs.iter() {
                     self.consume_operand(context, input);
                 }
             }
@@ -215,7 +211,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
                 cleanup: _,
             } => {
                 self.consume_operand(ContextKind::Assert.new(location), cond);
-                use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
+                use rustc::mir::interpret::InterpError::BoundsCheck;
                 if let BoundsCheck { ref len, ref index } = *msg {
                     self.consume_operand(ContextKind::Assert.new(location), len);
                     self.consume_operand(ContextKind::Assert.new(location), index);
@@ -432,11 +428,11 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
                         // have already taken the reservation
                     }
 
-                    (Read(_), BorrowKind::Shallow) | (Reservation(..), BorrowKind::Shallow)
-                    | (Read(_), BorrowKind::Shared) | (Reservation(..), BorrowKind::Shared)
+                    (Read(_), BorrowKind::Shallow)
+                    | (Read(_), BorrowKind::Shared)
                     | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Unique)
                     | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
-                        // Reads/reservations don't invalidate shared or shallow borrows
+                        // Reads don't invalidate shared or shallow borrows
                     }
 
                     (Read(_), BorrowKind::Unique) | (Read(_), BorrowKind::Mut { .. }) => {
@@ -452,16 +448,15 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
                         this.generate_invalidates(borrow_index, context.loc);
                     }
 
-                    (Reservation(_), BorrowKind::Unique)
-                        | (Reservation(_), BorrowKind::Mut { .. })
-                        | (Activation(_, _), _)
-                        | (Write(_), _) => {
-                            // unique or mutable borrows are invalidated by writes.
-                            // Reservations count as writes since we need to check
-                            // that activating the borrow will be OK
-                            // FIXME(bob_twinkles) is this actually the right thing to do?
-                            this.generate_invalidates(borrow_index, context.loc);
-                        }
+                    (Reservation(_), _)
+                    | (Activation(_, _), _)
+                    | (Write(_), _) => {
+                        // unique or mutable borrows are invalidated by writes.
+                        // Reservations count as writes since we need to check
+                        // that activating the borrow will be OK
+                        // FIXME(bob_twinkles) is this actually the right thing to do?
+                        this.generate_invalidates(borrow_index, context.loc);
+                    }
                 }
                 Control::Continue
             },
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index 3773f1a40c7..917e383cae8 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -583,7 +583,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             (self.to_error_region(fr), self.to_error_region(outlived_fr))
         {
             if let Some(ty::TyS {
-                sty: ty::TyKind::Opaque(did, substs),
+                sty: ty::Opaque(did, substs),
                 ..
             }) = infcx
                 .tcx
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
index f0df7070e6b..4c4b4c04319 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
@@ -3,7 +3,7 @@ use crate::borrow_check::nll::region_infer::values::{self, PointIndex, RegionVal
 use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
 use crate::borrow_check::nll::type_check::NormalizeLocation;
 use crate::borrow_check::nll::type_check::TypeChecker;
-use crate::dataflow::move_paths::indexes::MovePathIndex;
+use crate::dataflow::indexes::MovePathIndex;
 use crate::dataflow::move_paths::MoveData;
 use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
 use rustc::infer::canonical::QueryRegionConstraint;
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 3b559b28f12..ec5637d1707 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -28,7 +28,7 @@ use rustc::infer::canonical::QueryRegionConstraint;
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
 use rustc::infer::type_variable::TypeVariableOrigin;
-use rustc::mir::interpret::{EvalErrorKind::BoundsCheck, ConstValue};
+use rustc::mir::interpret::{InterpError::BoundsCheck, ConstValue};
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
 use rustc::mir::*;
@@ -39,7 +39,7 @@ use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::{Subst, SubstsRef, UnpackedKind, UserSubsts};
 use rustc::ty::{
-    self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserType,
+    self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, UserType,
     CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
     UserTypeAnnotationIndex,
 };
@@ -450,9 +450,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
         let place_ty = match place {
-            Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
-                ty: self.mir.local_decls[*index].ty,
-            },
+            Place::Base(PlaceBase::Local(index)) =>
+                PlaceTy::from_ty(self.mir.local_decls[*index].ty),
             Place::Base(PlaceBase::Static(box Static { kind, ty: sty })) => {
                 let sty = self.sanitize_type(place, sty);
                 let check_err =
@@ -493,7 +492,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                         check_err(self, place, ty, sty);
                     }
                 }
-                PlaceTy::Ty { ty: sty }
+                PlaceTy::from_ty(sty)
             }
             Place::Projection(ref proj) => {
                 let base_context = if context.is_mutating_use() {
@@ -502,12 +501,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                     PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
                 };
                 let base_ty = self.sanitize_place(&proj.base, location, base_context);
-                if let PlaceTy::Ty { ty } = base_ty {
-                    if ty.references_error() {
+                if base_ty.variant_index.is_none() {
+                    if base_ty.ty.references_error() {
                         assert!(self.errors_reported);
-                        return PlaceTy::Ty {
-                            ty: self.tcx().types.err,
-                        };
+                        return PlaceTy::from_ty(self.tcx().types.err);
                     }
                 }
                 self.sanitize_projection(base_ty, &proj.elem, place, location)
@@ -517,7 +514,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             let tcx = self.tcx();
             let trait_ref = ty::TraitRef {
                 def_id: tcx.lang_items().copy_trait().unwrap(),
-                substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]),
+                substs: tcx.mk_substs_trait(place_ty.ty, &[]),
             };
 
             // In order to have a Copy operand, the type T of the
@@ -615,40 +612,40 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
         let tcx = self.tcx();
-        let base_ty = base.to_ty(tcx);
+        let base_ty = base.ty;
         match *pi {
             ProjectionElem::Deref => {
                 let deref_ty = base_ty.builtin_deref(true);
-                PlaceTy::Ty {
-                    ty: deref_ty.map(|t| t.ty).unwrap_or_else(|| {
+                PlaceTy::from_ty(
+                    deref_ty.map(|t| t.ty).unwrap_or_else(|| {
                         span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty)
-                    }),
-                }
+                    })
+                )
             }
             ProjectionElem::Index(i) => {
-                let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).to_ty(tcx);
+                let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).ty;
                 if index_ty != tcx.types.usize {
-                    PlaceTy::Ty {
-                        ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
-                    }
+                    PlaceTy::from_ty(
+                        span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
+                    )
                 } else {
-                    PlaceTy::Ty {
-                        ty: base_ty.builtin_index().unwrap_or_else(|| {
+                    PlaceTy::from_ty(
+                        base_ty.builtin_index().unwrap_or_else(|| {
                             span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
                         }),
-                    }
+                    )
                 }
             }
             ProjectionElem::ConstantIndex { .. } => {
                 // consider verifying in-bounds
-                PlaceTy::Ty {
-                    ty: base_ty.builtin_index().unwrap_or_else(|| {
+                PlaceTy::from_ty(
+                    base_ty.builtin_index().unwrap_or_else(|| {
                         span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
                     }),
-                }
+                )
             }
-            ProjectionElem::Subslice { from, to } => PlaceTy::Ty {
-                ty: match base_ty.sty {
+            ProjectionElem::Subslice { from, to } => PlaceTy::from_ty(
+                match base_ty.sty {
                     ty::Array(inner, size) => {
                         let size = size.unwrap_usize(tcx);
                         let min_size = (from as u64) + (to as u64);
@@ -666,35 +663,39 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                     ty::Slice(..) => base_ty,
                     _ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty),
                 },
-            },
-            ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
-                ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
+            ),
+            ProjectionElem::Downcast(maybe_name, index) => match base_ty.sty {
+                ty::Adt(adt_def, _substs) if adt_def.is_enum() => {
                     if index.as_usize() >= adt_def.variants.len() {
-                        PlaceTy::Ty {
-                            ty: span_mirbug_and_err!(
+                        PlaceTy::from_ty(
+                            span_mirbug_and_err!(
                                 self,
                                 place,
                                 "cast to variant #{:?} but enum only has {:?}",
                                 index,
                                 adt_def.variants.len()
                             ),
-                        }
+                        )
                     } else {
-                        PlaceTy::Downcast {
-                            adt_def,
-                            substs,
-                            variant_index: index,
+                        PlaceTy {
+                            ty: base_ty,
+                            variant_index: Some(index),
                         }
                     }
                 }
-                _ => PlaceTy::Ty {
-                    ty: span_mirbug_and_err!(
-                        self,
-                        place,
-                        "can't downcast {:?} as {:?}",
-                        base_ty,
-                        adt_def1
-                    ),
+                _ => {
+                    let ty = if let Some(name) = maybe_name {
+                        span_mirbug_and_err!(
+                            self,
+                            place,
+                            "can't downcast {:?} as {:?}",
+                            base_ty,
+                            name
+                        )
+                    } else {
+                        span_mirbug_and_err!(self, place, "can't downcast {:?}", base_ty)
+                    };
+                    PlaceTy::from_ty(ty)
                 },
             },
             ProjectionElem::Field(field, fty) => {
@@ -723,7 +724,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                         field_count
                     ),
                 }
-                PlaceTy::Ty { ty: fty }
+                PlaceTy::from_ty(fty)
             }
         }
     }
@@ -743,12 +744,13 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         let tcx = self.tcx();
 
         let (variant, substs) = match base_ty {
-            PlaceTy::Downcast {
-                adt_def,
-                substs,
-                variant_index,
-            } => (&adt_def.variants[variant_index], substs),
-            PlaceTy::Ty { ty } => match ty.sty {
+            PlaceTy { ty, variant_index: Some(variant_index) } => {
+                match ty.sty {
+                    ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs),
+                    _ => bug!("can't have downcast of non-adt type"),
+                }
+            }
+            PlaceTy { ty, variant_index: None } => match ty.sty {
                 ty::Adt(adt_def, substs) if !adt_def.is_enum() =>
                     (&adt_def.variants[VariantIdx::new(0)], substs),
                 ty::Closure(def_id, substs) => {
@@ -1134,7 +1136,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         category: ConstraintCategory,
     ) -> Fallible<()> {
         if let Err(terr) = self.sub_types(sub, sup, locations, category) {
-            if let TyKind::Opaque(..) = sup.sty {
+            if let ty::Opaque(..) = sup.sty {
                 // When you have `let x: impl Foo = ...` in a closure,
                 // the resulting inferend values are stored with the
                 // def-id of the base function.
@@ -1161,7 +1163,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         &mut self,
         a: Ty<'tcx>,
         v: ty::Variance,
-        user_ty: &UserTypeProjection<'tcx>,
+        user_ty: &UserTypeProjection,
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
@@ -1185,7 +1187,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
                 user_ty.base, annotated_type, user_ty.projs, curr_projected_ty);
 
-        let ty = curr_projected_ty.to_ty(tcx);
+        let ty = curr_projected_ty.ty;
         self.relate_types(a, v, ty, locations, category)?;
 
         Ok(())
@@ -1333,7 +1335,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     _ => ConstraintCategory::Assignment,
                 };
 
-                let place_ty = place.ty(mir, tcx).to_ty(tcx);
+                let place_ty = place.ty(mir, tcx).ty;
                 let rv_ty = rv.ty(mir, tcx);
                 if let Err(terr) =
                     self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
@@ -1385,9 +1387,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 ref place,
                 variant_index,
             } => {
-                let place_type = place.ty(mir, tcx).to_ty(tcx);
+                let place_type = place.ty(mir, tcx).ty;
                 let adt = match place_type.sty {
-                    TyKind::Adt(adt, _) if adt.is_enum() => adt,
+                    ty::Adt(adt, _) if adt.is_enum() => adt,
                     _ => {
                         span_bug!(
                             stmt.source_info.span,
@@ -1407,7 +1409,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 };
             }
             StatementKind::AscribeUserType(ref place, variance, box ref projection) => {
-                let place_ty = place.ty(mir, tcx).to_ty(tcx);
+                let place_ty = place.ty(mir, tcx).ty;
                 if let Err(terr) = self.relate_type_and_user_type(
                     place_ty,
                     variance,
@@ -1463,7 +1465,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 target: _,
                 unwind: _,
             } => {
-                let place_ty = location.ty(mir, tcx).to_ty(tcx);
+                let place_ty = location.ty(mir, tcx).ty;
                 let rv_ty = value.ty(mir, tcx);
 
                 let locations = term_location.to_locations();
@@ -1611,7 +1613,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         let tcx = self.tcx();
         match *destination {
             Some((ref dest, _target_block)) => {
-                let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
+                let dest_ty = dest.ty(mir, tcx).ty;
                 let category = match *dest {
                     Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
                         if let Some(BorrowCheckContext {
@@ -2370,7 +2372,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             match *elem {
                 ProjectionElem::Deref => {
                     let tcx = self.infcx.tcx;
-                    let base_ty = base.ty(mir, tcx).to_ty(tcx);
+                    let base_ty = base.ty(mir, tcx).ty;
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.sty {
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index 6bc56ab721f..8269b7b95f4 100644
--- a/src/librustc_mir/borrow_check/place_ext.rs
+++ b/src/librustc_mir/borrow_check/place_ext.rs
@@ -63,7 +63,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
                     tcx, mir, locals_state_at_exit),
 
                 ProjectionElem::Deref => {
-                    let ty = proj.base.ty(mir, tcx).to_ty(tcx);
+                    let ty = proj.base.ty(mir, tcx).ty;
                     match ty.sty {
                         // For both derefs of raw pointers and `&T`
                         // references, the original path is `Copy` and
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 52119d6b19b..fbe8b8485dd 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -191,7 +191,7 @@ fn place_components_conflict<'gcx, 'tcx>(
                     Place::Projection(box Projection { base, elem }) => (base, elem),
                     _ => bug!("place has no base?"),
                 };
-                let base_ty = base.ty(mir, tcx).to_ty(tcx);
+                let base_ty = base.ty(mir, tcx).ty;
 
                 match (elem, &base_ty.sty, access) {
                     (_, _, Shallow(Some(ArtificialField::ArrayLength)))
@@ -427,7 +427,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                         debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
                         Overlap::EqualOrDisjoint
                     } else {
-                        let ty = pi1.base.ty(mir, tcx).to_ty(tcx);
+                        let ty = pi1.base.ty(mir, tcx).ty;
                         match ty.sty {
                             ty::Adt(def, _) if def.is_union() => {
                                 // Different fields of a union, we are basically stuck.
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index e70c9e81ebd..866f1cf994e 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -139,7 +139,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
             // derefs, except we stop at the deref of a shared
             // reference.
 
-            let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+            let ty = proj.base.ty(self.mir, self.tcx).ty;
             match ty.sty {
                 ty::RawPtr(_) |
                 ty::Ref(
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index cba5039122a..7469aceee3a 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -163,7 +163,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         // Then, the block may have an optional trailing expression which is a “return” value
         // of the block, which is stored into `destination`.
         let tcx = this.hir.tcx();
-        let destination_ty = destination.ty(&this.local_decls, tcx).to_ty(tcx);
+        let destination_ty = destination.ty(&this.local_decls, tcx).ty;
         if let Some(expr) = expr {
             let tail_result_is_ignored = destination_ty.is_unit() ||
                 this.block_context.currently_ignores_tail_results();
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs
index 199d03ac445..f7cf0902013 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -4,7 +4,7 @@ use crate::build::expr::category::Category;
 use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
-use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
+use rustc::mir::interpret::InterpError::BoundsCheck;
 use rustc::mir::*;
 use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
 
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 84f74484e60..7289dd96edb 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -7,7 +7,7 @@ use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
 use rustc::middle::region;
-use rustc::mir::interpret::EvalErrorKind;
+use rustc::mir::interpret::InterpError;
 use rustc::mir::*;
 use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts};
 use syntax_pos::Span;
@@ -101,7 +101,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         block,
                         Operand::Move(is_min),
                         false,
-                        EvalErrorKind::OverflowNeg,
+                        InterpError::OverflowNeg,
                         expr_span,
                     );
                 }
@@ -433,7 +433,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             let val = result_value.clone().field(val_fld, ty);
             let of = result_value.field(of_fld, bool_ty);
 
-            let err = EvalErrorKind::Overflow(op);
+            let err = InterpError::Overflow(op);
 
             block = self.assert(block, Operand::Move(of), false, err, span);
 
@@ -444,9 +444,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // and 2. there are two possible failure cases, divide-by-zero and overflow.
 
                 let (zero_err, overflow_err) = if op == BinOp::Div {
-                    (EvalErrorKind::DivisionByZero, EvalErrorKind::Overflow(op))
+                    (InterpError::DivisionByZero, InterpError::Overflow(op))
                 } else {
-                    (EvalErrorKind::RemainderByZero, EvalErrorKind::Overflow(op))
+                    (InterpError::RemainderByZero, InterpError::Overflow(op))
                 };
 
                 // Check for / 0
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs
index 9527a232795..b58914b017f 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir/build/expr/stmt.rs
@@ -188,11 +188,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     block,
                     Statement {
                         source_info,
-                        kind: StatementKind::InlineAsm {
-                            asm: box asm.clone(),
+                        kind: StatementKind::InlineAsm(box InlineAsm {
+                            asm: asm.clone(),
                             outputs,
                             inputs,
-                        },
+                        }),
                     },
                 );
                 this.block_context.pop();
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index be3d730c61a..566f1790f8f 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -374,7 +374,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 let ty_source_info = self.source_info(user_ty_span);
                 let user_ty = box pat_ascription_ty.user_ty(
                     &mut self.canonical_user_type_annotations,
-                    place.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
+                    place.ty(&self.local_decls, self.hir.tcx()).ty,
                     ty_source_info.span,
                 );
                 self.cfg.push(
@@ -575,7 +575,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub(super) fn visit_bindings(
         &mut self,
         pattern: &Pattern<'tcx>,
-        pattern_user_ty: UserTypeProjections<'tcx>,
+        pattern_user_ty: UserTypeProjections,
         f: &mut impl FnMut(
             &mut Self,
             Mutability,
@@ -584,7 +584,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             HirId,
             Span,
             Ty<'tcx>,
-            UserTypeProjections<'tcx>,
+            UserTypeProjections,
         ),
     ) {
         debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty);
@@ -1293,7 +1293,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows);
 
         all_fake_borrows.into_iter().map(|matched_place| {
-            let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).to_ty(tcx);
+            let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;
             let fake_borrow_ty = tcx.mk_imm_ref(tcx.types.re_erased, fake_borrow_deref_ty);
             let fake_borrow_temp = self.local_decls.push(
                 LocalDecl::new_temp(fake_borrow_ty, temp_span)
@@ -1587,7 +1587,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
             let user_ty = box ascription.user_ty.clone().user_ty(
                 &mut self.canonical_user_type_annotations,
-                ascription.source.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
+                ascription.source.ty(&self.local_decls, self.hir.tcx()).ty,
                 source_info.span
             );
             self.cfg.push(
@@ -1701,7 +1701,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         mode: BindingMode,
         var_id: HirId,
         var_ty: Ty<'tcx>,
-        user_ty: UserTypeProjections<'tcx>,
+        user_ty: UserTypeProjections,
         has_guard: ArmHasGuard,
         opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
         pat_span: Span,
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 0c93984fda8..b0602219610 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -693,7 +693,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         // So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
         // we want to create a set of derived match-patterns like
         // `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
-        let elem = ProjectionElem::Downcast(adt_def, variant_index);
+        let elem = ProjectionElem::Downcast(
+            Some(adt_def.variants[variant_index].ident.name), variant_index);
         let downcast_place = match_pair.place.elem(elem); // `(x as Variant)`
         let consequent_match_pairs =
             subpatterns.iter()
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index d76d3765ac7..d71a13dec5a 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -70,7 +70,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
     pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
         let tcx = self.hir.tcx();
-        let ty = place.ty(&self.local_decls, tcx).to_ty(tcx);
+        let ty = place.ty(&self.local_decls, tcx).ty;
         if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) {
             Operand::Move(place)
         } else {
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 2268568c5f8..4c8ab361e04 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -23,7 +23,7 @@ use syntax::source_map::{Span, DUMMY_SP};
 use crate::interpret::{self,
     PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Immediate, Scalar, Pointer,
     RawConst, ConstValue,
-    EvalResult, EvalError, EvalErrorKind, GlobalId, InterpretCx, StackPopCleanup,
+    EvalResult, EvalError, InterpError, GlobalId, InterpretCx, StackPopCleanup,
     Allocation, AllocId, MemoryKind,
     snapshot, RefTracking,
 };
@@ -173,7 +173,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
 
 impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
     fn into(self) -> EvalError<'tcx> {
-        EvalErrorKind::MachineError(self.to_string()).into()
+        InterpError::MachineError(self.to_string()).into()
     }
 }
 
@@ -351,7 +351,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
         Ok(Some(match ecx.load_mir(instance.def) {
             Ok(mir) => mir,
             Err(err) => {
-                if let EvalErrorKind::NoMirFor(ref path) = err.kind {
+                if let InterpError::NoMirFor(ref path) = err.kind {
                     return Err(
                         ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path))
                             .into(),
@@ -615,22 +615,9 @@ pub fn const_eval_raw_provider<'a, 'tcx>(
     let cid = key.value;
     let def_id = cid.instance.def.def_id();
 
-    if let Some(id) = tcx.hir().as_local_hir_id(def_id) {
-        let tables = tcx.typeck_tables_of(def_id);
-
-        // Do match-check before building MIR
-        // FIXME(#59378) check_match may have errored but we're not checking for that anymore
-        tcx.check_match(def_id);
-
-        if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind_by_hir_id(id) {
-            tcx.mir_const_qualif(def_id);
-        }
-
-        // Do not continue into miri if typeck errors occurred; it will fail horribly
-        if tables.tainted_by_errors {
-            return Err(ErrorHandled::Reported)
-        }
-    };
+    if def_id.is_local() && tcx.typeck_tables_of(def_id).tainted_by_errors {
+        return Err(ErrorHandled::Reported);
+    }
 
     let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
     res.and_then(|place| {
@@ -679,7 +666,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>(
                 // any other kind of error will be reported to the user as a deny-by-default lint
                 _ => if let Some(p) = cid.promoted {
                     let span = tcx.optimized_mir(def_id).promoted[p].span;
-                    if let EvalErrorKind::ReferencedConstant = err.error {
+                    if let InterpError::ReferencedConstant = err.error {
                         err.report_as_error(
                             tcx.at(span),
                             "evaluation of constant expression failed",
diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index f78c82a9302..aae4590a387 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -49,7 +49,7 @@ pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
 fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                                             mir: &Mir<'tcx>,
                                                             place: &mir::Place<'tcx>) -> bool {
-    let ty = place.ty(mir, tcx).to_ty(tcx);
+    let ty = place.ty(mir, tcx).ty;
     match ty.sty {
         ty::Array(..) => {
             debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
@@ -141,7 +141,7 @@ pub(crate) fn on_all_drop_children_bits<'a, 'gcx, 'tcx, F>(
 {
     on_all_children_bits(tcx, mir, &ctxt.move_data, path, |child| {
         let place = &ctxt.move_data.move_paths[path].place;
-        let ty = place.ty(mir, tcx).to_ty(tcx);
+        let ty = place.ty(mir, tcx).ty;
         debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, place, ty);
 
         let gcx = tcx.global_tcx();
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index b47aff3a4f8..43cb0ed4565 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -10,13 +10,18 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 use crate::dataflow::{BitDenotation, BlockSets, InitialFlow};
-pub use crate::dataflow::indexes::BorrowIndex;
 use crate::borrow_check::nll::region_infer::RegionInferenceContext;
 use crate::borrow_check::nll::ToRegionVid;
 use crate::borrow_check::places_conflict;
 
 use std::rc::Rc;
 
+newtype_index! {
+    pub struct BorrowIndex {
+        DEBUG_FORMAT = "bw{}"
+    }
+}
+
 /// `Borrows` stores the data used in the analyses that track the flow
 /// of borrows.
 ///
@@ -288,8 +293,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'gcx, 'tcx> {
                 self.kill_borrows_on_place(sets, &Place::Base(PlaceBase::Local(local)));
             }
 
-            mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => {
-                for (output, kind) in outputs.iter().zip(&asm.outputs) {
+            mir::StatementKind::InlineAsm(ref asm) => {
+                for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
                     if !kind.is_indirect && !kind.is_rw {
                         self.kill_borrows_on_place(sets, output);
                     }
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index af0e3f5a270..83221aca6c5 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -33,7 +33,12 @@ mod graphviz;
 mod impls;
 pub mod move_paths;
 
-pub(crate) use self::move_paths::indexes;
+pub(crate) mod indexes {
+    pub(crate) use super::{
+        move_paths::{MovePathIndex, MoveOutIndex, InitIndex},
+        impls::borrows::BorrowIndex,
+    };
+}
 
 pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD>
 where
diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
index 6dcc0325ec1..b26547c4ff7 100644
--- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs
+++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
@@ -18,8 +18,7 @@ use rustc::ty::Ty;
 pub struct AbstractOperand;
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct AbstractType;
-pub type AbstractElem<'tcx> =
-    ProjectionElem<'tcx, AbstractOperand, AbstractType>;
+pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
 
 pub trait Lift {
     type Abstract;
@@ -38,7 +37,7 @@ impl<'tcx> Lift for Ty<'tcx> {
     fn lift(&self) -> Self::Abstract { AbstractType }
 }
 impl<'tcx> Lift for PlaceElem<'tcx> {
-    type Abstract = AbstractElem<'tcx>;
+    type Abstract = AbstractElem;
     fn lift(&self) -> Self::Abstract {
         match *self {
             ProjectionElem::Deref =>
@@ -56,7 +55,7 @@ impl<'tcx> Lift for PlaceElem<'tcx> {
                     from_end,
                 },
             ProjectionElem::Downcast(a, u) =>
-                ProjectionElem::Downcast(a.clone(), u.clone()),
+                ProjectionElem::Downcast(a, u.clone()),
         }
     }
 }
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 71805fd02b8..2471c01e3f3 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -120,7 +120,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
         let base = self.move_path_for(&proj.base)?;
         let mir = self.builder.mir;
         let tcx = self.builder.tcx;
-        let place_ty = proj.base.ty(mir, tcx).to_ty(tcx);
+        let place_ty = proj.base.ty(mir, tcx).ty;
         match place_ty.sty {
             ty::Ref(..) | ty::RawPtr(..) =>
                 return Err(MoveError::cannot_move_out_of(
@@ -272,13 +272,13 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
             StatementKind::FakeRead(_, ref place) => {
                 self.create_move_path(place);
             }
-            StatementKind::InlineAsm { ref outputs, ref inputs, ref asm } => {
-                for (output, kind) in outputs.iter().zip(&asm.outputs) {
+            StatementKind::InlineAsm(ref asm) => {
+                for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
                     if !kind.is_indirect {
                         self.gather_init(output, InitKind::Deep);
                     }
                 }
-                for (_, input) in inputs.iter() {
+                for (_, input) in asm.inputs.iter() {
                     self.gather_operand(input);
                 }
             }
@@ -424,8 +424,8 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
             Place::Projection(box Projection {
                 base,
                 elem: ProjectionElem::Field(_, _),
-            }) if match base.ty(self.builder.mir, self.builder.tcx).to_ty(self.builder.tcx).sty {
-                    ty::TyKind::Adt(def, _) if def.is_union() => true,
+            }) if match base.ty(self.builder.mir, self.builder.tcx).ty.sty {
+                    ty::Adt(def, _) if def.is_union() => true,
                     _ => false,
             } => base,
             // Otherwise, lookup the place.
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index 7eef68e5f80..8810be9326b 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -1,7 +1,7 @@
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::util::nodemap::FxHashMap;
-use rustc_data_structures::indexed_vec::{IndexVec};
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use smallvec::SmallVec;
 use syntax_pos::{Span};
 
@@ -12,66 +12,23 @@ use self::abs_domain::{AbstractElem, Lift};
 
 mod abs_domain;
 
-// This submodule holds some newtype'd Index wrappers that are using
-// NonZero to ensure that Option<Index> occupies only a single word.
-// They are in a submodule to impose privacy restrictions; namely, to
-// ensure that other code does not accidentally access `index.0`
-// (which is likely to yield a subtle off-by-one error).
-pub(crate) mod indexes {
-    use std::fmt;
-    use std::num::NonZeroUsize;
-    use rustc_data_structures::indexed_vec::Idx;
-
-    macro_rules! new_index {
-        ($(#[$attrs:meta])* $Index:ident, $debug_name:expr) => {
-            #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-            pub struct $Index(NonZeroUsize);
-
-            impl Idx for $Index {
-                fn new(idx: usize) -> Self {
-                    $Index(NonZeroUsize::new(idx + 1).unwrap())
-                }
-                fn index(self) -> usize {
-                    self.0.get() - 1
-                }
-            }
-
-            impl fmt::Debug for $Index {
-                fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    write!(fmt, "{}{}", $debug_name, self.index())
-                }
-            }
-        }
+newtype_index! {
+    pub struct MovePathIndex {
+        DEBUG_FORMAT = "mp{}"
     }
+}
 
-    new_index!(
-        /// Index into MovePathData.move_paths
-        MovePathIndex,
-        "mp"
-    );
-
-    new_index!(
-        /// Index into MoveData.moves.
-        MoveOutIndex,
-        "mo"
-    );
-
-    new_index!(
-        /// Index into MoveData.inits.
-        InitIndex,
-        "in"
-    );
-
-    new_index!(
-        /// Index into Borrows.locations
-        BorrowIndex,
-        "bw"
-    );
+newtype_index! {
+    pub struct MoveOutIndex {
+        DEBUG_FORMAT = "mo{}"
+    }
 }
 
-pub use self::indexes::MovePathIndex;
-pub use self::indexes::MoveOutIndex;
-pub use self::indexes::InitIndex;
+newtype_index! {
+    pub struct InitIndex {
+        DEBUG_FORMAT = "in{}"
+    }
+}
 
 impl MoveOutIndex {
     pub fn move_path_index(&self, move_data: &MoveData<'_>) -> MovePathIndex {
@@ -148,7 +105,7 @@ pub struct MoveData<'tcx> {
     /// particular path being moved.)
     pub loc_map: LocationMap<SmallVec<[MoveOutIndex; 4]>>,
     pub path_map: IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
-    pub rev_lookup: MovePathLookup<'tcx>,
+    pub rev_lookup: MovePathLookup,
     pub inits: IndexVec<InitIndex, Init>,
     /// Each Location `l` is mapped to the Inits that are effects
     /// of executing the code at `l`.
@@ -258,7 +215,7 @@ impl Init {
 
 /// Tables mapping from a place to its MovePathIndex.
 #[derive(Debug)]
-pub struct MovePathLookup<'tcx> {
+pub struct MovePathLookup {
     locals: IndexVec<Local, MovePathIndex>,
 
     /// projections are made from a base-place and a projection
@@ -267,7 +224,7 @@ pub struct MovePathLookup<'tcx> {
     /// subsequent search so that it is solely relative to that
     /// base-place). For the remaining lookup, we map the projection
     /// elem to the associated MovePathIndex.
-    projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex>
+    projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>
 }
 
 mod builder;
@@ -278,7 +235,7 @@ pub enum LookupResult {
     Parent(Option<MovePathIndex>)
 }
 
-impl<'tcx> MovePathLookup<'tcx> {
+impl MovePathLookup {
     // Unlike the builder `fn move_path_for` below, this lookup
     // alternative will *not* create a MovePath on the fly for an
     // unknown place, but will rather return the nearest available
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index e1b66312da2..c8836fe5193 100644
--- a/src/librustc_mir/diagnostics.rs
+++ b/src/librustc_mir/diagnostics.rs
@@ -2307,10 +2307,10 @@ let q = *p;
 ```
 
 Here, the expression `&foo()` is borrowing the expression
-`foo()`. As `foo()` is call to a function, and not the name of
+`foo()`. As `foo()` is a call to a function, and not the name of
 a variable, this creates a **temporary** -- that temporary stores
 the return value from `foo()` so that it can be borrowed.
-So you might imagine that `let p = bar(&foo())` is equivalent
+You could imagine that `let p = bar(&foo());` is equivalent
 to this:
 
 ```compile_fail,E0597
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 303ffcb3bfb..a9c521f59a9 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -1754,7 +1754,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                     // they should be pointing to memory is when they are subslices of nonzero
                     // slices
                     let (opt_ptr, n, ty) = match value.ty.sty {
-                        ty::TyKind::Array(t, n) => {
+                        ty::Array(t, n) => {
                             match value.val {
                                 ConstValue::ByRef(ptr, alloc) => (
                                     Some((ptr, alloc)),
@@ -1767,7 +1767,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                                 ),
                             }
                         },
-                        ty::TyKind::Slice(t) => {
+                        ty::Slice(t) => {
                             match value.val {
                                 ConstValue::Slice(ptr, n) => (
                                     ptr.to_ptr().ok().map(|ptr| (
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 50df676aea9..7ded973701e 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -10,7 +10,7 @@ use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization::cmt_;
 use rustc::middle::region;
 use rustc::session::Session;
-use rustc::ty::{self, Ty, TyCtxt, TyKind};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::lint;
 use rustc_errors::{Applicability, DiagnosticBuilder};
@@ -481,7 +481,7 @@ fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(
             }
             let patterns = witnesses.iter().map(|p| (**p).clone()).collect::<Vec<Pattern<'_>>>();
             if patterns.len() < 4 {
-                for sp in maybe_point_at_variant(cx, &scrut_ty.sty, patterns.as_slice()) {
+                for sp in maybe_point_at_variant(cx, scrut_ty, patterns.as_slice()) {
                     err.span_label(sp, "not covered");
                 }
             }
@@ -498,11 +498,11 @@ fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(
 
 fn maybe_point_at_variant(
     cx: &mut MatchCheckCtxt<'a, 'tcx>,
-    sty: &TyKind<'tcx>,
+    ty: Ty<'tcx>,
     patterns: &[Pattern<'_>],
 ) -> Vec<Span> {
     let mut covered = vec![];
-    if let ty::Adt(def, _) = sty {
+    if let ty::Adt(def, _) = ty.sty {
         // Don't point at variants that have already been covered due to other patterns to avoid
         // visual clutter
         for pattern in patterns {
@@ -518,7 +518,7 @@ fn maybe_point_at_variant(
                         .map(|field_pattern| field_pattern.pattern.clone())
                         .collect::<Vec<_>>();
                     covered.extend(
-                        maybe_point_at_variant(cx, sty, subpatterns.as_slice()),
+                        maybe_point_at_variant(cx, ty, subpatterns.as_slice()),
                     );
                 }
             }
@@ -526,7 +526,7 @@ fn maybe_point_at_variant(
                 let subpatterns = subpatterns.iter()
                     .map(|field_pattern| field_pattern.pattern.clone())
                     .collect::<Vec<_>>();
-                covered.extend(maybe_point_at_variant(cx, sty, subpatterns.as_slice()));
+                covered.extend(maybe_point_at_variant(cx, ty, subpatterns.as_slice()));
             }
         }
     }
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 622cf00ed86..fc12443c092 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -74,7 +74,7 @@ impl<'tcx> PatternTypeProjection<'tcx> {
         annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
         inferred_ty: Ty<'tcx>,
         span: Span,
-    ) -> UserTypeProjection<'tcx> {
+    ) -> UserTypeProjection {
         UserTypeProjection {
             base: annotations.push(CanonicalUserTypeAnnotation {
                 span,
@@ -1094,7 +1094,7 @@ CloneImpls!{ <'tcx>
     Span, Field, Mutability, ast::Name, hir::HirId, usize, ty::Const<'tcx>,
     Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
     SubstsRef<'tcx>, &'tcx Kind<'tcx>, UserType<'tcx>,
-    UserTypeProjection<'tcx>, PatternTypeProjection<'tcx>
+    UserTypeProjection, PatternTypeProjection<'tcx>
 }
 
 impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index fe719bff250..5056d79bec4 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -4,7 +4,7 @@ use syntax::ast::{FloatTy, IntTy, UintTy};
 
 use rustc_apfloat::ieee::{Single, Double};
 use rustc::mir::interpret::{
-    Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind, truncate
+    Scalar, EvalResult, Pointer, PointerArithmetic, InterpError, truncate
 };
 use rustc::mir::CastKind;
 use rustc_apfloat::Float;
@@ -85,7 +85,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                             self.param_env,
                             def_id,
                             substs,
-                        ).ok_or_else(|| EvalErrorKind::TooGeneric.into());
+                        ).ok_or_else(|| InterpError::TooGeneric.into());
                         let fn_ptr = self.memory.create_fn_alloc(instance?).with_default_tag();
                         self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
                     }
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 8b7e28c3de0..32f7ecd97b2 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -16,7 +16,7 @@ use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::mir::interpret::{
     ErrorHandled,
     GlobalId, Scalar, FrameInfo, AllocId,
-    EvalResult, EvalErrorKind,
+    EvalResult, InterpError,
     truncate, sign_extend,
 };
 use rustc_data_structures::fx::FxHashMap;
@@ -108,34 +108,51 @@ pub enum StackPopCleanup {
 /// State of a local variable including a memoized layout
 #[derive(Clone, PartialEq, Eq)]
 pub struct LocalState<'tcx, Tag=(), Id=AllocId> {
-    pub state: LocalValue<Tag, Id>,
+    pub value: LocalValue<Tag, Id>,
     /// Don't modify if `Some`, this is only used to prevent computing the layout twice
     pub layout: Cell<Option<TyLayout<'tcx>>>,
 }
 
-/// State of a local variable
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+/// Current value of a local variable
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum LocalValue<Tag=(), Id=AllocId> {
+    /// This local is not currently alive, and cannot be used at all.
     Dead,
-    // Mostly for convenience, we re-use the `Operand` type here.
-    // This is an optimization over just always having a pointer here;
-    // we can thus avoid doing an allocation when the local just stores
-    // immediate values *and* never has its address taken.
+    /// This local is alive but not yet initialized. It can be written to
+    /// but not read from or its address taken. Locals get initialized on
+    /// first write because for unsized locals, we do not know their size
+    /// before that.
+    Uninitialized,
+    /// A normal, live local.
+    /// Mostly for convenience, we re-use the `Operand` type here.
+    /// This is an optimization over just always having a pointer here;
+    /// we can thus avoid doing an allocation when the local just stores
+    /// immediate values *and* never has its address taken.
     Live(Operand<Tag, Id>),
 }
 
-impl<'tcx, Tag> LocalState<'tcx, Tag> {
-    pub fn access(&self) -> EvalResult<'tcx, &Operand<Tag>> {
-        match self.state {
+impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
+    pub fn access(&self) -> EvalResult<'tcx, Operand<Tag>> {
+        match self.value {
             LocalValue::Dead => err!(DeadLocal),
-            LocalValue::Live(ref val) => Ok(val),
+            LocalValue::Uninitialized =>
+                bug!("The type checker should prevent reading from a never-written local"),
+            LocalValue::Live(val) => Ok(val),
         }
     }
 
-    pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand<Tag>> {
-        match self.state {
+    /// Overwrite the local.  If the local can be overwritten in place, return a reference
+    /// to do so; otherwise return the `MemPlace` to consult instead.
+    pub fn access_mut(
+        &mut self,
+    ) -> EvalResult<'tcx, Result<&mut LocalValue<Tag>, MemPlace<Tag>>> {
+        match self.value {
             LocalValue::Dead => err!(DeadLocal),
-            LocalValue::Live(ref mut val) => Ok(val),
+            LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)),
+            ref mut local @ LocalValue::Live(Operand::Immediate(_)) |
+            ref mut local @ LocalValue::Uninitialized => {
+                Ok(Ok(local))
+            }
         }
     }
 }
@@ -167,7 +184,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> LayoutOf
     #[inline]
     fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
         self.tcx.layout_of(self.param_env.and(ty))
-            .map_err(|layout| EvalErrorKind::Layout(layout).into())
+            .map_err(|layout| InterpError::Layout(layout).into())
     }
 }
 
@@ -255,7 +272,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
             self.param_env,
             def_id,
             substs,
-        ).ok_or_else(|| EvalErrorKind::TooGeneric.into())
+        ).ok_or_else(|| InterpError::TooGeneric.into())
     }
 
     pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
@@ -327,6 +344,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
                     let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
                     self.layout_of(local_ty)
                 })?;
+                // Layouts of locals are requested a lot, so we cache them.
                 frame.locals[local].layout.set(Some(layout));
                 Ok(layout)
             }
@@ -473,19 +491,15 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
 
         // don't allocate at all for trivial constants
         if mir.local_decls.len() > 1 {
-            // We put some marker immediate into the locals that we later want to initialize.
-            // This can be anything except for LocalValue::Dead -- because *that* is the
-            // value we use for things that we know are initially dead.
+            // Locals are initially uninitialized.
             let dummy = LocalState {
-                state: LocalValue::Live(Operand::Immediate(Immediate::Scalar(
-                    ScalarMaybeUndef::Undef,
-                ))),
+                value: LocalValue::Uninitialized,
                 layout: Cell::new(None),
             };
             let mut locals = IndexVec::from_elem(dummy, &mir.local_decls);
             // Return place is handled specially by the `eval_place` functions, and the
             // entry in `locals` should never be used. Make it dead, to be sure.
-            locals[mir::RETURN_PLACE].state = LocalValue::Dead;
+            locals[mir::RETURN_PLACE].value = LocalValue::Dead;
             // Now mark those locals as dead that we do not want to initialize
             match self.tcx.describe_def(instance.def_id()) {
                 // statics and constants don't have `Storage*` statements, no need to look for them
@@ -498,7 +512,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
                             match stmt.kind {
                                 StorageLive(local) |
                                 StorageDead(local) => {
-                                    locals[local].state = LocalValue::Dead;
+                                    locals[local].value = LocalValue::Dead;
                                 }
                                 _ => {}
                             }
@@ -506,21 +520,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
                     }
                 },
             }
-            // Finally, properly initialize all those that still have the dummy value
-            for (idx, local) in locals.iter_enumerated_mut() {
-                match local.state {
-                    LocalValue::Live(_) => {
-                        // This needs to be properly initialized.
-                        let ty = self.monomorphize(mir.local_decls[idx].ty)?;
-                        let layout = self.layout_of(ty)?;
-                        local.state = LocalValue::Live(self.uninit_operand(layout)?);
-                        local.layout = Cell::new(Some(layout));
-                    }
-                    LocalValue::Dead => {
-                        // Nothing to do
-                    }
-                }
-            }
             // done
             self.frame_mut().locals = locals;
         }
@@ -555,7 +554,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
         }
         // Deallocate all locals that are backed by an allocation.
         for local in frame.locals {
-            self.deallocate_local(local.state)?;
+            self.deallocate_local(local.value)?;
         }
         // Validate the return value. Do this after deallocating so that we catch dangling
         // references.
@@ -603,10 +602,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
         assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
         trace!("{:?} is now live", local);
 
-        let layout = self.layout_of_local(self.frame(), local, None)?;
-        let init = LocalValue::Live(self.uninit_operand(layout)?);
+        let local_val = LocalValue::Uninitialized;
         // StorageLive *always* kills the value that's currently stored
-        Ok(mem::replace(&mut self.frame_mut().locals[local].state, init))
+        Ok(mem::replace(&mut self.frame_mut().locals[local].value, local_val))
     }
 
     /// Returns the old value of the local.
@@ -615,7 +613,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
         assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
         trace!("{:?} is now dead", local);
 
-        mem::replace(&mut self.frame_mut().locals[local].state, LocalValue::Dead)
+        mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead)
     }
 
     pub(super) fn deallocate_local(
@@ -647,8 +645,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
         // `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
         let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
             match err {
-                ErrorHandled::Reported => EvalErrorKind::ReferencedConstant,
-                ErrorHandled::TooGeneric => EvalErrorKind::TooGeneric,
+                ErrorHandled::Reported => InterpError::ReferencedConstant,
+                ErrorHandled::TooGeneric => InterpError::TooGeneric,
             }
         })?;
         self.raw_const_to_mplace(val)
@@ -668,31 +666,31 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
                 }
                 write!(msg, ":").unwrap();
 
-                match self.stack[frame].locals[local].access() {
-                    Err(err) => {
-                        if let EvalErrorKind::DeadLocal = err.kind {
-                            write!(msg, " is dead").unwrap();
-                        } else {
-                            panic!("Failed to access local: {:?}", err);
-                        }
-                    }
-                    Ok(Operand::Indirect(mplace)) => {
-                        let (ptr, align) = mplace.to_scalar_ptr_align();
-                        match ptr {
+                match self.stack[frame].locals[local].value {
+                    LocalValue::Dead => write!(msg, " is dead").unwrap(),
+                    LocalValue::Uninitialized => write!(msg, " is uninitialized").unwrap(),
+                    LocalValue::Live(Operand::Indirect(mplace)) => {
+                        match mplace.ptr {
                             Scalar::Ptr(ptr) => {
-                                write!(msg, " by align({}) ref:", align.bytes()).unwrap();
+                                write!(msg, " by align({}){} ref:",
+                                    mplace.align.bytes(),
+                                    match mplace.meta {
+                                        Some(meta) => format!(" meta({:?})", meta),
+                                        None => String::new()
+                                    }
+                                ).unwrap();
                                 allocs.push(ptr.alloc_id);
                             }
                             ptr => write!(msg, " by integral ref: {:?}", ptr).unwrap(),
                         }
                     }
-                    Ok(Operand::Immediate(Immediate::Scalar(val))) => {
+                    LocalValue::Live(Operand::Immediate(Immediate::Scalar(val))) => {
                         write!(msg, " {:?}", val).unwrap();
                         if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val {
                             allocs.push(ptr.alloc_id);
                         }
                     }
-                    Ok(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => {
+                    LocalValue::Live(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => {
                         write!(msg, " ({:?}, {:?})", val1, val2).unwrap();
                         if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val1 {
                             allocs.push(ptr.alloc_id);
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 99dd654df21..d9721a8cadf 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -7,7 +7,7 @@ use rustc::ty;
 use rustc::ty::layout::{LayoutOf, Primitive, Size};
 use rustc::mir::BinOp;
 use rustc::mir::interpret::{
-    EvalResult, EvalErrorKind, Scalar,
+    EvalResult, InterpError, Scalar,
 };
 
 use super::{
@@ -87,7 +87,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                 let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?;
                 let kind = match layout_of.abi {
                     ty::layout::Abi::Scalar(ref scalar) => scalar.value,
-                    _ => Err(::rustc::mir::interpret::EvalErrorKind::TypeNotPrimitive(ty))?,
+                    _ => Err(::rustc::mir::interpret::InterpError::TypeNotPrimitive(ty))?,
                 };
                 let out_val = if intrinsic_name.ends_with("_nonzero") {
                     if bits == 0 {
@@ -248,7 +248,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
             let file = Symbol::intern(self.read_str(file_place)?);
             let line = self.read_scalar(line.into())?.to_u32()?;
             let col = self.read_scalar(col.into())?.to_u32()?;
-            return Err(EvalErrorKind::Panic { msg, file, line, col }.into());
+            return Err(InterpError::Panic { msg, file, line, col }.into());
         } else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() {
             assert!(args.len() == 2);
             // &'static str, &(&'static str, u32, u32)
@@ -266,7 +266,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
             let file = Symbol::intern(self.read_str(file_place)?);
             let line = self.read_scalar(line.into())?.to_u32()?;
             let col = self.read_scalar(col.into())?.to_u32()?;
-            return Err(EvalErrorKind::Panic { msg, file, line, col }.into());
+            return Err(InterpError::Panic { msg, file, line, col }.into());
         } else {
             return Ok(false);
         }
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 6ea200d4e4f..e5d8341dfcf 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -19,7 +19,7 @@ use syntax::ast::Mutability;
 
 use super::{
     Pointer, AllocId, Allocation, GlobalId, AllocationExtra,
-    EvalResult, Scalar, EvalErrorKind, AllocKind, PointerArithmetic,
+    EvalResult, Scalar, InterpError, AllocKind, PointerArithmetic,
     Machine, AllocMap, MayLeak, ErrorHandled, InboundsCheck,
 };
 
@@ -344,8 +344,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
             // no need to report anything, the const_eval call takes care of that for statics
             assert!(tcx.is_static(def_id).is_some());
             match err {
-                ErrorHandled::Reported => EvalErrorKind::ReferencedConstant.into(),
-                ErrorHandled::TooGeneric => EvalErrorKind::TooGeneric.into(),
+                ErrorHandled::Reported => InterpError::ReferencedConstant.into(),
+                ErrorHandled::TooGeneric => InterpError::TooGeneric.into(),
             }
         }).map(|raw_const| {
             let allocation = tcx.alloc_map.lock().unwrap_memory(raw_const.alloc_id);
@@ -458,7 +458,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
         trace!("reading fn ptr: {}", ptr.alloc_id);
         match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
             Some(AllocKind::Function(instance)) => Ok(instance),
-            _ => Err(EvalErrorKind::ExecuteMemory.into()),
+            _ => Err(InterpError::ExecuteMemory.into()),
         }
     }
 
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 38a9371b927..1ce6d09d7a4 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -9,12 +9,12 @@ use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerEx
 use rustc::mir::interpret::{
     GlobalId, AllocId, InboundsCheck,
     ConstValue, Pointer, Scalar,
-    EvalResult, EvalErrorKind,
+    EvalResult, InterpError,
     sign_extend, truncate,
 };
 use super::{
     InterpretCx, Machine,
-    MemPlace, MPlaceTy, PlaceTy, Place, MemoryKind,
+    MemPlace, MPlaceTy, PlaceTy, Place,
 };
 pub use rustc::mir::interpret::ScalarMaybeUndef;
 
@@ -369,37 +369,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, '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| EvalErrorKind::ValidationFailure(err.to_string()))?;
+            .map_err(|err| InterpError::ValidationFailure(err.to_string()))?;
         Ok(str)
     }
 
-    pub fn uninit_operand(
-        &mut self,
-        layout: TyLayout<'tcx>
-    ) -> EvalResult<'tcx, Operand<M::PointerTag>> {
-        // This decides which types we will use the Immediate optimization for, and hence should
-        // match what `try_read_immediate` and `eval_place_to_op` support.
-        if layout.is_zst() {
-            return Ok(Operand::Immediate(Immediate::Scalar(Scalar::zst().into())));
-        }
-
-        Ok(match layout.abi {
-            layout::Abi::Scalar(..) =>
-                Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef)),
-            layout::Abi::ScalarPair(..) =>
-                Operand::Immediate(Immediate::ScalarPair(
-                    ScalarMaybeUndef::Undef,
-                    ScalarMaybeUndef::Undef,
-                )),
-            _ => {
-                trace!("Forcing allocation for local of type {:?}", layout.ty);
-                Operand::Indirect(
-                    *self.allocate(layout, MemoryKind::Stack)
-                )
-            }
-        })
-    }
-
     /// Projection functions
     pub fn operand_field(
         &self,
@@ -486,8 +459,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
         layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         assert_ne!(local, mir::RETURN_PLACE);
-        let op = *frame.locals[local].access()?;
         let layout = self.layout_of_local(frame, local, layout)?;
+        let op = if layout.is_zst() {
+            // Do not read from ZST, they might not be initialized
+            Operand::Immediate(Immediate::Scalar(Scalar::zst().into()))
+        } else {
+            frame.locals[local].access()?
+        };
         Ok(OpTy { op, layout })
     }
 
@@ -502,7 +480,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                 Operand::Indirect(mplace)
             }
             Place::Local { frame, local } =>
-                *self.stack[frame].locals[local].access()?
+                *self.access_local(&self.stack[frame], local, None)?
         };
         Ok(OpTy { op, layout: place.layout })
     }
@@ -610,18 +588,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
     ) -> EvalResult<'tcx, (u128, VariantIdx)> {
         trace!("read_discriminant_value {:#?}", rval.layout);
 
-        let discr_kind = match rval.layout.variants {
+        let (discr_kind, discr_index) = match rval.layout.variants {
             layout::Variants::Single { index } => {
                 let discr_val = rval.layout.ty.ty_adt_def().map_or(
                     index.as_u32() as u128,
                     |def| def.discriminant_for_variant(*self.tcx, index).val);
                 return Ok((discr_val, index));
             }
-            layout::Variants::Multiple { ref discr_kind, .. } => discr_kind,
+            layout::Variants::Multiple { ref discr_kind, discr_index, .. } =>
+                (discr_kind, discr_index),
         };
 
         // read raw discriminant value
-        let discr_op = self.operand_field(rval, 0)?;
+        let discr_op = self.operand_field(rval, discr_index as u64)?;
         let discr_val = self.read_immediate(discr_op)?;
         let raw_discr = discr_val.to_scalar_or_undef();
         trace!("discr value: {:?}", raw_discr);
@@ -653,7 +632,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                     .expect("tagged layout for non adt")
                     .discriminants(self.tcx.tcx)
                     .find(|(_, var)| var.val == real_discr)
-                    .ok_or_else(|| EvalErrorKind::InvalidDiscriminant(raw_discr.erase_tag()))?;
+                    .ok_or_else(|| InterpError::InvalidDiscriminant(raw_discr.erase_tag()))?;
                 (real_discr, index.0)
             },
             layout::DiscriminantKind::Niche {
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 4d51772d5ea..32ad5274689 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -15,7 +15,7 @@ use rustc::ty::TypeFoldable;
 use super::{
     GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic,
     InterpretCx, Machine, AllocMap, AllocationExtra,
-    RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
+    RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue
 };
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -558,7 +558,7 @@ where
     pub fn place_projection(
         &mut self,
         base: PlaceTy<'tcx, M::PointerTag>,
-        proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
+        proj_elem: &mir::ProjectionElem<mir::Local, Ty<'tcx>>,
     ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::ProjectionElem::*;
         Ok(match *proj_elem {
@@ -639,6 +639,7 @@ where
                 None => return err!(InvalidNullPointerUsage),
             },
             Base(PlaceBase::Local(local)) => PlaceTy {
+                // This works even for dead/uninitialized locals; we check further when writing
                 place: Place::Local {
                     frame: self.cur_frame(),
                     local,
@@ -714,16 +715,19 @@ where
         // but not factored as a separate function.
         let mplace = match dest.place {
             Place::Local { frame, local } => {
-                match *self.stack[frame].locals[local].access_mut()? {
-                    Operand::Immediate(ref mut dest_val) => {
-                        // Yay, we can just change the local directly.
-                        *dest_val = src;
+                match self.stack[frame].locals[local].access_mut()? {
+                    Ok(local) => {
+                        // Local can be updated in-place.
+                        *local = LocalValue::Live(Operand::Immediate(src));
                         return Ok(());
-                    },
-                    Operand::Indirect(mplace) => mplace, // already in memory
+                    }
+                    Err(mplace) => {
+                        // The local is in memory, go on below.
+                        mplace
+                    }
                 }
             },
-            Place::Ptr(mplace) => mplace, // already in memory
+            Place::Ptr(mplace) => mplace, // already referring to memory
         };
         let dest = MPlaceTy { mplace, layout: dest.layout };
 
@@ -822,8 +826,6 @@ where
         src: OpTy<'tcx, M::PointerTag>,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
-        debug_assert!(!src.layout.is_unsized() && !dest.layout.is_unsized(),
-            "Cannot copy unsized data");
         // We do NOT compare the types for equality, because well-typed code can
         // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
         assert!(src.layout.details == dest.layout.details,
@@ -832,6 +834,7 @@ where
         // Let us see if the layout is simple so we take a shortcut, avoid force_allocation.
         let src = match self.try_read_immediate(src)? {
             Ok(src_val) => {
+                assert!(!src.layout.is_unsized(), "cannot have unsized immediates");
                 // Yay, we got a value that we can write directly.
                 // FIXME: Add a check to make sure that if `src` is indirect,
                 // it does not overlap with `dest`.
@@ -842,13 +845,19 @@ where
         // Slow path, this does not fit into an immediate. Just memcpy.
         trace!("copy_op: {:?} <- {:?}: {}", *dest, src, dest.layout.ty);
 
-        let dest = self.force_allocation(dest)?;
-        let (src_ptr, src_align) = src.to_scalar_ptr_align();
-        let (dest_ptr, dest_align) = dest.to_scalar_ptr_align();
+        // This interprets `src.meta` with the `dest` local's layout, if an unsized local
+        // is being initialized!
+        let (dest, size) = self.force_allocation_maybe_sized(dest, src.meta)?;
+        let size = size.unwrap_or_else(|| {
+            assert!(!dest.layout.is_unsized(),
+                "Cannot copy into already initialized unsized place");
+            dest.layout.size
+        });
+        assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances");
         self.memory.copy(
-            src_ptr, src_align,
-            dest_ptr, dest_align,
-            dest.layout.size,
+            src.ptr, src.align,
+            dest.ptr, dest.align,
+            size,
             /*nonoverlapping*/ true,
         )?;
 
@@ -866,11 +875,13 @@ where
             // Fast path: Just use normal `copy_op`
             return self.copy_op(src, dest);
         }
-        // We still require the sizes to match
-        debug_assert!(!src.layout.is_unsized() && !dest.layout.is_unsized(),
-            "Cannot copy unsized data");
+        // We still require the sizes to match.
         assert!(src.layout.size == dest.layout.size,
             "Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
+        // Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want
+        // to avoid that here.
+        assert!(!src.layout.is_unsized() && !dest.layout.is_unsized(),
+            "Cannot transmute unsized data");
 
         // The hard case is `ScalarPair`.  `src` is already read from memory in this case,
         // using `src.layout` to figure out which bytes to use for the 1st and 2nd field.
@@ -898,39 +909,70 @@ where
     /// If the place currently refers to a local that doesn't yet have a matching allocation,
     /// create such an allocation.
     /// This is essentially `force_to_memplace`.
-    pub fn force_allocation(
+    ///
+    /// This supports unsized types and returns the computed size to avoid some
+    /// redundant computation when copying; use `force_allocation` for a simpler, sized-only
+    /// version.
+    pub fn force_allocation_maybe_sized(
         &mut self,
         place: PlaceTy<'tcx, M::PointerTag>,
-    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
-        let mplace = match place.place {
+        meta: Option<Scalar<M::PointerTag>>,
+    ) -> EvalResult<'tcx, (MPlaceTy<'tcx, M::PointerTag>, Option<Size>)> {
+        let (mplace, size) = match place.place {
             Place::Local { frame, local } => {
-                match *self.stack[frame].locals[local].access()? {
-                    Operand::Indirect(mplace) => mplace,
-                    Operand::Immediate(value) => {
+                match self.stack[frame].locals[local].access_mut()? {
+                    Ok(local_val) => {
                         // We need to make an allocation.
                         // FIXME: Consider not doing anything for a ZST, and just returning
                         // a fake pointer?  Are we even called for ZST?
 
+                        // We cannot hold on to the reference `local_val` while allocating,
+                        // but we can hold on to the value in there.
+                        let old_val =
+                            if let LocalValue::Live(Operand::Immediate(value)) = *local_val {
+                                Some(value)
+                            } else {
+                                None
+                            };
+
                         // We need the layout of the local.  We can NOT use the layout we got,
                         // that might e.g., be an inner field of a struct with `Scalar` layout,
                         // that has different alignment than the outer field.
+                        // We also need to support unsized types, and hence cannot use `allocate`.
                         let local_layout = self.layout_of_local(&self.stack[frame], local, None)?;
-                        let ptr = self.allocate(local_layout, MemoryKind::Stack);
-                        // We don't have to validate as we can assume the local
-                        // was already valid for its type.
-                        self.write_immediate_to_mplace_no_validate(value, ptr)?;
-                        let mplace = ptr.mplace;
-                        // Update the local
-                        *self.stack[frame].locals[local].access_mut()? =
-                            Operand::Indirect(mplace);
-                        mplace
+                        let (size, align) = self.size_and_align_of(meta, local_layout)?
+                            .expect("Cannot allocate for non-dyn-sized type");
+                        let ptr = self.memory.allocate(size, align, MemoryKind::Stack);
+                        let ptr = M::tag_new_allocation(self, ptr, MemoryKind::Stack);
+                        let mplace = MemPlace { ptr: ptr.into(), align, meta };
+                        if let Some(value) = old_val {
+                            // Preserve old value.
+                            // We don't have to validate as we can assume the local
+                            // was already valid for its type.
+                            let mplace = MPlaceTy { mplace, layout: local_layout };
+                            self.write_immediate_to_mplace_no_validate(value, mplace)?;
+                        }
+                        // Now we can call `access_mut` again, asserting it goes well,
+                        // and actually overwrite things.
+                        *self.stack[frame].locals[local].access_mut().unwrap().unwrap() =
+                            LocalValue::Live(Operand::Indirect(mplace));
+                        (mplace, Some(size))
                     }
+                    Err(mplace) => (mplace, None), // this already was an indirect local
                 }
             }
-            Place::Ptr(mplace) => mplace
+            Place::Ptr(mplace) => (mplace, None)
         };
         // Return with the original layout, so that the caller can go on
-        Ok(MPlaceTy { mplace, layout: place.layout })
+        Ok((MPlaceTy { mplace, layout: place.layout }, size))
+    }
+
+    #[inline(always)]
+    pub fn force_allocation(
+        &mut self,
+        place: PlaceTy<'tcx, M::PointerTag>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+        Ok(self.force_allocation_maybe_sized(place, None)?.0)
     }
 
     pub fn allocate(
@@ -938,15 +980,9 @@ where
         layout: TyLayout<'tcx>,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> MPlaceTy<'tcx, M::PointerTag> {
-        if layout.is_unsized() {
-            assert!(self.tcx.features().unsized_locals, "cannot alloc memory for unsized type");
-            // FIXME: What should we do here? We should definitely also tag!
-            MPlaceTy::dangling(layout, self)
-        } else {
-            let ptr = self.memory.allocate(layout.size, layout.align.abi, kind);
-            let ptr = M::tag_new_allocation(self, ptr, kind);
-            MPlaceTy::from_aligned_ptr(ptr, layout)
-        }
+        let ptr = self.memory.allocate(layout.size, layout.align.abi, kind);
+        let ptr = M::tag_new_allocation(self, ptr, kind);
+        MPlaceTy::from_aligned_ptr(ptr, layout)
     }
 
     pub fn write_discriminant_index(
@@ -961,6 +997,7 @@ where
             layout::Variants::Multiple {
                 discr_kind: layout::DiscriminantKind::Tag,
                 ref discr,
+                discr_index,
                 ..
             } => {
                 let adt_def = dest.layout.ty.ty_adt_def().unwrap();
@@ -975,7 +1012,7 @@ where
                 let size = discr.value.size(self);
                 let discr_val = truncate(discr_val, size);
 
-                let discr_dest = self.place_field(dest, 0)?;
+                let discr_dest = self.place_field(dest, discr_index as u64)?;
                 self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?;
             }
             layout::Variants::Multiple {
@@ -984,6 +1021,7 @@ where
                     ref niche_variants,
                     niche_start,
                 },
+                discr_index,
                 ..
             } => {
                 assert!(
@@ -991,7 +1029,7 @@ where
                 );
                 if variant_index != dataful_variant {
                     let niche_dest =
-                        self.place_field(dest, 0)?;
+                        self.place_field(dest, discr_index as u64)?;
                     let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
                     let niche_value = (niche_value as u128)
                         .wrapping_add(niche_start);
diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs
index 8bb663f846b..0bb8b1d9d02 100644
--- a/src/librustc_mir/interpret/snapshot.rs
+++ b/src/librustc_mir/interpret/snapshot.rs
@@ -12,7 +12,7 @@ use rustc::mir;
 use rustc::mir::interpret::{
     AllocId, Pointer, Scalar,
     Relocations, Allocation, UndefMask,
-    EvalResult, EvalErrorKind,
+    EvalResult, InterpError,
 };
 
 use rustc::ty::{self, TyCtxt};
@@ -78,7 +78,7 @@ impl<'a, 'mir, 'tcx> InfiniteLoopDetector<'a, 'mir, 'tcx>
         }
 
         // Second cycle
-        Err(EvalErrorKind::InfiniteLoop.into())
+        Err(InterpError::InfiniteLoop.into())
     }
 }
 
@@ -114,10 +114,11 @@ macro_rules! impl_snapshot_for {
             fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item {
                 match *self {
                     $(
-                        $enum_name::$variant $( ( $(ref $field),* ) )? =>
+                        $enum_name::$variant $( ( $(ref $field),* ) )? => {
                             $enum_name::$variant $(
-                                ( $( __impl_snapshot_field!($field, __ctx $(, $delegate)?) ),* ),
+                                ( $( __impl_snapshot_field!($field, __ctx $(, $delegate)?) ),* )
                             )?
+                        }
                     )*
                 }
             }
@@ -250,11 +251,13 @@ impl_snapshot_for!(enum Operand {
 
 impl_stable_hash_for!(enum crate::interpret::LocalValue {
     Dead,
+    Uninitialized,
     Live(x),
 });
 impl_snapshot_for!(enum LocalValue {
-    Live(v),
     Dead,
+    Uninitialized,
+    Live(v),
 });
 
 impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations
@@ -360,13 +363,13 @@ impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalState<'tcx>
     type Item = LocalValue<(), AllocIdSnapshot<'a>>;
 
     fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
-        let LocalState { state, layout: _ } = self;
-        state.snapshot(ctx)
+        let LocalState { value, layout: _ } = self;
+        value.snapshot(ctx)
     }
 }
 
 impl_stable_hash_for!(struct LocalState<'tcx> {
-    state,
+    value,
     layout -> _,
 });
 
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 01965f53c15..ba48a28fc83 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -5,7 +5,7 @@ use rustc::ty::layout::{self, TyLayout, LayoutOf};
 use syntax::source_map::Span;
 use rustc_target::spec::abi::Abi;
 
-use rustc::mir::interpret::{EvalResult, PointerArithmetic, EvalErrorKind, Scalar};
+use rustc::mir::interpret::{EvalResult, PointerArithmetic, InterpError, Scalar};
 use super::{
     InterpretCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup
 };
@@ -134,7 +134,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                     self.goto_block(Some(target))?;
                 } else {
                     // Compute error message
-                    use rustc::mir::interpret::EvalErrorKind::*;
+                    use rustc::mir::interpret::InterpError::*;
                     return match *msg {
                         BoundsCheck { ref len, ref index } => {
                             let len = self.read_immediate(self.eval_operand(len, None)?)
@@ -212,7 +212,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
             return Ok(());
         }
         let caller_arg = caller_arg.next()
-            .ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?;
+            .ok_or_else(|| InterpError::FunctionArgCountMismatch)?;
         if rust_abi {
             debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
         }
@@ -315,12 +315,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                     );
 
                     // Figure out how to pass which arguments.
-                    // We have two iterators: Where the arguments come from,
-                    // and where they go to.
+                    // 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,
@@ -368,7 +369,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                     }
                     // Now we should have no more caller args
                     if caller_iter.next().is_some() {
-                        trace!("Caller has too many args over");
+                        trace!("Caller has passed too many args");
                         return err!(FunctionArgCountMismatch);
                     }
                     // Don't forget to check the return type!
@@ -406,9 +407,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
             }
             // cannot use the shim here, because that will only result in infinite recursion
             ty::InstanceDef::Virtual(_, idx) => {
+                let mut args = args.to_vec();
                 let ptr_size = self.pointer_size();
-                let ptr = self.deref_operand(args[0])?;
-                let vtable = ptr.vtable()?;
+                // We have to implement all "object safe receivers".  Currently we
+                // support built-in pointers (&, &mut, Box) as well as unsized-self.  We do
+                // not yet support custom self types.
+                // Also see librustc_codegen_llvm/abi.rs and librustc_codegen_llvm/mir/block.rs.
+                let receiver_place = match args[0].layout.ty.builtin_deref(true) {
+                    Some(_) => {
+                        // Built-in pointer.
+                        self.deref_operand(args[0])?
+                    }
+                    None => {
+                        // Unsized self.
+                        args[0].to_mem_place()
+                    }
+                };
+                // Find and consult vtable
+                let vtable = receiver_place.vtable()?;
                 self.memory.check_align(vtable.into(), self.tcx.data_layout.pointer_align.abi)?;
                 let fn_ptr = self.memory.get(vtable.alloc_id)?.read_ptr_sized(
                     self,
@@ -416,15 +432,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                 )?.to_ptr()?;
                 let instance = self.memory.get_fn(fn_ptr)?;
 
-                // We have to patch the self argument, in particular get the layout
-                // expected by the actual function. Cannot just use "field 0" due to
-                // Box<self>.
-                let mut args = args.to_vec();
-                let pointee = args[0].layout.ty.builtin_deref(true).unwrap().ty;
-                let fake_fat_ptr_ty = self.tcx.mk_mut_ptr(pointee);
-                args[0] = OpTy::from(ImmTy { // strip vtable
-                    layout: self.layout_of(fake_fat_ptr_ty)?.field(self, 0)?,
-                    imm: Immediate::Scalar(ptr.ptr.into())
+                // `*mut receiver_place.layout.ty` is almost the layout that we
+                // want for args[0]: We have to project to field 0 because we want
+                // a thin pointer.
+                assert!(receiver_place.layout.is_unsized());
+                let receiver_ptr_ty = self.tcx.mk_mut_ptr(receiver_place.layout.ty);
+                let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0)?;
+                // Adjust receiver argument.
+                args[0] = OpTy::from(ImmTy {
+                    layout: this_receiver_ptr,
+                    imm: Immediate::Scalar(receiver_place.ptr.into())
                 });
                 trace!("Patched self operand to {:#?}", args[0]);
                 // recurse with concrete function
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index cce6c95a312..a451f2afb46 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -1,9 +1,8 @@
-use rustc_data_structures::sync::Lrc;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{Size, Align, LayoutOf};
 use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
 
-use super::{InterpretCx, Machine, MemoryKind};
+use super::{InterpretCx, InterpError, Machine, MemoryKind};
 
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
     /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
@@ -35,7 +34,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
 
             self.tcx.vtable_methods(trait_ref)
         } else {
-            Lrc::new(Vec::new())
+            &[]
         };
 
         let layout = self.layout_of(ty)?;
@@ -76,7 +75,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
 
         for (i, method) in methods.iter().enumerate() {
             if let Some((def_id, substs)) = *method {
-                let instance = self.resolve(def_id, substs)?;
+                // resolve for vtable: insert shims where needed
+                let substs = self.subst_and_normalize_erasing_regions(substs)?;
+                let instance = ty::Instance::resolve_for_vtable(
+                    *self.tcx,
+                    self.param_env,
+                    def_id,
+                    substs,
+                ).ok_or_else(|| InterpError::TooGeneric)?;
                 let fn_ptr = self.memory.create_fn_alloc(instance).with_default_tag();
                 let method_ptr = vtable.offset(ptr_size * (3 + i as u64), self)?;
                 self.memory
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 3323ec387bf..d4cf906619d 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -7,7 +7,7 @@ use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx};
 use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
 use rustc::mir::interpret::{
-    Scalar, AllocKind, EvalResult, EvalErrorKind,
+    Scalar, AllocKind, EvalResult, InterpError,
 };
 
 use super::{
@@ -258,11 +258,11 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
         match self.walk_value(op) {
             Ok(()) => Ok(()),
             Err(err) => match err.kind {
-                EvalErrorKind::InvalidDiscriminant(val) =>
+                InterpError::InvalidDiscriminant(val) =>
                     validation_failure!(
                         val, self.path, "a valid enum discriminant"
                     ),
-                EvalErrorKind::ReadPointerAsBytes =>
+                InterpError::ReadPointerAsBytes =>
                     validation_failure!(
                         "a pointer", self.path, "plain (non-pointer) bytes"
                     ),
@@ -355,9 +355,9 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
                     Err(err) => {
                         error!("{:?} is not aligned to {:?}", ptr, align);
                         match err.kind {
-                            EvalErrorKind::InvalidNullPointerUsage =>
+                            InterpError::InvalidNullPointerUsage =>
                                 return validation_failure!("NULL reference", self.path),
-                            EvalErrorKind::AlignmentCheckFailed { required, has } =>
+                            InterpError::AlignmentCheckFailed { required, has } =>
                                 return validation_failure!(format!("unaligned reference \
                                     (required {} byte alignment but found {})",
                                     required.bytes(), has.bytes()), self.path),
@@ -562,7 +562,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
                     Err(err) => {
                         // For some errors we might be able to provide extra information
                         match err.kind {
-                            EvalErrorKind::ReadUndefBytes(offset) => {
+                            InterpError::ReadUndefBytes(offset) => {
                                 // Some byte was undefined, determine which
                                 // element that byte belongs to so we can
                                 // provide an index.
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index c45e694ebf8..deeed9a0b98 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -28,6 +28,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(explicit_outlives_requirements)]
 
 #[macro_use] extern crate log;
diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs
index 6d6a3f91472..572f7133cad 100644
--- a/src/librustc_mir/lints.rs
+++ b/src/librustc_mir/lints.rs
@@ -4,7 +4,7 @@ use rustc::hir::intravisit::FnKind;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::lint::builtin::UNCONDITIONAL_RECURSION;
 use rustc::mir::{self, Mir, TerminatorKind};
-use rustc::ty::{AssociatedItem, AssociatedItemContainer, Instance, TyCtxt, TyKind};
+use rustc::ty::{self, AssociatedItem, AssociatedItemContainer, Instance, TyCtxt};
 use rustc::ty::subst::InternalSubsts;
 
 pub fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -86,7 +86,7 @@ fn check_fn_for_unconditional_recursion(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 TerminatorKind::Call { ref func, .. } => {
                     let func_ty = func.ty(mir, tcx);
 
-                    if let TyKind::FnDef(fn_def_id, substs) = func_ty.sty {
+                    if let ty::FnDef(fn_def_id, substs) = func_ty.sty {
                         let (call_fn_id, call_substs) =
                             if let Some(instance) = Instance::resolve(tcx,
                                                                         param_env,
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 45b346b6413..af875c2f9e8 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -625,8 +625,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             }
             mir::TerminatorKind::Drop { ref location, .. } |
             mir::TerminatorKind::DropAndReplace { ref location, .. } => {
-                let ty = location.ty(self.mir, self.tcx)
-                    .to_ty(self.tcx);
+                let ty = location.ty(self.mir, self.tcx).ty;
                 let ty = tcx.subst_and_normalize_erasing_regions(
                     self.param_substs,
                     ty::ParamEnv::reveal_all(),
diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
index e8528eee0bc..b6436ec70ee 100644
--- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs
+++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
@@ -106,7 +106,7 @@ fn add_move_for_packed_drop<'a, 'tcx>(
     };
 
     let source_info = terminator.source_info;
-    let ty = location.ty(mir, tcx).to_ty(tcx);
+    let ty = location.ty(mir, tcx).ty;
     let temp = patch.new_temp(ty, terminator.source_info.span);
 
     let storage_dead_block = patch.new_block(BasicBlockData {
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index b13a5fd2fd1..a393847fd49 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -87,7 +87,7 @@ impl MirPass for AddRetag {
         let needs_retag = |place: &Place<'tcx>| {
             // FIXME: Instead of giving up for unstable places, we should introduce
             // a temporary and retag on that.
-            is_stable(place) && may_have_reference(place.ty(&*local_decls, tcx).to_ty(tcx), tcx)
+            is_stable(place) && may_have_reference(place.ty(&*local_decls, tcx).ty, tcx)
         };
 
         // PART 1
@@ -164,7 +164,7 @@ impl MirPass for AddRetag {
                         if src_ty.is_region_ptr() {
                             // The only `Misc` casts on references are those creating raw pointers.
                             assert!(dest_ty.is_unsafe_ptr());
-                            (RetagKind::Raw, place)
+                            (RetagKind::Raw, place.clone())
                         } else {
                             // Some other cast, no retag
                             continue
@@ -182,7 +182,7 @@ impl MirPass for AddRetag {
                             _ =>
                                 RetagKind::Default,
                         };
-                        (kind, place)
+                        (kind, place.clone())
                     }
                     // Do nothing for the rest
                     _ => continue,
@@ -191,7 +191,7 @@ impl MirPass for AddRetag {
                 let source_info = block_data.statements[i].source_info;
                 block_data.statements.insert(i+1, Statement {
                     source_info,
-                    kind: StatementKind::Retag(retag_kind, place.clone()),
+                    kind: StatementKind::Retag(retag_kind, place),
                 });
             }
         }
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 0e31515e4af..93f3afe1aea 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -227,7 +227,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                 }
                 let is_borrow_of_interior_mut = context.is_borrow() && !base
                     .ty(self.mir, self.tcx)
-                    .to_ty(self.tcx)
+                    .ty
                     .is_freeze(self.tcx, self.param_env, self.source_info.span);
                 // prevent
                 // * `&mut x.field`
@@ -249,7 +249,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                         self.source_info = self.mir.local_decls[local].source_info;
                     }
                 }
-                let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                let base_ty = base.ty(self.mir, self.tcx).ty;
                 match base_ty.sty {
                     ty::RawPtr(..) => {
                         self.require_unsafe("dereference of raw pointer",
@@ -420,7 +420,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
         }) = place {
             match *elem {
                 ProjectionElem::Field(..) => {
-                    let ty = base.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
+                    let ty = base.ty(&self.mir.local_decls, self.tcx).ty;
                     match ty.sty {
                         ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
                             (Bound::Unbounded, Bound::Unbounded) => {},
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index b3ef7407a7c..e0ff71cbe52 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -7,7 +7,7 @@ use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Loc
 use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind, Static, StaticKind};
 use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
-use rustc::mir::interpret::{EvalErrorKind, Scalar, GlobalId, EvalResult};
+use rustc::mir::interpret::{InterpError, Scalar, GlobalId, EvalResult};
 use rustc::ty::{TyCtxt, self, Instance};
 use syntax::source_map::{Span, DUMMY_SP};
 use rustc::ty::subst::InternalSubsts;
@@ -144,7 +144,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
             Ok(val) => Some(val),
             Err(error) => {
                 let diagnostic = error_to_const_error(&self.ecx, error);
-                use rustc::mir::interpret::EvalErrorKind::*;
+                use rustc::mir::interpret::InterpError::*;
                 match diagnostic.error {
                     // don't report these, they make no sense in a const prop context
                     | MachineError(_)
@@ -457,7 +457,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
                     )
                 } else {
                     if overflow {
-                        let err = EvalErrorKind::Overflow(op).into();
+                        let err = InterpError::Overflow(op).into();
                         let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
                         return None;
                     }
@@ -556,7 +556,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
         if let StatementKind::Assign(ref place, ref rval) = statement.kind {
             let place_ty: ty::Ty<'tcx> = place
                 .ty(&self.mir.local_decls, self.tcx)
-                .to_ty(self.tcx);
+                .ty;
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
                 if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
                     if let Place::Base(PlaceBase::Local(local)) = *place {
@@ -611,7 +611,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                         .hir()
                         .as_local_hir_id(self.source.def_id())
                         .expect("some part of a failing const eval must be local");
-                    use rustc::mir::interpret::EvalErrorKind::*;
+                    use rustc::mir::interpret::InterpError::*;
                     let msg = match msg {
                         Overflow(_) |
                         OverflowNeg |
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index c4e303eb9aa..e63c1899fe5 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -773,7 +773,7 @@ fn create_generator_resume_function<'a, 'tcx>(
 
     let mut cases = create_cases(mir, &transform, |point| Some(point.resume));
 
-    use rustc::mir::interpret::EvalErrorKind::{
+    use rustc::mir::interpret::InterpError::{
         GeneratorResumedAfterPanic,
         GeneratorResumedAfterReturn,
     };
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 1063381d6aa..027ae70b06a 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -319,8 +319,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     work_list.push(target);
                     // If the location doesn't actually need dropping, treat it like
                     // a regular goto.
-                    let ty = location.ty(callee_mir, tcx).subst(tcx, callsite.substs);
-                    let ty = ty.to_ty(tcx);
+                    let ty = location.ty(callee_mir, tcx).subst(tcx, callsite.substs).ty;
                     if ty.needs_drop(tcx, param_env) {
                         cost += CALL_PENALTY;
                         if let Some(unwind) = unwind {
@@ -563,7 +562,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             assert!(args.next().is_none());
 
             let tuple = Place::Base(PlaceBase::Local(tuple));
-            let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
+            let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).ty.sty {
                 s
             } else {
                 bug!("Closure arguments are not passed as a tuple");
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index e0e64fd1f9b..8187a81f0ed 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -2,7 +2,7 @@
 
 use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, ProjectionElem, Rvalue, Local};
 use rustc::mir::visit::{MutVisitor, Visitor};
-use rustc::ty::{TyCtxt, TyKind};
+use rustc::ty::{self, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::Idx;
 use std::mem;
@@ -82,15 +82,15 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         if let Rvalue::Ref(_, _, Place::Projection(ref projection)) = *rvalue {
             if let ProjectionElem::Deref = projection.elem {
-                if projection.base.ty(self.mir, self.tcx).to_ty(self.tcx).is_region_ptr() {
+                if projection.base.ty(self.mir, self.tcx).ty.is_region_ptr() {
                     self.optimizations.and_stars.insert(location);
                 }
             }
         }
 
         if let Rvalue::Len(ref place) = *rvalue {
-            let place_ty = place.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
-            if let TyKind::Array(_, len) = place_ty.sty {
+            let place_ty = place.ty(&self.mir.local_decls, self.tcx).ty;
+            if let ty::Array(_, len) = place_ty.sty {
                 let span = self.mir.source_info(location).span;
                 let ty = self.tcx.types.usize;
                 let constant = Constant { span, ty, literal: len, user_ty: None };
diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs
index 54fc63f3057..fd9d6bb5760 100644
--- a/src/librustc_mir/transform/lower_128bit.rs
+++ b/src/librustc_mir/transform/lower_128bit.rs
@@ -3,7 +3,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::LangItem;
 use rustc::mir::*;
-use rustc::ty::{List, Ty, TyCtxt, TyKind};
+use rustc::ty::{self, List, Ty, TyCtxt};
 use rustc_data_structures::indexed_vec::{Idx};
 use crate::transform::{MirPass, MirSource};
 
@@ -135,7 +135,7 @@ fn check_lang_item_type<'a, 'tcx, D>(
     let sig = poly_sig.no_bound_vars().unwrap();
     let lhs_ty = lhs.ty(local_decls, tcx);
     let rhs_ty = rhs.ty(local_decls, tcx);
-    let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
+    let place_ty = place.ty(local_decls, tcx).ty;
     let expected = [lhs_ty, rhs_ty, place_ty];
     assert_eq!(sig.inputs_and_output[..], expected,
         "lang item `{}`", tcx.def_path_str(did));
@@ -183,8 +183,8 @@ impl RhsKind {
 
 fn sign_of_128bit(ty: Ty<'_>) -> Option<bool> {
     match ty.sty {
-        TyKind::Int(syntax::ast::IntTy::I128) => Some(true),
-        TyKind::Uint(syntax::ast::UintTy::U128) => Some(false),
+        ty::Int(syntax::ast::IntTy::I128) => Some(true),
+        ty::Uint(syntax::ast::UintTy::U128) => Some(false),
         _ => None,
     }
 }
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 8df0d72407b..27cb87f5dca 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -8,7 +8,6 @@ use rustc::ty::steal::Steal;
 use rustc::hir;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::util::nodemap::DefIdSet;
-use rustc_data_structures::sync::Lrc;
 use std::borrow::Cow;
 use syntax::ast;
 use syntax_pos::Span;
@@ -59,7 +58,7 @@ fn is_mir_available<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> boo
 /// Finds the full set of `DefId`s within the current crate that have
 /// MIR associated with them.
 fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum)
-                      -> Lrc<DefIdSet> {
+                      -> &'tcx DefIdSet {
     assert_eq!(krate, LOCAL_CRATE);
 
     let mut set = DefIdSet::default();
@@ -94,7 +93,7 @@ fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum)
         set: &mut set,
     }.as_deep_visitor());
 
-    Lrc::new(set)
+    tcx.arena.alloc(set)
 }
 
 fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 73b88e9904b..ddf963c7fa9 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -44,8 +44,8 @@ pub enum TempState {
 impl TempState {
     pub fn is_promotable(&self) -> bool {
         debug!("is_promotable: self={:?}", self);
-        if let TempState::Defined { uses, .. } = *self {
-            uses > 0
+        if let TempState::Defined { .. } = *self {
+            true
         } else {
             false
         }
@@ -80,9 +80,14 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
                    context: PlaceContext<'tcx>,
                    location: Location) {
         debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location);
-        // We're only interested in temporaries
-        if self.mir.local_kind(index) != LocalKind::Temp {
-            return;
+        // We're only interested in temporaries and the return place
+        match self.mir.local_kind(index) {
+            | LocalKind::Temp
+            | LocalKind::ReturnPointer
+            => {},
+            | LocalKind::Arg
+            | LocalKind::Var
+            => return,
         }
 
         // Ignore drops, if the temp gets promoted,
@@ -101,7 +106,6 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
         if *temp == TempState::Undefined {
             match context {
                 PlaceContext::MutatingUse(MutatingUseContext::Store) |
-                PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
                 PlaceContext::MutatingUse(MutatingUseContext::Call) => {
                     *temp = TempState::Defined {
                         location,
@@ -310,7 +314,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                                 place = &mut proj.base;
                             };
 
-                            let ty = place.ty(local_decls, self.tcx).to_ty(self.tcx);
+                            let ty = place.ty(local_decls, self.tcx).ty;
                             let span = statement.source_info.span;
 
                             Operand::Move(mem::replace(place, promoted_place(ty, span)))
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 9bd5fce31f1..3154f8e89e3 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -168,7 +168,7 @@ trait Qualif {
             cx,
             proj.base.ty(cx.mir, cx.tcx)
                 .projection_ty(cx.tcx, &proj.elem)
-                .to_ty(cx.tcx),
+                .ty,
         );
         match proj.elem {
             ProjectionElem::Deref |
@@ -245,7 +245,7 @@ trait Qualif {
                 // Special-case reborrows to be more like a copy of the reference.
                 if let Place::Projection(ref proj) = *place {
                     if let ProjectionElem::Deref = proj.elem {
-                        let base_ty = proj.base.ty(cx.mir, cx.tcx).to_ty(cx.tcx);
+                        let base_ty = proj.base.ty(cx.mir, cx.tcx).ty;
                         if let ty::Ref(..) = base_ty.sty {
                             return Self::in_place(cx, &proj.base);
                         }
@@ -301,7 +301,7 @@ impl Qualif for HasMutInterior {
             // allowed in constants (and the `Checker` will error), and/or it
             // won't be promoted, due to `&mut ...` or interior mutability.
             Rvalue::Ref(_, kind, ref place) => {
-                let ty = place.ty(cx.mir, cx.tcx).to_ty(cx.tcx);
+                let ty = place.ty(cx.mir, cx.tcx).ty;
 
                 if let BorrowKind::Mut { .. } = kind {
                     // In theory, any zero-sized value could be borrowed
@@ -365,11 +365,11 @@ impl Qualif for NeedsDrop {
     }
 }
 
-// Not constant at all - non-`const fn` calls, asm!,
+// Not promotable at all - non-`const fn` calls, asm!,
 // pointer comparisons, ptr-to-int casts, etc.
-struct IsNotConst;
+struct IsNotPromotable;
 
-impl Qualif for IsNotConst {
+impl Qualif for IsNotPromotable {
     const IDX: usize = 2;
 
     fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool {
@@ -398,7 +398,7 @@ impl Qualif for IsNotConst {
 
             ProjectionElem::Field(..) => {
                 if cx.mode == Mode::Fn {
-                    let base_ty = proj.base.ty(cx.mir, cx.tcx).to_ty(cx.tcx);
+                    let base_ty = proj.base.ty(cx.mir, cx.tcx).ty;
                     if let Some(def) = base_ty.ty_adt_def() {
                         if def.is_union() {
                             return true;
@@ -508,13 +508,17 @@ impl Qualif for IsNotConst {
     }
 }
 
-// Refers to temporaries which cannot be promoted as
-// promote_consts decided they weren't simple enough.
-// FIXME(oli-obk,eddyb): Remove this flag entirely and
-// solely process this information via `IsNotConst`.
-struct IsNotPromotable;
-
-impl Qualif for IsNotPromotable {
+/// Refers to temporaries which cannot be promoted *implicitly*.
+/// Explicit promotion happens e.g. for constant arguments declared via `rustc_args_required_const`.
+/// Inside a const context all constness rules
+/// apply, so implicit promotion simply has to follow the regular constant rules (modulo interior
+/// mutability or `Drop` rules which are handled `HasMutInterior` and `NeedsDrop` respectively).
+/// Implicit promotion inside regular functions does not happen if `const fn` calls are involved,
+/// as the call may be perfectly alright at runtime, but fail at compile time e.g. due to addresses
+/// being compared inside the function.
+struct IsNotImplicitlyPromotable;
+
+impl Qualif for IsNotImplicitlyPromotable {
     const IDX: usize = 3;
 
     fn in_call(
@@ -550,15 +554,18 @@ macro_rules! static_assert_seq_qualifs {
         static_assert!(SEQ_QUALIFS: QUALIF_COUNT == $i);
     };
 }
-static_assert_seq_qualifs!(0 => HasMutInterior, NeedsDrop, IsNotConst, IsNotPromotable);
+static_assert_seq_qualifs!(
+    0 => HasMutInterior, NeedsDrop, IsNotPromotable, IsNotImplicitlyPromotable
+);
 
 impl ConstCx<'_, 'tcx> {
     fn qualifs_in_any_value_of_ty(&self, ty: Ty<'tcx>) -> PerQualif<bool> {
         let mut qualifs = PerQualif::default();
         qualifs[HasMutInterior] = HasMutInterior::in_any_value_of_ty(self, ty).unwrap_or(false);
         qualifs[NeedsDrop] = NeedsDrop::in_any_value_of_ty(self, ty).unwrap_or(false);
-        qualifs[IsNotConst] = IsNotConst::in_any_value_of_ty(self, ty).unwrap_or(false);
         qualifs[IsNotPromotable] = IsNotPromotable::in_any_value_of_ty(self, ty).unwrap_or(false);
+        qualifs[IsNotImplicitlyPromotable] =
+            IsNotImplicitlyPromotable::in_any_value_of_ty(self, ty).unwrap_or(false);
         qualifs
     }
 
@@ -566,8 +573,8 @@ impl ConstCx<'_, 'tcx> {
         let mut qualifs = PerQualif::default();
         qualifs[HasMutInterior] = HasMutInterior::in_local(self, local);
         qualifs[NeedsDrop] = NeedsDrop::in_local(self, local);
-        qualifs[IsNotConst] = IsNotConst::in_local(self, local);
         qualifs[IsNotPromotable] = IsNotPromotable::in_local(self, local);
+        qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_local(self, local);
         qualifs
     }
 
@@ -575,8 +582,8 @@ impl ConstCx<'_, 'tcx> {
         let mut qualifs = PerQualif::default();
         qualifs[HasMutInterior] = HasMutInterior::in_value(self, source);
         qualifs[NeedsDrop] = NeedsDrop::in_value(self, source);
-        qualifs[IsNotConst] = IsNotConst::in_value(self, source);
         qualifs[IsNotPromotable] = IsNotPromotable::in_value(self, source);
+        qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_value(self, source);
         qualifs
     }
 }
@@ -631,26 +638,21 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
         };
 
         for (local, decl) in mir.local_decls.iter_enumerated() {
-            match mir.local_kind(local) {
-                LocalKind::Arg => {
-                    let qualifs = cx.qualifs_in_any_value_of_ty(decl.ty);
-                    for (per_local, qualif) in &mut cx.per_local.as_mut().zip(qualifs).0 {
-                        if *qualif {
-                            per_local.insert(local);
-                        }
+            if let LocalKind::Arg = mir.local_kind(local) {
+                let qualifs = cx.qualifs_in_any_value_of_ty(decl.ty);
+                for (per_local, qualif) in &mut cx.per_local.as_mut().zip(qualifs).0 {
+                    if *qualif {
+                        per_local.insert(local);
                     }
-                    cx.per_local[IsNotPromotable].insert(local);
-                }
-
-                LocalKind::Var if mode == Mode::Fn => {
-                    cx.per_local[IsNotConst].insert(local);
                 }
-
-                LocalKind::Temp if !temps[local].is_promotable() => {
-                    cx.per_local[IsNotPromotable].insert(local);
-                }
-
-                _ => {}
+            }
+            if !temps[local].is_promotable() {
+                cx.per_local[IsNotPromotable].insert(local);
+            }
+            if let LocalKind::Var = mir.local_kind(local) {
+                // Sanity check to prevent implicit and explicit promotion of
+                // named locals
+                assert!(cx.per_local[IsNotPromotable].contains(local));
             }
         }
 
@@ -698,11 +700,11 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
             // the borrowed place is disallowed from being borrowed,
             // due to either a mutable borrow (with some exceptions),
             // or an shared borrow of a value with interior mutability.
-            // Then `HasMutInterior` is replaced with `IsNotConst`,
+            // Then `HasMutInterior` is replaced with `IsNotPromotable`,
             // to avoid duplicate errors (e.g. from reborrowing).
             if qualifs[HasMutInterior] {
                 qualifs[HasMutInterior] = false;
-                qualifs[IsNotConst] = true;
+                qualifs[IsNotPromotable] = true;
 
                 if self.mode != Mode::Fn {
                     if let BorrowKind::Mut { .. } = kind {
@@ -728,7 +730,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                                    interior mutability, create a static instead");
                     }
                 }
-            } else {
+            } else if let BorrowKind::Mut { .. } | BorrowKind::Shared = kind {
+                // Don't promote BorrowKind::Shallow borrows, as they don't
+                // reach codegen.
+
                 // We might have a candidate for promotion.
                 let candidate = Candidate::Ref(location);
                 // We can only promote interior borrows of promotable temps.
@@ -908,7 +913,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
 
         // Account for errors in consts by using the
         // conservative type qualification instead.
-        if qualifs[IsNotConst] {
+        if qualifs[IsNotPromotable] {
             qualifs = self.qualifs_in_any_value_of_ty(mir.return_ty());
         }
 
@@ -985,7 +990,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                             // `not_const` errors out in const contexts
                             self.not_const()
                         }
-                        let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                        let base_ty = proj.base.ty(self.mir, self.tcx).ty;
                         match self.mode {
                             Mode::Fn => {},
                             _ => {
@@ -1009,7 +1014,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                     ProjectionElem::Subslice {..} |
                     ProjectionElem::Field(..) |
                     ProjectionElem::Index(_) => {
-                        let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                        let base_ty = proj.base.ty(self.mir, self.tcx).ty;
                         if let Some(def) = base_ty.ty_adt_def() {
                             if def.is_union() {
                                 match self.mode {
@@ -1066,7 +1071,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
             let mut is_reborrow = false;
             if let Place::Projection(ref proj) = *place {
                 if let ProjectionElem::Deref = proj.elem {
-                    let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                    let base_ty = proj.base.ty(self.mir, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.sty {
                         is_reborrow = true;
                     }
@@ -1190,7 +1195,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                 self.assign(dest, ValueSource::Call {
                     callee: func,
                     args,
-                    return_ty: dest.ty(self.mir, self.tcx).to_ty(self.tcx),
+                    return_ty: dest.ty(self.mir, self.tcx).ty,
                 }, location);
             }
 
@@ -1323,7 +1328,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                     // which happens even without the user requesting it.
                     // We can error out with a hard error if the argument is not
                     // constant here.
-                    if !IsNotConst::in_operand(self, arg) {
+                    if !IsNotPromotable::in_operand(self, arg) {
                         debug!("visit_terminator_kind: candidate={:?}", candidate);
                         self.promotion_candidates.push(candidate);
                     } else {
@@ -1364,7 +1369,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
 
                 if let Some(span) = needs_drop {
                     // Double-check the type being dropped, to minimize false positives.
-                    let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
+                    let ty = place.ty(self.mir, self.tcx).ty;
                     if ty.needs_drop(self.tcx, self.param_env) {
                         struct_span_err!(self.tcx.sess, span, E0493,
                                          "destructors cannot be evaluated at compile-time")
@@ -1441,7 +1446,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     if mir.return_ty().references_error() {
         tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors");
-        return (1 << IsNotConst::IDX, Lrc::new(BitSet::new_empty(0)));
+        return (1 << IsNotPromotable::IDX, Lrc::new(BitSet::new_empty(0)));
     }
 
     Checker::new(tcx, def_id, mir, Mode::Const).check_const()
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
index b1d898bb5b0..616944dd7ef 100644
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ b/src/librustc_mir/transform/uniform_array_move_out.rs
@@ -69,7 +69,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
                                                      from_end: false} = proj.elem {
                     // no need to transformation
                 } else {
-                    let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                    let place_ty = proj.base.ty(self.mir, self.tcx).ty;
                     if let ty::Array(item_ty, const_size) = place_ty.sty {
                         if let Some(size) = const_size.assert_usize(self.tcx) {
                             assert!(size <= u32::max_value() as u64,
@@ -195,7 +195,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut {
 
                         let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
                         let opt_size = opt_src_place.and_then(|src_place| {
-                            let src_ty = src_place.ty(mir, tcx).to_ty(tcx);
+                            let src_ty = src_place.ty(mir, tcx).ty;
                             if let ty::Array(_, ref size_o) = src_ty.sty {
                                 size_o.assert_usize(tcx)
                             } else {
diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs
index 7be34d001df..788b7fdaaf9 100644
--- a/src/librustc_mir/util/alignment.rs
+++ b/src/librustc_mir/util/alignment.rs
@@ -17,7 +17,7 @@ pub fn is_disaligned<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return false
     }
 
-    let ty = place.ty(local_decls, tcx).to_ty(tcx);
+    let ty = place.ty(local_decls, tcx).ty;
     match tcx.layout_raw(param_env.and(ty)) {
         Ok(layout) if layout.align.abi.bytes() == 1 => {
             // if the alignment is 1, the type can't be further
@@ -46,7 +46,7 @@ fn is_within_packed<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             // encountered a Deref, which is ABI-aligned
             ProjectionElem::Deref => break,
             ProjectionElem::Field(..) => {
-                let ty = base.ty(local_decls, tcx).to_ty(tcx);
+                let ty = base.ty(local_decls, tcx).ty;
                 match ty.sty {
                     ty::Adt(def, _) if def.repr.packed() => {
                         return true
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 37b38338ab9..2d275c9a137 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -122,7 +122,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
     where D: DropElaborator<'b, 'tcx>
 {
     fn place_ty(&self, place: &Place<'tcx>) -> Ty<'tcx> {
-        place.ty(self.elaborator.mir(), self.tcx()).to_ty(self.tcx())
+        place.ty(self.elaborator.mir(), self.tcx()).ty
     }
 
     fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
@@ -412,8 +412,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 self.path, variant_index);
             if let Some(variant_path) = subpath {
                 let base_place = self.place.clone().elem(
-                    ProjectionElem::Downcast(adt, variant_index)
-                        );
+                    ProjectionElem::Downcast(Some(adt.variants[variant_index].ident.name),
+                                             variant_index));
                 let fields = self.move_paths_for_fields(
                     &base_place,
                     variant_path,
diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml
index 7d88aa59b3a..bda40785725 100644
--- a/src/librustc_msan/Cargo.toml
+++ b/src/librustc_msan/Cargo.toml
@@ -12,7 +12,7 @@ test = false
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cmake = "0.1.18"
+cmake = "0.1.38"
 
 [dependencies]
 alloc = { path = "../liballoc" }
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index ff2e345d084..20442a4a566 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -12,6 +12,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use]
 extern crate rustc;
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 030883c0159..9a8970b2935 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -1,6 +1,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs
index 461d02e515d..931bce91d7d 100644
--- a/src/librustc_resolve/error_reporting.rs
+++ b/src/librustc_resolve/error_reporting.rs
@@ -4,16 +4,17 @@ use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use log::debug;
 use rustc::hir::def::{Def, CtorKind, Namespace::*};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
-use rustc::session::config::nightly_options;
-use syntax::ast::{Expr, ExprKind};
-use syntax::symbol::keywords;
-use syntax_pos::Span;
+use rustc::session::{Session, config::nightly_options};
+use syntax::ast::{Expr, ExprKind, Ident};
+use syntax::ext::base::MacroKind;
+use syntax::symbol::{Symbol, keywords};
+use syntax_pos::{BytePos, Span};
 
 use crate::macros::ParentScope;
-use crate::resolve_imports::ImportResolver;
+use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
 use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_names_to_string};
 use crate::{AssocSuggestion, CrateLint, ImportSuggestion, ModuleOrUniformRoot, PathResult,
-            PathSource, Resolver, Segment};
+            PathSource, Resolver, Segment, Suggestion};
 
 impl<'a> Resolver<'a> {
     /// Handles error reporting for `smart_resolve_path_fragment` function.
@@ -428,7 +429,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         span: Span,
         mut path: Vec<Segment>,
         parent_scope: &ParentScope<'b>,
-    ) -> Option<(Vec<Segment>, Option<String>)> {
+    ) -> Option<(Vec<Segment>, Vec<String>)> {
         debug!("make_path_suggestion: span={:?} path={:?}", span, path);
 
         match (path.get(0), path.get(1)) {
@@ -463,13 +464,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         span: Span,
         mut path: Vec<Segment>,
         parent_scope: &ParentScope<'b>,
-    ) -> Option<(Vec<Segment>, Option<String>)> {
+    ) -> Option<(Vec<Segment>, Vec<String>)> {
         // Replace first ident with `self` and check if that is valid.
         path[0].ident.name = keywords::SelfLower.name();
         let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
         debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
         if let PathResult::Module(..) = result {
-            Some((path, None))
+            Some((path, Vec::new()))
         } else {
             None
         }
@@ -487,7 +488,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         span: Span,
         mut path: Vec<Segment>,
         parent_scope: &ParentScope<'b>,
-    ) -> Option<(Vec<Segment>, Option<String>)> {
+    ) -> Option<(Vec<Segment>, Vec<String>)> {
         // Replace first ident with `crate` and check if that is valid.
         path[0].ident.name = keywords::Crate.name();
         let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
@@ -495,11 +496,11 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         if let PathResult::Module(..) = result {
             Some((
                 path,
-                Some(
+                vec![
                     "`use` statements changed in Rust 2018; read more at \
                      <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
                      clarity.html>".to_string()
-                ),
+                ],
             ))
         } else {
             None
@@ -518,13 +519,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         span: Span,
         mut path: Vec<Segment>,
         parent_scope: &ParentScope<'b>,
-    ) -> Option<(Vec<Segment>, Option<String>)> {
+    ) -> Option<(Vec<Segment>, Vec<String>)> {
         // Replace first ident with `crate` and check if that is valid.
         path[0].ident.name = keywords::Super.name();
         let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
         debug!("make_missing_super_suggestion:  path={:?} result={:?}", path, result);
         if let PathResult::Module(..) = result {
-            Some((path, None))
+            Some((path, Vec::new()))
         } else {
             None
         }
@@ -545,7 +546,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         span: Span,
         mut path: Vec<Segment>,
         parent_scope: &ParentScope<'b>,
-    ) -> Option<(Vec<Segment>, Option<String>)> {
+    ) -> Option<(Vec<Segment>, Vec<String>)> {
         if path[1].ident.span.rust_2015() {
             return None;
         }
@@ -564,10 +565,290 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
                     name, path, result);
             if let PathResult::Module(..) = result {
-                return Some((path, None));
+                return Some((path, Vec::new()));
             }
         }
 
         None
     }
+
+    /// Suggests importing a macro from the root of the crate rather than a module within
+    /// the crate.
+    ///
+    /// ```
+    /// help: a macro with this name exists at the root of the crate
+    ///    |
+    /// LL | use issue_59764::makro;
+    ///    |     ^^^^^^^^^^^^^^^^^^
+    ///    |
+    ///    = note: this could be because a macro annotated with `#[macro_export]` will be exported
+    ///            at the root of the crate instead of the module where it is defined
+    /// ```
+    pub(crate) fn check_for_module_export_macro(
+        &self,
+        directive: &'b ImportDirective<'b>,
+        module: ModuleOrUniformRoot<'b>,
+        ident: Ident,
+    ) -> Option<(Option<Suggestion>, Vec<String>)> {
+        let mut crate_module = if let ModuleOrUniformRoot::Module(module) = module {
+            module
+        } else {
+            return None;
+        };
+
+        while let Some(parent) = crate_module.parent {
+            crate_module = parent;
+        }
+
+        if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) {
+            // Don't make a suggestion if the import was already from the root of the
+            // crate.
+            return None;
+        }
+
+        let resolutions = crate_module.resolutions.borrow();
+        let resolution = resolutions.get(&(ident, MacroNS))?;
+        let binding = resolution.borrow().binding()?;
+        if let Def::Macro(_, MacroKind::Bang) = binding.def() {
+            let module_name = crate_module.kind.name().unwrap();
+            let import = match directive.subclass {
+                ImportDirectiveSubclass::SingleImport { source, target, .. } if source != target =>
+                    format!("{} as {}", source, target),
+                _ => format!("{}", ident),
+            };
+
+            let mut corrections: Vec<(Span, String)> = Vec::new();
+            if !directive.is_nested() {
+                // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
+                // intermediate segments.
+                corrections.push((directive.span, format!("{}::{}", module_name, import)));
+            } else {
+                // Find the binding span (and any trailing commas and spaces).
+                //   ie. `use a::b::{c, d, e};`
+                //                      ^^^
+                let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
+                    self.resolver.session, directive.span, directive.use_span,
+                );
+                debug!("check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}",
+                       found_closing_brace, binding_span);
+
+                let mut removal_span = binding_span;
+                if found_closing_brace {
+                    // If the binding span ended with a closing brace, as in the below example:
+                    //   ie. `use a::b::{c, d};`
+                    //                      ^
+                    // Then expand the span of characters to remove to include the previous
+                    // binding's trailing comma.
+                    //   ie. `use a::b::{c, d};`
+                    //                    ^^^
+                    if let Some(previous_span) = extend_span_to_previous_binding(
+                        self.resolver.session, binding_span,
+                    ) {
+                        debug!("check_for_module_export_macro: previous_span={:?}", previous_span);
+                        removal_span = removal_span.with_lo(previous_span.lo());
+                    }
+                }
+                debug!("check_for_module_export_macro: removal_span={:?}", removal_span);
+
+                // Remove the `removal_span`.
+                corrections.push((removal_span, "".to_string()));
+
+                // Find the span after the crate name and if it has nested imports immediatately
+                // after the crate name already.
+                //   ie. `use a::b::{c, d};`
+                //               ^^^^^^^^^
+                //   or  `use a::{b, c, d}};`
+                //               ^^^^^^^^^^^
+                let (has_nested, after_crate_name) = find_span_immediately_after_crate_name(
+                    self.resolver.session, module_name, directive.use_span,
+                );
+                debug!("check_for_module_export_macro: has_nested={:?} after_crate_name={:?}",
+                       has_nested, after_crate_name);
+
+                let source_map = self.resolver.session.source_map();
+
+                // Add the import to the start, with a `{` if required.
+                let start_point = source_map.start_point(after_crate_name);
+                if let Ok(start_snippet) = source_map.span_to_snippet(start_point) {
+                    corrections.push((
+                        start_point,
+                        if has_nested {
+                            // In this case, `start_snippet` must equal '{'.
+                            format!("{}{}, ", start_snippet, import)
+                        } else {
+                            // In this case, add a `{`, then the moved import, then whatever
+                            // was there before.
+                            format!("{{{}, {}", import, start_snippet)
+                        }
+                    ));
+                }
+
+                // Add a `};` to the end if nested, matching the `{` added at the start.
+                if !has_nested {
+                    corrections.push((source_map.end_point(after_crate_name),
+                                     "};".to_string()));
+                }
+            }
+
+            let suggestion = Some((
+                corrections,
+                String::from("a macro with this name exists at the root of the crate"),
+                Applicability::MaybeIncorrect,
+            ));
+            let note = vec![
+                "this could be because a macro annotated with `#[macro_export]` will be exported \
+                 at the root of the crate instead of the module where it is defined".to_string(),
+            ];
+            Some((suggestion, note))
+        } else {
+            None
+        }
+    }
+}
+
+/// Given a `binding_span` of a binding within a use statement:
+///
+/// ```
+/// use foo::{a, b, c};
+///              ^
+/// ```
+///
+/// then return the span until the next binding or the end of the statement:
+///
+/// ```
+/// use foo::{a, b, c};
+///              ^^^
+/// ```
+pub(crate) fn find_span_of_binding_until_next_binding(
+    sess: &Session,
+    binding_span: Span,
+    use_span: Span,
+) -> (bool, Span) {
+    let source_map = sess.source_map();
+
+    // Find the span of everything after the binding.
+    //   ie. `a, e};` or `a};`
+    let binding_until_end = binding_span.with_hi(use_span.hi());
+
+    // Find everything after the binding but not including the binding.
+    //   ie. `, e};` or `};`
+    let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
+
+    // Keep characters in the span until we encounter something that isn't a comma or
+    // whitespace.
+    //   ie. `, ` or ``.
+    //
+    // Also note whether a closing brace character was encountered. If there
+    // was, then later go backwards to remove any trailing commas that are left.
+    let mut found_closing_brace = false;
+    let after_binding_until_next_binding = source_map.span_take_while(
+        after_binding_until_end,
+        |&ch| {
+            if ch == '}' { found_closing_brace = true; }
+            ch == ' ' || ch == ','
+        }
+    );
+
+    // Combine the two spans.
+    //   ie. `a, ` or `a`.
+    //
+    // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
+    let span = binding_span.with_hi(after_binding_until_next_binding.hi());
+
+    (found_closing_brace, span)
+}
+
+/// Given a `binding_span`, return the span through to the comma or opening brace of the previous
+/// binding.
+///
+/// ```
+/// use foo::a::{a, b, c};
+///               ^^--- binding span
+///               |
+///               returned span
+///
+/// use foo::{a, b, c};
+///           --- binding span
+/// ```
+pub(crate) fn extend_span_to_previous_binding(
+    sess: &Session,
+    binding_span: Span,
+) -> Option<Span> {
+    let source_map = sess.source_map();
+
+    // `prev_source` will contain all of the source that came before the span.
+    // Then split based on a command and take the first (ie. closest to our span)
+    // snippet. In the example, this is a space.
+    let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
+
+    let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
+    let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
+    if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
+        return None;
+    }
+
+    let prev_comma = prev_comma.first().unwrap();
+    let prev_starting_brace = prev_starting_brace.first().unwrap();
+
+    // If the amount of source code before the comma is greater than
+    // the amount of source code before the starting brace then we've only
+    // got one item in the nested item (eg. `issue_52891::{self}`).
+    if prev_comma.len() > prev_starting_brace.len() {
+        return None;
+    }
+
+    Some(binding_span.with_lo(BytePos(
+        // Take away the number of bytes for the characters we've found and an
+        // extra for the comma.
+        binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1
+    )))
+}
+
+/// Given a `use_span` of a binding within a use statement, returns the highlighted span and if
+/// it is a nested use tree.
+///
+/// ```
+/// use foo::a::{b, c};
+///          ^^^^^^^^^^ // false
+///
+/// use foo::{a, b, c};
+///          ^^^^^^^^^^ // true
+///
+/// use foo::{a, b::{c, d}};
+///          ^^^^^^^^^^^^^^^ // true
+/// ```
+fn find_span_immediately_after_crate_name(
+    sess: &Session,
+    module_name: Symbol,
+    use_span: Span,
+) -> (bool, Span) {
+    debug!("find_span_immediately_after_crate_name: module_name={:?} use_span={:?}",
+           module_name, use_span);
+    let source_map = sess.source_map();
+
+    // Using `use issue_59764::foo::{baz, makro};` as an example throughout..
+    let mut num_colons = 0;
+    // Find second colon.. `use issue_59764:`
+    let until_second_colon = source_map.span_take_while(use_span, |c| {
+        if *c == ':' { num_colons += 1; }
+        match c {
+            ':' if num_colons == 2 => false,
+            _ => true,
+        }
+    });
+    // Find everything after the second colon.. `foo::{baz, makro};`
+    let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
+
+    let mut found_a_non_whitespace_character = false;
+    // Find the first non-whitespace character in `from_second_colon`.. `f`
+    let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
+        if found_a_non_whitespace_character { return false; }
+        if !c.is_whitespace() { found_a_non_whitespace_character = true; }
+        true
+    });
+
+    // Find the first `{` in from_second_colon.. `foo::{`
+    let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
+
+    (next_left_bracket == after_second_colon, from_second_colon)
 }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 3703ea08b62..b34786d8f12 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -8,6 +8,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 pub use rustc::hir::def::{Namespace, PerNS};
 
@@ -49,7 +50,7 @@ use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
 use syntax::ptr::P;
 use syntax::{span_err, struct_span_err, unwrap_or, walk_list};
 
-use syntax_pos::{BytePos, Span, DUMMY_SP, MultiSpan};
+use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 
 use log::debug;
@@ -61,6 +62,7 @@ use std::mem::replace;
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_data_structures::sync::Lrc;
 
+use error_reporting::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
 use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
 use macros::{InvocationData, LegacyBinding, ParentScope};
 
@@ -137,8 +139,8 @@ impl Ord for BindingError {
     }
 }
 
-/// A span, message, replacement text, and applicability.
-type Suggestion = (Span, String, String, Applicability);
+/// A vector of spans and replacements, a message and applicability.
+type Suggestion = (Vec<(Span, String)>, String, Applicability);
 
 enum ResolutionError<'a> {
     /// Error E0401: can't use type or const parameters from outer function.
@@ -388,8 +390,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
                                            "failed to resolve: {}", &label);
             err.span_label(span, label);
 
-            if let Some((span, msg, suggestion, applicability)) = suggestion {
-                err.span_suggestion(span, &msg, suggestion, applicability);
+            if let Some((suggestions, msg, applicability)) = suggestion {
+                err.multipart_suggestion(&msg, suggestions, applicability);
             }
 
             err
@@ -1090,6 +1092,16 @@ enum ModuleKind {
     Def(Def, Name),
 }
 
+impl ModuleKind {
+    /// Get name of the module.
+    pub fn name(&self) -> Option<Name> {
+        match self {
+            ModuleKind::Block(..) => None,
+            ModuleKind::Def(_, name) => Some(*name),
+        }
+    }
+}
+
 /// One node in the tree of modules.
 pub struct ModuleData<'a> {
     parent: Option<Module<'a>>,
@@ -1352,7 +1364,7 @@ impl<'a> NameBinding<'a> {
         }
     }
 
-    // We sometimes need to treat variants as `pub` for backwards compatibility
+    // We sometimes need to treat variants as `pub` for backwards compatibility.
     fn pseudo_vis(&self) -> ty::Visibility {
         if self.is_variant() && self.def().def_id().is_local() {
             ty::Visibility::Public
@@ -2714,7 +2726,7 @@ impl<'a> Resolver<'a> {
     {
         let mut self_type_rib = Rib::new(NormalRibKind);
 
-        // plain insert (no renaming, types are not currently hygienic....)
+        // Plain insert (no renaming, since types are not currently hygienic)
         self_type_rib.bindings.insert(keywords::SelfUpper.ident(), self_def);
         self.ribs[TypeNS].push(self_type_rib);
         f(self);
@@ -3730,9 +3742,16 @@ impl<'a> Resolver<'a> {
                             def, path.len() - i - 1
                         ));
                     } else {
+                        let label = format!(
+                            "`{}` is {} {}, not a module",
+                            ident,
+                            def.article(),
+                            def.kind_name(),
+                        );
+
                         return PathResult::Failed {
                             span: ident.span,
-                            label: format!("not a module `{}`", ident),
+                            label,
                             suggestion: None,
                             is_error_from_last_segment: is_last,
                         };
@@ -3762,9 +3781,8 @@ impl<'a> Resolver<'a> {
                             (
                                 String::from("unresolved import"),
                                 Some((
-                                    ident.span,
+                                    vec![(ident.span, candidate.path.to_string())],
                                     String::from("a similar path exists"),
-                                    candidate.path.to_string(),
                                     Applicability::MaybeIncorrect,
                                 )),
                             )
@@ -4438,26 +4456,47 @@ impl<'a> Resolver<'a> {
             let mut collected_traits = Vec::new();
             module.for_each_child(|name, ns, binding| {
                 if ns != TypeNS { return }
-                if let Def::Trait(_) = binding.def() {
-                    collected_traits.push((name, binding));
+                match binding.def() {
+                    Def::Trait(_) |
+                    Def::TraitAlias(_) => collected_traits.push((name, binding)),
+                    _ => (),
                 }
             });
             *traits = Some(collected_traits.into_boxed_slice());
         }
 
         for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
-            let module = binding.module().unwrap();
-            let mut ident = ident;
-            if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() {
-                continue
-            }
-            if self.resolve_ident_in_module_unadjusted(
-                ModuleOrUniformRoot::Module(module),
-                ident,
-                ns,
-                false,
-                module.span,
-            ).is_ok() {
+            // Traits have pseudo-modules that can be used to search for the given ident.
+            if let Some(module) = binding.module() {
+                let mut ident = ident;
+                if ident.span.glob_adjust(
+                    module.expansion,
+                    binding.span.ctxt().modern(),
+                ).is_none() {
+                    continue
+                }
+                if self.resolve_ident_in_module_unadjusted(
+                    ModuleOrUniformRoot::Module(module),
+                    ident,
+                    ns,
+                    false,
+                    module.span,
+                ).is_ok() {
+                    let import_id = match binding.kind {
+                        NameBindingKind::Import { directive, .. } => {
+                            self.maybe_unused_trait_imports.insert(directive.id);
+                            self.add_to_glob_map(&directive, trait_name);
+                            Some(directive.id)
+                        }
+                        _ => None,
+                    };
+                    let trait_def_id = module.def_id().unwrap();
+                    found_traits.push(TraitCandidate { def_id: trait_def_id, import_id });
+                }
+            } else if let Def::TraitAlias(_) = binding.def() {
+                // For now, just treat all trait aliases as possible candidates, since we don't
+                // know if the ident is somewhere in the transitive bounds.
+
                 let import_id = match binding.kind {
                     NameBindingKind::Import { directive, .. } => {
                         self.maybe_unused_trait_imports.insert(directive.id);
@@ -4466,8 +4505,10 @@ impl<'a> Resolver<'a> {
                     }
                     _ => None,
                 };
-                let trait_def_id = module.def_id().unwrap();
-                found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id });
+                let trait_def_id = binding.def().def_id();
+                found_traits.push(TraitCandidate { def_id: trait_def_id, import_id });
+            } else {
+                bug!("candidate is not trait or trait alias?")
             }
         }
     }
@@ -5110,7 +5151,6 @@ impl<'a> Resolver<'a> {
     ) {
         assert!(directive.is_nested());
         let message = "remove unnecessary import";
-        let source_map = self.session.source_map();
 
         // Two examples will be used to illustrate the span manipulations we're doing:
         //
@@ -5119,73 +5159,24 @@ impl<'a> Resolver<'a> {
         // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is
         //   `a` and `directive.use_span` is `issue_52891::{d, e, a};`.
 
-        // Find the span of everything after the binding.
-        //   ie. `a, e};` or `a};`
-        let binding_until_end = binding_span.with_hi(directive.use_span.hi());
-
-        // Find everything after the binding but not including the binding.
-        //   ie. `, e};` or `};`
-        let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
-
-        // Keep characters in the span until we encounter something that isn't a comma or
-        // whitespace.
-        //   ie. `, ` or ``.
-        //
-        // Also note whether a closing brace character was encountered. If there
-        // was, then later go backwards to remove any trailing commas that are left.
-        let mut found_closing_brace = false;
-        let after_binding_until_next_binding = source_map.span_take_while(
-            after_binding_until_end,
-            |&ch| {
-                if ch == '}' { found_closing_brace = true; }
-                ch == ' ' || ch == ','
-            }
+        let (found_closing_brace, span) = find_span_of_binding_until_next_binding(
+            self.session, binding_span, directive.use_span,
         );
 
-        // Combine the two spans.
-        //   ie. `a, ` or `a`.
-        //
-        // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
-        let span = binding_span.with_hi(after_binding_until_next_binding.hi());
-
         // If there was a closing brace then identify the span to remove any trailing commas from
         // previous imports.
         if found_closing_brace {
-            if let Ok(prev_source) = source_map.span_to_prev_source(span) {
-                // `prev_source` will contain all of the source that came before the span.
-                // Then split based on a command and take the first (ie. closest to our span)
-                // snippet. In the example, this is a space.
-                let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
-                let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
-                if prev_comma.len() > 1 && prev_starting_brace.len() > 1 {
-                    let prev_comma = prev_comma.first().unwrap();
-                    let prev_starting_brace = prev_starting_brace.first().unwrap();
-
-                    // If the amount of source code before the comma is greater than
-                    // the amount of source code before the starting brace then we've only
-                    // got one item in the nested item (eg. `issue_52891::{self}`).
-                    if prev_comma.len() > prev_starting_brace.len() {
-                        // So just remove the entire line...
-                        err.span_suggestion(
-                            directive.use_span_with_attributes,
-                            message,
-                            String::new(),
-                            Applicability::MaybeIncorrect,
-                        );
-                        return;
-                    }
-
-                    let span = span.with_lo(BytePos(
-                        // Take away the number of bytes for the characters we've found and an
-                        // extra for the comma.
-                        span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1
-                    ));
-                    err.tool_only_span_suggestion(
-                        span, message, String::new(), Applicability::MaybeIncorrect,
-                    );
-                    return;
-                }
+            if let Some(span) = extend_span_to_previous_binding(self.session, span) {
+                err.tool_only_span_suggestion(span, message, String::new(),
+                                              Applicability::MaybeIncorrect);
+            } else {
+                // Remove the entire line if we cannot extend the span back, this indicates a
+                // `issue_52891::{self}` case.
+                err.span_suggestion(directive.use_span_with_attributes, message, String::new(),
+                                    Applicability::MaybeIncorrect);
             }
+
+            return;
         }
 
         err.span_suggestion(span, message, String::new(), Applicability::MachineApplicable);
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 7ea07f5e0cb..62af6e19603 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -145,7 +145,7 @@ pub struct NameResolution<'a> {
 
 impl<'a> NameResolution<'a> {
     // Returns the binding for the name if it is known or None if it not known.
-    fn binding(&self) -> Option<&'a NameBinding<'a>> {
+    pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> {
         self.binding.and_then(|binding| {
             if !binding.is_glob_import() ||
                self.single_imports.is_empty() { Some(binding) } else { None }
@@ -636,7 +636,7 @@ impl<'a> Resolver<'a> {
 struct UnresolvedImportError {
     span: Span,
     label: Option<String>,
-    note: Option<String>,
+    note: Vec<String>,
     suggestion: Option<Suggestion>,
 }
 
@@ -756,8 +756,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         /// Upper limit on the number of `span_label` messages.
         const MAX_LABEL_COUNT: usize = 10;
 
-        let (span, msg, note) = if errors.is_empty() {
-            (span.unwrap(), "unresolved import".to_string(), None)
+        let (span, msg) = if errors.is_empty() {
+            (span.unwrap(), "unresolved import".to_string())
         } else {
             let span = MultiSpan::from_spans(
                 errors
@@ -766,11 +766,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                     .collect(),
             );
 
-            let note = errors
-                .iter()
-                .filter_map(|(_, err)| err.note.as_ref())
-                .last();
-
             let paths = errors
                 .iter()
                 .map(|(path, _)| format!("`{}`", path))
@@ -782,13 +777,15 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 paths.join(", "),
             );
 
-            (span, msg, note)
+            (span, msg)
         };
 
         let mut diag = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg);
 
-        if let Some(note) = &note {
-            diag.note(note);
+        if let Some((_, UnresolvedImportError { note, .. })) = errors.iter().last() {
+            for message in note {
+                diag.note(&message);
+            }
         }
 
         for (_, err) in errors.into_iter().take(MAX_LABEL_COUNT) {
@@ -796,8 +793,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 diag.span_label(err.span, label);
             }
 
-            if let Some((span, msg, suggestion, applicability)) = err.suggestion {
-                diag.span_suggestion(span, &msg, suggestion, applicability);
+            if let Some((suggestions, msg, applicability)) = err.suggestion {
+                diag.multipart_suggestion(&msg, suggestions, applicability);
             }
         }
 
@@ -950,9 +947,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                                 label: None,
                                 note,
                                 suggestion: Some((
-                                    span,
+                                    vec![(span, Segment::names_to_string(&suggestion))],
                                     String::from("a similar path exists"),
-                                    Segment::names_to_string(&suggestion),
                                     Applicability::MaybeIncorrect,
                                 )),
                             }
@@ -961,7 +957,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                             UnresolvedImportError {
                                 span,
                                 label: Some(label),
-                                note: None,
+                                note: Vec::new(),
                                 suggestion,
                             }
                         }
@@ -1006,7 +1002,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                         return Some(UnresolvedImportError {
                             span: directive.span,
                             label: Some(String::from("cannot glob-import a module into itself")),
-                            note: None,
+                            note: Vec::new(),
                             suggestion: None,
                         });
                     }
@@ -1114,15 +1110,19 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                     }
                 });
 
-                let lev_suggestion =
-                    find_best_match_for_name(names, &ident.as_str(), None).map(|suggestion| {
-                        (
-                            ident.span,
-                            String::from("a similar name exists in the module"),
-                            suggestion.to_string(),
-                            Applicability::MaybeIncorrect,
-                        )
-                    });
+                let lev_suggestion = find_best_match_for_name(names, &ident.as_str(), None)
+                   .map(|suggestion|
+                        (vec![(ident.span, suggestion.to_string())],
+                         String::from("a similar name exists in the module"),
+                         Applicability::MaybeIncorrect)
+                    );
+
+                let (suggestion, note) = match self.check_for_module_export_macro(
+                    directive, module, ident,
+                ) {
+                    Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),
+                    _ => (lev_suggestion, Vec::new()),
+                };
 
                 let label = match module {
                     ModuleOrUniformRoot::Module(module) => {
@@ -1143,11 +1143,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                         }
                     }
                 };
+
                 Some(UnresolvedImportError {
                     span: directive.span,
                     label: Some(label),
-                    note: None,
-                    suggestion: lev_suggestion,
+                    note,
+                    suggestion,
                 })
             } else {
                 // `resolve_ident_in_module` reported a privacy error.
@@ -1334,7 +1335,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
 
         self.populate_module_if_necessary(module);
 
-        if let Some(Def::Trait(_)) = module.def() {
+        if module.is_trait() {
             self.session.span_err(directive.span, "items in traits are not importable.");
             return;
         } else if module.def_id() == directive.parent_scope.module.def_id()  {
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 898ea62046d..d6923b4490d 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -2,6 +2,7 @@
 #![feature(custom_attribute)]
 #![feature(nll)]
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(unused_attributes)]
 
 #![recursion_limit="256"]
@@ -22,7 +23,6 @@ use rustc::middle::cstore::ExternCrate;
 use rustc::session::config::{CrateType, Input, OutputType};
 use rustc::ty::{self, DefIdTree, TyCtxt};
 use rustc::{bug, span_bug};
-use rustc_typeck::hir_ty_to_ty;
 use rustc_codegen_utils::link::{filename_for_metadata, out_filename};
 use rustc_data_structures::sync::Lrc;
 
@@ -647,6 +647,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             Node::Pat(&hir::Pat {
                 node: hir::PatKind::TupleStruct(ref qpath, ..),
                 ..
+            }) |
+            Node::Ty(&hir::Ty {
+                node: hir::TyKind::Path(ref qpath),
+                ..
             }) => {
                 let hir_id = self.tcx.hir().node_to_hir_id(id);
                 self.tables.qpath_def(qpath, hir_id)
@@ -657,25 +661,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 ..
             }) => HirDef::Local(self.tcx.hir().hir_to_node_id(canonical_id)),
 
-            Node::Ty(ty) => if let hir::Ty {
-                node: hir::TyKind::Path(ref qpath),
-                ..
-            } = *ty
-            {
-                match *qpath {
-                    hir::QPath::Resolved(_, ref path) => path.def,
-                    hir::QPath::TypeRelative(..) => {
-                        let ty = hir_ty_to_ty(self.tcx, ty);
-                        if let ty::Projection(proj) = ty.sty {
-                            return HirDef::AssociatedTy(proj.item_def_id);
-                        }
-                        HirDef::Err
-                    }
-                }
-            } else {
-                HirDef::Err
-            },
-
             _ => HirDef::Err,
         }
     }
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 235b530a7ef..59eda97a2f9 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -828,12 +828,13 @@ pub enum Variants {
         index: VariantIdx,
     },
 
-    /// Enums with more than one inhabited variant: for each case there is
-    /// a struct, and they all have space reserved for the discriminant,
-    /// which is the sole field of the enum layout.
+    /// Enum-likes with more than one inhabited variant: for each case there is
+    /// a struct, and they all have space reserved for the discriminant.
+    /// For enums this is the sole field of the layout.
     Multiple {
         discr: Scalar,
         discr_kind: DiscriminantKind,
+        discr_index: usize,
         variants: IndexVec<VariantIdx, LayoutDetails>,
     },
 }
@@ -845,8 +846,9 @@ pub enum DiscriminantKind {
 
     /// Niche (values invalid for a type) encoding the discriminant:
     /// the variant `dataful_variant` contains a niche at an arbitrary
-    /// offset (field 0 of the enum), which for a variant with discriminant
-    /// `d` is set to `(d - niche_variants.start).wrapping_add(niche_start)`.
+    /// offset (field `discr_index` of the enum), which for a variant with
+    /// discriminant `d` is set to
+    /// `(d - niche_variants.start).wrapping_add(niche_start)`.
     ///
     /// For example, `Option<(usize, &T)>`  is represented such that
     /// `None` has a null pointer for the second tuple field, and
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index efffb198572..f1812c20dcc 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -16,6 +16,7 @@
 #![feature(step_trait)]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use] extern crate log;
 
diff --git a/src/librustc_target/spec/wasm32_base.rs b/src/librustc_target/spec/wasm32_base.rs
index c7e75b4fa09..edaf902c130 100644
--- a/src/librustc_target/spec/wasm32_base.rs
+++ b/src/librustc_target/spec/wasm32_base.rs
@@ -118,6 +118,15 @@ pub fn options() -> TargetOptions {
 
         pre_link_args,
 
+        // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when
+        // PIC code is implemented this has quite a drastric effect if it stays
+        // at the default, `pic`. In an effort to keep wasm binaries as minimal
+        // as possible we're defaulting to `static` for now, but the hope is
+        // that eventually we can ship a `pic`-compatible standard library which
+        // works with `static` as well (or works with some method of generating
+        // non-relative calls and such later on).
+        relocation_model: "static".to_string(),
+
         .. Default::default()
     }
 }
diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
index 7c369daa2a8..46cf4cd8ae3 100644
--- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
@@ -21,6 +21,15 @@ pub fn target() -> Result<Target, String> {
         "-Wl,--no-undefined-version",
         "-Wl,-Bsymbolic",
         "-Wl,--export-dynamic",
+        // The following symbols are needed by libunwind, which is linked after
+        // libstd. Make sure they're included in the link.
+        "-Wl,-u,__rust_abort",
+        "-Wl,-u,__rust_c_alloc",
+        "-Wl,-u,__rust_c_dealloc",
+        "-Wl,-u,__rust_print_err",
+        "-Wl,-u,__rust_rwlock_rdlock",
+        "-Wl,-u,__rust_rwlock_unlock",
+        "-Wl,-u,__rust_rwlock_wrlock",
     ];
 
     const EXPORT_SYMBOLS: &[&str] = &[
diff --git a/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
index 0b2d7aacc4d..73151b194de 100644
--- a/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
@@ -5,7 +5,8 @@ pub fn target() -> TargetResult {
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string());
-    base.stack_probes = true;
+    // BUG: temporarily workaround #59674
+    base.stack_probes = false;
     base.has_elf_tls = false;
     // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
     // breaks code gen. See LLVM bug 36743
diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs
index d52a976981d..bc034e1fb16 100644
--- a/src/librustc_traits/lib.rs
+++ b/src/librustc_traits/lib.rs
@@ -2,6 +2,7 @@
 //! the guts are broken up into modules; see the comments in those modules.
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml
index d805833a7ef..82045dd0cdd 100644
--- a/src/librustc_tsan/Cargo.toml
+++ b/src/librustc_tsan/Cargo.toml
@@ -12,7 +12,7 @@ test = false
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cmake = "0.1.18"
+cmake = "0.1.38"
 
 [dependencies]
 alloc = { path = "../liballoc" }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index fba4414c127..0c206b27f80 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -99,11 +99,6 @@ enum GenericArgPosition {
     MethodCall,
 }
 
-/// Dummy type used for the `Self` of a `TraitRef` created for converting
-/// a trait object, and which gets removed in `ExistentialTraitRef`.
-/// This type must not appear anywhere in other converted types.
-const TRAIT_OBJECT_DUMMY_SELF: ty::TyKind<'static> = ty::Infer(ty::FreshTy(0));
-
 impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
     pub fn ast_region_to_region(&self,
         lifetime: &hir::Lifetime,
@@ -595,7 +590,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
             infer_types,
         );
 
-        let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
+        let is_object = self_ty.map_or(false, |ty| {
+            ty == self.tcx().types.trait_object_dummy_self
+        });
         let default_needs_object_self = |param: &ty::GenericParamDef| {
             if let GenericParamDefKind::Type { has_default, .. } = param.kind {
                 if is_object && has_default {
@@ -956,10 +953,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
     }
 
     /// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
-    /// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
+    /// removing the dummy `Self` type (`trait_object_dummy_self`).
     fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
                                 -> ty::ExistentialTraitRef<'tcx> {
-        if trait_ref.self_ty().sty != TRAIT_OBJECT_DUMMY_SELF {
+        if trait_ref.self_ty() != self.tcx().types.trait_object_dummy_self {
             bug!("trait_ref_to_existential called on {:?} with non-dummy Self", trait_ref);
         }
         ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
@@ -980,7 +977,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         }
 
         let mut projection_bounds = Vec::new();
-        let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
+        let dummy_self = self.tcx().types.trait_object_dummy_self;
         let (principal, potential_assoc_types) = self.instantiate_poly_trait_ref(
             &trait_bounds[0],
             dummy_self,
@@ -1030,7 +1027,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 }
                 ty::Predicate::Projection(pred) => {
                     // A `Self` within the original bound will be substituted with a
-                    // `TRAIT_OBJECT_DUMMY_SELF`, so check for that.
+                    // `trait_object_dummy_self`, so check for that.
                     let references_self =
                         pred.skip_binder().ty.walk().any(|t| t == dummy_self);
 
@@ -1130,7 +1127,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
             err.emit();
         }
 
-        // Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above.
+        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
         let existential_principal = principal.map_bound(|trait_ref| {
             self.trait_ref_to_existential(trait_ref)
         });
@@ -1365,12 +1362,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                     let msg = format!("expected type, found variant `{}`", assoc_ident);
                     tcx.sess.span_err(span, &msg);
                 } else if qself_ty.is_enum() {
-                    // Report as incorrect enum variant rather than ambiguous type.
                     let mut err = tcx.sess.struct_span_err(
-                        span,
-                        &format!("no variant `{}` on enum `{}`", &assoc_ident.as_str(), qself_ty),
+                        assoc_ident.span,
+                        &format!("no variant `{}` in enum `{}`", assoc_ident, qself_ty),
                     );
-                    // Check if it was a typo.
+
                     let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
                     if let Some(suggested_name) = find_best_match_for_name(
                         adt_def.variants.iter().map(|variant| &variant.ident.name),
@@ -1378,14 +1374,20 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                         None,
                     ) {
                         err.span_suggestion(
-                            span,
-                            "did you mean",
-                            format!("{}::{}", qself_ty, suggested_name),
+                            assoc_ident.span,
+                            "there is a variant with a similar name",
+                            suggested_name.to_string(),
                             Applicability::MaybeIncorrect,
                         );
                     } else {
-                        err.span_label(span, "unknown variant");
+                        err.span_label(span, format!("variant not found in `{}`", qself_ty));
                     }
+
+                    if let Some(sp) = tcx.hir().span_if_local(adt_def.did) {
+                        let sp = tcx.sess.source_map().def_span(sp);
+                        err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
+                    }
+
                     err.emit();
                 } else if !qself_ty.references_error() {
                     // Don't print `TyErr` to the user.
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index affd3a2d16a..032821e6d42 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -732,6 +732,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                         source: match_src,
                         prior_arms: other_arms.clone(),
                         last_ty: prior_arm_ty.unwrap(),
+                        discrim_hir_id: discrim.hir_id,
                     })
                 };
                 coercion.coerce(self, &cause, &arm.body, arm_ty);
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 40dd6217335..42156213f21 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -896,20 +896,36 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         let trait_substs = self.fresh_item_substs(trait_def_id);
         let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
 
-        for item in self.impl_or_trait_item(trait_def_id) {
-            // Check whether `trait_def_id` defines a method with suitable name:
-            if !self.has_applicable_self(&item) {
-                debug!("method has inapplicable self");
-                self.record_static_candidate(TraitSource(trait_def_id));
-                continue;
-            }
+        if self.tcx.is_trait_alias(trait_def_id) {
+            // For trait aliases, assume all super-traits are relevant.
+            let bounds = iter::once(trait_ref.to_poly_trait_ref());
+            self.elaborate_bounds(bounds, |this, new_trait_ref, item| {
+                let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
+
+                let (xform_self_ty, xform_ret_ty) =
+                    this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs);
+                this.push_candidate(Candidate {
+                    xform_self_ty, xform_ret_ty, item, import_id,
+                    kind: TraitCandidate(new_trait_ref),
+                }, true);
+            });
+        } else {
+            debug_assert!(self.tcx.is_trait(trait_def_id));
+            for item in self.impl_or_trait_item(trait_def_id) {
+                // Check whether `trait_def_id` defines a method with suitable name.
+                if !self.has_applicable_self(&item) {
+                    debug!("method has inapplicable self");
+                    self.record_static_candidate(TraitSource(trait_def_id));
+                    continue;
+                }
 
-            let (xform_self_ty, xform_ret_ty) =
-                self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs);
-            self.push_candidate(Candidate {
-                xform_self_ty, xform_ret_ty, item, import_id,
-                kind: TraitCandidate(trait_ref),
-            }, false);
+                let (xform_self_ty, xform_ret_ty) =
+                    self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs);
+                self.push_candidate(Candidate {
+                    xform_self_ty, xform_ret_ty, item, import_id,
+                    kind: TraitCandidate(trait_ref),
+                }, false);
+            }
         }
         Ok(())
     }
@@ -930,7 +946,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             .filter(|&name| set.insert(name))
             .collect();
 
-        // sort them by the name so we have a stable result
+        // Sort them by the name so we have a stable result.
         names.sort_by_cached_key(|n| n.as_str());
         names
     }
@@ -945,6 +961,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             return r;
         }
 
+        debug!("pick: actual search failed, assemble diagnotics");
+
         let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
         let private_candidate = self.private_candidate.take();
         let unsatisfied_predicates = mem::replace(&mut self.unsatisfied_predicates, vec![]);
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index fde0e47650d..31b7724d638 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -14,11 +14,11 @@ use rustc::hir::map as hir_map;
 use rustc::hir::print;
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::traits::Obligation;
-use rustc::ty::{self, Adt, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
+use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
 use rustc::ty::print::with_crate_prefix;
 use syntax_pos::{Span, FileName};
 use syntax::ast;
-use syntax::util::lev_distance::find_best_match_for_name;
+use syntax::util::lev_distance;
 
 use std::cmp::Ordering;
 
@@ -188,17 +188,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 let actual = self.resolve_type_vars_if_possible(&rcvr_ty);
                 let ty_str = self.ty_to_string(actual);
                 let is_method = mode == Mode::MethodCall;
-                let mut suggestion = None;
                 let item_kind = if is_method {
                     "method"
                 } else if actual.is_enum() {
-                    if let Adt(ref adt_def, _) = actual.sty {
-                        let names = adt_def.variants.iter().map(|s| &s.ident.name);
-                        suggestion = find_best_match_for_name(names,
-                                                              &item_name.as_str(),
-                                                              None);
-                    }
-                    "variant"
+                    "variant or associated item"
                 } else {
                     match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
                         (Some(name), false) if name.is_lowercase() => {
@@ -299,7 +292,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         return;
                     } else {
                         span = item_name.span;
-                        let mut err = struct_span_err!(
+                        struct_span_err!(
                             tcx.sess,
                             span,
                             E0599,
@@ -307,17 +300,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             item_kind,
                             item_name,
                             ty_str
-                        );
-                        if let Some(suggestion) = suggestion {
-                            // enum variant
-                            err.span_suggestion(
-                                span,
-                                "did you mean",
-                                suggestion.to_string(),
-                                Applicability::MaybeIncorrect,
-                            );
-                        }
-                        err
+                        )
                     }
                 } else {
                     tcx.sess.diagnostic().struct_dummy()
@@ -469,14 +452,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                   out_of_scope_traits);
                 }
 
+                if actual.is_enum() {
+                    let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
+                    if let Some(suggestion) = lev_distance::find_best_match_for_name(
+                        adt_def.variants.iter().map(|s| &s.ident.name),
+                        &item_name.as_str(),
+                        None,
+                    ) {
+                        err.span_suggestion(
+                            span,
+                            "there is a variant with a similar name",
+                            suggestion.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
+
                 if let Some(lev_candidate) = lev_candidate {
+                    let def = lev_candidate.def();
                     err.span_suggestion(
                         span,
-                        "did you mean",
+                        &format!(
+                            "there is {} {} with a similar name",
+                            def.article(),
+                            def.kind_name(),
+                        ),
                         lev_candidate.ident.to_string(),
                         Applicability::MaybeIncorrect,
                     );
                 }
+
                 err.emit();
             }
 
@@ -757,9 +762,13 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<DefId>
 
     impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
         fn visit_item(&mut self, i: &'v hir::Item) {
-            if let hir::ItemKind::Trait(..) = i.node {
-                let def_id = self.map.local_def_id_from_hir_id(i.hir_id);
-                self.traits.push(def_id);
+            match i.node {
+                hir::ItemKind::Trait(..) |
+                hir::ItemKind::TraitAlias(..) => {
+                    let def_id = self.map.local_def_id_from_hir_id(i.hir_id);
+                    self.traits.push(def_id);
+                }
+                _ => ()
             }
         }
 
@@ -781,7 +790,8 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<DefId>
                            external_mods: &mut FxHashSet<DefId>,
                            def: Def) {
         match def {
-            Def::Trait(def_id) => {
+            Def::Trait(def_id) |
+            Def::TraitAlias(def_id) => {
                 traits.push(def_id);
             }
             Def::Mod(def_id) => {
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index d6932094ddd..d2fe099e433 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -3,7 +3,7 @@
 use super::{FnCtxt, Needs};
 use super::method::MethodCallee;
 use rustc::ty::{self, Ty, TypeFoldable};
-use rustc::ty::TyKind::{Ref, Adt, Str, Uint, Never, Tuple, Char, Array};
+use rustc::ty::TyKind::{Ref, Adt, FnDef, Str, Uint, Never, Tuple, Char, Array};
 use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::infer::type_variable::TypeVariableOrigin;
 use errors::{self,Applicability};
@@ -333,8 +333,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 lhs_ty);
 
                             if !lhs_expr.span.eq(&rhs_expr.span) {
-                                err.span_label(lhs_expr.span, lhs_ty.to_string());
-                                err.span_label(rhs_expr.span, rhs_ty.to_string());
+                                self.add_type_neq_err_label(
+                                    &mut err,
+                                    lhs_expr.span,
+                                    lhs_ty,
+                                    rhs_ty,
+                                    op,
+                                    is_assign
+                                );
+                                self.add_type_neq_err_label(
+                                    &mut err,
+                                    rhs_expr.span,
+                                    rhs_ty,
+                                    lhs_ty,
+                                    op,
+                                    is_assign
+                                );
                             }
 
                             let mut suggested_deref = false;
@@ -415,6 +429,62 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         (lhs_ty, rhs_ty, return_ty)
     }
 
+    fn add_type_neq_err_label(
+        &self,
+        err: &mut errors::DiagnosticBuilder<'_>,
+        span: Span,
+        ty: Ty<'tcx>,
+        other_ty: Ty<'tcx>,
+        op: hir::BinOp,
+        is_assign: IsAssign,
+    ) {
+        err.span_label(span, ty.to_string());
+        if let FnDef(def_id, _) = ty.sty {
+            let source_map = self.tcx.sess.source_map();
+            let hir_id = &self.tcx.hir().as_local_hir_id(def_id).unwrap();
+            let fn_sig = {
+                match self.tcx.typeck_tables_of(def_id).liberated_fn_sigs().get(*hir_id) {
+                    Some(f) => f.clone(),
+                    None => {
+                        bug!("No fn-sig entry for def_id={:?}", def_id);
+                    }
+                }
+            };
+
+            let other_ty = if let FnDef(def_id, _) = other_ty.sty {
+                let hir_id = &self.tcx.hir().as_local_hir_id(def_id).unwrap();
+                match self.tcx.typeck_tables_of(def_id).liberated_fn_sigs().get(*hir_id) {
+                    Some(f) => f.clone().output(),
+                    None => {
+                        bug!("No fn-sig entry for def_id={:?}", def_id);
+                    }
+                }
+            } else {
+                other_ty
+            };
+
+            if self.lookup_op_method(fn_sig.output(),
+                                    &[other_ty],
+                                    Op::Binary(op, is_assign))
+                    .is_ok() {
+                let (variable_snippet, applicability) = if fn_sig.inputs().len() > 0 {
+                    (format!("{}( /* arguments */ )", source_map.span_to_snippet(span).unwrap()),
+                    Applicability::HasPlaceholders)
+                } else {
+                    (format!("{}()", source_map.span_to_snippet(span).unwrap()),
+                    Applicability::MaybeIncorrect)
+                };
+
+                err.span_suggestion(
+                    span,
+                    "you might have forgotten to call this function",
+                    variable_snippet,
+                    applicability,
+                );
+            }
+        }
+    }
+
     fn check_str_addition(
         &self,
         expr: &'gcx hir::Expr,
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 3579810b8d7..d108e7c3107 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -3,7 +3,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
 
 use crate::hir::def_id::DefId;
 use rustc::traits::{self, ObligationCauseCode};
-use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable, ToPredicate};
+use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
 use rustc::ty::subst::{Subst, InternalSubsts};
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::mir::interpret::ConstValue;
@@ -354,7 +354,7 @@ fn check_item_type<'a, 'tcx>(
 
         let mut forbid_unsized = true;
         if allow_foreign_ty {
-            if let TyKind::Foreign(_) = fcx.tcx.struct_tail(item_ty).sty {
+            if let ty::Foreign(_) = fcx.tcx.struct_tail(item_ty).sty {
                 forbid_unsized = false;
             }
         }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 5edb8c92a3b..0cd7fe91594 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1918,7 +1918,10 @@ fn explicit_predicates_of<'a, 'tcx>(
         }
     }
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
+    let hir_id = match tcx.hir().as_local_hir_id(def_id) {
+        Some(hir_id) => hir_id,
+        None => return tcx.predicates_of(def_id),
+    };
     let node = tcx.hir().get_by_hir_id(hir_id);
 
     let mut is_trait = None;
@@ -1979,6 +1982,7 @@ fn explicit_predicates_of<'a, 'tcx>(
                     ref bounds,
                     impl_trait_fn,
                     ref generics,
+                    origin: _,
                 }) => {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     let opaque_ty = tcx.mk_opaque(def_id, substs);
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 1fa16352b86..21d1af229dd 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -71,6 +71,7 @@ This API is completely unstable and subject to change.
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(explicit_outlives_requirements)]
 
 #[macro_use] extern crate log;
@@ -108,7 +109,6 @@ use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::query::Providers;
 use rustc::util;
-use rustc::util::profiling::ProfileCategory;
 use syntax_pos::Span;
 use util::common::time;
 
@@ -318,7 +318,7 @@ pub fn provide(providers: &mut Providers<'_>) {
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
                              -> Result<(), ErrorReported>
 {
-    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::TypeChecking, "type-check crate"));
+    tcx.sess.profiler(|p| p.start_activity("type-check crate"));
 
     // this ensures that later parts of type checking can assume that items
     // have valid types and not error
@@ -369,7 +369,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
 
-    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::TypeChecking, "type-check crate"));
+    tcx.sess.profiler(|p| p.end_activity("type-check crate"));
 
     if tcx.sess.err_count() == 0 {
         Ok(())
@@ -378,7 +378,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
     }
 }
 
-/// A quasi-deprecated helper used in rustdoc and save-analysis to get
+/// A quasi-deprecated helper used in rustdoc and clippy to get
 /// the type from a HIR node.
 pub fn hir_ty_to_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> {
     // In case there are any projections etc, find the "environment"
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index a8c9166591d..4d2c03a4f2f 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -10,6 +10,6 @@ path = "lib.rs"
 
 [dependencies]
 pulldown-cmark = { version = "0.1.2", default-features = false }
-minifier = "0.0.28"
+minifier = "0.0.29"
 tempfile = "3"
 parking_lot = "0.7"
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index adbe73b165e..555cb1bd64f 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -568,7 +568,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                 (replaced.clone(), replaced.clean(self.cx))
             });
 
-        let full_generics = (&type_generics, &tcx.predicates_of(did));
+        let full_generics = (&type_generics, &tcx.explicit_predicates_of(did));
         let Generics {
             params: mut generic_params,
             ..
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index aaae0bafd9e..570c61f1ffc 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -132,7 +132,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                                      .collect();
 
                         let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics);
-                        let predicates = infcx.tcx.predicates_of(impl_def_id);
+                        let predicates = infcx.tcx.explicit_predicates_of(impl_def_id);
 
                         impls.push(Item {
                             source: infcx.tcx.def_span(impl_def_id).clean(self.cx),
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index d9a63969fec..8da71cf708a 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -228,7 +228,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function {
 }
 
 fn build_enum(cx: &DocContext<'_>, did: DefId) -> clean::Enum {
-    let predicates = cx.tcx.predicates_of(did);
+    let predicates = cx.tcx.explicit_predicates_of(did);
 
     clean::Enum {
         generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
@@ -238,7 +238,7 @@ fn build_enum(cx: &DocContext<'_>, did: DefId) -> clean::Enum {
 }
 
 fn build_struct(cx: &DocContext<'_>, did: DefId) -> clean::Struct {
-    let predicates = cx.tcx.predicates_of(did);
+    let predicates = cx.tcx.explicit_predicates_of(did);
     let variant = cx.tcx.adt_def(did).non_enum_variant();
 
     clean::Struct {
@@ -254,7 +254,7 @@ fn build_struct(cx: &DocContext<'_>, did: DefId) -> clean::Struct {
 }
 
 fn build_union(cx: &DocContext<'_>, did: DefId) -> clean::Union {
-    let predicates = cx.tcx.predicates_of(did);
+    let predicates = cx.tcx.explicit_predicates_of(did);
     let variant = cx.tcx.adt_def(did).non_enum_variant();
 
     clean::Union {
@@ -266,7 +266,7 @@ fn build_union(cx: &DocContext<'_>, did: DefId) -> clean::Union {
 }
 
 fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
-    let predicates = cx.tcx.predicates_of(did);
+    let predicates = cx.tcx.explicit_predicates_of(did);
 
     clean::Typedef {
         type_: cx.tcx.type_of(did).clean(cx),
@@ -325,7 +325,7 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, ret: &mut Vec<clean::Item>) {
         }
     }
 
-    let predicates = tcx.predicates_of(did);
+    let predicates = tcx.explicit_predicates_of(did);
     let (trait_items, generics) = if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
         match tcx.hir().expect_item_by_hir_id(hir_id).node {
             hir::ItemKind::Impl(.., ref gen, _, _, ref item_ids) => {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 27ffe4583df..e994c661fdc 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2288,7 +2288,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
             }
             ty::AssociatedKind::Method => {
                 let generics = (cx.tcx.generics_of(self.def_id),
-                                &cx.tcx.predicates_of(self.def_id)).clean(cx);
+                                &cx.tcx.explicit_predicates_of(self.def_id)).clean(cx);
                 let sig = cx.tcx.fn_sig(self.def_id);
                 let mut decl = (self.def_id, sig).clean(cx);
 
@@ -2361,7 +2361,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
                     // are actually located on the trait/impl itself, so we need to load
                     // all of the generics from there and then look for bounds that are
                     // applied to this associated type in question.
-                    let predicates = cx.tcx.predicates_of(did);
+                    let predicates = cx.tcx.explicit_predicates_of(did);
                     let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
                     let mut bounds = generics.where_predicates.iter().filter_map(|pred| {
                         let (name, self_type, trait_, bounds) = match *pred {
@@ -3069,7 +3069,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
             ty::Opaque(def_id, substs) => {
                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                 // by looking up the projections associated with the def_id.
-                let predicates_of = cx.tcx.predicates_of(def_id);
+                let predicates_of = cx.tcx.explicit_predicates_of(def_id);
                 let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
                 let bounds = predicates_of.instantiate(cx.tcx, substs);
                 let mut regions = vec![];
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 6ff3917a265..acf019fd225 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -157,11 +157,11 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
         window.rootPath = \"{root_path}\";\
         window.currentCrate = \"{krate}\";\
     </script>\
-    <script src=\"{root_path}aliases.js\"></script>\
+    <script src=\"{root_path}aliases{suffix}.js\"></script>\
     <script src=\"{static_root_path}main{suffix}.js\"></script>\
     {static_extra_scripts}\
     {extra_scripts}\
-    <script defer src=\"{root_path}search-index.js\"></script>\
+    <script defer src=\"{root_path}search-index{suffix}.js\"></script>\
 </body>\
 </html>",
     css_extension = if css_file_extension {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index f7e8cdeaeca..3ee131d8f5c 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -965,7 +965,11 @@ themePicker.onblur = handleThemeButtonsBlur;
                 if for_search_index && line.starts_with("var R") {
                     variables.push(line.clone());
                     // We need to check if the crate name has been put into a variable as well.
-                    let tokens = js::simple_minify(&line).apply(js::clean_tokens);
+                    let tokens: js::Tokens<'_> = js::simple_minify(&line)
+                                                    .into_iter()
+                                                    .filter(js::clean_token)
+                                                    .collect::<Vec<_>>()
+                                                    .into();
                     let mut pos = 0;
                     while pos < tokens.len() {
                         if let Some((var_pos, Some(value_pos))) =
@@ -1009,7 +1013,7 @@ themePicker.onblur = handleThemeButtonsBlur;
                 })
     }
 
-    let dst = cx.dst.join("aliases.js");
+    let dst = cx.dst.join(&format!("aliases{}.js", cx.shared.resource_suffix));
     {
         let (mut all_aliases, _, _) = try_err!(collect(&dst, &krate.name, "ALIASES", false), &dst);
         let mut w = try_err!(File::create(&dst), &dst);
@@ -1060,11 +1064,22 @@ themePicker.onblur = handleThemeButtonsBlur;
                                                         .expect("invalid osstring conversion")))
                                       .collect::<Vec<_>>();
             files.sort_unstable_by(|a, b| a.cmp(b));
-            // FIXME(imperio): we could avoid to generate "dirs" and "files" if they're empty.
-            format!("{{\"name\":\"{name}\",\"dirs\":[{subs}],\"files\":[{files}]}}",
+            let subs = subs.iter().map(|s| s.to_json_string()).collect::<Vec<_>>().join(",");
+            let dirs = if subs.is_empty() {
+                String::new()
+            } else {
+                format!(",\"dirs\":[{}]", subs)
+            };
+            let files = files.join(",");
+            let files = if files.is_empty() {
+                String::new()
+            } else {
+                format!(",\"files\":[{}]", files)
+            };
+            format!("{{\"name\":\"{name}\"{dirs}{files}}}",
                     name=self.elem.to_str().expect("invalid osstring conversion"),
-                    subs=subs.iter().map(|s| s.to_json_string()).collect::<Vec<_>>().join(","),
-                    files=files.join(","))
+                    dirs=dirs,
+                    files=files)
         }
     }
 
@@ -1095,7 +1110,7 @@ themePicker.onblur = handleThemeButtonsBlur;
             }
         }
 
-        let dst = cx.dst.join("source-files.js");
+        let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix));
         let (mut all_sources, _krates, _) = try_err!(collect(&dst, &krate.name, "sourcesIndex",
                                                              false),
                                                      &dst);
@@ -1111,7 +1126,7 @@ themePicker.onblur = handleThemeButtonsBlur;
     }
 
     // Update the search index
-    let dst = cx.dst.join("search-index.js");
+    let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix));
     let (mut all_indexes, mut krates, variables) = try_err!(collect(&dst,
                                                                     &krate.name,
                                                                     "searchIndex",
@@ -1288,46 +1303,51 @@ fn write_minify_replacer<W: Write>(
     contents: &str,
     enable_minification: bool,
 ) -> io::Result<()> {
-    use minifier::js::{Keyword, ReservedChar, Token};
+    use minifier::js::{simple_minify, Keyword, ReservedChar, Token, Tokens};
 
     if enable_minification {
         writeln!(dst, "{}",
-                 minifier::js::simple_minify(contents)
-                              .apply(|f| {
-                                  // We keep backlines.
-                                  minifier::js::clean_tokens_except(f, |c| {
-                                      c.get_char() != Some(ReservedChar::Backline)
-                                  })
-                              })
-                              .apply(|f| {
-                                  minifier::js::replace_token_with(f, |t| {
-                                      match *t {
-                                          Token::Keyword(Keyword::Null) => Some(Token::Other("N")),
-                                          Token::String(s) => {
-                                              let s = &s[1..s.len() -1]; // The quotes are included
-                                              if s.is_empty() {
-                                                  Some(Token::Other("E"))
-                                              } else if s == "t" {
-                                                  Some(Token::Other("T"))
-                                              } else if s == "u" {
-                                                  Some(Token::Other("U"))
-                                              } else {
-                                                  None
-                                              }
-                                          }
-                                          _ => None,
-                                      }
-                                  })
-                              })
-                              .apply(|f| {
-                                  // We add a backline after the newly created variables.
-                                  minifier::js::aggregate_strings_into_array_with_separation(
-                                      f,
-                                      "R",
-                                      Token::Char(ReservedChar::Backline),
-                                  )
-                              })
-                              .to_string())
+                 {
+                    let tokens: Tokens<'_> = simple_minify(contents)
+                        .into_iter()
+                        .filter(|f| {
+                            // We keep backlines.
+                            minifier::js::clean_token_except(f, &|c: &Token<'_>| {
+                                c.get_char() != Some(ReservedChar::Backline)
+                            })
+                        })
+                        .map(|f| {
+                            minifier::js::replace_token_with(f, &|t: &Token<'_>| {
+                                match *t {
+                                    Token::Keyword(Keyword::Null) => Some(Token::Other("N")),
+                                    Token::String(s) => {
+                                        let s = &s[1..s.len() -1]; // The quotes are included
+                                        if s.is_empty() {
+                                            Some(Token::Other("E"))
+                                        } else if s == "t" {
+                                            Some(Token::Other("T"))
+                                        } else if s == "u" {
+                                            Some(Token::Other("U"))
+                                        } else {
+                                            None
+                                        }
+                                    }
+                                    _ => None,
+                                }
+                            })
+                        })
+                        .collect::<Vec<_>>()
+                        .into();
+                    tokens.apply(|f| {
+                        // We add a backline after the newly created variables.
+                        minifier::js::aggregate_strings_into_array_with_separation(
+                            f,
+                            "R",
+                            Token::Char(ReservedChar::Backline),
+                        )
+                    })
+                    .to_string()
+                })
     } else {
         writeln!(dst, "{}", contents)
     }
@@ -1474,7 +1494,7 @@ impl<'a> SourceCollector<'a> {
             description: &desc,
             keywords: BASIC_KEYWORDS,
             resource_suffix: &self.scx.resource_suffix,
-            extra_scripts: &["source-files"],
+            extra_scripts: &[&format!("source-files{}", self.scx.resource_suffix)],
             static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)],
         };
         layout::render(&mut w, &self.scx.layout,
@@ -3127,7 +3147,6 @@ fn item_trait(
             // FIXME: we should be using a derived_id for the Anchors here
             write!(w, "{{\n")?;
             for t in &types {
-                write!(w, "    ")?;
                 render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
                 write!(w, ";\n")?;
             }
@@ -3135,7 +3154,6 @@ fn item_trait(
                 w.write_str("\n")?;
             }
             for t in &consts {
-                write!(w, "    ")?;
                 render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
                 write!(w, ";\n")?;
             }
@@ -3143,7 +3161,6 @@ fn item_trait(
                 w.write_str("\n")?;
             }
             for (pos, m) in required.iter().enumerate() {
-                write!(w, "    ")?;
                 render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
                 write!(w, ";\n")?;
 
@@ -3155,7 +3172,6 @@ fn item_trait(
                 w.write_str("\n")?;
             }
             for (pos, m) in provided.iter().enumerate() {
-                write!(w, "    ")?;
                 render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
                 match m.inner {
                     clean::MethodItem(ref inner) if !inner.generics.where_predicates.is_empty() => {
@@ -3464,8 +3480,9 @@ fn render_assoc_item(w: &mut fmt::Formatter<'_>,
             (0, true)
         };
         render_attributes(w, meth)?;
-        write!(w, "{}{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
+        write!(w, "{}{}{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
+               if parent == ItemType::Trait { "    " } else { "" },
                VisSpace(&meth.visibility),
                ConstnessSpace(header.constness),
                UnsafetySpace(header.unsafety),
@@ -3766,7 +3783,7 @@ const ATTRIBUTE_WHITELIST: &'static [&'static str] = &[
     "non_exhaustive"
 ];
 
-fn render_attributes(w: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Result {
+fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item) -> fmt::Result {
     let mut attrs = String::new();
 
     for attr in &it.attrs.other_attrs {
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 412029cf376..00ca78b749e 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -930,10 +930,10 @@ if (!DOMTokenList.prototype.remove) {
                     returned = checkReturned(ty, output, true);
                     if (output.name === "*" || returned === true) {
                         in_args = false;
-                        var module = false;
+                        var is_module = false;
 
                         if (input === "*") {
-                            module = true;
+                            is_module = true;
                         } else {
                             var allFound = true;
                             for (var it = 0; allFound === true && it < inputs.length; it++) {
@@ -955,7 +955,7 @@ if (!DOMTokenList.prototype.remove) {
                                 dontValidate: true,
                             };
                         }
-                        if (module === true) {
+                        if (is_module === true) {
                             results[fullId] = {
                                 id: i,
                                 index: -1,
@@ -1073,6 +1073,10 @@ if (!DOMTokenList.prototype.remove) {
                     if (index !== -1 || lev <= MAX_LEV_DISTANCE) {
                         if (index !== -1 && paths.length < 2) {
                             lev = 0;
+                        } else if (searchWords[j] === val) {
+                            // Small trick to fix when you're looking for a one letter type
+                            // and there are other short named types.
+                            lev = -1;
                         }
                         if (results[fullId] === undefined) {
                             results[fullId] = {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 5314255ac32..2228e58b0d2 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -1577,3 +1577,17 @@ div.name.expand::before {
 	left: -15px;
 	top: 2px;
 }
+
+/* This part is to fix the "Expand attributes" part in the type declaration. */
+.type-decl > pre > :first-child {
+	margin-left: 0 !important;
+}
+.type-decl > pre > :nth-child(2) {
+	margin-left: 1.8em !important;
+}
+.type-decl > pre > .toggle-attributes {
+	margin-left: 2.2em;
+}
+.type-decl > pre > .docblock.attributes {
+	margin-left: 4em;
+}
diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js
index 509c628ce5a..567022b4139 100644
--- a/src/librustdoc/html/static/source-script.js
+++ b/src/librustdoc/html/static/source-script.js
@@ -39,28 +39,32 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
     children.className = "children";
     var folders = document.createElement("div");
     folders.className = "folders";
-    for (var i = 0; i < elem.dirs.length; ++i) {
-        if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
-                           hasFoundFile) === true) {
-            addClass(name, "expand");
-            hasFoundFile = true;
+    if (elem.dirs) {
+        for (var i = 0; i < elem.dirs.length; ++i) {
+            if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
+                               hasFoundFile) === true) {
+                addClass(name, "expand");
+                hasFoundFile = true;
+            }
         }
     }
     children.appendChild(folders);
 
     var files = document.createElement("div");
     files.className = "files";
-    for (i = 0; i < elem.files.length; ++i) {
-        var file = document.createElement("a");
-        file.innerText = elem.files[i];
-        file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
-        if (hasFoundFile === false &&
-                currentFile === fullPath + elem.files[i]) {
-            file.className = "selected";
-            addClass(name, "expand");
-            hasFoundFile = true;
+    if (elem.files) {
+        for (i = 0; i < elem.files.length; ++i) {
+            var file = document.createElement("a");
+            file.innerText = elem.files[i];
+            file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
+            if (hasFoundFile === false &&
+                    currentFile === fullPath + elem.files[i]) {
+                file.className = "selected";
+                addClass(name, "expand");
+                hasFoundFile = true;
+            }
+            files.appendChild(file);
         }
-        files.appendChild(file);
     }
     search.fullPath = fullPath;
     children.appendChild(files);
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 2ebb465d53d..6cb937d9216 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -1,4 +1,5 @@
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index ee182237b49..dbc55b62ef8 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -196,6 +196,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 _ => Err(())
             }
         } else {
+            debug!("attempting to resolve item without parent module: {}", path_str);
             Err(())
         }
     }
@@ -404,6 +405,15 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
             self.fold_item_recur(item)
         }
     }
+
+    // FIXME: if we can resolve intra-doc links from other crates, we can use the stock
+    // `fold_crate`, but until then we should avoid scanning `krate.external_traits` since those
+    // will never resolve properly
+    fn fold_crate(&mut self, mut c: Crate) -> Crate {
+        c.module = c.module.take().and_then(|module| self.fold_item(module));
+
+        c
+    }
 }
 
 /// Resolves a string as a macro.
diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs
index cf948078b08..8ef8c2b4c0a 100644
--- a/src/libserialize/serialize.rs
+++ b/src/libserialize/serialize.rs
@@ -911,4 +911,5 @@ impl<T: UseSpecializedDecodable> Decodable for T {
 impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {}
 impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {}
 impl<T: Decodable> UseSpecializedDecodable for Box<T> {}
-
+impl<'a, T: Decodable> UseSpecializedDecodable for &'a T {}
+impl<'a, T: Decodable> UseSpecializedDecodable for &'a [T] {}
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 9ac03adfc27..86ad334d886 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -19,7 +19,7 @@ panic_unwind = { path = "../libpanic_unwind", optional = true }
 panic_abort = { path = "../libpanic_abort" }
 core = { path = "../libcore" }
 libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.8" }
+compiler_builtins = { version = "0.1.9" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
 rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] }
@@ -54,6 +54,7 @@ backtrace = ["backtrace-sys"]
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
 compiler_builtins_c = ["compiler_builtins/c"]
+llvm-libunwind = ["unwind/llvm-libunwind"]
 
 # Make panics and failed asserts immediately abort without formatting any message
 panic_immediate_abort = ["core/panic_immediate_abort"]
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 89d5b2ff30f..b9fcc2365fa 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -627,7 +627,11 @@ impl<T, S> HashSet<T, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_subset(&self, other: &HashSet<T, S>) -> bool {
-        self.iter().all(|v| other.contains(v))
+        if self.len() <= other.len() {
+            self.iter().all(|v| other.contains(v))
+        } else {
+            false
+        }
     }
 
     /// Returns `true` if the set is a superset of another,
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 2952c6aea00..133540ed6b9 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -193,11 +193,11 @@ impl f32 {
     }
 
     /// Returns a number composed of the magnitude of `self` and the sign of
-    /// `y`.
+    /// `sign`.
     ///
-    /// Equal to `self` if the sign of `self` and `y` are the same, otherwise
+    /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
     /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
-    /// `y` is returned.
+    /// `sign` is returned.
     ///
     /// # Examples
     ///
@@ -216,8 +216,8 @@ impl f32 {
     #[inline]
     #[must_use]
     #[stable(feature = "copysign", since = "1.35.0")]
-    pub fn copysign(self, y: f32) -> f32 {
-        unsafe { intrinsics::copysignf32(self, y) }
+    pub fn copysign(self, sign: f32) -> f32 {
+        unsafe { intrinsics::copysignf32(self, sign) }
     }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index 3c3a35573ad..87467aeed8b 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -171,11 +171,11 @@ impl f64 {
     }
 
     /// Returns a number composed of the magnitude of `self` and the sign of
-    /// `y`.
+    /// `sign`.
     ///
-    /// Equal to `self` if the sign of `self` and `y` are the same, otherwise
+    /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
     /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
-    /// `y` is returned.
+    /// `sign` is returned.
     ///
     /// # Examples
     ///
@@ -194,8 +194,8 @@ impl f64 {
     #[inline]
     #[must_use]
     #[stable(feature = "copysign", since = "1.35.0")]
-    pub fn copysign(self, y: f64) -> f64 {
-        unsafe { intrinsics::copysignf64(self, y) }
+    pub fn copysign(self, sign: f64) -> f64 {
+        unsafe { intrinsics::copysignf64(self, sign) }
     }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 01e7a57cd00..13aee783750 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -960,6 +960,7 @@ impl IntoInner<Buf> for OsString {
 }
 
 impl AsInner<Slice> for OsStr {
+    #[inline]
     fn as_inner(&self) -> &Slice {
         &self.inner
     }
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 705dc8f40b5..dea198d8c91 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -9,7 +9,7 @@
 
 use crate::fmt;
 use crate::ffi::OsString;
-use crate::io::{self, SeekFrom, Seek, Read, Initializer, Write};
+use crate::io::{self, SeekFrom, Seek, Read, Initializer, Write, IoVec, IoVecMut};
 use crate::path::{Path, PathBuf};
 use crate::sys::fs as fs_imp;
 use crate::sys_common::{AsInnerMut, FromInner, AsInner, IntoInner};
@@ -21,7 +21,9 @@ use crate::time::SystemTime;
 /// it was opened with. Files also implement [`Seek`] to alter the logical cursor
 /// that the file contains internally.
 ///
-/// Files are automatically closed when they go out of scope.
+/// Files are automatically closed when they go out of scope.  Errors detected
+/// on closing are ignored by the implementation of `Drop`.  Use the method
+/// [`sync_all`] if these errors must be manually handled.
 ///
 /// # Examples
 ///
@@ -84,6 +86,7 @@ use crate::time::SystemTime;
 /// [`Read`]: ../io/trait.Read.html
 /// [`Write`]: ../io/trait.Write.html
 /// [`BufReader<R>`]: ../io/struct.BufReader.html
+/// [`sync_all`]: struct.File.html#method.sync_all
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct File {
     inner: fs_imp::File,
@@ -391,9 +394,13 @@ impl File {
 
     /// Attempts to sync all OS-internal metadata to disk.
     ///
-    /// This function will attempt to ensure that all in-core data reaches the
+    /// This function will attempt to ensure that all in-memory data reaches the
     /// filesystem before returning.
     ///
+    /// This can be used to handle errors that would otherwise only be caught
+    /// when the `File` is closed.  Dropping a file will ignore errors in
+    /// synchronizing this in-memory data.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -608,6 +615,10 @@ impl Read for File {
         self.inner.read(buf)
     }
 
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -618,6 +629,11 @@ impl Write for File {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(buf)
     }
+
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.inner.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -632,6 +648,10 @@ impl Read for &File {
         self.inner.read(buf)
     }
 
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -642,6 +662,11 @@ impl Write for &File {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(buf)
     }
+
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.inner.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -881,6 +906,10 @@ impl OpenOptions {
     }
 }
 
+impl AsInner<fs_imp::OpenOptions> for OpenOptions {
+    fn as_inner(&self) -> &fs_imp::OpenOptions { &self.0 }
+}
+
 impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
     fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 }
 }
@@ -1104,6 +1133,10 @@ impl AsInner<fs_imp::FileAttr> for Metadata {
     fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 }
 }
 
+impl FromInner<fs_imp::FileAttr> for Metadata {
+    fn from_inner(attr: fs_imp::FileAttr) -> Metadata { Metadata(attr) }
+}
+
 impl Permissions {
     /// Returns `true` if these permissions describe a readonly (unwritable) file.
     ///
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index aa784746122..898387cb9f5 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -5,7 +5,7 @@ use core::marker::Unpin;
 use core::pin::Pin;
 use core::option::Option;
 use core::ptr::NonNull;
-use core::task::{Waker, Poll};
+use core::task::{Context, Poll};
 use core::ops::{Drop, Generator, GeneratorState};
 
 #[doc(inline)]
@@ -32,10 +32,10 @@ impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
 #[unstable(feature = "gen_future", issue = "50547")]
 impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
     type Output = T::Return;
-    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
         // Safe because we're !Unpin + !Drop mapping to a ?Unpin value
         let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
-        set_task_waker(waker, || match gen.resume() {
+        set_task_context(cx, || match gen.resume() {
             GeneratorState::Yielded(()) => Poll::Pending,
             GeneratorState::Complete(x) => Poll::Ready(x),
         })
@@ -43,61 +43,72 @@ impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
 }
 
 thread_local! {
-    static TLS_WAKER: Cell<Option<NonNull<Waker>>> = Cell::new(None);
+    static TLS_CX: Cell<Option<NonNull<Context<'static>>>> = Cell::new(None);
 }
 
-struct SetOnDrop(Option<NonNull<Waker>>);
+struct SetOnDrop(Option<NonNull<Context<'static>>>);
 
 impl Drop for SetOnDrop {
     fn drop(&mut self) {
-        TLS_WAKER.with(|tls_waker| {
-            tls_waker.set(self.0.take());
+        TLS_CX.with(|tls_cx| {
+            tls_cx.set(self.0.take());
         });
     }
 }
 
 #[unstable(feature = "gen_future", issue = "50547")]
 /// Sets the thread-local task context used by async/await futures.
-pub fn set_task_waker<F, R>(waker: &Waker, f: F) -> R
+pub fn set_task_context<F, R>(cx: &mut Context<'_>, f: F) -> R
 where
     F: FnOnce() -> R
 {
-    let old_waker = TLS_WAKER.with(|tls_waker| {
-        tls_waker.replace(Some(NonNull::from(waker)))
+    // transmute the context's lifetime to 'static so we can store it.
+    let cx = unsafe {
+        core::mem::transmute::<&mut Context<'_>, &mut Context<'static>>(cx)
+    };
+    let old_cx = TLS_CX.with(|tls_cx| {
+        tls_cx.replace(Some(NonNull::from(cx)))
     });
-    let _reset_waker = SetOnDrop(old_waker);
+    let _reset = SetOnDrop(old_cx);
     f()
 }
 
 #[unstable(feature = "gen_future", issue = "50547")]
-/// Retrieves the thread-local task waker used by async/await futures.
+/// Retrieves the thread-local task context used by async/await futures.
 ///
-/// This function acquires exclusive access to the task waker.
+/// This function acquires exclusive access to the task context.
 ///
-/// Panics if no waker has been set or if the waker has already been
-/// retrieved by a surrounding call to get_task_waker.
-pub fn get_task_waker<F, R>(f: F) -> R
+/// Panics if no context has been set or if the context has already been
+/// retrieved by a surrounding call to get_task_context.
+pub fn get_task_context<F, R>(f: F) -> R
 where
-    F: FnOnce(&Waker) -> R
+    F: FnOnce(&mut Context<'_>) -> R
 {
-    let waker_ptr = TLS_WAKER.with(|tls_waker| {
+    let cx_ptr = TLS_CX.with(|tls_cx| {
         // Clear the entry so that nested `get_task_waker` calls
         // will fail or set their own value.
-        tls_waker.replace(None)
+        tls_cx.replace(None)
     });
-    let _reset_waker = SetOnDrop(waker_ptr);
+    let _reset = SetOnDrop(cx_ptr);
 
-    let waker_ptr = waker_ptr.expect(
-        "TLS Waker not set. This is a rustc bug. \
+    let mut cx_ptr = cx_ptr.expect(
+        "TLS Context not set. This is a rustc bug. \
         Please file an issue on https://github.com/rust-lang/rust.");
-    unsafe { f(waker_ptr.as_ref()) }
+
+    // Safety: we've ensured exclusive access to the context by
+    // removing the pointer from TLS, only to be replaced once
+    // we're done with it.
+    //
+    // The pointer that was inserted came from an `&mut Context<'_>`,
+    // so it is safe to treat as mutable.
+    unsafe { f(cx_ptr.as_mut()) }
 }
 
 #[unstable(feature = "gen_future", issue = "50547")]
 /// Polls a future in the current thread-local task waker.
-pub fn poll_with_tls_waker<F>(f: Pin<&mut F>) -> Poll<F::Output>
+pub fn poll_with_tls_context<F>(f: Pin<&mut F>) -> Poll<F::Output>
 where
     F: Future
 {
-    get_task_waker(|waker| F::poll(f, waker))
+    get_task_context(|cx| F::poll(f, cx))
 }
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 0bbff5769ab..1848ddeab65 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -5,7 +5,7 @@ use crate::io::prelude::*;
 use crate::cell::RefCell;
 use crate::fmt;
 use crate::io::lazy::Lazy;
-use crate::io::{self, Initializer, BufReader, LineWriter};
+use crate::io::{self, Initializer, BufReader, LineWriter, IoVec, IoVecMut};
 use crate::sync::{Arc, Mutex, MutexGuard};
 use crate::sys::stdio;
 use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
@@ -75,6 +75,10 @@ fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) }
 impl Read for StdinRaw {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
 
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -82,10 +86,20 @@ impl Read for StdinRaw {
 }
 impl Write for StdoutRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
+
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> { self.0.flush() }
 }
 impl Write for StderrRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
+
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> { self.0.flush() }
 }
 
@@ -102,6 +116,14 @@ impl<W: io::Write> io::Write for Maybe<W> {
         }
     }
 
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        let total = bufs.iter().map(|b| b.len()).sum();
+        match self {
+            Maybe::Real(w) => handle_ebadf(w.write_vectored(bufs), total),
+            Maybe::Fake => Ok(total),
+        }
+    }
+
     fn flush(&mut self) -> io::Result<()> {
         match *self {
             Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
@@ -117,6 +139,13 @@ impl<R: io::Read> io::Read for Maybe<R> {
             Maybe::Fake => Ok(0)
         }
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        match self {
+            Maybe::Real(r) => handle_ebadf(r.read_vectored(bufs), 0),
+            Maybe::Fake => Ok(0)
+        }
+    }
 }
 
 fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
@@ -305,6 +334,9 @@ impl Read for Stdin {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.lock().read(buf)
     }
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.lock().read_vectored(bufs)
+    }
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -325,6 +357,11 @@ impl Read for StdinLock<'_> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -483,6 +520,9 @@ impl Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.lock().write(buf)
     }
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.lock().write_vectored(bufs)
+    }
     fn flush(&mut self) -> io::Result<()> {
         self.lock().flush()
     }
@@ -498,6 +538,9 @@ impl Write for StdoutLock<'_> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.borrow_mut().write(buf)
     }
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.inner.borrow_mut().write_vectored(bufs)
+    }
     fn flush(&mut self) -> io::Result<()> {
         self.inner.borrow_mut().flush()
     }
@@ -636,6 +679,9 @@ impl Write for Stderr {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.lock().write(buf)
     }
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.lock().write_vectored(bufs)
+    }
     fn flush(&mut self) -> io::Result<()> {
         self.lock().flush()
     }
@@ -651,6 +697,9 @@ impl Write for StderrLock<'_> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.borrow_mut().write(buf)
     }
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.inner.borrow_mut().write_vectored(bufs)
+    }
     fn flush(&mut self) -> io::Result<()> {
         self.inner.borrow_mut().flush()
     }
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index 7b0d1549e06..ffe50f11e8a 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -25,8 +25,7 @@
 ///
 /// For more information on what `as` is capable of, see the [Reference]
 ///
-/// [Reference]:
-/// https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
+/// [Reference]: ../reference/expressions/operator-expr.html#type-cast-expressions
 /// [`crate`]: keyword.crate.html
 mod as_keyword { }
 
@@ -80,8 +79,8 @@ mod as_keyword { }
 ///
 /// [pointer]: primitive.pointer.html
 /// [Rust Book]:
-/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
-/// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html
+/// ../book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
+/// [Reference]: ../reference/items/constant-items.html
 mod const_keyword { }
 
 #[doc(keyword = "crate")]
@@ -114,7 +113,7 @@ mod const_keyword { }
 /// }
 /// ```
 ///
-/// [Reference]: https://doc.rust-lang.org/reference/items/extern-crates.html
+/// [Reference]: ../reference/items/extern-crates.html
 mod crate_keyword { }
 
 #[doc(keyword = "enum")]
@@ -169,8 +168,8 @@ mod crate_keyword { }
 ///
 /// [Algebraic Data Types]: https://en.wikipedia.org/wiki/Algebraic_data_type
 /// [`Option`]: option/enum.Option.html
-/// [Rust Book]: https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html
-/// [Reference]: https://doc.rust-lang.org/reference/items/enumerations.html
+/// [Rust Book]: ../book/ch06-01-defining-an-enum.html
+/// [Reference]: ../reference/items/enumerations.html
 mod enum_keyword { }
 
 #[doc(keyword = "extern")]
@@ -211,8 +210,8 @@ mod enum_keyword { }
 /// For more information on FFI, check the [Rust book] or the [Reference].
 ///
 /// [Rust book]:
-/// https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code
-/// [Reference]: https://doc.rust-lang.org/reference/items/external-blocks.html
+/// ../book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code
+/// [Reference]: ../reference/items/external-blocks.html
 mod extern_keyword { }
 
 #[doc(keyword = "fn")]
@@ -278,8 +277,8 @@ mod extern_keyword { }
 ///
 /// [`impl`]: keyword.impl.html
 /// [`extern`]: keyword.extern.html
-/// [Rust book]: https://doc.rust-lang.org/book/ch03-03-how-functions-work.html
-/// [Reference]: https://doc.rust-lang.org/reference/items/functions.html
+/// [Rust book]: ../book/ch03-03-how-functions-work.html
+/// [Reference]: ../reference/items/functions.html
 mod fn_keyword { }
 
 #[doc(keyword = "for")]
@@ -352,12 +351,11 @@ mod fn_keyword { }
 /// For more information on for-loops, see the [Rust book] or the [Reference].
 ///
 /// [`impl`]: keyword.impl.html
-/// [higher-ranked trait bounds]:
-/// https://doc.rust-lang.org/nightly/reference/trait-bounds.html#higher-ranked-trait-bounds
+/// [higher-ranked trait bounds]: ../reference/trait-bounds.html#higher-ranked-trait-bounds
 /// [`IntoIterator`]: iter/trait.IntoIterator.html
 /// [Rust book]:
-/// https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html#looping-through-a-collection-with-for
-/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops
+/// ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
+/// [Reference]: ../reference/expressions/loop-expr.html#iterator-loops
 mod for_keyword { }
 
 #[doc(keyword = "if")]
@@ -430,9 +428,8 @@ mod for_keyword { }
 ///
 /// For more information on `if` expressions, see the [Rust book] or the [Reference].
 ///
-/// [Rust book]:
-/// https://doc.rust-lang.org/stable/book/2018-edition/ch03-05-control-flow.html#if-expressions
-/// [Reference]: https://doc.rust-lang.org/reference/expressions/if-expr.html
+/// [Rust book]: ../book/ch03-05-control-flow.html#if-expressions
+/// [Reference]: ../reference/expressions/if-expr.html
 mod if_keyword { }
 
 #[doc(keyword = "impl")]
@@ -493,10 +490,9 @@ mod if_keyword { }
 ///
 /// For more information on `impl Trait` syntax, see the [Rust book][book2].
 ///
-/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch05-03-method-syntax.html
-/// [Reference]: https://doc.rust-lang.org/reference/items/implementations.html
-/// [book2]:
-/// https://doc.rust-lang.org/stable/book/2018-edition/ch10-02-traits.html#returning-traits
+/// [book1]: ../book/ch05-03-method-syntax.html
+/// [Reference]: ../reference/items/implementations.html
+/// [book2]: ../book/ch10-02-traits.html#returning-types-that-implement-traits
 mod impl_keyword { }
 
 #[doc(keyword = "let")]
@@ -554,13 +550,12 @@ mod impl_keyword { }
 /// enumerations. `while let` also exists, which runs a loop with a pattern matched value until
 /// that pattern can't be matched.
 ///
-/// For more information on the `let` keyword, see the [Rust book] or the [Reference]
+/// For more information on the `let` keyword, see the [Rust book][book2] or the [Reference]
 ///
-/// [book1]: https://doc.rust-lang.org/stable/book/2018-edition/ch06-02-match.html
+/// [book1]: ../book/ch06-02-match.html
 /// [`if`]: keyword.if.html
-/// [book2]:
-/// https://doc.rust-lang.org/stable/book/2018-edition/ch18-01-all-the-places-for-patterns.html#let-statements
-/// [Reference]: https://doc.rust-lang.org/reference/statements.html#let-statements
+/// [book2]: ../book/ch18-01-all-the-places-for-patterns.html#let-statements
+/// [Reference]: ../reference/statements.html#let-statements
 mod let_keyword { }
 
 #[doc(keyword = "loop")]
@@ -605,7 +600,7 @@ mod let_keyword { }
 ///
 /// For more information on `loop` and loops in general, see the [Reference].
 ///
-/// [Reference]: https://doc.rust-lang.org/reference/expressions/loop-expr.html
+/// [Reference]: ../reference/expressions/loop-expr.html
 mod loop_keyword { }
 
 #[doc(keyword = "struct")]
@@ -712,6 +707,6 @@ mod loop_keyword { }
 /// [Reference][reference].
 ///
 /// [`PhantomData`]: marker/struct.PhantomData.html
-/// [book]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html
-/// [reference]: https://doc.rust-lang.org/reference/items/structs.html
+/// [book]: ../book/ch05-01-defining-structs.html
+/// [reference]: ../reference/items/structs.html
 mod struct_keyword { }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index d11dee8fc97..ee6ba3f438f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -229,7 +229,6 @@
 #![feature(align_offset)]
 #![feature(alloc_error_handler)]
 #![feature(alloc_layout_extra)]
-#![feature(alloc)]
 #![feature(allocator_api)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index be4db1f737d..14b266a4344 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -346,7 +346,7 @@ macro_rules! r#await {
         let mut pinned = $e;
         loop {
             if let $crate::task::Poll::Ready(x) =
-                $crate::future::poll_with_tls_waker(unsafe {
+                $crate::future::poll_with_tls_context(unsafe {
                     $crate::pin::Pin::new_unchecked(&mut pinned)
                 })
             {
@@ -836,9 +836,11 @@ mod builtin {
     /// boolean expression evaluation of configuration flags. This frequently
     /// leads to less duplicated code.
     ///
-    /// The syntax given to this macro is the same syntax as the `cfg`
+    /// The syntax given to this macro is the same syntax as the [`cfg`]
     /// attribute.
     ///
+    /// [`cfg`]: ../reference/conditional-compilation.html#the-cfg-attribute
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/src/libstd/num.rs b/src/libstd/num.rs
index 828d5720eec..d67d0b55a79 100644
--- a/src/libstd/num.rs
+++ b/src/libstd/num.rs
@@ -13,6 +13,8 @@ pub use core::num::Wrapping;
 
 #[stable(feature = "nonzero", since = "1.28.0")]
 pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
+#[stable(feature = "signed_nonzero", since = "1.34.0")]
+pub use core::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize};
 
 #[cfg(test)] use crate::fmt;
 #[cfg(test)] use crate::ops::{Add, Sub, Mul, Div, Rem};
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index cc147d851de..5a8101e2301 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -12,7 +12,7 @@ use crate::panicking;
 use crate::ptr::{Unique, NonNull};
 use crate::rc::Rc;
 use crate::sync::{Arc, Mutex, RwLock, atomic};
-use crate::task::{Waker, Poll};
+use crate::task::{Context, Poll};
 use crate::thread::Result;
 
 #[stable(feature = "panic_hooks", since = "1.10.0")]
@@ -323,9 +323,9 @@ impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
 impl<F: Future> Future for AssertUnwindSafe<F> {
     type Output = F::Output;
 
-    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
         let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) };
-        F::poll(pinned_field, waker)
+        F::poll(pinned_field, cx)
     }
 }
 
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 71e82f0a9b0..1bbda9b5bcb 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1551,9 +1551,7 @@ impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
     fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
-        for p in iter {
-            self.push(p.as_ref())
-        }
+        iter.into_iter().for_each(move |p| self.push(p.as_ref()));
     }
 }
 
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index e0c9b7cad86..ef5626700e8 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -111,7 +111,7 @@ use crate::io::prelude::*;
 use crate::ffi::OsStr;
 use crate::fmt;
 use crate::fs;
-use crate::io::{self, Initializer};
+use crate::io::{self, Initializer, IoVec, IoVecMut};
 use crate::path::Path;
 use crate::str;
 use crate::sys::pipe::{read2, AnonPipe};
@@ -225,6 +225,10 @@ impl Write for ChildStdin {
         self.inner.write(buf)
     }
 
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.inner.write_vectored(bufs)
+    }
+
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -271,6 +275,11 @@ impl Read for ChildStdout {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
@@ -318,6 +327,11 @@ impl Read for ChildStderr {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
diff --git a/src/libstd/sys/cloudabi/shims/fs.rs b/src/libstd/sys/cloudabi/shims/fs.rs
index ee045b8e515..abd7f0fd3ee 100644
--- a/src/libstd/sys/cloudabi/shims/fs.rs
+++ b/src/libstd/sys/cloudabi/shims/fs.rs
@@ -1,7 +1,7 @@
 use crate::ffi::OsString;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
-use crate::io::{self, SeekFrom};
+use crate::io::{self, SeekFrom, IoVec, IoVecMut};
 use crate::path::{Path, PathBuf};
 use crate::sys::time::SystemTime;
 use crate::sys::{unsupported, Void};
@@ -198,10 +198,18 @@ impl File {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/cloudabi/shims/pipe.rs b/src/libstd/sys/cloudabi/shims/pipe.rs
index f3debb95047..804d3e001ac 100644
--- a/src/libstd/sys/cloudabi/shims/pipe.rs
+++ b/src/libstd/sys/cloudabi/shims/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoVec, IoVecMut};
 use crate::sys::Void;
 
 pub struct AnonPipe(Void);
@@ -8,10 +8,18 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs
index f853346e0e6..7da16c4d247 100644
--- a/src/libstd/sys/cloudabi/thread.rs
+++ b/src/libstd/sys/cloudabi/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::cmp;
 use crate::ffi::CStr;
 use crate::io;
@@ -22,7 +21,7 @@ unsafe impl Sync for Thread {}
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(stack: usize, p: Box<dyn FnBox()>) -> io::Result<Thread> {
+    pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         let p = box p;
         let mut native: libc::pthread_t = mem::zeroed();
         let mut attr: libc::pthread_attr_t = mem::zeroed();
diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs
index 3ef9925705f..c86c6000eae 100644
--- a/src/libstd/sys/redox/fs.rs
+++ b/src/libstd/sys/redox/fs.rs
@@ -2,7 +2,7 @@ use crate::os::unix::prelude::*;
 
 use crate::ffi::{OsString, OsStr};
 use crate::fmt;
-use crate::io::{self, Error, ErrorKind, SeekFrom};
+use crate::io::{self, Error, SeekFrom, IoVec, IoVecMut};
 use crate::path::{Path, PathBuf};
 use crate::sync::Arc;
 use crate::sys::fd::FileDesc;
@@ -10,6 +10,9 @@ use crate::sys::time::SystemTime;
 use crate::sys::{cvt, syscall};
 use crate::sys_common::{AsInner, FromInner};
 
+pub use crate::sys_common::fs::copy;
+pub use crate::sys_common::fs::remove_dir_all;
+
 pub struct File(FileDesc);
 
 #[derive(Clone)]
@@ -275,10 +278,18 @@ impl File {
         self.0.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        crate::io::default_read_vectored(|buf| self.read(buf), bufs)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        crate::io::default_write_vectored(|buf| self.write(buf), bufs)
+    }
+
     pub fn flush(&self) -> io::Result<()> { Ok(()) }
 
     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
@@ -392,27 +403,6 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
     Ok(())
 }
 
-pub fn remove_dir_all(path: &Path) -> io::Result<()> {
-    let filetype = lstat(path)?.file_type();
-    if filetype.is_symlink() {
-        unlink(path)
-    } else {
-        remove_dir_all_recursive(path)
-    }
-}
-
-fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
-    for child in readdir(path)? {
-        let child = child?;
-        if child.file_type()?.is_dir() {
-            remove_dir_all_recursive(&child.path())?;
-        } else {
-            unlink(&child.path())?;
-        }
-    }
-    rmdir(path)
-}
-
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
     let fd = cvt(syscall::open(p.to_str().unwrap(),
                                syscall::O_CLOEXEC | syscall::O_SYMLINK | syscall::O_RDONLY))?;
@@ -455,19 +445,3 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
     let file = File(FileDesc::new(fd));
     file.path()
 }
-
-pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
-    use crate::fs::{File, set_permissions};
-    if !from.is_file() {
-        return Err(Error::new(ErrorKind::InvalidInput,
-                              "the source path is not an existing regular file"))
-    }
-
-    let mut reader = File::open(from)?;
-    let mut writer = File::create(to)?;
-    let perm = reader.metadata()?.permissions();
-
-    let ret = io::copy(&mut reader, &mut writer)?;
-    set_permissions(to, perm)?;
-    Ok(ret)
-}
diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs
index 911ba9c3f65..b926968f7b3 100644
--- a/src/libstd/sys/redox/pipe.rs
+++ b/src/libstd/sys/redox/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoVec, IoVecMut};
 use crate::sys::{cvt, syscall};
 use crate::sys::fd::FileDesc;
 
@@ -24,10 +24,18 @@ impl AnonPipe {
         self.0.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        crate::io::default_read_vectored(|buf| self.read(buf), bufs)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        crate::io::default_write_vectored(|buf| self.write(buf), bufs)
+    }
+
     pub fn fd(&self) -> &FileDesc { &self.0 }
     pub fn into_fd(self) -> FileDesc { self.0 }
 }
diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs
index ae0b91b4d6c..9d40a7e8bb8 100644
--- a/src/libstd/sys/redox/thread.rs
+++ b/src/libstd/sys/redox/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::ffi::CStr;
 use crate::io;
 use crate::mem;
@@ -19,7 +18,7 @@ unsafe impl Sync for Thread {}
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(_stack: usize, p: Box<dyn FnBox()>) -> io::Result<Thread> {
+    pub unsafe fn new(_stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         let p = box p;
 
         let id = cvt(syscall::clone(syscall::CLONE_VM | syscall::CLONE_FS | syscall::CLONE_FILES))?;
diff --git a/src/libstd/sys/sgx/abi/mod.rs b/src/libstd/sys/sgx/abi/mod.rs
index 85ec8be4aae..1f433e25ee1 100644
--- a/src/libstd/sys/sgx/abi/mod.rs
+++ b/src/libstd/sys/sgx/abi/mod.rs
@@ -69,9 +69,9 @@ extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64
         }
 
         // check entry is being called according to ABI
-        assert_eq!(p3, 0);
-        assert_eq!(p4, 0);
-        assert_eq!(p5, 0);
+        rtassert!(p3 == 0);
+        rtassert!(p4 == 0);
+        rtassert!(p5 == 0);
 
         unsafe {
             // The actual types of these arguments are `p1: *const Arg, p2:
diff --git a/src/libstd/sys/sgx/abi/reloc.rs b/src/libstd/sys/sgx/abi/reloc.rs
index a39841bc36f..6dd24c524fc 100644
--- a/src/libstd/sys/sgx/abi/reloc.rs
+++ b/src/libstd/sys/sgx/abi/reloc.rs
@@ -23,7 +23,7 @@ pub fn relocate_elf_rela() {
     };
     for rela in relas {
         if rela.info != (/*0 << 32 |*/ R_X86_64_RELATIVE as u64) {
-            panic!("Invalid relocation");
+            rtabort!("Invalid relocation");
         }
         unsafe { *mem::rel_ptr_mut::<*const ()>(rela.offset) = mem::rel_ptr(rela.addend) };
     }
diff --git a/src/libstd/sys/sgx/abi/tls.rs b/src/libstd/sys/sgx/abi/tls.rs
index fa82e8ccf05..03e08ad547d 100644
--- a/src/libstd/sys/sgx/abi/tls.rs
+++ b/src/libstd/sys/sgx/abi/tls.rs
@@ -100,20 +100,24 @@ impl Tls {
     }
 
     pub fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
-        let index = TLS_KEY_IN_USE.set().expect("TLS limit exceeded");
+        let index = if let Some(index) = TLS_KEY_IN_USE.set() {
+            index
+        } else {
+            rtabort!("TLS limit exceeded")
+        };
         TLS_DESTRUCTOR[index].store(dtor.map_or(0, |f| f as usize), Ordering::Relaxed);
         Key::from_index(index)
     }
 
     pub fn set(key: Key, value: *mut u8) {
         let index = key.to_index();
-        assert!(TLS_KEY_IN_USE.get(index));
+        rtassert!(TLS_KEY_IN_USE.get(index));
         unsafe { Self::current() }.data[index].set(value);
     }
 
     pub fn get(key: Key) -> *mut u8 {
         let index = key.to_index();
-        assert!(TLS_KEY_IN_USE.get(index));
+        rtassert!(TLS_KEY_IN_USE.get(index));
         unsafe { Self::current() }.data[index].get()
     }
 
diff --git a/src/libstd/sys/sgx/abi/usercalls/alloc.rs b/src/libstd/sys/sgx/abi/usercalls/alloc.rs
index ec9c30a3e4f..22ae2a8e07d 100644
--- a/src/libstd/sys/sgx/abi/usercalls/alloc.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/alloc.rs
@@ -190,11 +190,15 @@ impl<T: ?Sized> User<T> where T: UserSafe {
         unsafe {
             // Mustn't call alloc with size 0.
             let ptr = if size > 0 {
-                super::alloc(size, T::align_of()).expect("User memory allocation failed") as _
+                rtunwrap!(Ok, super::alloc(size, T::align_of())) as _
             } else {
                 T::align_of() as _ // dangling pointer ok for size 0
             };
-            User(NonNull::new_userref(T::from_raw_sized(ptr, size)))
+            if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) {
+                User(NonNull::new_userref(v))
+            } else {
+                rtabort!("Got invalid pointer from alloc() usercall")
+            }
         }
     }
 
diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs
index d84b6154cbe..0abfc26bced 100644
--- a/src/libstd/sys/sgx/abi/usercalls/mod.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs
@@ -52,7 +52,7 @@ pub fn close(fd: Fd) {
 
 fn string_from_bytebuffer(buf: &alloc::UserRef<ByteBuffer>, usercall: &str, arg: &str) -> String {
     String::from_utf8(buf.copy_user_buffer())
-        .unwrap_or_else(|_| panic!("Usercall {}: expected {} to be valid UTF-8", usercall, arg))
+        .unwrap_or_else(|_| rtabort!("Usercall {}: expected {} to be valid UTF-8", usercall, arg))
 }
 
 /// Usercall `bind_stream`. See the ABI documentation for more information.
@@ -176,7 +176,7 @@ fn check_os_error(err: Result) -> i32 {
     {
         err
     } else {
-        panic!("Usercall: returned invalid error value {}", err)
+        rtabort!("Usercall: returned invalid error value {}", err)
     }
 }
 
diff --git a/src/libstd/sys/sgx/abi/usercalls/raw.rs b/src/libstd/sys/sgx/abi/usercalls/raw.rs
index ad0b6d7b3d8..e4694a8827a 100644
--- a/src/libstd/sys/sgx/abi/usercalls/raw.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/raw.rs
@@ -131,22 +131,22 @@ impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
 
 impl ReturnValue for ! {
     fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self {
-        panic!("Usercall {}: did not expect to be re-entered", call);
+        rtabort!("Usercall {}: did not expect to be re-entered", call);
     }
 }
 
 impl ReturnValue for () {
-    fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
-        assert_eq!(regs.0, 0, "Usercall {}: expected {} return value to be 0", call, "1st");
-        assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
+    fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
+        rtassert!(usercall_retval.0 == 0);
+        rtassert!(usercall_retval.1 == 0);
         ()
     }
 }
 
 impl<T: RegisterArgument> ReturnValue for T {
-    fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
-        assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
-        T::from_register(regs.0)
+    fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
+        rtassert!(usercall_retval.1 == 0);
+        T::from_register(usercall_retval.0)
     }
 }
 
@@ -174,8 +174,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 RegisterArgument::into_register($n3),
@@ -191,8 +190,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 RegisterArgument::into_register($n3),
@@ -208,8 +206,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 0,0,
@@ -224,8 +221,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f($n1: $t1) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 RegisterArgument::into_register($n1),
                 0,0,0,
                 return_type_is_abort!($r)
@@ -239,8 +235,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
         #[inline(always)]
         pub unsafe fn $f() -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                NonZeroU64::new(Usercalls::$f as Register)
-                    .expect("Usercall number must be non-zero"),
+                rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
                 0,0,0,0,
                 return_type_is_abort!($r)
             ))
diff --git a/src/libstd/sys/sgx/alloc.rs b/src/libstd/sys/sgx/alloc.rs
index 98eb8397436..40daec758a9 100644
--- a/src/libstd/sys/sgx/alloc.rs
+++ b/src/libstd/sys/sgx/alloc.rs
@@ -30,3 +30,17 @@ unsafe impl GlobalAlloc for System {
         DLMALLOC.lock().realloc(ptr, layout.size(), layout.align(), new_size)
     }
 }
+
+// The following functions are needed by libunwind. These symbols are named
+// in pre-link args for the target specification, so keep that in sync.
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
+    crate::alloc::alloc(Layout::from_size_align_unchecked(size, align))
+}
+
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
+    crate::alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
+}
diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs
index f9a76f0baf5..000bb19f269 100644
--- a/src/libstd/sys/sgx/condvar.rs
+++ b/src/libstd/sys/sgx/condvar.rs
@@ -32,9 +32,8 @@ impl Condvar {
         mutex.lock()
     }
 
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, _dur: Duration) -> bool {
-        mutex.unlock(); // don't hold the lock while panicking
-        panic!("timeout not supported in SGX");
+    pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
+        rtabort!("timeout not supported in SGX");
     }
 
     #[inline]
diff --git a/src/libstd/sys/sgx/fs.rs b/src/libstd/sys/sgx/fs.rs
index 68c8e9356a8..c3c898eb23e 100644
--- a/src/libstd/sys/sgx/fs.rs
+++ b/src/libstd/sys/sgx/fs.rs
@@ -1,7 +1,7 @@
 use crate::ffi::OsString;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
-use crate::io::{self, SeekFrom};
+use crate::io::{self, SeekFrom, IoVec, IoVecMut};
 use crate::path::{Path, PathBuf};
 use crate::sys::time::SystemTime;
 use crate::sys::{unsupported, Void};
@@ -200,10 +200,18 @@ impl File {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs
index dc51a932c61..a99a534f41e 100644
--- a/src/libstd/sys/sgx/mod.rs
+++ b/src/libstd/sys/sgx/mod.rs
@@ -130,6 +130,15 @@ pub unsafe fn abort_internal() -> ! {
     abi::usercalls::exit(true)
 }
 
+// This function is needed by the panic runtime. The symbol is named in
+// pre-link args for the target specification, so keep that in sync.
+#[cfg(not(test))]
+#[no_mangle]
+// NB. used by both libunwind and libpanic_abort
+pub unsafe extern "C" fn __rust_abort() {
+    abort_internal();
+}
+
 pub fn hashmap_random_keys() -> (u64, u64) {
     fn rdrand64() -> u64 {
         unsafe {
@@ -139,7 +148,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
                     return ret;
                 }
             }
-            panic!("Failed to obtain random data");
+            rtabort!("Failed to obtain random data");
         }
     }
     (rdrand64(), rdrand64())
diff --git a/src/libstd/sys/sgx/pipe.rs b/src/libstd/sys/sgx/pipe.rs
index 2582b993b60..804d3e001ac 100644
--- a/src/libstd/sys/sgx/pipe.rs
+++ b/src/libstd/sys/sgx/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoVec, IoVecMut};
 use crate::sys::Void;
 
 pub struct AnonPipe(Void);
@@ -8,18 +8,23 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
 }
 
-pub fn read2(p1: AnonPipe,
-             _v1: &mut Vec<u8>,
-             _p2: AnonPipe,
-             _v2: &mut Vec<u8>) -> io::Result<()> {
+pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
     match p1.0 {}
 }
diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs
index 4cba36aa64d..30c47e44eef 100644
--- a/src/libstd/sys/sgx/rwlock.rs
+++ b/src/libstd/sys/sgx/rwlock.rs
@@ -1,10 +1,4 @@
-#[cfg(not(test))]
-use crate::alloc::{self, Layout};
 use crate::num::NonZeroUsize;
-#[cfg(not(test))]
-use crate::slice;
-#[cfg(not(test))]
-use crate::str;
 
 use super::waitqueue::{
     try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
@@ -105,7 +99,7 @@ impl RWLock {
                 *wguard.lock_var_mut() = true;
             } else {
                 // No writers were waiting, the lock is released
-                assert!(rguard.queue_empty());
+                rtassert!(rguard.queue_empty());
             }
         }
     }
@@ -165,10 +159,11 @@ impl RWLock {
     pub unsafe fn destroy(&self) {}
 }
 
+// The following functions are needed by libunwind. These symbols are named
+// in pre-link args for the target specification, so keep that in sync.
 #[cfg(not(test))]
 const EINVAL: i32 = 22;
 
-// used by libunwind port
 #[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
@@ -198,39 +193,6 @@ pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
     return 0;
 }
 
-// the following functions are also used by the libunwind port. They're
-// included here to make sure parallel codegen and LTO don't mess things up.
-#[cfg(not(test))]
-#[no_mangle]
-pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
-    if s < 0 {
-        return;
-    }
-    let buf = slice::from_raw_parts(m as *const u8, s as _);
-    if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
-        eprint!("{}", s);
-    }
-}
-
-#[cfg(not(test))]
-#[no_mangle]
-// NB. used by both libunwind and libpanic_abort
-pub unsafe extern "C" fn __rust_abort() {
-    crate::sys::abort_internal();
-}
-
-#[cfg(not(test))]
-#[no_mangle]
-pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
-    alloc::alloc(Layout::from_size_align_unchecked(size, align))
-}
-
-#[cfg(not(test))]
-#[no_mangle]
-pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
-    alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/src/libstd/sys/sgx/stdio.rs b/src/libstd/sys/sgx/stdio.rs
index f2c6892bfb7..a575401f5f6 100644
--- a/src/libstd/sys/sgx/stdio.rs
+++ b/src/libstd/sys/sgx/stdio.rs
@@ -2,6 +2,10 @@ use fortanix_sgx_abi as abi;
 
 use crate::io;
 use crate::sys::fd::FileDesc;
+#[cfg(not(test))]
+use crate::slice;
+#[cfg(not(test))]
+use crate::str;
 
 pub struct Stdin(());
 pub struct Stdout(());
@@ -62,3 +66,17 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 pub fn panic_output() -> Option<impl io::Write> {
     super::abi::panic::SgxPanicOutput::new()
 }
+
+// This function is needed by libunwind. The symbol is named in pre-link args
+// for the target specification, so keep that in sync.
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
+    if s < 0 {
+        return;
+    }
+    let buf = slice::from_raw_parts(m as *const u8, s as _);
+    if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
+        eprint!("{}", s);
+    }
+}
diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs
index a3637723ba1..b9f42d4ad1c 100644
--- a/src/libstd/sys/sgx/thread.rs
+++ b/src/libstd/sys/sgx/thread.rs
@@ -1,5 +1,4 @@
 #![cfg_attr(test, allow(dead_code))] // why is this necessary?
-use crate::boxed::FnBox;
 use crate::ffi::CStr;
 use crate::io;
 use crate::time::Duration;
@@ -13,17 +12,16 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
 mod task_queue {
     use crate::sync::{Mutex, MutexGuard, Once};
     use crate::sync::mpsc;
-    use crate::boxed::FnBox;
 
     pub type JoinHandle = mpsc::Receiver<()>;
 
     pub(super) struct Task {
-        p: Box<dyn FnBox()>,
+        p: Box<dyn FnOnce()>,
         done: mpsc::Sender<()>,
     }
 
     impl Task {
-        pub(super) fn new(p: Box<dyn FnBox()>) -> (Task, JoinHandle) {
+        pub(super) fn new(p: Box<dyn FnOnce()>) -> (Task, JoinHandle) {
             let (done, recv) = mpsc::channel();
             (Task { p, done }, recv)
         }
@@ -51,7 +49,7 @@ mod task_queue {
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(_stack: usize, p: Box<dyn FnBox()>)
+    pub unsafe fn new(_stack: usize, p: Box<dyn FnOnce()>)
         -> io::Result<Thread>
     {
         let mut queue_lock = task_queue::lock();
@@ -62,17 +60,15 @@ impl Thread {
     }
 
     pub(super) fn entry() {
-        let mut guard = task_queue::lock();
-        let task = guard.pop().expect("Thread started but no tasks pending");
-        drop(guard); // make sure to not hold the task queue lock longer than necessary
+        let mut pending_tasks = task_queue::lock();
+        let task = rtunwrap!(Some, pending_tasks.pop());
+        drop(pending_tasks); // make sure to not hold the task queue lock longer than necessary
         task.run()
     }
 
     pub fn yield_now() {
-        assert_eq!(
-            usercalls::wait(0, usercalls::raw::WAIT_NO).unwrap_err().kind(),
-            io::ErrorKind::WouldBlock
-        );
+        let wait_error = rtunwrap!(Err, usercalls::wait(0, usercalls::raw::WAIT_NO));
+        rtassert!(wait_error.kind() == io::ErrorKind::WouldBlock);
     }
 
     pub fn set_name(_name: &CStr) {
@@ -80,7 +76,7 @@ impl Thread {
     }
 
     pub fn sleep(_dur: Duration) {
-        panic!("can't sleep"); // FIXME
+        rtabort!("can't sleep"); // FIXME
     }
 
     pub fn join(self) {
diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs
index f4adb7d1e16..d542f9b4101 100644
--- a/src/libstd/sys/sgx/waitqueue.rs
+++ b/src/libstd/sys/sgx/waitqueue.rs
@@ -121,7 +121,7 @@ impl<'a, T> Drop for WaitGuard<'a, T> {
             NotifiedTcs::Single(tcs) => Some(tcs),
             NotifiedTcs::All { .. } => None
         };
-        usercalls::send(EV_UNPARK, target_tcs).unwrap();
+        rtunwrap!(Ok, usercalls::send(EV_UNPARK, target_tcs));
     }
 }
 
@@ -141,6 +141,7 @@ impl WaitQueue {
     ///
     /// This function does not return until this thread has been awoken.
     pub fn wait<T>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>) {
+        // very unsafe: check requirements of UnsafeList::push
         unsafe {
             let mut entry = UnsafeListEntry::new(SpinMutex::new(WaitEntry {
                 tcs: thread::current(),
@@ -149,10 +150,9 @@ impl WaitQueue {
             let entry = guard.queue.inner.push(&mut entry);
             drop(guard);
             while !entry.lock().wake {
-                assert_eq!(
-                    usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap() & EV_UNPARK,
-                    EV_UNPARK
-                );
+                // don't panic, this would invalidate `entry` during unwinding
+                let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE));
+                rtassert!(eventset & EV_UNPARK == EV_UNPARK);
             }
         }
     }
@@ -269,7 +269,7 @@ mod unsafe_list {
                         // ,-------> /---------\ next ---,
                         // |         |head_tail|         |
                         // `--- prev \---------/ <-------`
-                        assert_eq!(self.head_tail.as_ref().prev, first);
+                        rtassert!(self.head_tail.as_ref().prev == first);
                         true
                     } else {
                         false
@@ -285,7 +285,9 @@ mod unsafe_list {
         /// # Safety
         ///
         /// The entry must remain allocated until the entry is removed from the
-        /// list AND the caller who popped is done using the entry.
+        /// list AND the caller who popped is done using the entry. Special
+        /// care must be taken in the caller of `push` to ensure unwinding does
+        /// not destroy the stack frame containing the entry.
         pub unsafe fn push<'a>(&mut self, entry: &'a mut UnsafeListEntry<T>) -> &'a T {
             self.init();
 
@@ -303,6 +305,7 @@ mod unsafe_list {
             entry.as_mut().prev = prev_tail;
             entry.as_mut().next = self.head_tail;
             prev_tail.as_mut().next = entry;
+            // unwrap ok: always `Some` on non-dummy entries
             (*entry.as_ptr()).value.as_ref().unwrap()
         }
 
@@ -333,6 +336,7 @@ mod unsafe_list {
                 second.as_mut().prev = self.head_tail;
                 first.as_mut().next = NonNull::dangling();
                 first.as_mut().prev = NonNull::dangling();
+                // unwrap ok: always `Some` on non-dummy entries
                 Some((*first.as_ptr()).value.as_ref().unwrap())
             }
         }
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index a36dae2f5a1..a14db108c34 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -2,7 +2,7 @@ use crate::os::unix::prelude::*;
 
 use crate::ffi::{CString, CStr, OsString, OsStr};
 use crate::fmt;
-use crate::io::{self, Error, ErrorKind, SeekFrom};
+use crate::io::{self, Error, ErrorKind, SeekFrom, IoVec, IoVecMut};
 use crate::mem;
 use crate::path::{Path, PathBuf};
 use crate::ptr;
@@ -36,6 +36,8 @@ use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off_t as off64_t,
               target_os = "fuchsia")))]
 use libc::{readdir_r as readdir64_r};
 
+pub use crate::sys_common::fs::remove_dir_all;
+
 pub struct File(FileDesc);
 
 #[derive(Clone)]
@@ -558,6 +560,10 @@ impl File {
         self.0.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         self.0.read_at(buf, offset)
     }
@@ -566,6 +572,10 @@ impl File {
         self.0.write(buf)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         self.0.write_at(buf, offset)
     }
@@ -734,27 +744,6 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
     Ok(())
 }
 
-pub fn remove_dir_all(path: &Path) -> io::Result<()> {
-    let filetype = lstat(path)?.file_type();
-    if filetype.is_symlink() {
-        unlink(path)
-    } else {
-        remove_dir_all_recursive(path)
-    }
-}
-
-fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
-    for child in readdir(path)? {
-        let child = child?;
-        if child.file_type()?.is_dir() {
-            remove_dir_all_recursive(&child.path())?;
-        } else {
-            unlink(&child.path())?;
-        }
-    }
-    rmdir(path)
-}
-
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
     let c_path = cstr(p)?;
     let p = c_path.as_ptr();
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index bc3c026adab..a7792d42af9 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoVec, IoVecMut};
 use crate::mem;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::fd::FileDesc;
@@ -60,10 +60,18 @@ impl AnonPipe {
         self.0.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
     pub fn fd(&self) -> &FileDesc { &self.0 }
     pub fn into_fd(self) -> FileDesc { self.0 }
 }
diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs
index 35f163bbdb1..bc2986f624e 100644
--- a/src/libstd/sys/unix/stdio.rs
+++ b/src/libstd/sys/unix/stdio.rs
@@ -1,5 +1,6 @@
-use crate::io;
+use crate::io::{self, IoVec, IoVecMut};
 use crate::sys::fd::FileDesc;
+use crate::mem::ManuallyDrop;
 
 pub struct Stdin(());
 pub struct Stdout(());
@@ -11,10 +12,11 @@ impl Stdin {
 
 impl io::Read for Stdin {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        let fd = FileDesc::new(libc::STDIN_FILENO);
-        let ret = fd.read(buf);
-        fd.into_raw(); // do not close this FD
-        ret
+        ManuallyDrop::new(FileDesc::new(libc::STDIN_FILENO)).read(buf)
+    }
+
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(FileDesc::new(libc::STDIN_FILENO)).read_vectored(bufs)
     }
 }
 
@@ -24,10 +26,11 @@ impl Stdout {
 
 impl io::Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let fd = FileDesc::new(libc::STDOUT_FILENO);
-        let ret = fd.write(buf);
-        fd.into_raw(); // do not close this FD
-        ret
+        ManuallyDrop::new(FileDesc::new(libc::STDOUT_FILENO)).write(buf)
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(FileDesc::new(libc::STDOUT_FILENO)).write_vectored(bufs)
     }
 
     fn flush(&mut self) -> io::Result<()> {
@@ -41,10 +44,11 @@ impl Stderr {
 
 impl io::Write for Stderr {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        let fd = FileDesc::new(libc::STDERR_FILENO);
-        let ret = fd.write(buf);
-        fd.into_raw(); // do not close this FD
-        ret
+        ManuallyDrop::new(FileDesc::new(libc::STDERR_FILENO)).write(buf)
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(FileDesc::new(libc::STDERR_FILENO)).write_vectored(bufs)
     }
 
     fn flush(&mut self) -> io::Result<()> {
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index feb15e8f585..f7d604ac4c8 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::cmp;
 use crate::ffi::CStr;
 use crate::io;
@@ -39,7 +38,7 @@ unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t,
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(stack: usize, p: Box<dyn FnBox()>)
+    pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>)
                           -> io::Result<Thread> {
         let p = box p;
         let mut native: libc::pthread_t = mem::zeroed();
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
index 127ae6aa104..e21c32cd91b 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -114,7 +114,8 @@ impl Hash for Timespec {
 #[cfg(any(target_os = "macos", target_os = "ios"))]
 mod inner {
     use crate::fmt;
-    use crate::sync::Once;
+    use crate::mem;
+    use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
     use crate::sys::cvt;
     use crate::sys_common::mul_div_u64;
     use crate::time::Duration;
@@ -229,18 +230,30 @@ mod inner {
         Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64))
     }
 
-    fn info() -> &'static libc::mach_timebase_info {
+    fn info() -> libc::mach_timebase_info {
         static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
             numer: 0,
             denom: 0,
         };
-        static ONCE: Once = Once::new();
+        static STATE: AtomicUsize = AtomicUsize::new(0);
 
         unsafe {
-            ONCE.call_once(|| {
-                libc::mach_timebase_info(&mut INFO);
-            });
-            &INFO
+            // If a previous thread has filled in this global state, use that.
+            if STATE.load(SeqCst) == 2 {
+                return INFO;
+            }
+
+            // ... otherwise learn for ourselves ...
+            let mut info = mem::zeroed();
+            libc::mach_timebase_info(&mut info);
+
+            // ... and attempt to be the one thread that stores it globally for
+            // all other threads
+            if STATE.compare_exchange(0, 1, SeqCst, SeqCst).is_ok() {
+                INFO = info;
+                STATE.store(2, SeqCst);
+            }
+            return info;
         }
     }
 }
diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs
index 20558a8042d..9c8e59e4fb5 100644
--- a/src/libstd/sys/wasi/args.rs
+++ b/src/libstd/sys/wasi/args.rs
@@ -1,30 +1,15 @@
-use crate::any::Any;
 use crate::ffi::CStr;
+use crate::io;
+use crate::sys::cvt_wasi;
 use crate::ffi::OsString;
 use crate::marker::PhantomData;
 use crate::os::wasi::ffi::OsStringExt;
-use crate::ptr;
 use crate::vec;
 
-static mut ARGC: isize = 0;
-static mut ARGV: *const *const u8 = ptr::null();
-
-#[cfg(not(target_feature = "atomics"))]
-pub unsafe fn args_lock() -> impl Any {
-    // No need for a lock if we're single-threaded, but this function will need
-    // to get implemented for multi-threaded scenarios
-}
-
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
-    let _guard = args_lock();
-    ARGC = argc;
-    ARGV = argv;
+pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
 }
 
 pub unsafe fn cleanup() {
-    let _guard = args_lock();
-    ARGC = 0;
-    ARGV = ptr::null();
 }
 
 pub struct Args {
@@ -34,18 +19,31 @@ pub struct Args {
 
 /// Returns the command line arguments
 pub fn args() -> Args {
+    maybe_args().unwrap_or_else(|_| {
+        Args {
+            iter: Vec::new().into_iter(),
+            _dont_send_or_sync_me: PhantomData
+        }
+    })
+}
+
+fn maybe_args() -> io::Result<Args> {
     unsafe {
-        let _guard = args_lock();
-        let args = (0..ARGC)
-            .map(|i| {
-                let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
-                OsStringExt::from_vec(cstr.to_bytes().to_vec())
-            })
+        let (mut argc, mut argv_buf_size) = (0, 0);
+        cvt_wasi(libc::__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?;
+
+        let mut argc = vec![0 as *mut libc::c_char; argc];
+        let mut argv_buf = vec![0; argv_buf_size];
+        cvt_wasi(libc::__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?;
+
+        let args = argc.into_iter()
+            .map(|ptr| CStr::from_ptr(ptr).to_bytes().to_vec())
+            .map(|bytes| OsString::from_vec(bytes))
             .collect::<Vec<_>>();
-        Args {
+        Ok(Args {
             iter: args.into_iter(),
             _dont_send_or_sync_me: PhantomData,
-        }
+        })
     }
 }
 
diff --git a/src/libstd/sys/wasi/ext/ffi.rs b/src/libstd/sys/wasi/ext/ffi.rs
index 07b93dd143f..f71f316d1ba 100644
--- a/src/libstd/sys/wasi/ext/ffi.rs
+++ b/src/libstd/sys/wasi/ext/ffi.rs
@@ -2,60 +2,5 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::ffi::{OsStr, OsString};
-use crate::mem;
-use crate::sys::os_str::Buf;
-use crate::sys_common::{FromInner, IntoInner, AsInner};
-
-/// WASI-specific extensions to [`OsString`].
-///
-/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStringExt {
-    /// Creates an `OsString` from a byte vector.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn from_vec(vec: Vec<u8>) -> Self;
-
-    /// Yields the underlying byte vector of this `OsString`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn into_vec(self) -> Vec<u8>;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStringExt for OsString {
-    fn from_vec(vec: Vec<u8>) -> OsString {
-        FromInner::from_inner(Buf { inner: vec })
-    }
-    fn into_vec(self) -> Vec<u8> {
-        self.into_inner().inner
-    }
-}
-
-/// WASI-specific extensions to [`OsStr`].
-///
-/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStrExt {
-    #[stable(feature = "rust1", since = "1.0.0")]
-    /// Creates an [`OsStr`] from a byte slice.
-    ///
-    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
-    fn from_bytes(slice: &[u8]) -> &Self;
-
-    /// Gets the underlying byte view of the [`OsStr`] slice.
-    ///
-    /// [`OsStr`]: ../../../ffi/struct.OsStr.html
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn as_bytes(&self) -> &[u8];
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStrExt for OsStr {
-    fn from_bytes(slice: &[u8]) -> &OsStr {
-        unsafe { mem::transmute(slice) }
-    }
-    fn as_bytes(&self) -> &[u8] {
-        &self.as_inner().inner
-    }
-}
-
+pub use crate::sys_common::os_str_bytes::*;
diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs
new file mode 100644
index 00000000000..53f415c7821
--- /dev/null
+++ b/src/libstd/sys/wasi/ext/fs.rs
@@ -0,0 +1,412 @@
+//! WASI-specific extensions to primitives in the `std::fs` module.
+
+#![unstable(feature = "wasi_ext", issue = "0")]
+
+use crate::fs::{self, File, Metadata, OpenOptions};
+use crate::io::{self, IoVec, IoVecMut};
+use crate::os::wasi::ffi::OsStrExt;
+use crate::path::{Path, PathBuf};
+use crate::sys_common::{AsInner, AsInnerMut, FromInner};
+
+/// WASI-specific extensions to [`File`].
+///
+/// [`File`]: ../../../../std/fs/struct.File.html
+pub trait FileExt {
+    /// Reads a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes read.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// Note that similar to [`File::read_vectored`], it is not an error to
+    /// return with a short read.
+    ///
+    /// [`File::read`]: ../../../../std/fs/struct.File.html#method.read_vectored
+    fn read_at(&self, bufs: &mut [IoVecMut<'_>], offset: u64) -> io::Result<usize>;
+
+    /// Writes a number of bytes starting from a given offset.
+    ///
+    /// Returns the number of bytes written.
+    ///
+    /// The offset is relative to the start of the file and thus independent
+    /// from the current cursor.
+    ///
+    /// The current file cursor is not affected by this function.
+    ///
+    /// When writing beyond the end of the file, the file is appropriately
+    /// extended and the intermediate bytes are initialized with the value 0.
+    ///
+    /// Note that similar to [`File::write_vectored`], it is not an error to return a
+    /// short write.
+    ///
+    /// [`File::write`]: ../../../../std/fs/struct.File.html#method.write_vectored
+    fn write_at(&self, bufs: &[IoVec<'_>], offset: u64) -> io::Result<usize>;
+
+    /// Returns the current position within the file.
+    ///
+    /// This corresponds to the `__wasi_fd_tell` syscall and is similar to
+    /// `seek` where you offset 0 bytes from the current position.
+    fn tell(&self) -> io::Result<u64>;
+
+    /// Adjust the flags associated with this file.
+    ///
+    /// This corresponds to the `__wasi_fd_fdstat_set_flags` syscall.
+    fn fdstat_set_flags(&self, flags: u16) -> io::Result<()>;
+
+    /// Adjust the rights associated with this file.
+    ///
+    /// This corresponds to the `__wasi_fd_fdstat_set_rights` syscall.
+    fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()>;
+
+    /// Provide file advisory information on a file descriptor.
+    ///
+    /// This corresponds to the `__wasi_fd_advise` syscall.
+    fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()>;
+
+    /// Force the allocation of space in a file.
+    ///
+    /// This corresponds to the `__wasi_fd_allocate` syscall.
+    fn allocate(&self, offset: u64, len: u64) -> io::Result<()>;
+
+    /// Create a directory.
+    ///
+    /// This corresponds to the `__wasi_path_create_directory` syscall.
+    fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()>;
+
+    /// Read the contents of a symbolic link.
+    ///
+    /// This corresponds to the `__wasi_path_readlink` syscall.
+    fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf>;
+
+    /// Return the attributes of a file or directory.
+    ///
+    /// This corresponds to the `__wasi_path_filestat_get` syscall.
+    fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<Metadata>;
+
+    /// Unlink a file.
+    ///
+    /// This corresponds to the `__wasi_path_unlink_file` syscall.
+    fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
+
+    /// Remove a directory.
+    ///
+    /// This corresponds to the `__wasi_path_remove_directory` syscall.
+    fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
+}
+
+// FIXME: bind __wasi_fd_fdstat_get - need to define a custom return type
+// FIXME: bind __wasi_fd_readdir - can't return `ReadDir` since we only have entry name
+// FIXME: bind __wasi_fd_filestat_set_times maybe? - on crates.io for unix
+// FIXME: bind __wasi_path_filestat_set_times maybe? - on crates.io for unix
+// FIXME: bind __wasi_poll_oneoff maybe? - probably should wait for I/O to settle
+// FIXME: bind __wasi_random_get maybe? - on crates.io for unix
+
+impl FileExt for fs::File {
+    fn read_at(&self, bufs: &mut [IoVecMut<'_>], offset: u64) -> io::Result<usize> {
+        self.as_inner().fd().pread(bufs, offset)
+    }
+
+    fn write_at(&self, bufs: &[IoVec<'_>], offset: u64) -> io::Result<usize> {
+        self.as_inner().fd().pwrite(bufs, offset)
+    }
+
+    fn tell(&self) -> io::Result<u64> {
+        self.as_inner().fd().tell()
+    }
+
+    fn fdstat_set_flags(&self, flags: u16) -> io::Result<()> {
+        self.as_inner().fd().set_flags(flags)
+    }
+
+    fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()> {
+        self.as_inner().fd().set_rights(rights, inheriting)
+    }
+
+    fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()> {
+        self.as_inner().fd().advise(offset, len, advice)
+    }
+
+    fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
+        self.as_inner().fd().allocate(offset, len)
+    }
+
+    fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()> {
+        self.as_inner()
+            .fd()
+            .create_directory(dir.as_ref().as_os_str().as_bytes())
+    }
+
+    fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf> {
+        self.as_inner().read_link(path.as_ref())
+    }
+
+    fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<Metadata> {
+        let m = self.as_inner().metadata_at(lookup_flags, path.as_ref())?;
+        Ok(FromInner::from_inner(m))
+    }
+
+    fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+        self.as_inner()
+            .fd()
+            .unlink_file(path.as_ref().as_os_str().as_bytes())
+    }
+
+    fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+        self.as_inner()
+            .fd()
+            .remove_directory(path.as_ref().as_os_str().as_bytes())
+    }
+}
+
+/// WASI-specific extensions to [`fs::OpenOptions`].
+///
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
+pub trait OpenOptionsExt {
+    /// Pass custom `dirflags` argument to `__wasi_path_open`.
+    ///
+    /// This option configures the `dirflags` argument to the
+    /// `__wasi_path_open` syscall which `OpenOptions` will eventually call. The
+    /// `dirflags` argument configures how the file is looked up, currently
+    /// primarily affecting whether symlinks are followed or not.
+    ///
+    /// By default this value is `__WASI_LOOKUP_SYMLINK_FOLLOW`, or symlinks are
+    /// followed. You can call this method with 0 to disable following symlinks
+    fn lookup_flags(&mut self, flags: u32) -> &mut Self;
+
+    /// Indicates whether `OpenOptions` must open a directory or not.
+    ///
+    /// This method will configure whether the `__WASI_O_DIRECTORY` flag is
+    /// passed when opening a file. When passed it will require that the opened
+    /// path is a directory.
+    ///
+    /// This option is by default `false`
+    fn directory(&mut self, dir: bool) -> &mut Self;
+
+    /// Indicates whether `__WASI_FDFLAG_DSYNC` is passed in the `fs_flags`
+    /// field of `__wasi_path_open`.
+    ///
+    /// This option is by default `false`
+    fn dsync(&mut self, dsync: bool) -> &mut Self;
+
+    /// Indicates whether `__WASI_FDFLAG_NONBLOCK` is passed in the `fs_flags`
+    /// field of `__wasi_path_open`.
+    ///
+    /// This option is by default `false`
+    fn nonblock(&mut self, nonblock: bool) -> &mut Self;
+
+    /// Indicates whether `__WASI_FDFLAG_RSYNC` is passed in the `fs_flags`
+    /// field of `__wasi_path_open`.
+    ///
+    /// This option is by default `false`
+    fn rsync(&mut self, rsync: bool) -> &mut Self;
+
+    /// Indicates whether `__WASI_FDFLAG_SYNC` is passed in the `fs_flags`
+    /// field of `__wasi_path_open`.
+    ///
+    /// This option is by default `false`
+    fn sync(&mut self, sync: bool) -> &mut Self;
+
+    /// Indicates the value that should be passed in for the `fs_rights_base`
+    /// parameter of `__wasi_path_open`.
+    ///
+    /// This option defaults based on the `read` and `write` configuration of
+    /// this `OpenOptions` builder. If this method is called, however, the
+    /// exact mask passed in will be used instead.
+    fn fs_rights_base(&mut self, rights: u64) -> &mut Self;
+
+    /// Indicates the value that should be passed in for the
+    /// `fs_rights_inheriting` parameter of `__wasi_path_open`.
+    ///
+    /// The default for this option is the same value as what will be passed
+    /// for the `fs_rights_base` parameter but if this method is called then
+    /// the specified value will be used instead.
+    fn fs_rights_inheriting(&mut self, rights: u64) -> &mut Self;
+
+    /// Open a file or directory.
+    ///
+    /// This corresponds to the `__wasi_path_open` syscall.
+    fn open_at<P: AsRef<Path>>(&self, file: &File, path: P) -> io::Result<File>;
+}
+
+impl OpenOptionsExt for OpenOptions {
+    fn lookup_flags(&mut self, flags: u32) -> &mut OpenOptions {
+        self.as_inner_mut().lookup_flags(flags);
+        self
+    }
+
+    fn directory(&mut self, dir: bool) -> &mut OpenOptions {
+        self.as_inner_mut().directory(dir);
+        self
+    }
+
+    fn dsync(&mut self, enabled: bool) -> &mut OpenOptions {
+        self.as_inner_mut().dsync(enabled);
+        self
+    }
+
+    fn nonblock(&mut self, enabled: bool) -> &mut OpenOptions {
+        self.as_inner_mut().nonblock(enabled);
+        self
+    }
+
+    fn rsync(&mut self, enabled: bool) -> &mut OpenOptions {
+        self.as_inner_mut().rsync(enabled);
+        self
+    }
+
+    fn sync(&mut self, enabled: bool) -> &mut OpenOptions {
+        self.as_inner_mut().sync(enabled);
+        self
+    }
+
+    fn fs_rights_base(&mut self, rights: u64) -> &mut OpenOptions {
+        self.as_inner_mut().fs_rights_base(rights);
+        self
+    }
+
+    fn fs_rights_inheriting(&mut self, rights: u64) -> &mut OpenOptions {
+        self.as_inner_mut().fs_rights_inheriting(rights);
+        self
+    }
+
+    fn open_at<P: AsRef<Path>>(&self, file: &File, path: P) -> io::Result<File> {
+        let inner = file.as_inner().open_at(path.as_ref(), self.as_inner())?;
+        Ok(File::from_inner(inner))
+    }
+}
+
+/// WASI-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
+pub trait MetadataExt {
+    /// Returns the `st_dev` field of the internal `__wasi_filestat_t`
+    fn dev(&self) -> u64;
+    /// Returns the `st_ino` field of the internal `__wasi_filestat_t`
+    fn ino(&self) -> u64;
+    /// Returns the `st_nlink` field of the internal `__wasi_filestat_t`
+    fn nlink(&self) -> u32;
+    /// Returns the `st_atim` field of the internal `__wasi_filestat_t`
+    fn atim(&self) -> u64;
+    /// Returns the `st_mtim` field of the internal `__wasi_filestat_t`
+    fn mtim(&self) -> u64;
+    /// Returns the `st_ctim` field of the internal `__wasi_filestat_t`
+    fn ctim(&self) -> u64;
+}
+
+impl MetadataExt for fs::Metadata {
+    fn dev(&self) -> u64 {
+        self.as_inner().as_wasi().st_dev
+    }
+    fn ino(&self) -> u64 {
+        self.as_inner().as_wasi().st_ino
+    }
+    fn nlink(&self) -> u32 {
+        self.as_inner().as_wasi().st_nlink
+    }
+    fn atim(&self) -> u64 {
+        self.as_inner().as_wasi().st_atim
+    }
+    fn mtim(&self) -> u64 {
+        self.as_inner().as_wasi().st_mtim
+    }
+    fn ctim(&self) -> u64 {
+        self.as_inner().as_wasi().st_ctim
+    }
+}
+
+/// WASI-specific extensions for [`FileType`].
+///
+/// Adds support for special WASI file types such as block/character devices,
+/// pipes, and sockets.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
+pub trait FileTypeExt {
+    /// Returns `true` if this file type is a block device.
+    fn is_block_device(&self) -> bool;
+    /// Returns `true` if this file type is a character device.
+    fn is_character_device(&self) -> bool;
+    /// Returns `true` if this file type is a socket datagram.
+    fn is_socket_dgram(&self) -> bool;
+    /// Returns `true` if this file type is a socket stream.
+    fn is_socket_stream(&self) -> bool;
+}
+
+impl FileTypeExt for fs::FileType {
+    fn is_block_device(&self) -> bool {
+        self.as_inner().bits() == libc::__WASI_FILETYPE_BLOCK_DEVICE
+    }
+    fn is_character_device(&self) -> bool {
+        self.as_inner().bits() == libc::__WASI_FILETYPE_CHARACTER_DEVICE
+    }
+    fn is_socket_dgram(&self) -> bool {
+        self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_DGRAM
+    }
+    fn is_socket_stream(&self) -> bool {
+        self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_STREAM
+    }
+}
+
+/// WASI-specific extension methods for [`fs::DirEntry`].
+///
+/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
+pub trait DirEntryExt {
+    /// Returns the underlying `d_ino` field of the `__wasi_dirent_t`
+    fn ino(&self) -> u64;
+}
+
+impl DirEntryExt for fs::DirEntry {
+    fn ino(&self) -> u64 {
+        self.as_inner().ino()
+    }
+}
+
+/// Create a hard link.
+///
+/// This corresponds to the `__wasi_path_link` syscall.
+pub fn link<P: AsRef<Path>, U: AsRef<Path>>(
+    old_fd: &File,
+    old_flags: u32,
+    old_path: P,
+    new_fd: &File,
+    new_path: U,
+) -> io::Result<()> {
+    old_fd.as_inner().fd().link(
+        old_flags,
+        old_path.as_ref().as_os_str().as_bytes(),
+        new_fd.as_inner().fd(),
+        new_path.as_ref().as_os_str().as_bytes(),
+    )
+}
+
+/// Rename a file or directory.
+///
+/// This corresponds to the `__wasi_path_rename` syscall.
+pub fn rename<P: AsRef<Path>, U: AsRef<Path>>(
+    old_fd: &File,
+    old_path: P,
+    new_fd: &File,
+    new_path: U,
+) -> io::Result<()> {
+    old_fd.as_inner().fd().rename(
+        old_path.as_ref().as_os_str().as_bytes(),
+        new_fd.as_inner().fd(),
+        new_path.as_ref().as_os_str().as_bytes(),
+    )
+}
+
+/// Create a symbolic link.
+///
+/// This corresponds to the `__wasi_path_symlink` syscall.
+pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>(
+    old_path: P,
+    fd: &File,
+    new_path: U,
+) -> io::Result<()> {
+    fd.as_inner().fd().symlink(
+        old_path.as_ref().as_os_str().as_bytes(),
+        new_path.as_ref().as_os_str().as_bytes(),
+    )
+}
diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs
new file mode 100644
index 00000000000..12afd1d42dc
--- /dev/null
+++ b/src/libstd/sys/wasi/ext/io.rs
@@ -0,0 +1,142 @@
+//! WASI-specific extensions to general I/O primitives
+
+#![unstable(feature = "wasi_ext", issue = "0")]
+
+use crate::fs;
+use crate::io;
+use crate::sys;
+use crate::net;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+
+/// Raw file descriptors.
+pub type RawFd = u32;
+
+/// A trait to extract the raw WASI file descriptor from an underlying
+/// object.
+pub trait AsRawFd {
+    /// Extracts the raw file descriptor.
+    ///
+    /// This method does **not** pass ownership of the raw file descriptor
+    /// to the caller. The descriptor is only guaranteed to be valid while
+    /// the original object has not yet been destroyed.
+    fn as_raw_fd(&self) -> RawFd;
+}
+
+/// A trait to express the ability to construct an object from a raw file
+/// descriptor.
+pub trait FromRawFd {
+    /// Constructs a new instance of `Self` from the given raw file
+    /// descriptor.
+    ///
+    /// This function **consumes ownership** of the specified file
+    /// descriptor. The returned object will take responsibility for closing
+    /// it when the object goes out of scope.
+    ///
+    /// This function is also unsafe as the primitives currently returned
+    /// have the contract that they are the sole owner of the file
+    /// descriptor they are wrapping. Usage of this function could
+    /// accidentally allow violating this contract which can cause memory
+    /// unsafety in code that relies on it being true.
+    unsafe fn from_raw_fd(fd: RawFd) -> Self;
+}
+
+/// A trait to express the ability to consume an object and acquire ownership of
+/// its raw file descriptor.
+pub trait IntoRawFd {
+    /// Consumes this object, returning the raw underlying file descriptor.
+    ///
+    /// This function **transfers ownership** of the underlying file descriptor
+    /// to the caller. Callers are then the unique owners of the file descriptor
+    /// and must close the descriptor once it's no longer needed.
+    fn into_raw_fd(self) -> RawFd;
+}
+
+impl AsRawFd for net::TcpStream {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().as_raw()
+    }
+}
+
+impl FromRawFd for net::TcpStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+        net::TcpStream::from_inner(sys::net::TcpStream::from_inner(fd))
+    }
+}
+
+impl IntoRawFd for net::TcpStream {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+impl AsRawFd for net::TcpListener {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().as_raw()
+    }
+}
+
+impl FromRawFd for net::TcpListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+        net::TcpListener::from_inner(sys::net::TcpListener::from_inner(fd))
+    }
+}
+
+impl IntoRawFd for net::TcpListener {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+impl AsRawFd for net::UdpSocket {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().as_raw()
+    }
+}
+
+impl FromRawFd for net::UdpSocket {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
+        net::UdpSocket::from_inner(sys::net::UdpSocket::from_inner(fd))
+    }
+}
+
+impl IntoRawFd for net::UdpSocket {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+impl AsRawFd for fs::File {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().as_raw()
+    }
+}
+
+impl FromRawFd for fs::File {
+    unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
+        fs::File::from_inner(sys::fs::File::from_inner(fd))
+    }
+}
+
+impl IntoRawFd for fs::File {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+impl AsRawFd for io::Stdin {
+    fn as_raw_fd(&self) -> RawFd {
+        libc::STDIN_FILENO as u32
+    }
+}
+
+impl AsRawFd for io::Stdout {
+    fn as_raw_fd(&self) -> RawFd {
+        libc::STDOUT_FILENO as u32
+    }
+}
+
+impl AsRawFd for io::Stderr {
+    fn as_raw_fd(&self) -> RawFd {
+        libc::STDERR_FILENO as u32
+    }
+}
diff --git a/src/libstd/sys/wasi/ext/mod.rs b/src/libstd/sys/wasi/ext/mod.rs
index 877b9ed89d8..1c24b244b8c 100644
--- a/src/libstd/sys/wasi/ext/mod.rs
+++ b/src/libstd/sys/wasi/ext/mod.rs
@@ -1,4 +1,6 @@
 pub mod ffi;
+pub mod fs;
+pub mod io;
 
 /// A prelude for conveniently writing platform-specific code.
 ///
@@ -7,4 +9,10 @@ pub mod ffi;
 pub mod prelude {
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use crate::sys::ext::ffi::{OsStringExt, OsStrExt};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use crate::sys::ext::fs::{FileExt, DirEntryExt, MetadataExt, OpenOptionsExt};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use crate::sys::ext::fs::FileTypeExt;
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use crate::sys::ext::io::{AsRawFd, IntoRawFd, FromRawFd};
 }
diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs
index 29e1880b8f1..0b68b6f4d9c 100644
--- a/src/libstd/sys/wasi/fd.rs
+++ b/src/libstd/sys/wasi/fd.rs
@@ -6,6 +6,7 @@ use crate::net::Shutdown;
 use crate::sys::cvt_wasi;
 use libc::{self, c_char, c_void};
 
+#[derive(Debug)]
 pub struct WasiFd {
     fd: libc::__wasi_fd_t,
 }
@@ -52,6 +53,16 @@ impl WasiFd {
         WasiFd { fd }
     }
 
+    pub fn into_raw(self) -> libc::__wasi_fd_t {
+        let ret = self.fd;
+        mem::forget(self);
+        ret
+    }
+
+    pub fn as_raw(&self) -> libc::__wasi_fd_t {
+        self.fd
+    }
+
     pub fn datasync(&self) -> io::Result<()> {
         cvt_wasi(unsafe { libc::__wasi_fd_datasync(self.fd) })
     }
@@ -123,7 +134,7 @@ impl WasiFd {
         cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) })
     }
 
-    pub fn crate_directory(&self, path: &[u8]) -> io::Result<()> {
+    pub fn create_directory(&self, path: &[u8]) -> io::Result<()> {
         cvt_wasi(unsafe {
             libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len())
         })
@@ -217,7 +228,9 @@ impl WasiFd {
         })
     }
 
-    // FIXME: __wasi_fd_filestat_get
+    pub fn filestat_get(&self, buf: *mut libc::__wasi_filestat_t) -> io::Result<()> {
+        cvt_wasi(unsafe { libc::__wasi_fd_filestat_get(self.fd, buf) })
+    }
 
     pub fn filestat_set_times(
         &self,
@@ -232,7 +245,22 @@ impl WasiFd {
         cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) })
     }
 
-    // FIXME: __wasi_path_filestat_get
+    pub fn path_filestat_get(
+        &self,
+        flags: LookupFlags,
+        path: &[u8],
+        buf: *mut libc::__wasi_filestat_t,
+    ) -> io::Result<()> {
+        cvt_wasi(unsafe {
+            libc::__wasi_path_filestat_get(
+                self.fd,
+                flags,
+                path.as_ptr() as *const c_char,
+                path.len(),
+                buf,
+            )
+        })
+    }
 
     pub fn path_filestat_set_times(
         &self,
diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs
index 68c8e9356a8..589593299d6 100644
--- a/src/libstd/sys/wasi/fs.rs
+++ b/src/libstd/sys/wasi/fs.rs
@@ -1,138 +1,142 @@
-use crate::ffi::OsString;
+use crate::ffi::{CStr, CString, OsStr, OsString};
 use crate::fmt;
-use crate::hash::{Hash, Hasher};
-use crate::io::{self, SeekFrom};
+use crate::io::{self, IoVec, IoVecMut, SeekFrom};
+use crate::iter;
+use crate::mem::{self, ManuallyDrop};
+use crate::os::wasi::ffi::{OsStrExt, OsStringExt};
 use crate::path::{Path, PathBuf};
+use crate::ptr;
+use crate::sync::Arc;
+use crate::sys::fd::{DirCookie, WasiFd};
 use crate::sys::time::SystemTime;
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
+use crate::sys_common::FromInner;
 
-pub struct File(Void);
+pub use crate::sys_common::fs::copy;
+pub use crate::sys_common::fs::remove_dir_all;
 
-pub struct FileAttr(Void);
+pub struct File {
+    fd: WasiFd,
+}
+
+#[derive(Clone)]
+pub struct FileAttr {
+    meta: libc::__wasi_filestat_t,
+}
 
-pub struct ReadDir(Void);
+pub struct ReadDir {
+    inner: Arc<ReadDirInner>,
+    cookie: Option<DirCookie>,
+    buf: Vec<u8>,
+    offset: usize,
+    cap: usize,
+}
 
-pub struct DirEntry(Void);
+struct ReadDirInner {
+    root: PathBuf,
+    dir: File,
+}
+
+pub struct DirEntry {
+    meta: libc::__wasi_dirent_t,
+    name: Vec<u8>,
+    inner: Arc<ReadDirInner>,
+}
 
-#[derive(Clone, Debug)]
-pub struct OpenOptions { }
+#[derive(Clone, Debug, Default)]
+pub struct OpenOptions {
+    read: bool,
+    write: bool,
+    dirflags: libc::__wasi_lookupflags_t,
+    fdflags: libc::__wasi_fdflags_t,
+    oflags: libc::__wasi_oflags_t,
+    rights_base: Option<libc::__wasi_rights_t>,
+    rights_inheriting: Option<libc::__wasi_rights_t>,
+}
 
-pub struct FilePermissions(Void);
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FilePermissions {
+    readonly: bool,
+}
 
-pub struct FileType(Void);
+#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
+pub struct FileType {
+    bits: libc::__wasi_filetype_t,
+}
 
 #[derive(Debug)]
-pub struct DirBuilder { }
+pub struct DirBuilder {}
 
 impl FileAttr {
+    fn zero() -> FileAttr {
+        FileAttr {
+            meta: unsafe { mem::zeroed() },
+        }
+    }
+
     pub fn size(&self) -> u64 {
-        match self.0 {}
+        self.meta.st_size
     }
 
     pub fn perm(&self) -> FilePermissions {
-        match self.0 {}
+        // not currently implemented in wasi yet
+        FilePermissions { readonly: false }
     }
 
     pub fn file_type(&self) -> FileType {
-        match self.0 {}
+        FileType {
+            bits: self.meta.st_filetype,
+        }
     }
 
     pub fn modified(&self) -> io::Result<SystemTime> {
-        match self.0 {}
+        Ok(SystemTime::from_wasi_timestamp(self.meta.st_mtim))
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        match self.0 {}
+        Ok(SystemTime::from_wasi_timestamp(self.meta.st_atim))
     }
 
     pub fn created(&self) -> io::Result<SystemTime> {
-        match self.0 {}
+        Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim))
     }
-}
 
-impl Clone for FileAttr {
-    fn clone(&self) -> FileAttr {
-        match self.0 {}
+    pub fn as_wasi(&self) -> &libc::__wasi_filestat_t {
+        &self.meta
     }
 }
 
 impl FilePermissions {
     pub fn readonly(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn set_readonly(&mut self, _readonly: bool) {
-        match self.0 {}
-    }
-}
-
-impl Clone for FilePermissions {
-    fn clone(&self) -> FilePermissions {
-        match self.0 {}
-    }
-}
-
-impl PartialEq for FilePermissions {
-    fn eq(&self, _other: &FilePermissions) -> bool {
-        match self.0 {}
+        self.readonly
     }
-}
-
-impl Eq for FilePermissions {
-}
 
-impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+    pub fn set_readonly(&mut self, readonly: bool) {
+        self.readonly = readonly;
     }
 }
 
 impl FileType {
     pub fn is_dir(&self) -> bool {
-        match self.0 {}
+        self.bits == libc::__WASI_FILETYPE_DIRECTORY
     }
 
     pub fn is_file(&self) -> bool {
-        match self.0 {}
+        self.bits == libc::__WASI_FILETYPE_REGULAR_FILE
     }
 
     pub fn is_symlink(&self) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Clone for FileType {
-    fn clone(&self) -> FileType {
-        match self.0 {}
-    }
-}
-
-impl Copy for FileType {}
-
-impl PartialEq for FileType {
-    fn eq(&self, _other: &FileType) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for FileType {
-}
-
-impl Hash for FileType {
-    fn hash<H: Hasher>(&self, _h: &mut H) {
-        match self.0 {}
+        self.bits == libc::__WASI_FILETYPE_SYMBOLIC_LINK
     }
-}
 
-impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+    pub fn bits(&self) -> libc::__wasi_filetype_t {
+        self.bits
     }
 }
 
 impl fmt::Debug for ReadDir {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("ReadDir").finish()
     }
 }
 
@@ -140,155 +144,548 @@ impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        match self.0 {}
+        loop {
+            // If we've reached the capacity of our buffer then we need to read
+            // some more from the OS, otherwise we pick up at our old offset.
+            let offset = if self.offset == self.cap {
+                let cookie = self.cookie.take()?;
+                match self.inner.dir.fd.readdir(&mut self.buf, cookie) {
+                    Ok(bytes) => self.cap = bytes,
+                    Err(e) => return Some(Err(e)),
+                }
+                self.offset = 0;
+                self.cookie = Some(cookie);
+
+                // If we didn't actually read anything, this is in theory the
+                // end of the directory.
+                if self.cap == 0 {
+                    self.cookie = None;
+                    return None;
+                }
+
+                0
+            } else {
+                self.offset
+            };
+            let data = &self.buf[offset..self.cap];
+
+            // If we're not able to read a directory entry then that means it
+            // must have been truncated at the end of the buffer, so reset our
+            // offset so we can go back and reread into the buffer, picking up
+            // where we last left off.
+            let dirent_size = mem::size_of::<libc::__wasi_dirent_t>();
+            if data.len() < dirent_size {
+                assert!(self.cookie.is_some());
+                assert!(self.buf.len() >= dirent_size);
+                self.offset = self.cap;
+                continue;
+            }
+            let (dirent, data) = data.split_at(dirent_size);
+            let dirent =
+                unsafe { ptr::read_unaligned(dirent.as_ptr() as *const libc::__wasi_dirent_t) };
+
+            // If the file name was truncated, then we need to reinvoke
+            // `readdir` so we truncate our buffer to start over and reread this
+            // descriptor. Note that if our offset is 0 that means the file name
+            // is massive and we need a bigger buffer.
+            if data.len() < dirent.d_namlen as usize {
+                if offset == 0 {
+                    let amt_to_add = self.buf.capacity();
+                    self.buf.extend(iter::repeat(0).take(amt_to_add));
+                }
+                assert!(self.cookie.is_some());
+                self.offset = self.cap;
+                continue;
+            }
+            self.cookie = Some(dirent.d_next);
+            self.offset = offset + dirent_size + dirent.d_namlen as usize;
+
+            let name = &data[..(dirent.d_namlen as usize)];
+
+            // These names are skipped on all other platforms, so let's skip
+            // them here too
+            if name == b"." || name == b".." {
+                continue;
+            }
+
+            return Some(Ok(DirEntry {
+                meta: dirent,
+                name: name.to_vec(),
+                inner: self.inner.clone(),
+            }));
+        }
     }
 }
 
 impl DirEntry {
     pub fn path(&self) -> PathBuf {
-        match self.0 {}
+        let name = OsStr::from_bytes(&self.name);
+        self.inner.root.join(name)
     }
 
     pub fn file_name(&self) -> OsString {
-        match self.0 {}
+        OsString::from_vec(self.name.clone())
     }
 
     pub fn metadata(&self) -> io::Result<FileAttr> {
-        match self.0 {}
+        metadata_at(
+            &self.inner.dir.fd,
+            0,
+            OsStr::from_bytes(&self.name).as_ref(),
+        )
     }
 
     pub fn file_type(&self) -> io::Result<FileType> {
-        match self.0 {}
+        Ok(FileType {
+            bits: self.meta.d_type,
+        })
+    }
+
+    pub fn ino(&self) -> libc::__wasi_inode_t {
+        self.meta.d_ino
     }
 }
 
 impl OpenOptions {
     pub fn new() -> OpenOptions {
-        OpenOptions { }
+        let mut base = OpenOptions::default();
+        base.dirflags = libc::__WASI_LOOKUP_SYMLINK_FOLLOW;
+        return base;
+    }
+
+    pub fn read(&mut self, read: bool) {
+        self.read = read;
+    }
+
+    pub fn write(&mut self, write: bool) {
+        self.write = write;
+    }
+
+    pub fn truncate(&mut self, truncate: bool) {
+        self.oflag(libc::__WASI_O_TRUNC, truncate);
+    }
+
+    pub fn create(&mut self, create: bool) {
+        self.oflag(libc::__WASI_O_CREAT, create);
+    }
+
+    pub fn create_new(&mut self, create_new: bool) {
+        self.oflag(libc::__WASI_O_EXCL, create_new);
+        self.oflag(libc::__WASI_O_CREAT, create_new);
+    }
+
+    pub fn directory(&mut self, directory: bool) {
+        self.oflag(libc::__WASI_O_DIRECTORY, directory);
+    }
+
+    fn oflag(&mut self, bit: libc::__wasi_oflags_t, set: bool) {
+        if set {
+            self.oflags |= bit;
+        } else {
+            self.oflags &= !bit;
+        }
+    }
+
+    pub fn append(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_APPEND, set);
+    }
+
+    pub fn dsync(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_DSYNC, set);
+    }
+
+    pub fn nonblock(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_NONBLOCK, set);
+    }
+
+    pub fn rsync(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_RSYNC, set);
+    }
+
+    pub fn sync(&mut self, set: bool) {
+        self.fdflag(libc::__WASI_FDFLAG_SYNC, set);
+    }
+
+    fn fdflag(&mut self, bit: libc::__wasi_fdflags_t, set: bool) {
+        if set {
+            self.fdflags |= bit;
+        } else {
+            self.fdflags &= !bit;
+        }
+    }
+
+    pub fn fs_rights_base(&mut self, rights: libc::__wasi_rights_t) {
+        self.rights_base = Some(rights);
+    }
+
+    pub fn fs_rights_inheriting(&mut self, rights: libc::__wasi_rights_t) {
+        self.rights_inheriting = Some(rights);
+    }
+
+    fn rights_base(&self) -> libc::__wasi_rights_t {
+        if let Some(rights) = self.rights_base {
+            return rights;
+        }
+
+        // If rights haven't otherwise been specified try to pick a reasonable
+        // set. This can always be overridden by users via extension traits, and
+        // implementations may give us fewer rights silently than we ask for. So
+        // given that, just look at `read` and `write` and bucket permissions
+        // based on that.
+        let mut base = 0;
+        if self.read {
+            base |= libc::__WASI_RIGHT_FD_READ;
+            base |= libc::__WASI_RIGHT_FD_READDIR;
+        }
+        if self.write {
+            base |= libc::__WASI_RIGHT_FD_WRITE;
+            base |= libc::__WASI_RIGHT_FD_DATASYNC;
+            base |= libc::__WASI_RIGHT_FD_ALLOCATE;
+            base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_SIZE;
+        }
+
+        // FIXME: some of these should probably be read-only or write-only...
+        base |= libc::__WASI_RIGHT_FD_ADVISE;
+        base |= libc::__WASI_RIGHT_FD_FDSTAT_SET_FLAGS;
+        base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_TIMES;
+        base |= libc::__WASI_RIGHT_FD_SEEK;
+        base |= libc::__WASI_RIGHT_FD_SYNC;
+        base |= libc::__WASI_RIGHT_FD_TELL;
+        base |= libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY;
+        base |= libc::__WASI_RIGHT_PATH_CREATE_FILE;
+        base |= libc::__WASI_RIGHT_PATH_FILESTAT_GET;
+        base |= libc::__WASI_RIGHT_PATH_LINK_SOURCE;
+        base |= libc::__WASI_RIGHT_PATH_LINK_TARGET;
+        base |= libc::__WASI_RIGHT_PATH_OPEN;
+        base |= libc::__WASI_RIGHT_PATH_READLINK;
+        base |= libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY;
+        base |= libc::__WASI_RIGHT_PATH_RENAME_SOURCE;
+        base |= libc::__WASI_RIGHT_PATH_RENAME_TARGET;
+        base |= libc::__WASI_RIGHT_PATH_SYMLINK;
+        base |= libc::__WASI_RIGHT_PATH_UNLINK_FILE;
+        base |= libc::__WASI_RIGHT_POLL_FD_READWRITE;
+
+        return base;
     }
 
-    pub fn read(&mut self, _read: bool) { }
-    pub fn write(&mut self, _write: bool) { }
-    pub fn append(&mut self, _append: bool) { }
-    pub fn truncate(&mut self, _truncate: bool) { }
-    pub fn create(&mut self, _create: bool) { }
-    pub fn create_new(&mut self, _create_new: bool) { }
+    fn rights_inheriting(&self) -> libc::__wasi_rights_t {
+        self.rights_inheriting.unwrap_or_else(|| self.rights_base())
+    }
+
+    pub fn lookup_flags(&mut self, flags: libc::__wasi_lookupflags_t) {
+        self.dirflags = flags;
+    }
 }
 
 impl File {
-    pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
-        unsupported()
+    pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
+        let (dir, file) = open_parent(path, libc::__WASI_RIGHT_PATH_OPEN)?;
+        open_at(&dir, &file, opts)
+    }
+
+    pub fn open_at(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
+        open_at(&self.fd, path, opts)
     }
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
-        match self.0 {}
+        let mut ret = FileAttr::zero();
+        self.fd.filestat_get(&mut ret.meta)?;
+        Ok(ret)
+    }
+
+    pub fn metadata_at(
+        &self,
+        flags: libc::__wasi_lookupflags_t,
+        path: &Path,
+    ) -> io::Result<FileAttr> {
+        metadata_at(&self.fd, flags, path)
     }
 
     pub fn fsync(&self) -> io::Result<()> {
-        match self.0 {}
+        self.fd.sync()
     }
 
     pub fn datasync(&self) -> io::Result<()> {
-        match self.0 {}
+        self.fd.datasync()
+    }
+
+    pub fn truncate(&self, size: u64) -> io::Result<()> {
+        self.fd.filestat_set_size(size)
     }
 
-    pub fn truncate(&self, _size: u64) -> io::Result<()> {
-        match self.0 {}
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.read_vectored(&mut [IoVecMut::new(buf)])
     }
 
-    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.fd.read(bufs)
     }
 
-    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        self.write_vectored(&[IoVec::new(buf)])
+    }
+
+    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.fd.write(bufs)
     }
 
     pub fn flush(&self) -> io::Result<()> {
-        match self.0 {}
+        Ok(())
     }
 
-    pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
-        match self.0 {}
+    pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
+        self.fd.seek(pos)
     }
 
     pub fn duplicate(&self) -> io::Result<File> {
-        match self.0 {}
+        // https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-rationale.md#why-no-dup
+        unsupported()
     }
 
     pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
-        match self.0 {}
+        // Permissions haven't been fully figured out in wasi yet, so this is
+        // likely temporary
+        unsupported()
     }
 
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
+    pub fn fd(&self) -> &WasiFd {
+        &self.fd
     }
-}
 
-impl DirBuilder {
-    pub fn new() -> DirBuilder {
-        DirBuilder { }
+    pub fn into_fd(self) -> WasiFd {
+        self.fd
     }
 
-    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
-        unsupported()
+    pub fn read_link(&self, file: &Path) -> io::Result<PathBuf> {
+        read_link(&self.fd, file)
     }
 }
 
-impl fmt::Debug for File {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+impl FromInner<u32> for File {
+    fn from_inner(fd: u32) -> File {
+        unsafe {
+            File {
+                fd: WasiFd::from_raw(fd),
+            }
+        }
     }
 }
 
-pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
-    unsupported()
-}
+impl DirBuilder {
+    pub fn new() -> DirBuilder {
+        DirBuilder {}
+    }
 
-pub fn unlink(_p: &Path) -> io::Result<()> {
-    unsupported()
+    pub fn mkdir(&self, p: &Path) -> io::Result<()> {
+        let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY)?;
+        dir.create_directory(file.as_os_str().as_bytes())
+    }
 }
 
-pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
+impl fmt::Debug for File {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("File")
+            .field("fd", &self.fd.as_raw())
+            .finish()
+    }
+}
+
+pub fn readdir(p: &Path) -> io::Result<ReadDir> {
+    let mut opts = OpenOptions::new();
+    opts.directory(true);
+    opts.read(true);
+    let dir = File::open(p, &opts)?;
+    Ok(ReadDir {
+        cookie: Some(0),
+        buf: vec![0; 128],
+        offset: 0,
+        cap: 0,
+        inner: Arc::new(ReadDirInner {
+            dir,
+            root: p.to_path_buf(),
+        }),
+    })
+}
+
+pub fn unlink(p: &Path) -> io::Result<()> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_UNLINK_FILE)?;
+    dir.unlink_file(file.as_os_str().as_bytes())
+}
+
+pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
+    let (old, old_file) = open_parent(old, libc::__WASI_RIGHT_PATH_RENAME_SOURCE)?;
+    let (new, new_file) = open_parent(new, libc::__WASI_RIGHT_PATH_RENAME_TARGET)?;
+    old.rename(
+        old_file.as_os_str().as_bytes(),
+        &new,
+        new_file.as_os_str().as_bytes(),
+    )
+}
+
+pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
+    // Permissions haven't been fully figured out in wasi yet, so this is
+    // likely temporary
     unsupported()
 }
 
-pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
-    match perm.0 {}
+pub fn rmdir(p: &Path) -> io::Result<()> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY)?;
+    dir.remove_directory(file.as_os_str().as_bytes())
 }
 
-pub fn rmdir(_p: &Path) -> io::Result<()> {
-    unsupported()
+pub fn readlink(p: &Path) -> io::Result<PathBuf> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_READLINK)?;
+    read_link(&dir, &file)
 }
 
-pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
-    unsupported()
+fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> {
+    // Try to get a best effort initial capacity for the vector we're going to
+    // fill. Note that if it's not a symlink we don't use a file to avoid
+    // allocating gigabytes if you read_link a huge movie file by accident.
+    // Additionally we add 1 to the initial size so if it doesn't change until
+    // when we call `readlink` the returned length will be less than the
+    // capacity, guaranteeing that we got all the data.
+    let meta = metadata_at(fd, 0, file)?;
+    let initial_size = if meta.file_type().is_symlink() {
+        (meta.size() as usize).saturating_add(1)
+    } else {
+        1 // this'll fail in just a moment
+    };
+
+    // Now that we have an initial guess of how big to make our buffer, call
+    // `readlink` in a loop until it fails or reports it filled fewer bytes than
+    // we asked for, indicating we got everything.
+    let file = file.as_os_str().as_bytes();
+    let mut destination = vec![0u8; initial_size];
+    loop {
+        let len = fd.readlink(file, &mut destination)?;
+        if len < destination.len() {
+            destination.truncate(len);
+            destination.shrink_to_fit();
+            return Ok(PathBuf::from(OsString::from_vec(destination)));
+        }
+        let amt_to_add = destination.len();
+        destination.extend(iter::repeat(0).take(amt_to_add));
+    }
 }
 
-pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
-    unsupported()
+pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
+    let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_SYMLINK)?;
+    dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes())
 }
 
-pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
-    unsupported()
+pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
+    let (src, src_file) = open_parent(src, libc::__WASI_RIGHT_PATH_LINK_SOURCE)?;
+    let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_LINK_TARGET)?;
+    src.link(
+        libc::__WASI_LOOKUP_SYMLINK_FOLLOW,
+        src_file.as_os_str().as_bytes(),
+        &dst,
+        dst_file.as_os_str().as_bytes(),
+    )
 }
 
-pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
-    unsupported()
+pub fn stat(p: &Path) -> io::Result<FileAttr> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
+    metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, &file)
 }
 
-pub fn stat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
+pub fn lstat(p: &Path) -> io::Result<FileAttr> {
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
+    metadata_at(&dir, 0, &file)
 }
 
-pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
+fn metadata_at(
+    fd: &WasiFd,
+    flags: libc::__wasi_lookupflags_t,
+    path: &Path,
+) -> io::Result<FileAttr> {
+    let mut ret = FileAttr::zero();
+    fd.path_filestat_get(flags, path.as_os_str().as_bytes(), &mut ret.meta)?;
+    Ok(ret)
 }
 
 pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
+    // This seems to not be in wasi's API yet, and we may need to end up
+    // emulating it ourselves. For now just return an error.
     unsupported()
 }
 
-pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
-    unsupported()
+fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
+    let fd = fd.open(
+        opts.dirflags,
+        path.as_os_str().as_bytes(),
+        opts.oflags,
+        opts.rights_base(),
+        opts.rights_inheriting(),
+        opts.fdflags,
+    )?;
+    Ok(File { fd })
+}
+
+/// Attempts to open a bare path `p`.
+///
+/// WASI has no fundamental capability to do this. All syscalls and operations
+/// are relative to already-open file descriptors. The C library, however,
+/// manages a map of preopened file descriptors to their path, and then the C
+/// library provides an API to look at this. In other words, when you want to
+/// open a path `p`, you have to find a previously opened file descriptor in a
+/// global table and then see if `p` is relative to that file descriptor.
+///
+/// This function, if successful, will return two items:
+///
+/// * The first is a `ManuallyDrop<WasiFd>`. This represents a preopened file
+///   descriptor which we don't have ownership of, but we can use. You shouldn't
+///   actually drop the `fd`.
+///
+/// * The second is a path that should be a part of `p` and represents a
+///   relative traversal from the file descriptor specified to the desired
+///   location `p`.
+///
+/// If successful you can use the returned file descriptor to perform
+/// file-descriptor-relative operations on the path returned as well. The
+/// `rights` argument indicates what operations are desired on the returned file
+/// descriptor, and if successful the returned file descriptor should have the
+/// appropriate rights for performing `rights` actions.
+///
+/// Note that this can fail if `p` doesn't look like it can be opened relative
+/// to any preopened file descriptor.
+fn open_parent(
+    p: &Path,
+    rights: libc::__wasi_rights_t,
+) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
+    let p = CString::new(p.as_os_str().as_bytes())?;
+    unsafe {
+        let mut ret = ptr::null();
+        let fd = __wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret);
+        if fd == -1 {
+            let msg = format!(
+                "failed to find a preopened file descriptor \
+                 through which {:?} could be opened",
+                p
+            );
+            return Err(io::Error::new(io::ErrorKind::Other, msg));
+        }
+        let path = Path::new(OsStr::from_bytes(CStr::from_ptr(ret).to_bytes()));
+
+        // FIXME: right now `path` is a pointer into `p`, the `CString` above.
+        // When we return `p` is deallocated and we can't use it, so we need to
+        // currently separately allocate `path`. If this becomes an issue though
+        // we should probably turn this into a closure-taking interface or take
+        // `&CString` and then pass off `&Path` tied to the same lifetime.
+        let path = path.to_path_buf();
+
+        return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path));
+    }
+
+    // FIXME(rust-lang/libc#1314) use the `libc` crate for this when the API
+    // there is published
+    extern "C" {
+        pub fn __wasilibc_find_relpath(
+            path: *const libc::c_char,
+            rights_base: libc::__wasi_rights_t,
+            rights_inheriting: libc::__wasi_rights_t,
+            relative_path: *mut *const libc::c_char,
+        ) -> libc::c_int;
+    }
 }
diff --git a/src/libstd/sys/wasi/net.rs b/src/libstd/sys/wasi/net.rs
index 1579aa4b572..5486cdec4c0 100644
--- a/src/libstd/sys/wasi/net.rs
+++ b/src/libstd/sys/wasi/net.rs
@@ -4,8 +4,12 @@ use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
 use crate::time::Duration;
 use crate::sys::{unsupported, Void};
 use crate::convert::TryFrom;
+use crate::sys::fd::{WasiFd};
+use crate::sys_common::FromInner;
 
-pub struct TcpStream(Void);
+pub struct TcpStream {
+    fd: WasiFd,
+}
 
 impl TcpStream {
     pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
@@ -17,89 +21,111 @@ impl TcpStream {
     }
 
     pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn write(&self, _: &[u8]) -> io::Result<usize> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result<usize> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn duplicate(&self) -> io::Result<TcpStream> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn nodelay(&self) -> io::Result<bool> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
+    }
+
+    pub fn fd(&self) -> &WasiFd {
+        &self.fd
+    }
+
+    pub fn into_fd(self) -> WasiFd {
+        self.fd
+    }
+}
+
+impl FromInner<u32> for TcpStream {
+    fn from_inner(fd: u32) -> TcpStream {
+        unsafe {
+            TcpStream {
+                fd: WasiFd::from_raw(fd),
+            }
+        }
     }
 }
 
 impl fmt::Debug for TcpStream {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("TcpStream")
+            .field("fd", &self.fd.as_raw())
+            .finish()
     }
 }
 
-pub struct TcpListener(Void);
+pub struct TcpListener {
+    fd: WasiFd
+}
 
 impl TcpListener {
     pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
@@ -107,49 +133,71 @@ impl TcpListener {
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn duplicate(&self) -> io::Result<TcpListener> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn only_v6(&self) -> io::Result<bool> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
+    }
+
+    pub fn fd(&self) -> &WasiFd {
+        &self.fd
+    }
+
+    pub fn into_fd(self) -> WasiFd {
+        self.fd
+    }
+}
+
+impl FromInner<u32> for TcpListener {
+    fn from_inner(fd: u32) -> TcpListener {
+        unsafe {
+            TcpListener {
+                fd: WasiFd::from_raw(fd),
+            }
+        }
     }
 }
 
 impl fmt::Debug for TcpListener {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("TcpListener")
+            .field("fd", &self.fd.as_raw())
+            .finish()
     }
 }
 
-pub struct UdpSocket(Void);
+pub struct UdpSocket {
+    fd: WasiFd,
+}
 
 impl UdpSocket {
     pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
@@ -157,133 +205,153 @@ impl UdpSocket {
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn duplicate(&self) -> io::Result<UdpSocket> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn broadcast(&self) -> io::Result<bool> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn multicast_loop_v6(&self) -> io::Result<bool> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
                          -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32)
                          -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
                           -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32)
                           -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn send(&self, _: &[u8]) -> io::Result<usize> {
-        match self.0 {}
+        unsupported()
     }
 
     pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
-        match self.0 {}
+        unsupported()
+    }
+
+    pub fn fd(&self) -> &WasiFd {
+        &self.fd
+    }
+
+    pub fn into_fd(self) -> WasiFd {
+        self.fd
+    }
+}
+
+impl FromInner<u32> for UdpSocket {
+    fn from_inner(fd: u32) -> UdpSocket {
+        unsafe {
+            UdpSocket {
+                fd: WasiFd::from_raw(fd),
+            }
+        }
     }
 }
 
 impl fmt::Debug for UdpSocket {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("UdpSocket")
+            .field("fd", &self.fd.as_raw())
+            .finish()
     }
 }
 
diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs
index 6d4d6aae61b..822ea02a11b 100644
--- a/src/libstd/sys/wasi/os.rs
+++ b/src/libstd/sys/wasi/os.rs
@@ -27,8 +27,21 @@ pub fn errno() -> i32 {
     unsafe { errno as i32 }
 }
 
-pub fn error_string(_errno: i32) -> String {
-    "operation failed".to_string()
+pub fn error_string(errno: i32) -> String {
+    extern {
+        fn strerror_r(errnum: libc::c_int, buf: *mut libc::c_char,
+                      buflen: libc::size_t) -> libc::c_int;
+    }
+
+    let mut buf = [0 as libc::c_char; 1024];
+
+    let p = buf.as_mut_ptr();
+    unsafe {
+        if strerror_r(errno as libc::c_int, p, buf.len()) < 0 {
+            panic!("strerror_r failure");
+        }
+        str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
+    }
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
diff --git a/src/libstd/sys/wasi/pipe.rs b/src/libstd/sys/wasi/pipe.rs
index 2582b993b60..aa6bf8076f6 100644
--- a/src/libstd/sys/wasi/pipe.rs
+++ b/src/libstd/sys/wasi/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoVec, IoVecMut};
 use crate::sys::Void;
 
 pub struct AnonPipe(Void);
@@ -8,10 +8,18 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/wasi/process.rs b/src/libstd/sys/wasi/process.rs
index a02e009d953..788b829f4ba 100644
--- a/src/libstd/sys/wasi/process.rs
+++ b/src/libstd/sys/wasi/process.rs
@@ -67,8 +67,8 @@ impl From<AnonPipe> for Stdio {
 }
 
 impl From<File> for Stdio {
-    fn from(file: File) -> Stdio {
-        file.diverge()
+    fn from(_file: File) -> Stdio {
+        panic!("unsupported")
     }
 }
 
diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs
index f6a4958897d..bdad4084891 100644
--- a/src/libstd/sys/wasi/stdio.rs
+++ b/src/libstd/sys/wasi/stdio.rs
@@ -1,6 +1,7 @@
-use crate::io;
+use crate::io::{self, IoVec, IoVecMut};
 use crate::libc;
-use crate::sys::cvt;
+use crate::mem::ManuallyDrop;
+use crate::sys::fd::WasiFd;
 
 pub struct Stdin;
 pub struct Stdout;
@@ -12,10 +13,12 @@ impl Stdin {
     }
 
     pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
-        let amt = cvt(unsafe {
-            libc::read(libc::STDIN_FILENO, data.as_mut_ptr() as *mut _, data.len())
-        })?;
-        Ok(amt as usize)
+        self.read_vectored(&mut [IoVecMut::new(data)])
+    }
+
+    pub fn read_vectored(&self, data: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) })
+            .read(data)
     }
 }
 
@@ -25,10 +28,12 @@ impl Stdout {
     }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
-        let amt = cvt(unsafe {
-            libc::write(libc::STDOUT_FILENO, data.as_ptr() as *const _, data.len())
-        })?;
-        Ok(amt as usize)
+        self.write_vectored(&[IoVec::new(data)])
+    }
+
+    pub fn write_vectored(&self, data: &[IoVec<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDOUT_FILENO as u32) })
+            .write(data)
     }
 
     pub fn flush(&self) -> io::Result<()> {
@@ -42,10 +47,12 @@ impl Stderr {
     }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
-        let amt = cvt(unsafe {
-            libc::write(libc::STDERR_FILENO, data.as_ptr() as *const _, data.len())
-        })?;
-        Ok(amt as usize)
+        self.write_vectored(&[IoVec::new(data)])
+    }
+
+    pub fn write_vectored(&self, data: &[IoVec<'_>]) -> io::Result<usize> {
+        ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDERR_FILENO as u32) })
+            .write(data)
     }
 
     pub fn flush(&self) -> io::Result<()> {
diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs
index 9d3c6ac59d1..5e69e4d948f 100644
--- a/src/libstd/sys/wasi/thread.rs
+++ b/src/libstd/sys/wasi/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::cmp;
 use crate::ffi::CStr;
 use crate::io;
@@ -13,7 +12,7 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(_stack: usize, _p: Box<dyn FnBox()>)
+    pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>)
         -> io::Result<Thread>
     {
         unsupported()
diff --git a/src/libstd/sys/wasi/time.rs b/src/libstd/sys/wasi/time.rs
index e1b92e7c5a7..3f14c80928c 100644
--- a/src/libstd/sys/wasi/time.rs
+++ b/src/libstd/sys/wasi/time.rs
@@ -57,6 +57,10 @@ impl SystemTime {
         SystemTime(current_time(libc::__WASI_CLOCK_REALTIME))
     }
 
+    pub fn from_wasi_timestamp(ts: libc::__wasi_timestamp_t) -> SystemTime {
+        SystemTime(Duration::from_nanos(ts))
+    }
+
     pub fn sub_time(&self, other: &SystemTime)
                     -> Result<Duration, Duration> {
         self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
diff --git a/src/libstd/sys/wasm/fs.rs b/src/libstd/sys/wasm/fs.rs
index 68c8e9356a8..c3c898eb23e 100644
--- a/src/libstd/sys/wasm/fs.rs
+++ b/src/libstd/sys/wasm/fs.rs
@@ -1,7 +1,7 @@
 use crate::ffi::OsString;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
-use crate::io::{self, SeekFrom};
+use crate::io::{self, SeekFrom, IoVec, IoVecMut};
 use crate::path::{Path, PathBuf};
 use crate::sys::time::SystemTime;
 use crate::sys::{unsupported, Void};
@@ -200,10 +200,18 @@ impl File {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/wasm/pipe.rs b/src/libstd/sys/wasm/pipe.rs
index 2582b993b60..aa6bf8076f6 100644
--- a/src/libstd/sys/wasm/pipe.rs
+++ b/src/libstd/sys/wasm/pipe.rs
@@ -1,4 +1,4 @@
-use crate::io;
+use crate::io::{self, IoVec, IoVecMut};
 use crate::sys::Void;
 
 pub struct AnonPipe(Void);
@@ -8,10 +8,18 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn read_vectored(&self, _bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         match self.0 {}
     }
 
+    pub fn write_vectored(&self, _bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs
index a65c413119f..1dc786cd5d7 100644
--- a/src/libstd/sys/wasm/thread.rs
+++ b/src/libstd/sys/wasm/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::ffi::CStr;
 use crate::io;
 use crate::sys::{unsupported, Void};
@@ -10,7 +9,7 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(_stack: usize, _p: Box<dyn FnBox()>)
+    pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>)
         -> io::Result<Thread>
     {
         unsupported()
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 4ebbb0707f7..1d8e47a4793 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -2,7 +2,7 @@ use crate::os::windows::prelude::*;
 
 use crate::ffi::OsString;
 use crate::fmt;
-use crate::io::{self, Error, SeekFrom};
+use crate::io::{self, Error, SeekFrom, IoVec, IoVecMut};
 use crate::mem;
 use crate::path::{Path, PathBuf};
 use crate::ptr;
@@ -314,6 +314,10 @@ impl File {
         self.handle.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.handle.read_vectored(bufs)
+    }
+
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         self.handle.read_at(buf, offset)
     }
@@ -322,6 +326,10 @@ impl File {
         self.handle.write(buf)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.handle.write_vectored(bufs)
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         self.handle.write_at(buf, offset)
     }
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index 02549088c87..c3fa6c4e0bd 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -1,7 +1,7 @@
 #![unstable(issue = "0", feature = "windows_handle")]
 
 use crate::cmp;
-use crate::io::{self, ErrorKind, Read};
+use crate::io::{self, ErrorKind, Read, IoVec, IoVecMut};
 use crate::mem;
 use crate::ops::Deref;
 use crate::ptr;
@@ -89,6 +89,10 @@ impl RawHandle {
         }
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        crate::io::default_read_vectored(|buf| self.read(buf), bufs)
+    }
+
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         let mut read = 0;
         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
@@ -169,6 +173,10 @@ impl RawHandle {
         Ok(amt as usize)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        crate::io::default_write_vectored(|buf| self.write(buf), bufs)
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         let mut written = 0;
         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
@@ -199,4 +207,8 @@ impl<'a> Read for &'a RawHandle {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         (**self).read(buf)
     }
+
+    fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        (**self).read_vectored(bufs)
+    }
 }
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index b38727830f3..6613d3a0567 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -1,7 +1,7 @@
 use crate::os::windows::prelude::*;
 
 use crate::ffi::OsStr;
-use crate::io;
+use crate::io::{self, IoVec, IoVecMut};
 use crate::mem;
 use crate::path::Path;
 use crate::ptr;
@@ -166,9 +166,17 @@ impl AnonPipe {
         self.inner.read(buf)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
+        self.inner.read_vectored(bufs)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(buf)
     }
+
+    pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
+        self.inner.write_vectored(bufs)
+    }
 }
 
 pub fn read2(p1: AnonPipe,
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 1b0a811f13b..ebdf3612e06 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::io;
 use crate::ffi::CStr;
 use crate::mem;
@@ -20,7 +19,7 @@ pub struct Thread {
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(stack: usize, p: Box<dyn FnBox()>)
+    pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>)
                           -> io::Result<Thread> {
         let p = box p;
 
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
index 4c9d2aee157..e0f0e3a1a45 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -173,7 +173,7 @@ fn intervals2dur(intervals: u64) -> Duration {
 
 mod perf_counter {
     use super::{NANOS_PER_SEC};
-    use crate::sync::Once;
+    use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
     use crate::sys_common::mul_div_u64;
     use crate::sys::c;
     use crate::sys::cvt;
@@ -210,13 +210,25 @@ mod perf_counter {
 
     fn frequency() -> c::LARGE_INTEGER {
         static mut FREQUENCY: c::LARGE_INTEGER = 0;
-        static ONCE: Once = Once::new();
+        static STATE: AtomicUsize = AtomicUsize::new(0);
 
         unsafe {
-            ONCE.call_once(|| {
-                cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap();
-            });
-            FREQUENCY
+            // If a previous thread has filled in this global state, use that.
+            if STATE.load(SeqCst) == 2 {
+                return FREQUENCY;
+            }
+
+            // ... otherwise learn for ourselves ...
+            let mut frequency = 0;
+            cvt(c::QueryPerformanceFrequency(&mut frequency)).unwrap();
+
+            // ... and attempt to be the one thread that stores it globally for
+            // all other threads
+            if STATE.compare_exchange(0, 1, SeqCst, SeqCst).is_ok() {
+                FREQUENCY = frequency;
+                STATE.store(2, SeqCst);
+            }
+            return frequency;
         }
     }
 
diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs
index 1181b861611..cdb72ee872e 100644
--- a/src/libstd/sys_common/at_exit_imp.rs
+++ b/src/libstd/sys_common/at_exit_imp.rs
@@ -2,12 +2,11 @@
 //!
 //! Documentation can be found on the `rt::at_exit` function.
 
-use crate::boxed::FnBox;
 use crate::ptr;
 use crate::mem;
 use crate::sys_common::mutex::Mutex;
 
-type Queue = Vec<Box<dyn FnBox()>>;
+type Queue = Vec<Box<dyn FnOnce()>>;
 
 // NB these are specifically not types from `std::sync` as they currently rely
 // on poisoning and this module needs to operate at a lower level than requiring
@@ -61,7 +60,7 @@ pub fn cleanup() {
     }
 }
 
-pub fn push(f: Box<dyn FnBox()>) -> bool {
+pub fn push(f: Box<dyn FnOnce()>) -> bool {
     unsafe {
         let _guard = LOCK.lock();
         if init() {
diff --git a/src/libstd/sys_common/fs.rs b/src/libstd/sys_common/fs.rs
new file mode 100644
index 00000000000..7152fcd215c
--- /dev/null
+++ b/src/libstd/sys_common/fs.rs
@@ -0,0 +1,41 @@
+#![allow(dead_code)] // not used on all platforms
+
+use crate::path::Path;
+use crate::fs;
+use crate::io::{self, Error, ErrorKind};
+
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    if !from.is_file() {
+        return Err(Error::new(ErrorKind::InvalidInput,
+                              "the source path is not an existing regular file"))
+    }
+
+    let mut reader = fs::File::open(from)?;
+    let mut writer = fs::File::create(to)?;
+    let perm = reader.metadata()?.permissions();
+
+    let ret = io::copy(&mut reader, &mut writer)?;
+    fs::set_permissions(to, perm)?;
+    Ok(ret)
+}
+
+pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+    let filetype = fs::symlink_metadata(path)?.file_type();
+    if filetype.is_symlink() {
+        fs::remove_file(path)
+    } else {
+        remove_dir_all_recursive(path)
+    }
+}
+
+fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
+    for child in fs::read_dir(path)? {
+        let child = child?;
+        if child.file_type()?.is_dir() {
+            remove_dir_all_recursive(&child.path())?;
+        } else {
+            fs::remove_file(&child.path())?;
+        }
+    }
+    fs::remove_dir(path)
+}
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 883ab34f07c..6260c3b77ff 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -28,6 +28,15 @@ macro_rules! rtassert {
     })
 }
 
+#[allow(unused_macros)] // not used on all platforms
+macro_rules! rtunwrap {
+    ($ok:ident, $e:expr) => (if let $ok(v) = $e {
+        v
+    } else {
+        rtabort!(concat!("unwrap failed: ", stringify!($e)));
+    })
+}
+
 pub mod alloc;
 pub mod at_exit_imp;
 #[cfg(feature = "backtrace")]
@@ -52,6 +61,7 @@ pub mod util;
 pub mod wtf8;
 pub mod bytestring;
 pub mod process;
+pub mod fs;
 
 cfg_if! {
     if #[cfg(any(target_os = "cloudabi",
diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs
index 7cc93477a73..a4961974d89 100644
--- a/src/libstd/sys_common/os_str_bytes.rs
+++ b/src/libstd/sys_common/os_str_bytes.rs
@@ -236,9 +236,11 @@ pub trait OsStrExt {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl OsStrExt for OsStr {
+    #[inline]
     fn from_bytes(slice: &[u8]) -> &OsStr {
         unsafe { mem::transmute(slice) }
     }
+    #[inline]
     fn as_bytes(&self) -> &[u8] {
         &self.as_inner().inner
     }
diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs
index b2142e75308..6ab0d5cbe9c 100644
--- a/src/libstd/sys_common/thread.rs
+++ b/src/libstd/sys_common/thread.rs
@@ -1,4 +1,3 @@
-use crate::boxed::FnBox;
 use crate::env;
 use crate::sync::atomic::{self, Ordering};
 use crate::sys::stack_overflow;
@@ -11,7 +10,7 @@ pub unsafe fn start_thread(main: *mut u8) {
     let _handler = stack_overflow::Handler::new();
 
     // Finally, let's run some code.
-    Box::from_raw(main as *mut Box<dyn FnBox()>)()
+    Box::from_raw(main as *mut Box<dyn FnOnce()>)()
 }
 
 pub fn min_stack() -> usize {
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index 7fe1818291e..f17020de44e 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -388,9 +388,7 @@ impl Extend<CodePoint> for Wtf8Buf {
         let (low, _high) = iterator.size_hint();
         // Lower bound of one byte per code point (ASCII only)
         self.bytes.reserve(low);
-        for code_point in iterator {
-            self.push(code_point);
-        }
+        iterator.for_each(move |code_point| self.push(code_point));
     }
 }
 
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index cb507971091..c59226e0c0b 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -157,7 +157,6 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::any::Any;
-use crate::boxed::FnBox;
 use crate::cell::UnsafeCell;
 use crate::ffi::{CStr, CString};
 use crate::fmt;
@@ -488,7 +487,9 @@ impl Builder {
             // returning.
             native: Some(imp::Thread::new(
                 stack_size,
-                mem::transmute::<Box<dyn FnBox() + 'a>, Box<dyn FnBox() + 'static>>(Box::new(main))
+                mem::transmute::<Box<dyn FnOnce() + 'a>, Box<dyn FnOnce() + 'static>>(Box::new(
+                    main,
+                )),
             )?),
             thread: my_thread,
             packet: Packet(my_packet),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index bcc8fdf8cd4..cf909e30e32 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -946,7 +946,7 @@ pub struct Expr {
 
 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::<Expr>() == 88);
+static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::<Expr>() == 96);
 
 impl Expr {
     /// Whether this expression would be valid somewhere that expects a value; for example, an `if`
diff --git a/src/libsyntax/diagnostics/metadata.rs b/src/libsyntax/diagnostics/metadata.rs
index 704135fe1d5..53f37bb10bd 100644
--- a/src/libsyntax/diagnostics/metadata.rs
+++ b/src/libsyntax/diagnostics/metadata.rs
@@ -36,9 +36,9 @@ pub struct ErrorLocation {
 impl ErrorLocation {
     /// Creates an error location from a span.
     pub fn from_span(ecx: &ExtCtxt<'_>, sp: Span) -> ErrorLocation {
-        let loc = ecx.source_map().lookup_char_pos_adj(sp.lo());
+        let loc = ecx.source_map().lookup_char_pos(sp.lo());
         ErrorLocation {
-            filename: loc.filename,
+            filename: loc.file.name.clone(),
             line: loc.line
         }
     }
diff --git a/src/libsyntax/early_buffered_lints.rs b/src/libsyntax/early_buffered_lints.rs
index 29cb9cd7f30..977e6d45877 100644
--- a/src/libsyntax/early_buffered_lints.rs
+++ b/src/libsyntax/early_buffered_lints.rs
@@ -12,8 +12,6 @@ pub enum BufferedEarlyLintId {
     /// Usage of `?` as a macro separator is deprecated.
     QuestionMarkMacroSep,
     IllFormedAttributeInput,
-    /// Usage of a duplicate macro matcher binding name.
-    DuplicateMacroMatcherBindingName,
 }
 
 /// Stores buffered lint info which can later be passed to `librustc`.
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 12912044e4e..b1b9d25b3d5 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -497,22 +497,14 @@ fn check_lhs_duplicate_matcher_bindings(
     node_id: ast::NodeId,
 ) -> bool {
     use self::quoted::TokenTree;
-    use crate::early_buffered_lints::BufferedEarlyLintId;
     for tt in tts {
         match *tt {
             TokenTree::MetaVarDecl(span, name, _kind) => {
                 if let Some(&prev_span) = metavar_names.get(&name) {
-                    // FIXME(mark-i-m): in a few cycles, make this a hard error.
-                    // sess.span_diagnostic
-                    //     .struct_span_err(span, "duplicate matcher binding")
-                    //     .span_note(prev_span, "previous declaration was here")
-                    //     .emit();
-                    sess.buffer_lint(
-                        BufferedEarlyLintId::DuplicateMacroMatcherBindingName,
-                        crate::source_map::MultiSpan::from(vec![prev_span, span]),
-                        node_id,
-                        "duplicate matcher binding"
-                    );
+                    sess.span_diagnostic
+                        .struct_span_err(span, "duplicate matcher binding")
+                        .span_note(prev_span, "previous declaration was here")
+                        .emit();
                     return false;
                 } else {
                     metavar_names.insert(name, span);
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index dcb55fb572f..f77593ed02a 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -903,7 +903,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
     ("thread_local", Whitelisted, template!(Word), Gated(Stability::Unstable,
                                         "thread_local",
                                         "`#[thread_local]` is an experimental feature, and does \
-                                         not currently handle destructors.",
+                                         not currently handle destructors",
                                         cfg_fn!(thread_local))),
 
     ("rustc_on_unimplemented", Whitelisted, template!(List:
@@ -1438,18 +1438,34 @@ pub enum GateStrength {
     Soft,
 }
 
-pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
-                        explain: &str) {
+pub fn emit_feature_err(
+    sess: &ParseSess,
+    feature: &str,
+    span: Span,
+    issue: GateIssue,
+    explain: &str,
+) {
     feature_err(sess, feature, span, issue, explain).emit();
 }
 
-pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
-                       explain: &str) -> DiagnosticBuilder<'a> {
+pub fn feature_err<'a>(
+    sess: &'a ParseSess,
+    feature: &str,
+    span: Span,
+    issue: GateIssue,
+    explain: &str,
+) -> DiagnosticBuilder<'a> {
     leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
 }
 
-fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
-                           explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
+fn leveled_feature_err<'a>(
+    sess: &'a ParseSess,
+    feature: &str,
+    span: Span,
+    issue: GateIssue,
+    explain: &str,
+    level: GateStrength,
+) -> DiagnosticBuilder<'a> {
     let diag = &sess.span_diagnostic;
 
     let issue = match issue {
@@ -1457,23 +1473,26 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue
         GateIssue::Library(lib) => lib,
     };
 
-    let explanation = match issue {
-        None | Some(0) => explain.to_owned(),
-        Some(n) => format!("{} (see issue #{})", explain, n)
-    };
-
     let mut err = match level {
         GateStrength::Hard => {
-            diag.struct_span_err_with_code(span, &explanation, stringify_error_code!(E0658))
+            diag.struct_span_err_with_code(span, explain, stringify_error_code!(E0658))
         }
-        GateStrength::Soft => diag.struct_span_warn(span, &explanation),
+        GateStrength::Soft => diag.struct_span_warn(span, explain),
     };
 
+    match issue {
+        None | Some(0) => {}  // We still accept `0` as a stand-in for backwards compatibility
+        Some(n) => {
+            err.note(&format!(
+                "for more information, see https://github.com/rust-lang/rust/issues/{}",
+                n,
+            ));
+        }
+    }
+
     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
     if sess.unstable_features.is_nightly_build() {
-        err.help(&format!("add #![feature({})] to the \
-                           crate attributes to enable",
-                          feature));
+        err.help(&format!("add #![feature({})] to the crate attributes to enable", feature));
     }
 
     // If we're on stable and only emitting a "soft" warning, add a note to
@@ -1488,10 +1507,10 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue
 }
 
 const EXPLAIN_BOX_SYNTAX: &str =
-    "box expression syntax is experimental; you can call `Box::new` instead.";
+    "box expression syntax is experimental; you can call `Box::new` instead";
 
 pub const EXPLAIN_STMT_ATTR_SYNTAX: &str =
-    "attributes on expressions are experimental.";
+    "attributes on expressions are experimental";
 
 pub const EXPLAIN_ASM: &str =
     "inline assembly is not stable enough for use and is subject to change";
@@ -1685,10 +1704,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
     fn visit_name(&mut self, sp: Span, name: ast::Name) {
         if !name.as_str().is_ascii() {
-            gate_feature_post!(&self,
-                               non_ascii_idents,
-                               self.context.parse_sess.source_map().def_span(sp),
-                               "non-ascii idents are not fully supported.");
+            gate_feature_post!(
+                &self,
+                non_ascii_idents,
+                self.context.parse_sess.source_map().def_span(sp),
+                "non-ascii idents are not fully supported"
+            );
         }
     }
 
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index 9acd0d099a0..838dfc62646 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -348,19 +348,17 @@ impl DiagnosticSpanLine {
     /// `span` within the line.
     fn from_span(span: Span, je: &JsonEmitter) -> Vec<DiagnosticSpanLine> {
         je.sm.span_to_lines(span)
-             .map(|lines| {
-                 let fm = &*lines.file;
-                 lines.lines
-                      .iter()
-                      .map(|line| {
-                          DiagnosticSpanLine::line_from_source_file(fm,
-                                                                line.line_index,
-                                                                line.start_col.0 + 1,
-                                                                line.end_col.0 + 1)
-                      })
-                     .collect()
-             })
-            .unwrap_or_else(|_| vec![])
+            .map(|lines| {
+                let fm = &*lines.file;
+                lines.lines
+                    .iter()
+                    .map(|line| DiagnosticSpanLine::line_from_source_file(
+                        fm,
+                        line.line_index,
+                        line.start_col.0 + 1,
+                        line.end_col.0 + 1,
+                    )).collect()
+            }).unwrap_or_else(|_| vec![])
     }
 }
 
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index a6145d5dcb3..9905b981395 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -8,6 +8,7 @@
        test(attr(deny(warnings))))]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index cd4944deadb..5557e281a66 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1,10 +1,9 @@
 use crate::ast::{self, Ident};
-use crate::source_map::{SourceMap, FilePathMapping};
 use crate::parse::{token, ParseSess};
 use crate::symbol::Symbol;
 
 use errors::{Applicability, FatalError, Diagnostic, DiagnosticBuilder};
-use syntax_pos::{BytePos, CharPos, Pos, Span, NO_EXPANSION};
+use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION};
 use core::unicode::property::Pattern_White_Space;
 
 use std::borrow::Cow;
@@ -43,16 +42,16 @@ pub struct UnmatchedBrace {
 }
 
 pub struct StringReader<'a> {
-    pub sess: &'a ParseSess,
+    crate sess: &'a ParseSess,
     /// The absolute offset within the source_map of the next character to read
-    pub next_pos: BytePos,
+    crate next_pos: BytePos,
     /// The absolute offset within the source_map of the current character
-    pub pos: BytePos,
+    crate pos: BytePos,
     /// The current character (which has been read from self.pos)
-    pub ch: Option<char>,
-    pub source_file: Lrc<syntax_pos::SourceFile>,
+    crate ch: Option<char>,
+    crate source_file: Lrc<syntax_pos::SourceFile>,
     /// Stop reading src at this index.
-    pub end_src_index: usize,
+    crate end_src_index: usize,
     // cached:
     peek_tok: token::Token,
     peek_span: Span,
@@ -126,7 +125,7 @@ impl<'a> StringReader<'a> {
     }
 
     /// Immutably extract string if found at current position with given delimiters
-    pub fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<String> {
+    fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<String> {
         let mut pos = self.pos;
         let mut idx = self.src_index(pos);
         let mut ch = char_at(&self.src, idx);
@@ -191,7 +190,7 @@ impl<'a> StringReader<'a> {
         self.fatal_span(self.peek_span, m)
     }
 
-    pub fn emit_fatal_errors(&mut self) {
+    crate fn emit_fatal_errors(&mut self) {
         for err in &mut self.fatal_errs {
             err.emit();
         }
@@ -667,14 +666,9 @@ impl<'a> StringReader<'a> {
                     return None;
                 }
 
-                // I guess this is the only way to figure out if
-                // we're at the beginning of the file...
-                let smap = SourceMap::new(FilePathMapping::empty());
-                smap.files.borrow_mut().source_files.push(self.source_file.clone());
-                let loc = smap.lookup_char_pos_adj(self.pos);
-                debug!("Skipping a shebang");
-                if loc.line == 1 && loc.col == CharPos(0) {
-                    // FIXME: Add shebang "token", return it
+                let is_beginning_of_file = self.pos == self.source_file.start_pos;
+                if is_beginning_of_file {
+                    debug!("Skipping a shebang");
                     let start = self.pos;
                     while !self.ch_is('\n') && !self.is_eof() {
                         self.bump();
@@ -1911,7 +1905,7 @@ mod tests {
 
     use crate::ast::{Ident, CrateConfig};
     use crate::symbol::Symbol;
-    use crate::source_map::SourceMap;
+    use crate::source_map::{SourceMap, FilePathMapping};
     use crate::feature_gate::UnstableFeatures;
     use crate::parse::token;
     use crate::diagnostics::plugin::ErrorMap;
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 37360a56395..a5adb37f745 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -851,8 +851,34 @@ impl<'a> Parser<'a> {
                 }
             }
 
+            let is_semi_suggestable = expected.iter().any(|t| match t {
+                TokenType::Token(token::Semi) => true, // we expect a `;` here
+                _ => false,
+            }) && ( // a `;` would be expected before the current keyword
+                self.token.is_keyword(keywords::Break) ||
+                self.token.is_keyword(keywords::Continue) ||
+                self.token.is_keyword(keywords::For) ||
+                self.token.is_keyword(keywords::If) ||
+                self.token.is_keyword(keywords::Let) ||
+                self.token.is_keyword(keywords::Loop) ||
+                self.token.is_keyword(keywords::Match) ||
+                self.token.is_keyword(keywords::Return) ||
+                self.token.is_keyword(keywords::While)
+            );
             let cm = self.sess.source_map();
             match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
+                (Ok(ref a), Ok(ref b)) if a.line != b.line && is_semi_suggestable => {
+                    // The spans are in different lines, expected `;` and found `let` or `return`.
+                    // High likelihood that it is only a missing `;`.
+                    err.span_suggestion_short(
+                        label_sp,
+                        "a semicolon may be missing here",
+                        ";".to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.emit();
+                    return Ok(true);
+                }
                 (Ok(ref a), Ok(ref b)) if a.line == b.line => {
                     // When the spans are in the same line, it means that the only content between
                     // them is whitespace, point at the found token in that case:
@@ -2165,9 +2191,11 @@ impl<'a> Parser<'a> {
                     suffix,
                 ) = self.token {
                     let suffix = suffix.and_then(|s| {
-                        let s = s.as_str().get();
-                        if ["f32", "f64"].contains(&s) {
-                            Some(s)
+                        let s = s.as_str();
+                        if s == "f32" {
+                            Some("f32")
+                        } else if s == "f64" {
+                            Some("f64")
                         } else {
                             None
                         }
@@ -4089,7 +4117,15 @@ impl<'a> Parser<'a> {
     {
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
-        Ok(self.mk_expr(span_lo.to(body.span), ExprKind::TryBlock(body), attrs))
+        if self.eat_keyword(keywords::Catch) {
+            let mut error = self.struct_span_err(self.prev_span,
+                                                 "keyword `catch` cannot follow a `try` block");
+            error.help("try using `match` on the result of the `try` block instead");
+            error.emit();
+            Err(error)
+        } else {
+            Ok(self.mk_expr(span_lo.to(body.span), ExprKind::TryBlock(body), attrs))
+        }
     }
 
     // `match` token already eaten
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index f5a9aded845..ca05ff71c94 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -645,7 +645,7 @@ pub trait PrintState<'a> {
             ast::LitKind::Float(ref f, t) => {
                 self.writer().word(format!("{}{}", &f, t.ty_to_string()))
             }
-            ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(f.as_str().get()),
+            ast::LitKind::FloatUnsuffixed(ref f) => self.writer().word(f.as_str().to_string()),
             ast::LitKind::Bool(val) => {
                 if val { self.writer().word("true") } else { self.writer().word("false") }
             }
@@ -731,7 +731,7 @@ pub trait PrintState<'a> {
                 if segment.ident.name == keywords::DollarCrate.name() {
                     self.print_dollar_crate(segment.ident)?;
                 } else {
-                    self.writer().word(segment.ident.as_str().get())?;
+                    self.writer().word(segment.ident.as_str().to_string())?;
                 }
             }
         }
@@ -749,7 +749,7 @@ pub trait PrintState<'a> {
         }
         self.maybe_print_comment(attr.span.lo())?;
         if attr.is_sugared_doc {
-            self.writer().word(attr.value_str().unwrap().as_str().get())?;
+            self.writer().word(attr.value_str().unwrap().as_str().to_string())?;
             self.writer().hardbreak()
         } else {
             match attr.style {
@@ -858,7 +858,7 @@ pub trait PrintState<'a> {
         if !ast::Ident::with_empty_ctxt(name).is_path_segment_keyword() {
             self.writer().word("::")?;
         }
-        self.writer().word(name.as_str().get())
+        self.writer().word(name.as_str().to_string())
     }
 }
 
@@ -1300,7 +1300,7 @@ impl<'a> State<'a> {
             }
             ast::ItemKind::GlobalAsm(ref ga) => {
                 self.head(visibility_qualified(&item.vis, "global_asm!"))?;
-                self.s.word(ga.asm.as_str().get())?;
+                self.s.word(ga.asm.as_str().to_string())?;
                 self.end()?;
             }
             ast::ItemKind::Ty(ref ty, ref generics) => {
@@ -2437,7 +2437,7 @@ impl<'a> State<'a> {
         if ident.is_raw_guess() {
             self.s.word(format!("r#{}", ident))?;
         } else {
-            self.s.word(ident.as_str().get())?;
+            self.s.word(ident.as_str().to_string())?;
         }
         self.ann.post(self, AnnNode::Ident(&ident))
     }
@@ -2447,7 +2447,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
-        self.s.word(name.as_str().get())?;
+        self.s.word(name.as_str().to_string())?;
         self.ann.post(self, AnnNode::Name(&name))
     }
 
diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs
index 62a6972122a..08abbf5e8a4 100644
--- a/src/libsyntax/source_map.rs
+++ b/src/libsyntax/source_map.rs
@@ -388,16 +388,6 @@ impl SourceMap {
         }
     }
 
-    pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt {
-        let loc = self.lookup_char_pos(pos);
-        LocWithOpt {
-            filename: loc.file.name.clone(),
-            line: loc.line,
-            col: loc.col,
-            file: Some(loc.file)
-        }
-    }
-
     /// Returns `Some(span)`, a union of the lhs and rhs span. The lhs must precede the rhs. If
     /// there are gaps between lhs and rhs, the resulting union will cross these gaps.
     /// For this to work, the spans have to be:
@@ -438,10 +428,10 @@ impl SourceMap {
             return "no-location".to_string();
         }
 
-        let lo = self.lookup_char_pos_adj(sp.lo());
-        let hi = self.lookup_char_pos_adj(sp.hi());
+        let lo = self.lookup_char_pos(sp.lo());
+        let hi = self.lookup_char_pos(sp.hi());
         format!("{}:{}:{}: {}:{}",
-                        lo.filename,
+                        lo.file.name,
                         lo.line,
                         lo.col.to_usize() + 1,
                         hi.line,
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 5efa6b36f67..24fbc9b6caf 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -347,9 +347,9 @@ impl<'a, 'b> Context<'a, 'b> {
 
             Named(name) => {
                 match self.names.get(&name) {
-                    Some(idx) => {
+                    Some(&idx) => {
                         // Treat as positional arg.
-                        self.verify_arg_type(Exact(*idx), ty)
+                        self.verify_arg_type(Exact(idx), ty)
                     }
                     None => {
                         let msg = format!("there is no argument named `{}`", name);
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index aa472eee3ca..ee0b86963f3 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -3,6 +3,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(in_band_lifetimes)]
 #![feature(proc_macro_diagnostic)]
diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs
index f902e8169b6..09dce775790 100644
--- a/src/libsyntax_ext/proc_macro_server.rs
+++ b/src/libsyntax_ext/proc_macro_server.rs
@@ -336,11 +336,11 @@ impl Ident {
         }
     }
     fn new(sym: Symbol, is_raw: bool, span: Span) -> Ident {
-        let string = sym.as_str().get();
-        if !Self::is_valid(string) {
+        let string = sym.as_str();
+        if !Self::is_valid(&string) {
             panic!("`{:?}` is not a valid identifier", string)
         }
-        if is_raw && !ast::Ident::from_str(string).can_be_raw() {
+        if is_raw && !ast::Ident::from_interned_str(sym.as_interned_str()).can_be_raw() {
             panic!("`{}` cannot be a raw identifier", string);
         }
         Ident { sym, is_raw, span }
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 6331fe60886..1ffecea44ed 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -218,14 +218,17 @@ pub fn clear_markings() {
 }
 
 impl SyntaxContext {
+    #[inline]
     pub const fn empty() -> Self {
         SyntaxContext(0)
     }
 
+    #[inline]
     crate fn as_u32(self) -> u32 {
         self.0
     }
 
+    #[inline]
     crate fn from_u32(raw: u32) -> SyntaxContext {
         SyntaxContext(raw)
     }
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 48d087ee43c..81cf804cf0b 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -7,6 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(const_fn)]
 #![feature(crate_visibility_modifier)]
@@ -1294,7 +1295,7 @@ impl Sub for CharPos {
 }
 
 // _____________________________________________________________________________
-// Loc, LocWithOpt, SourceFileAndLine, SourceFileAndBytePos
+// Loc, SourceFileAndLine, SourceFileAndBytePos
 //
 
 /// A source code location used for error reporting.
@@ -1310,17 +1311,6 @@ pub struct Loc {
     pub col_display: usize,
 }
 
-/// A source code location used as the result of `lookup_char_pos_adj`.
-// Actually, *none* of the clients use the filename *or* file field;
-// perhaps they should just be removed.
-#[derive(Debug)]
-pub struct LocWithOpt {
-    pub filename: FileName,
-    pub line: usize,
-    pub col: CharPos,
-    pub file: Option<Lrc<SourceFile>>,
-}
-
 // Used to be structural records.
 #[derive(Debug)]
 pub struct SourceFileAndLine { pub sf: Lrc<SourceFile>, pub line: usize }
diff --git a/src/libsyntax_pos/span_encoding.rs b/src/libsyntax_pos/span_encoding.rs
index 03d7a9eb742..525ec136232 100644
--- a/src/libsyntax_pos/span_encoding.rs
+++ b/src/libsyntax_pos/span_encoding.rs
@@ -9,122 +9,106 @@ use crate::{BytePos, SpanData};
 use crate::hygiene::SyntaxContext;
 
 use rustc_data_structures::fx::FxHashMap;
-use std::hash::{Hash, Hasher};
 
 /// A compressed span.
-/// Contains either fields of `SpanData` inline if they are small, or index into span interner.
-/// The primary goal of `Span` is to be as small as possible and fit into other structures
-/// (that's why it uses `packed` as well). Decoding speed is the second priority.
-/// See `SpanData` for the info on span fields in decoded representation.
-#[repr(packed)]
-pub struct Span(u32);
-
-impl Copy for Span {}
-impl Clone for Span {
-    #[inline]
-    fn clone(&self) -> Span {
-        *self
-    }
-}
-impl PartialEq for Span {
-    #[inline]
-    fn eq(&self, other: &Span) -> bool {
-        let a = self.0;
-        let b = other.0;
-        a == b
-    }
-}
-impl Eq for Span {}
-impl Hash for Span {
-    #[inline]
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        let a = self.0;
-        a.hash(state)
-    }
+///
+/// `SpanData` is 12 bytes, which is a bit too big to stick everywhere. `Span`
+/// is a form that only takes up 8 bytes, with less space for the length and
+/// context. The vast majority (99.9%+) of `SpanData` instances will fit within
+/// those 8 bytes; any `SpanData` whose fields don't fit into a `Span` are
+/// stored in a separate interner table, and the `Span` will index into that
+/// table. Interning is rare enough that the cost is low, but common enough
+/// that the code is exercised regularly.
+///
+/// An earlier version of this code used only 4 bytes for `Span`, but that was
+/// slower because only 80--90% of spans could be stored inline (even less in
+/// very large crates) and so the interner was used a lot more.
+///
+/// Inline (compressed) format:
+/// - `span.base_or_index == span_data.lo`
+/// - `span.len_or_tag == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`)
+/// - `span.ctxt == span_data.ctxt` (must be `<= MAX_CTXT`)
+///
+/// Interned format:
+/// - `span.base_or_index == index` (indexes into the interner table)
+/// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero)
+/// - `span.ctxt == 0`
+///
+/// The inline form uses 0 for the tag value (rather than 1) so that we don't
+/// need to mask out the tag bit when getting the length, and so that the
+/// dummy span can be all zeroes.
+///
+/// Notes about the choice of field sizes:
+/// - `base` is 32 bits in both `Span` and `SpanData`, which means that `base`
+///   values never cause interning. The number of bits needed for `base`
+///   depends on the crate size. 32 bits allows up to 4 GiB of code in a crate.
+///   `script-servo` is the largest crate in `rustc-perf`, requiring 26 bits
+///   for some spans.
+/// - `len` is 15 bits in `Span` (a u16, minus 1 bit for the tag) and 32 bits
+///   in `SpanData`, which means that large `len` values will cause interning.
+///   The number of bits needed for `len` does not depend on the crate size.
+///   The most common number of bits for `len` are 0--7, with a peak usually at
+///   3 or 4, and then it drops off quickly from 8 onwards. 15 bits is enough
+///   for 99.99%+ of cases, but larger values (sometimes 20+ bits) might occur
+///   dozens of times in a typical crate.
+/// - `ctxt` is 16 bits in `Span` and 32 bits in `SpanData`, which means that
+///   large `ctxt` values will cause interning. The number of bits needed for
+///   `ctxt` values depend partly on the crate size and partly on the form of
+///   the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`,
+///   but larger crates might need more than 16 bits.
+///
+#[derive(Clone, Copy, Eq, PartialEq, Hash)]
+pub struct Span {
+    base_or_index: u32,
+    len_or_tag: u16,
+    ctxt_or_zero: u16
 }
 
+const LEN_TAG: u16 = 0b1000_0000_0000_0000;
+const MAX_LEN: u32 = 0b0111_1111_1111_1111;
+const MAX_CTXT: u32 = 0b1111_1111_1111_1111;
+
 /// Dummy span, both position and length are zero, syntax context is zero as well.
-/// This span is kept inline and encoded with format 0.
-pub const DUMMY_SP: Span = Span(0);
+pub const DUMMY_SP: Span = Span { base_or_index: 0, len_or_tag: 0, ctxt_or_zero: 0 };
 
 impl Span {
     #[inline]
-    pub fn new(lo: BytePos, hi: BytePos, ctxt: SyntaxContext) -> Self {
-        encode(&match lo <= hi {
-            true => SpanData { lo, hi, ctxt },
-            false => SpanData { lo: hi, hi: lo, ctxt },
-        })
+    pub fn new(mut lo: BytePos, mut hi: BytePos, ctxt: SyntaxContext) -> Self {
+        if lo > hi {
+            std::mem::swap(&mut lo, &mut hi);
+        }
+
+        let (base, len, ctxt2) = (lo.0, hi.0 - lo.0, ctxt.as_u32());
+
+        if len <= MAX_LEN && ctxt2 <= MAX_CTXT {
+            // Inline format.
+            Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_zero: ctxt2 as u16 }
+        } else {
+            // Interned format.
+            let index = with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt }));
+            Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_zero: 0 }
+        }
     }
 
     #[inline]
     pub fn data(self) -> SpanData {
-        decode(self)
+        if self.len_or_tag != LEN_TAG {
+            // Inline format.
+            debug_assert!(self.len_or_tag as u32 <= MAX_LEN);
+            SpanData {
+                lo: BytePos(self.base_or_index),
+                hi: BytePos(self.base_or_index + self.len_or_tag as u32),
+                ctxt: SyntaxContext::from_u32(self.ctxt_or_zero as u32),
+            }
+        } else {
+            // Interned format.
+            debug_assert!(self.ctxt_or_zero == 0);
+            let index = self.base_or_index;
+            with_span_interner(|interner| *interner.get(index))
+        }
     }
 }
 
-// Tags
-const TAG_INLINE: u32 = 0;
-const TAG_INTERNED: u32 = 1;
-const TAG_MASK: u32 = 1;
-
-// Fields indexes
-const BASE_INDEX: usize = 0;
-const LEN_INDEX: usize = 1;
-const CTXT_INDEX: usize = 2;
-
-// Tag = 0, inline format.
-// -------------------------------------------------------------
-// | base 31:8  | len 7:1  | ctxt (currently 0 bits) | tag 0:0 |
-// -------------------------------------------------------------
-// Since there are zero bits for ctxt, only SpanData with a 0 SyntaxContext
-// can be inline.
-const INLINE_SIZES: [u32; 3] = [24, 7, 0];
-const INLINE_OFFSETS: [u32; 3] = [8, 1, 1];
-
-// Tag = 1, interned format.
-// ------------------------
-// | index 31:1 | tag 0:0 |
-// ------------------------
-const INTERNED_INDEX_SIZE: u32 = 31;
-const INTERNED_INDEX_OFFSET: u32 = 1;
-
-#[inline]
-fn encode(sd: &SpanData) -> Span {
-    let (base, len, ctxt) = (sd.lo.0, sd.hi.0 - sd.lo.0, sd.ctxt.as_u32());
-
-    let val = if (base >> INLINE_SIZES[BASE_INDEX]) == 0 &&
-                 (len >> INLINE_SIZES[LEN_INDEX]) == 0 &&
-                 (ctxt >> INLINE_SIZES[CTXT_INDEX]) == 0 {
-        (base << INLINE_OFFSETS[BASE_INDEX]) | (len << INLINE_OFFSETS[LEN_INDEX]) |
-        (ctxt << INLINE_OFFSETS[CTXT_INDEX]) | TAG_INLINE
-    } else {
-        let index = with_span_interner(|interner| interner.intern(sd));
-        (index << INTERNED_INDEX_OFFSET) | TAG_INTERNED
-    };
-    Span(val)
-}
-
-#[inline]
-fn decode(span: Span) -> SpanData {
-    let val = span.0;
-
-    // Extract a field at position `pos` having size `size`.
-    let extract = |pos: u32, size: u32| {
-        let mask = ((!0u32) as u64 >> (32 - size)) as u32; // Can't shift u32 by 32
-        (val >> pos) & mask
-    };
-
-    let (base, len, ctxt) = if val & TAG_MASK == TAG_INLINE {(
-        extract(INLINE_OFFSETS[BASE_INDEX], INLINE_SIZES[BASE_INDEX]),
-        extract(INLINE_OFFSETS[LEN_INDEX], INLINE_SIZES[LEN_INDEX]),
-        extract(INLINE_OFFSETS[CTXT_INDEX], INLINE_SIZES[CTXT_INDEX]),
-    )} else {
-        let index = extract(INTERNED_INDEX_OFFSET, INTERNED_INDEX_SIZE);
-        return with_span_interner(|interner| *interner.get(index));
-    };
-    SpanData { lo: BytePos(base), hi: BytePos(base + len), ctxt: SyntaxContext::from_u32(ctxt) }
-}
-
 #[derive(Default)]
 pub struct SpanInterner {
     spans: FxHashMap<SpanData, u32>,
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index f61aa4284d2..393f52e7de5 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -524,7 +524,11 @@ impl LocalInternedString {
         }
     }
 
-    pub fn get(&self) -> &'static str {
+    pub fn get(&self) -> &str {
+        // This returns a valid string since we ensure that `self` outlives the interner
+        // by creating the interner on a thread which outlives threads which can access it.
+        // This type cannot move to a thread which outlives the interner since it does
+        // not implement Send.
         self.string
     }
 }
diff --git a/src/libterm/Cargo.toml b/src/libterm/Cargo.toml
new file mode 100644
index 00000000000..4eba9a9d79c
--- /dev/null
+++ b/src/libterm/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "term"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "term"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
new file mode 100644
index 00000000000..711716d9b92
--- /dev/null
+++ b/src/libterm/lib.rs
@@ -0,0 +1,201 @@
+//! Terminal formatting library.
+//!
+//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
+//! Terminal][ansi] to provide color printing, among other things. There are two
+//! implementations, the `TerminfoTerminal`, which uses control characters from
+//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
+//! API][win].
+//!
+//! # Examples
+//!
+//! ```no_run
+//! # #![feature(rustc_private)]
+//! extern crate term;
+//! use std::io::prelude::*;
+//!
+//! fn main() {
+//!     let mut t = term::stdout().unwrap();
+//!
+//!     t.fg(term::color::GREEN).unwrap();
+//!     write!(t, "hello, ").unwrap();
+//!
+//!     t.fg(term::color::RED).unwrap();
+//!     writeln!(t, "world!").unwrap();
+//!
+//!     assert!(t.reset().unwrap());
+//! }
+//! ```
+//!
+//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
+//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
+//! [ti]: https://en.wikipedia.org/wiki/Terminfo
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
+       html_playground_url = "https://play.rust-lang.org/",
+       test(attr(deny(warnings))))]
+#![deny(missing_docs)]
+
+#![deny(rust_2018_idioms)]
+
+#![cfg_attr(windows, feature(libc))]
+// Handle rustfmt skips
+#![feature(custom_attribute)]
+#![allow(unused_attributes)]
+
+use std::io::prelude::*;
+use std::io::{self, Stdout, Stderr};
+
+pub use terminfo::TerminfoTerminal;
+#[cfg(windows)]
+pub use win::WinConsole;
+
+pub mod terminfo;
+
+#[cfg(windows)]
+mod win;
+
+/// Alias for stdout terminals.
+pub type StdoutTerminal = dyn Terminal<Output = Stdout> + Send;
+/// Alias for stderr terminals.
+pub type StderrTerminal = dyn Terminal<Output = Stderr> + Send;
+
+#[cfg(not(windows))]
+/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
+/// opened.
+pub fn stdout() -> Option<Box<StdoutTerminal>> {
+    TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box<StdoutTerminal>)
+}
+
+#[cfg(windows)]
+/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
+/// opened.
+pub fn stdout() -> Option<Box<StdoutTerminal>> {
+    TerminfoTerminal::new(io::stdout())
+        .map(|t| Box::new(t) as Box<StdoutTerminal>)
+        .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box<StdoutTerminal>))
+}
+
+#[cfg(not(windows))]
+/// Returns a Terminal wrapping stderr, or None if a terminal couldn't be
+/// opened.
+pub fn stderr() -> Option<Box<StderrTerminal>> {
+    TerminfoTerminal::new(io::stderr()).map(|t| Box::new(t) as Box<StderrTerminal>)
+}
+
+#[cfg(windows)]
+/// Returns a Terminal wrapping stderr, or None if a terminal couldn't be
+/// opened.
+pub fn stderr() -> Option<Box<StderrTerminal>> {
+    TerminfoTerminal::new(io::stderr())
+        .map(|t| Box::new(t) as Box<StderrTerminal>)
+        .or_else(|| WinConsole::new(io::stderr()).ok().map(|t| Box::new(t) as Box<StderrTerminal>))
+}
+
+
+/// Terminal color definitions
+#[allow(missing_docs)]
+pub mod color {
+    /// Number for a terminal color
+    pub type Color = u16;
+
+    pub const BLACK: Color = 0;
+    pub const RED: Color = 1;
+    pub const GREEN: Color = 2;
+    pub const YELLOW: Color = 3;
+    pub const BLUE: Color = 4;
+    pub const MAGENTA: Color = 5;
+    pub const CYAN: Color = 6;
+    pub const WHITE: Color = 7;
+
+    pub const BRIGHT_BLACK: Color = 8;
+    pub const BRIGHT_RED: Color = 9;
+    pub const BRIGHT_GREEN: Color = 10;
+    pub const BRIGHT_YELLOW: Color = 11;
+    pub const BRIGHT_BLUE: Color = 12;
+    pub const BRIGHT_MAGENTA: Color = 13;
+    pub const BRIGHT_CYAN: Color = 14;
+    pub const BRIGHT_WHITE: Color = 15;
+}
+
+/// Terminal attributes for use with term.attr().
+///
+/// Most attributes can only be turned on and must be turned off with term.reset().
+/// The ones that can be turned off explicitly take a boolean value.
+/// Color is also represented as an attribute for convenience.
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+pub enum Attr {
+    /// Bold (or possibly bright) mode
+    Bold,
+    /// Dim mode, also called faint or half-bright. Often not supported
+    Dim,
+    /// Italics mode. Often not supported
+    Italic(bool),
+    /// Underline mode
+    Underline(bool),
+    /// Blink mode
+    Blink,
+    /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
+    Standout(bool),
+    /// Reverse mode, inverts the foreground and background colors
+    Reverse,
+    /// Secure mode, also called invis mode. Hides the printed text
+    Secure,
+    /// Convenience attribute to set the foreground color
+    ForegroundColor(color::Color),
+    /// Convenience attribute to set the background color
+    BackgroundColor(color::Color),
+}
+
+/// A terminal with similar capabilities to an ANSI Terminal
+/// (foreground/background colors etc).
+pub trait Terminal: Write {
+    /// The terminal's output writer type.
+    type Output: Write;
+
+    /// Sets the foreground color to the given color.
+    ///
+    /// If the color is a bright color, but the terminal only supports 8 colors,
+    /// the corresponding normal color will be used instead.
+    ///
+    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
+    /// if there was an I/O error.
+    fn fg(&mut self, color: color::Color) -> io::Result<bool>;
+
+    /// Sets the background color to the given color.
+    ///
+    /// If the color is a bright color, but the terminal only supports 8 colors,
+    /// the corresponding normal color will be used instead.
+    ///
+    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
+    /// if there was an I/O error.
+    fn bg(&mut self, color: color::Color) -> io::Result<bool>;
+
+    /// Sets the given terminal attribute, if supported. Returns `Ok(true)`
+    /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if
+    /// there was an I/O error.
+    fn attr(&mut self, attr: Attr) -> io::Result<bool>;
+
+    /// Returns `true` if the given terminal attribute is supported.
+    fn supports_attr(&self, attr: Attr) -> bool;
+
+    /// Resets all terminal attributes and colors to their defaults.
+    ///
+    /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there
+    /// was an I/O error.
+    ///
+    /// *Note: This does not flush.*
+    ///
+    /// That means the reset command may get buffered so, if you aren't planning on doing anything
+    /// else that might flush stdout's buffer (e.g., writing a line of text), you should flush after
+    /// calling reset.
+    fn reset(&mut self) -> io::Result<bool>;
+
+    /// Gets an immutable reference to the stream inside
+    fn get_ref(&self) -> &Self::Output;
+
+    /// Gets a mutable reference to the stream inside
+    fn get_mut(&mut self) -> &mut Self::Output;
+
+    /// Returns the contained stream, destroying the `Terminal`
+    fn into_inner(self) -> Self::Output where Self: Sized;
+}
diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs
new file mode 100644
index 00000000000..be90195065e
--- /dev/null
+++ b/src/libterm/terminfo/mod.rs
@@ -0,0 +1,265 @@
+//! Terminfo database interface.
+
+use std::collections::HashMap;
+use std::env;
+use std::error;
+use std::fmt;
+use std::fs::File;
+use std::io::{self, prelude::*, BufReader};
+use std::path::Path;
+
+use crate::Attr;
+use crate::color;
+use crate::Terminal;
+
+use searcher::get_dbpath_for_term;
+use parser::compiled::{parse, msys_terminfo};
+use parm::{expand, Variables, Param};
+
+/// A parsed terminfo database entry.
+#[derive(Debug)]
+pub struct TermInfo {
+    /// Names for the terminal
+    pub names: Vec<String>,
+    /// Map of capability name to boolean value
+    pub bools: HashMap<String, bool>,
+    /// Map of capability name to numeric value
+    pub numbers: HashMap<String, u16>,
+    /// Map of capability name to raw (unexpanded) string
+    pub strings: HashMap<String, Vec<u8>>,
+}
+
+/// A terminfo creation error.
+#[derive(Debug)]
+pub enum Error {
+    /// TermUnset Indicates that the environment doesn't include enough information to find
+    /// the terminfo entry.
+    TermUnset,
+    /// MalformedTerminfo indicates that parsing the terminfo entry failed.
+    MalformedTerminfo(String),
+    /// io::Error forwards any io::Errors encountered when finding or reading the terminfo entry.
+    IoError(io::Error),
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &str {
+        "failed to create TermInfo"
+    }
+
+    fn cause(&self) -> Option<&dyn error::Error> {
+        use Error::*;
+        match *self {
+            IoError(ref e) => Some(e),
+            _ => None,
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use Error::*;
+        match *self {
+            TermUnset => Ok(()),
+            MalformedTerminfo(ref e) => e.fmt(f),
+            IoError(ref e) => e.fmt(f),
+        }
+    }
+}
+
+impl TermInfo {
+    /// Creates a TermInfo based on current environment.
+    pub fn from_env() -> Result<TermInfo, Error> {
+        let term = match env::var("TERM") {
+            Ok(name) => TermInfo::from_name(&name),
+            Err(..) => return Err(Error::TermUnset),
+        };
+
+        if term.is_err() && env::var("MSYSCON").ok().map_or(false, |s| "mintty.exe" == s) {
+            // msys terminal
+            Ok(msys_terminfo())
+        } else {
+            term
+        }
+    }
+
+    /// Creates a TermInfo for the named terminal.
+    pub fn from_name(name: &str) -> Result<TermInfo, Error> {
+        get_dbpath_for_term(name)
+            .ok_or_else(|| {
+                Error::IoError(io::Error::new(io::ErrorKind::NotFound, "terminfo file not found"))
+            })
+            .and_then(|p| TermInfo::from_path(&(*p)))
+    }
+
+    /// Parse the given TermInfo.
+    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<TermInfo, Error> {
+        Self::_from_path(path.as_ref())
+    }
+    // Keep the metadata small
+    fn _from_path(path: &Path) -> Result<TermInfo, Error> {
+        let file = File::open(path).map_err(Error::IoError)?;
+        let mut reader = BufReader::new(file);
+        parse(&mut reader, false).map_err(Error::MalformedTerminfo)
+    }
+}
+
+pub mod searcher;
+
+/// TermInfo format parsing.
+pub mod parser {
+    //! ncurses-compatible compiled terminfo format parsing (term(5))
+    pub mod compiled;
+}
+pub mod parm;
+
+
+fn cap_for_attr(attr: Attr) -> &'static str {
+    match attr {
+        Attr::Bold => "bold",
+        Attr::Dim => "dim",
+        Attr::Italic(true) => "sitm",
+        Attr::Italic(false) => "ritm",
+        Attr::Underline(true) => "smul",
+        Attr::Underline(false) => "rmul",
+        Attr::Blink => "blink",
+        Attr::Standout(true) => "smso",
+        Attr::Standout(false) => "rmso",
+        Attr::Reverse => "rev",
+        Attr::Secure => "invis",
+        Attr::ForegroundColor(_) => "setaf",
+        Attr::BackgroundColor(_) => "setab",
+    }
+}
+
+/// A Terminal that knows how many colors it supports, with a reference to its
+/// parsed Terminfo database record.
+pub struct TerminfoTerminal<T> {
+    num_colors: u16,
+    out: T,
+    ti: TermInfo,
+}
+
+impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
+    type Output = T;
+    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
+        let color = self.dim_if_necessary(color);
+        if self.num_colors > color {
+            return self.apply_cap("setaf", &[Param::Number(color as i32)]);
+        }
+        Ok(false)
+    }
+
+    fn bg(&mut self, color: color::Color) -> io::Result<bool> {
+        let color = self.dim_if_necessary(color);
+        if self.num_colors > color {
+            return self.apply_cap("setab", &[Param::Number(color as i32)]);
+        }
+        Ok(false)
+    }
+
+    fn attr(&mut self, attr: Attr) -> io::Result<bool> {
+        match attr {
+            Attr::ForegroundColor(c) => self.fg(c),
+            Attr::BackgroundColor(c) => self.bg(c),
+            _ => self.apply_cap(cap_for_attr(attr), &[]),
+        }
+    }
+
+    fn supports_attr(&self, attr: Attr) -> bool {
+        match attr {
+            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0,
+            _ => {
+                let cap = cap_for_attr(attr);
+                self.ti.strings.get(cap).is_some()
+            }
+        }
+    }
+
+    fn reset(&mut self) -> io::Result<bool> {
+        // are there any terminals that have color/attrs and not sgr0?
+        // Try falling back to sgr, then op
+        let cmd = match ["sgr0", "sgr", "op"]
+                            .iter()
+                            .filter_map(|cap| self.ti.strings.get(*cap))
+                            .next() {
+            Some(op) => {
+                match expand(&op, &[], &mut Variables::new()) {
+                    Ok(cmd) => cmd,
+                    Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
+                }
+            }
+            None => return Ok(false),
+        };
+        self.out.write_all(&cmd).and(Ok(true))
+    }
+
+    fn get_ref(&self) -> &T {
+        &self.out
+    }
+
+    fn get_mut(&mut self) -> &mut T {
+        &mut self.out
+    }
+
+    fn into_inner(self) -> T
+        where Self: Sized
+    {
+        self.out
+    }
+}
+
+impl<T: Write + Send> TerminfoTerminal<T> {
+    /// Creates a new TerminfoTerminal with the given TermInfo and Write.
+    pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal<T> {
+        let nc = if terminfo.strings.contains_key("setaf") &&
+                    terminfo.strings.contains_key("setab") {
+            terminfo.numbers.get("colors").map_or(0, |&n| n)
+        } else {
+            0
+        };
+
+        TerminfoTerminal {
+            out,
+            ti: terminfo,
+            num_colors: nc,
+        }
+    }
+
+    /// Creates a new TerminfoTerminal for the current environment with the given Write.
+    ///
+    /// Returns `None` when the terminfo cannot be found or parsed.
+    pub fn new(out: T) -> Option<TerminfoTerminal<T>> {
+        TermInfo::from_env().map(move |ti| TerminfoTerminal::new_with_terminfo(out, ti)).ok()
+    }
+
+    fn dim_if_necessary(&self, color: color::Color) -> color::Color {
+        if color >= self.num_colors && color >= 8 && color < 16 {
+            color - 8
+        } else {
+            color
+        }
+    }
+
+    fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
+        match self.ti.strings.get(cmd) {
+            Some(cmd) => {
+                match expand(&cmd, params, &mut Variables::new()) {
+                    Ok(s) => self.out.write_all(&s).and(Ok(true)),
+                    Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
+                }
+            }
+            None => Ok(false),
+        }
+    }
+}
+
+
+impl<T: Write> Write for TerminfoTerminal<T> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.out.write(buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        self.out.flush()
+    }
+}
diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs
new file mode 100644
index 00000000000..28229bd87b0
--- /dev/null
+++ b/src/libterm/terminfo/parm.rs
@@ -0,0 +1,669 @@
+//! Parameterized string expansion
+
+use self::Param::*;
+use self::States::*;
+
+use std::iter::repeat;
+
+#[derive(Clone, Copy, PartialEq)]
+enum States {
+    Nothing,
+    Percent,
+    SetVar,
+    GetVar,
+    PushParam,
+    CharConstant,
+    CharClose,
+    IntConstant(i32),
+    FormatPattern(Flags, FormatState),
+    SeekIfElse(usize),
+    SeekIfElsePercent(usize),
+    SeekIfEnd(usize),
+    SeekIfEndPercent(usize),
+}
+
+#[derive(Copy, PartialEq, Clone)]
+enum FormatState {
+    Flags,
+    Width,
+    Precision,
+}
+
+/// Types of parameters a capability can use
+#[allow(missing_docs)]
+#[derive(Clone)]
+pub enum Param {
+    Words(String),
+    Number(i32),
+}
+
+/// Container for static and dynamic variable arrays
+pub struct Variables {
+    /// Static variables A-Z
+    sta_va: [Param; 26],
+    /// Dynamic variables a-z
+    dyn_va: [Param; 26],
+}
+
+impl Variables {
+    /// Returns a new zero-initialized Variables
+    pub fn new() -> Variables {
+        Variables {
+            sta_va: [
+                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
+                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
+                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
+                Number(0), Number(0), Number(0), Number(0), Number(0)
+            ],
+            dyn_va: [
+                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
+                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
+                Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
+                Number(0), Number(0), Number(0), Number(0), Number(0)
+            ],
+        }
+    }
+}
+
+/// Expand a parameterized capability
+///
+/// # Arguments
+/// * `cap`    - string to expand
+/// * `params` - vector of params for %p1 etc
+/// * `vars`   - Variables struct for %Pa etc
+///
+/// To be compatible with ncurses, `vars` should be the same between calls to `expand` for
+/// multiple capabilities for the same terminal.
+pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result<Vec<u8>, String> {
+    let mut state = Nothing;
+
+    // expanded cap will only rarely be larger than the cap itself
+    let mut output = Vec::with_capacity(cap.len());
+
+    let mut stack: Vec<Param> = Vec::new();
+
+    // Copy parameters into a local vector for mutability
+    let mut mparams = [Number(0), Number(0), Number(0), Number(0), Number(0), Number(0),
+                       Number(0), Number(0), Number(0)];
+    for (dst, src) in mparams.iter_mut().zip(params.iter()) {
+        *dst = (*src).clone();
+    }
+
+    for &c in cap.iter() {
+        let cur = c as char;
+        let mut old_state = state;
+        match state {
+            Nothing => {
+                if cur == '%' {
+                    state = Percent;
+                } else {
+                    output.push(c);
+                }
+            }
+            Percent => {
+                match cur {
+                    '%' => {
+                        output.push(c);
+                        state = Nothing
+                    }
+                    'c' => {
+                        match stack.pop() {
+                            // if c is 0, use 0200 (128) for ncurses compatibility
+                            Some(Number(0)) => output.push(128u8),
+                            // Don't check bounds. ncurses just casts and truncates.
+                            Some(Number(c)) => output.push(c as u8),
+                            Some(_) => return Err("a non-char was used with %c".to_string()),
+                            None => return Err("stack is empty".to_string()),
+                        }
+                    }
+                    'p' => state = PushParam,
+                    'P' => state = SetVar,
+                    'g' => state = GetVar,
+                    '\'' => state = CharConstant,
+                    '{' => state = IntConstant(0),
+                    'l' => {
+                        match stack.pop() {
+                            Some(Words(s)) => stack.push(Number(s.len() as i32)),
+                            Some(_) => return Err("a non-str was used with %l".to_string()),
+                            None => return Err("stack is empty".to_string()),
+                        }
+                    }
+                    '+' | '-' | '/' | '*' | '^' | '&' | '|' | 'm' => {
+                        match (stack.pop(), stack.pop()) {
+                            (Some(Number(y)), Some(Number(x))) => {
+                                stack.push(Number(match cur {
+                                    '+' => x + y,
+                                    '-' => x - y,
+                                    '*' => x * y,
+                                    '/' => x / y,
+                                    '|' => x | y,
+                                    '&' => x & y,
+                                    '^' => x ^ y,
+                                    'm' => x % y,
+                                    _ => unreachable!("All cases handled"),
+                                }))
+                            }
+                            (Some(_), Some(_)) => {
+                                return Err(format!("non-numbers on stack with {}", cur))
+                            }
+                            _ => return Err("stack is empty".to_string()),
+                        }
+                    }
+                    '=' | '>' | '<' | 'A' | 'O' => {
+                        match (stack.pop(), stack.pop()) {
+                            (Some(Number(y)), Some(Number(x))) => {
+                                stack.push(Number(if match cur {
+                                    '=' => x == y,
+                                    '<' => x < y,
+                                    '>' => x > y,
+                                    'A' => x > 0 && y > 0,
+                                    'O' => x > 0 || y > 0,
+                                    _ => unreachable!(),
+                                } {
+                                    1
+                                } else {
+                                    0
+                                }))
+                            }
+                            (Some(_), Some(_)) => {
+                                return Err(format!("non-numbers on stack with {}", cur))
+                            }
+                            _ => return Err("stack is empty".to_string()),
+                        }
+                    }
+                    '!' | '~' => {
+                        match stack.pop() {
+                            Some(Number(x)) => {
+                                stack.push(Number(match cur {
+                                    '!' if x > 0 => 0,
+                                    '!' => 1,
+                                    '~' => !x,
+                                    _ => unreachable!(),
+                                }))
+                            }
+                            Some(_) => return Err(format!("non-numbers on stack with {}", cur)),
+                            None => return Err("stack is empty".to_string()),
+                        }
+                    }
+                    'i' => {
+                        match (&mparams[0], &mparams[1]) {
+                            (&Number(x), &Number(y)) => {
+                                mparams[0] = Number(x + 1);
+                                mparams[1] = Number(y + 1);
+                            }
+                            _ => {
+                                return Err("first two params not numbers with %i".to_string())
+                            }
+                        }
+                    }
+
+                    // printf-style support for %doxXs
+                    'd' | 'o' | 'x' | 'X' | 's' => {
+                        if let Some(arg) = stack.pop() {
+                            let flags = Flags::new();
+                            let res = format(arg, FormatOp::from_char(cur), flags)?;
+                            output.extend(res.iter().cloned());
+                        } else {
+                            return Err("stack is empty".to_string());
+                        }
+                    }
+                    ':' | '#' | ' ' | '.' | '0'..='9' => {
+                        let mut flags = Flags::new();
+                        let mut fstate = FormatState::Flags;
+                        match cur {
+                            ':' => (),
+                            '#' => flags.alternate = true,
+                            ' ' => flags.space = true,
+                            '.' => fstate = FormatState::Precision,
+                            '0'..='9' => {
+                                flags.width = cur as usize - '0' as usize;
+                                fstate = FormatState::Width;
+                            }
+                            _ => unreachable!(),
+                        }
+                        state = FormatPattern(flags, fstate);
+                    }
+
+                    // conditionals
+                    '?' => (),
+                    't' => {
+                        match stack.pop() {
+                            Some(Number(0)) => state = SeekIfElse(0),
+                            Some(Number(_)) => (),
+                            Some(_) => {
+                                return Err("non-number on stack with conditional".to_string())
+                            }
+                            None => return Err("stack is empty".to_string()),
+                        }
+                    }
+                    'e' => state = SeekIfEnd(0),
+                    ';' => (),
+                    _ => return Err(format!("unrecognized format option {}", cur)),
+                }
+            }
+            PushParam => {
+                // params are 1-indexed
+                stack.push(mparams[match cur.to_digit(10) {
+                               Some(d) => d as usize - 1,
+                               None => return Err("bad param number".to_string()),
+                           }]
+                           .clone());
+            }
+            SetVar => {
+                if cur >= 'A' && cur <= 'Z' {
+                    if let Some(arg) = stack.pop() {
+                        let idx = (cur as u8) - b'A';
+                        vars.sta_va[idx as usize] = arg;
+                    } else {
+                        return Err("stack is empty".to_string());
+                    }
+                } else if cur >= 'a' && cur <= 'z' {
+                    if let Some(arg) = stack.pop() {
+                        let idx = (cur as u8) - b'a';
+                        vars.dyn_va[idx as usize] = arg;
+                    } else {
+                        return Err("stack is empty".to_string());
+                    }
+                } else {
+                    return Err("bad variable name in %P".to_string());
+                }
+            }
+            GetVar => {
+                if cur >= 'A' && cur <= 'Z' {
+                    let idx = (cur as u8) - b'A';
+                    stack.push(vars.sta_va[idx as usize].clone());
+                } else if cur >= 'a' && cur <= 'z' {
+                    let idx = (cur as u8) - b'a';
+                    stack.push(vars.dyn_va[idx as usize].clone());
+                } else {
+                    return Err("bad variable name in %g".to_string());
+                }
+            }
+            CharConstant => {
+                stack.push(Number(c as i32));
+                state = CharClose;
+            }
+            CharClose => {
+                if cur != '\'' {
+                    return Err("malformed character constant".to_string());
+                }
+            }
+            IntConstant(i) => {
+                if cur == '}' {
+                    stack.push(Number(i));
+                    state = Nothing;
+                } else if let Some(digit) = cur.to_digit(10) {
+                    match i.checked_mul(10).and_then(|i_ten| i_ten.checked_add(digit as i32)) {
+                        Some(i) => {
+                            state = IntConstant(i);
+                            old_state = Nothing;
+                        }
+                        None => return Err("int constant too large".to_string()),
+                    }
+                } else {
+                    return Err("bad int constant".to_string());
+                }
+            }
+            FormatPattern(ref mut flags, ref mut fstate) => {
+                old_state = Nothing;
+                match (*fstate, cur) {
+                    (_, 'd') | (_, 'o') | (_, 'x') | (_, 'X') | (_, 's') => {
+                        if let Some(arg) = stack.pop() {
+                            let res = format(arg, FormatOp::from_char(cur), *flags)?;
+                            output.extend(res.iter().cloned());
+                            // will cause state to go to Nothing
+                            old_state = FormatPattern(*flags, *fstate);
+                        } else {
+                            return Err("stack is empty".to_string());
+                        }
+                    }
+                    (FormatState::Flags, '#') => {
+                        flags.alternate = true;
+                    }
+                    (FormatState::Flags, '-') => {
+                        flags.left = true;
+                    }
+                    (FormatState::Flags, '+') => {
+                        flags.sign = true;
+                    }
+                    (FormatState::Flags, ' ') => {
+                        flags.space = true;
+                    }
+                    (FormatState::Flags, '0'..='9') => {
+                        flags.width = cur as usize - '0' as usize;
+                        *fstate = FormatState::Width;
+                    }
+                    (FormatState::Flags, '.') => {
+                        *fstate = FormatState::Precision;
+                    }
+                    (FormatState::Width, '0'..='9') => {
+                        let old = flags.width;
+                        flags.width = flags.width * 10 + (cur as usize - '0' as usize);
+                        if flags.width < old {
+                            return Err("format width overflow".to_string());
+                        }
+                    }
+                    (FormatState::Width, '.') => {
+                        *fstate = FormatState::Precision;
+                    }
+                    (FormatState::Precision, '0'..='9') => {
+                        let old = flags.precision;
+                        flags.precision = flags.precision * 10 + (cur as usize - '0' as usize);
+                        if flags.precision < old {
+                            return Err("format precision overflow".to_string());
+                        }
+                    }
+                    _ => return Err("invalid format specifier".to_string()),
+                }
+            }
+            SeekIfElse(level) => {
+                if cur == '%' {
+                    state = SeekIfElsePercent(level);
+                }
+                old_state = Nothing;
+            }
+            SeekIfElsePercent(level) => {
+                if cur == ';' {
+                    if level == 0 {
+                        state = Nothing;
+                    } else {
+                        state = SeekIfElse(level - 1);
+                    }
+                } else if cur == 'e' && level == 0 {
+                    state = Nothing;
+                } else if cur == '?' {
+                    state = SeekIfElse(level + 1);
+                } else {
+                    state = SeekIfElse(level);
+                }
+            }
+            SeekIfEnd(level) => {
+                if cur == '%' {
+                    state = SeekIfEndPercent(level);
+                }
+                old_state = Nothing;
+            }
+            SeekIfEndPercent(level) => {
+                if cur == ';' {
+                    if level == 0 {
+                        state = Nothing;
+                    } else {
+                        state = SeekIfEnd(level - 1);
+                    }
+                } else if cur == '?' {
+                    state = SeekIfEnd(level + 1);
+                } else {
+                    state = SeekIfEnd(level);
+                }
+            }
+        }
+        if state == old_state {
+            state = Nothing;
+        }
+    }
+    Ok(output)
+}
+
+#[derive(Copy, PartialEq, Clone)]
+struct Flags {
+    width: usize,
+    precision: usize,
+    alternate: bool,
+    left: bool,
+    sign: bool,
+    space: bool,
+}
+
+impl Flags {
+    fn new() -> Flags {
+        Flags {
+            width: 0,
+            precision: 0,
+            alternate: false,
+            left: false,
+            sign: false,
+            space: false,
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+enum FormatOp {
+    Digit,
+    Octal,
+    LowerHex,
+    UpperHex,
+    String,
+}
+
+impl FormatOp {
+    fn from_char(c: char) -> FormatOp {
+        match c {
+            'd' => FormatOp::Digit,
+            'o' => FormatOp::Octal,
+            'x' => FormatOp::LowerHex,
+            'X' => FormatOp::UpperHex,
+            's' => FormatOp::String,
+            _ => panic!("bad FormatOp char"),
+        }
+    }
+    fn to_char(self) -> char {
+        match self {
+            FormatOp::Digit => 'd',
+            FormatOp::Octal => 'o',
+            FormatOp::LowerHex => 'x',
+            FormatOp::UpperHex => 'X',
+            FormatOp::String => 's',
+        }
+    }
+}
+
+fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8>, String> {
+    let mut s = match val {
+        Number(d) => {
+            match op {
+                FormatOp::Digit => {
+                    if flags.sign {
+                        format!("{:+01$}", d, flags.precision)
+                    } else if d < 0 {
+                        // C doesn't take sign into account in precision calculation.
+                        format!("{:01$}", d, flags.precision + 1)
+                    } else if flags.space {
+                        format!(" {:01$}", d, flags.precision)
+                    } else {
+                        format!("{:01$}", d, flags.precision)
+                    }
+                }
+                FormatOp::Octal => {
+                    if flags.alternate {
+                        // Leading octal zero counts against precision.
+                        format!("0{:01$o}", d, flags.precision.saturating_sub(1))
+                    } else {
+                        format!("{:01$o}", d, flags.precision)
+                    }
+                }
+                FormatOp::LowerHex => {
+                    if flags.alternate && d != 0 {
+                        format!("0x{:01$x}", d, flags.precision)
+                    } else {
+                        format!("{:01$x}", d, flags.precision)
+                    }
+                }
+                FormatOp::UpperHex => {
+                    if flags.alternate && d != 0 {
+                        format!("0X{:01$X}", d, flags.precision)
+                    } else {
+                        format!("{:01$X}", d, flags.precision)
+                    }
+                }
+                FormatOp::String => return Err("non-number on stack with %s".to_string()),
+            }
+            .into_bytes()
+        }
+        Words(s) => {
+            match op {
+                FormatOp::String => {
+                    let mut s = s.into_bytes();
+                    if flags.precision > 0 && flags.precision < s.len() {
+                        s.truncate(flags.precision);
+                    }
+                    s
+                }
+                _ => return Err(format!("non-string on stack with %{}", op.to_char())),
+            }
+        }
+    };
+    if flags.width > s.len() {
+        let n = flags.width - s.len();
+        if flags.left {
+            s.extend(repeat(b' ').take(n));
+        } else {
+            let mut s_ = Vec::with_capacity(flags.width);
+            s_.extend(repeat(b' ').take(n));
+            s_.extend(s.into_iter());
+            s = s_;
+        }
+    }
+    Ok(s)
+}
+
+#[cfg(test)]
+mod test {
+    use super::{expand, Variables};
+    use super::Param::{self, Words, Number};
+    use std::result::Result::Ok;
+
+    #[test]
+    fn test_basic_setabf() {
+        let s = b"\\E[48;5;%p1%dm";
+        assert_eq!(expand(s, &[Number(1)], &mut Variables::new()).unwrap(),
+                   "\\E[48;5;1m".bytes().collect::<Vec<_>>());
+    }
+
+    #[test]
+    fn test_multiple_int_constants() {
+        assert_eq!(expand(b"%{1}%{2}%d%d", &[], &mut Variables::new()).unwrap(),
+                   "21".bytes().collect::<Vec<_>>());
+    }
+
+    #[test]
+    fn test_op_i() {
+        let mut vars = Variables::new();
+        assert_eq!(expand(b"%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d",
+                          &[Number(1), Number(2), Number(3)],
+                          &mut vars),
+                   Ok("123233".bytes().collect::<Vec<_>>()));
+        assert_eq!(expand(b"%p1%d%p2%d%i%p1%d%p2%d", &[], &mut vars),
+                   Ok("0011".bytes().collect::<Vec<_>>()));
+    }
+
+    #[test]
+    fn test_param_stack_failure_conditions() {
+        let mut varstruct = Variables::new();
+        let vars = &mut varstruct;
+        fn get_res(fmt: &str,
+                   cap: &str,
+                   params: &[Param],
+                   vars: &mut Variables)
+                   -> Result<Vec<u8>, String> {
+            let mut u8v: Vec<_> = fmt.bytes().collect();
+            u8v.extend(cap.as_bytes().iter().map(|&b| b));
+            expand(&u8v, params, vars)
+        }
+
+        let caps = ["%d", "%c", "%s", "%Pa", "%l", "%!", "%~"];
+        for &cap in caps.iter() {
+            let res = get_res("", cap, &[], vars);
+            assert!(res.is_err(),
+                    "Op {} succeeded incorrectly with 0 stack entries",
+                    cap);
+            let p = if cap == "%s" || cap == "%l" {
+                Words("foo".to_string())
+            } else {
+                Number(97)
+            };
+            let res = get_res("%p1", cap, &[p], vars);
+            assert!(res.is_ok(),
+                    "Op {} failed with 1 stack entry: {}",
+                    cap,
+                    res.unwrap_err());
+        }
+        let caps = ["%+", "%-", "%*", "%/", "%m", "%&", "%|", "%A", "%O"];
+        for &cap in caps.iter() {
+            let res = expand(cap.as_bytes(), &[], vars);
+            assert!(res.is_err(),
+                    "Binop {} succeeded incorrectly with 0 stack entries",
+                    cap);
+            let res = get_res("%{1}", cap, &[], vars);
+            assert!(res.is_err(),
+                    "Binop {} succeeded incorrectly with 1 stack entry",
+                    cap);
+            let res = get_res("%{1}%{2}", cap, &[], vars);
+            assert!(res.is_ok(),
+                    "Binop {} failed with 2 stack entries: {}",
+                    cap,
+                    res.unwrap_err());
+        }
+    }
+
+    #[test]
+    fn test_push_bad_param() {
+        assert!(expand(b"%pa", &[], &mut Variables::new()).is_err());
+    }
+
+    #[test]
+    fn test_comparison_ops() {
+        let v = [('<', [1u8, 0u8, 0u8]), ('=', [0u8, 1u8, 0u8]), ('>', [0u8, 0u8, 1u8])];
+        for &(op, bs) in v.iter() {
+            let s = format!("%{{1}}%{{2}}%{}%d", op);
+            let res = expand(s.as_bytes(), &[], &mut Variables::new());
+            assert!(res.is_ok(), res.unwrap_err());
+            assert_eq!(res.unwrap(), vec![b'0' + bs[0]]);
+            let s = format!("%{{1}}%{{1}}%{}%d", op);
+            let res = expand(s.as_bytes(), &[], &mut Variables::new());
+            assert!(res.is_ok(), res.unwrap_err());
+            assert_eq!(res.unwrap(), vec![b'0' + bs[1]]);
+            let s = format!("%{{2}}%{{1}}%{}%d", op);
+            let res = expand(s.as_bytes(), &[], &mut Variables::new());
+            assert!(res.is_ok(), res.unwrap_err());
+            assert_eq!(res.unwrap(), vec![b'0' + bs[2]]);
+        }
+    }
+
+    #[test]
+    fn test_conditionals() {
+        let mut vars = Variables::new();
+        let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m";
+        let res = expand(s, &[Number(1)], &mut vars);
+        assert!(res.is_ok(), res.unwrap_err());
+        assert_eq!(res.unwrap(), "\\E[31m".bytes().collect::<Vec<_>>());
+        let res = expand(s, &[Number(8)], &mut vars);
+        assert!(res.is_ok(), res.unwrap_err());
+        assert_eq!(res.unwrap(), "\\E[90m".bytes().collect::<Vec<_>>());
+        let res = expand(s, &[Number(42)], &mut vars);
+        assert!(res.is_ok(), res.unwrap_err());
+        assert_eq!(res.unwrap(), "\\E[38;5;42m".bytes().collect::<Vec<_>>());
+    }
+
+    #[test]
+    fn test_format() {
+        let mut varstruct = Variables::new();
+        let vars = &mut varstruct;
+        assert_eq!(expand(b"%p1%s%p2%2s%p3%2s%p4%.2s",
+                          &[Words("foo".to_string()),
+                            Words("foo".to_string()),
+                            Words("f".to_string()),
+                            Words("foo".to_string())],
+                          vars),
+                   Ok("foofoo ffo".bytes().collect::<Vec<_>>()));
+        assert_eq!(expand(b"%p1%:-4.2s", &[Words("foo".to_string())], vars),
+                   Ok("fo  ".bytes().collect::<Vec<_>>()));
+
+        assert_eq!(expand(b"%p1%d%p1%.3d%p1%5d%p1%:+d", &[Number(1)], vars),
+                   Ok("1001    1+1".bytes().collect::<Vec<_>>()));
+        assert_eq!(expand(b"%p1%o%p1%#o%p2%6.4x%p2%#6.4X",
+                          &[Number(15), Number(27)],
+                          vars),
+                   Ok("17017  001b0X001B".bytes().collect::<Vec<_>>()));
+    }
+}
diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs
new file mode 100644
index 00000000000..05a8c9420ed
--- /dev/null
+++ b/src/libterm/terminfo/parser/compiled.rs
@@ -0,0 +1,346 @@
+#![allow(non_upper_case_globals, missing_docs)]
+
+//! ncurses-compatible compiled terminfo format parsing (term(5))
+
+use std::collections::HashMap;
+use std::io;
+use std::io::prelude::*;
+use super::super::TermInfo;
+
+// These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable.
+
+#[rustfmt::skip]
+pub static boolfnames: &[&str] = &["auto_left_margin", "auto_right_margin",
+    "no_esc_ctlc", "ceol_standout_glitch", "eat_newline_glitch", "erase_overstrike", "generic_type",
+    "hard_copy", "has_meta_key", "has_status_line", "insert_null_glitch", "memory_above",
+    "memory_below", "move_insert_mode", "move_standout_mode", "over_strike", "status_line_esc_ok",
+    "dest_tabs_magic_smso", "tilde_glitch", "transparent_underline", "xon_xoff", "needs_xon_xoff",
+    "prtr_silent", "hard_cursor", "non_rev_rmcup", "no_pad_char", "non_dest_scroll_region",
+    "can_change", "back_color_erase", "hue_lightness_saturation", "col_addr_glitch",
+    "cr_cancels_micro_mode", "has_print_wheel", "row_addr_glitch", "semi_auto_right_margin",
+    "cpi_changes_res", "lpi_changes_res", "backspaces_with_bs", "crt_no_scrolling",
+    "no_correctly_working_cr", "gnu_has_meta_key", "linefeed_is_newline", "has_hardware_tabs",
+    "return_does_clr_eol"];
+
+#[rustfmt::skip]
+pub static boolnames: &[&str] = &["bw", "am", "xsb", "xhp", "xenl", "eo",
+    "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon",
+    "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy",
+    "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"];
+
+#[rustfmt::skip]
+pub static numfnames: &[&str] = &[ "columns", "init_tabs", "lines",
+    "lines_of_memory", "magic_cookie_glitch", "padding_baud_rate", "virtual_terminal",
+    "width_status_line", "num_labels", "label_height", "label_width", "max_attributes",
+    "maximum_windows", "max_colors", "max_pairs", "no_color_video", "buffer_capacity",
+    "dot_vert_spacing", "dot_horz_spacing", "max_micro_address", "max_micro_jump", "micro_col_size",
+    "micro_line_size", "number_of_pins", "output_res_char", "output_res_line",
+    "output_res_horz_inch", "output_res_vert_inch", "print_rate", "wide_char_size", "buttons",
+    "bit_image_entwining", "bit_image_type", "magic_cookie_glitch_ul", "carriage_return_delay",
+    "new_line_delay", "backspace_delay", "horizontal_tab_delay", "number_of_function_keys"];
+
+#[rustfmt::skip]
+pub static numnames: &[&str] = &[ "cols", "it", "lines", "lm", "xmc", "pb",
+    "vt", "wsl", "nlab", "lh", "lw", "ma", "wnum", "colors", "pairs", "ncv", "bufsz", "spinv",
+    "spinh", "maddr", "mjump", "mcs", "mls", "npins", "orc", "orl", "orhi", "orvi", "cps", "widcs",
+    "btns", "bitwin", "bitype", "UTug", "OTdC", "OTdN", "OTdB", "OTdT", "OTkn"];
+
+#[rustfmt::skip]
+pub static stringfnames: &[&str] = &[ "back_tab", "bell", "carriage_return",
+    "change_scroll_region", "clear_all_tabs", "clear_screen", "clr_eol", "clr_eos",
+    "column_address", "command_character", "cursor_address", "cursor_down", "cursor_home",
+    "cursor_invisible", "cursor_left", "cursor_mem_address", "cursor_normal", "cursor_right",
+    "cursor_to_ll", "cursor_up", "cursor_visible", "delete_character", "delete_line",
+    "dis_status_line", "down_half_line", "enter_alt_charset_mode", "enter_blink_mode",
+    "enter_bold_mode", "enter_ca_mode", "enter_delete_mode", "enter_dim_mode", "enter_insert_mode",
+    "enter_secure_mode", "enter_protected_mode", "enter_reverse_mode", "enter_standout_mode",
+    "enter_underline_mode", "erase_chars", "exit_alt_charset_mode", "exit_attribute_mode",
+    "exit_ca_mode", "exit_delete_mode", "exit_insert_mode", "exit_standout_mode",
+    "exit_underline_mode", "flash_screen", "form_feed", "from_status_line", "init_1string",
+    "init_2string", "init_3string", "init_file", "insert_character", "insert_line",
+    "insert_padding", "key_backspace", "key_catab", "key_clear", "key_ctab", "key_dc", "key_dl",
+    "key_down", "key_eic", "key_eol", "key_eos", "key_f0", "key_f1", "key_f10", "key_f2", "key_f3",
+    "key_f4", "key_f5", "key_f6", "key_f7", "key_f8", "key_f9", "key_home", "key_ic", "key_il",
+    "key_left", "key_ll", "key_npage", "key_ppage", "key_right", "key_sf", "key_sr", "key_stab",
+    "key_up", "keypad_local", "keypad_xmit", "lab_f0", "lab_f1", "lab_f10", "lab_f2", "lab_f3",
+    "lab_f4", "lab_f5", "lab_f6", "lab_f7", "lab_f8", "lab_f9", "meta_off", "meta_on", "newline",
+    "pad_char", "parm_dch", "parm_delete_line", "parm_down_cursor", "parm_ich", "parm_index",
+    "parm_insert_line", "parm_left_cursor", "parm_right_cursor", "parm_rindex", "parm_up_cursor",
+    "pkey_key", "pkey_local", "pkey_xmit", "print_screen", "prtr_off", "prtr_on", "repeat_char",
+    "reset_1string", "reset_2string", "reset_3string", "reset_file", "restore_cursor",
+    "row_address", "save_cursor", "scroll_forward", "scroll_reverse", "set_attributes", "set_tab",
+    "set_window", "tab", "to_status_line", "underline_char", "up_half_line", "init_prog", "key_a1",
+    "key_a3", "key_b2", "key_c1", "key_c3", "prtr_non", "char_padding", "acs_chars", "plab_norm",
+    "key_btab", "enter_xon_mode", "exit_xon_mode", "enter_am_mode", "exit_am_mode", "xon_character",
+    "xoff_character", "ena_acs", "label_on", "label_off", "key_beg", "key_cancel", "key_close",
+    "key_command", "key_copy", "key_create", "key_end", "key_enter", "key_exit", "key_find",
+    "key_help", "key_mark", "key_message", "key_move", "key_next", "key_open", "key_options",
+    "key_previous", "key_print", "key_redo", "key_reference", "key_refresh", "key_replace",
+    "key_restart", "key_resume", "key_save", "key_suspend", "key_undo", "key_sbeg", "key_scancel",
+    "key_scommand", "key_scopy", "key_screate", "key_sdc", "key_sdl", "key_select", "key_send",
+    "key_seol", "key_sexit", "key_sfind", "key_shelp", "key_shome", "key_sic", "key_sleft",
+    "key_smessage", "key_smove", "key_snext", "key_soptions", "key_sprevious", "key_sprint",
+    "key_sredo", "key_sreplace", "key_sright", "key_srsume", "key_ssave", "key_ssuspend",
+    "key_sundo", "req_for_input", "key_f11", "key_f12", "key_f13", "key_f14", "key_f15", "key_f16",
+    "key_f17", "key_f18", "key_f19", "key_f20", "key_f21", "key_f22", "key_f23", "key_f24",
+    "key_f25", "key_f26", "key_f27", "key_f28", "key_f29", "key_f30", "key_f31", "key_f32",
+    "key_f33", "key_f34", "key_f35", "key_f36", "key_f37", "key_f38", "key_f39", "key_f40",
+    "key_f41", "key_f42", "key_f43", "key_f44", "key_f45", "key_f46", "key_f47", "key_f48",
+    "key_f49", "key_f50", "key_f51", "key_f52", "key_f53", "key_f54", "key_f55", "key_f56",
+    "key_f57", "key_f58", "key_f59", "key_f60", "key_f61", "key_f62", "key_f63", "clr_bol",
+    "clear_margins", "set_left_margin", "set_right_margin", "label_format", "set_clock",
+    "display_clock", "remove_clock", "create_window", "goto_window", "hangup", "dial_phone",
+    "quick_dial", "tone", "pulse", "flash_hook", "fixed_pause", "wait_tone", "user0", "user1",
+    "user2", "user3", "user4", "user5", "user6", "user7", "user8", "user9", "orig_pair",
+    "orig_colors", "initialize_color", "initialize_pair", "set_color_pair", "set_foreground",
+    "set_background", "change_char_pitch", "change_line_pitch", "change_res_horz",
+    "change_res_vert", "define_char", "enter_doublewide_mode", "enter_draft_quality",
+    "enter_italics_mode", "enter_leftward_mode", "enter_micro_mode", "enter_near_letter_quality",
+    "enter_normal_quality", "enter_shadow_mode", "enter_subscript_mode", "enter_superscript_mode",
+    "enter_upward_mode", "exit_doublewide_mode", "exit_italics_mode", "exit_leftward_mode",
+    "exit_micro_mode", "exit_shadow_mode", "exit_subscript_mode", "exit_superscript_mode",
+    "exit_upward_mode", "micro_column_address", "micro_down", "micro_left", "micro_right",
+    "micro_row_address", "micro_up", "order_of_pins", "parm_down_micro", "parm_left_micro",
+    "parm_right_micro", "parm_up_micro", "select_char_set", "set_bottom_margin",
+    "set_bottom_margin_parm", "set_left_margin_parm", "set_right_margin_parm", "set_top_margin",
+    "set_top_margin_parm", "start_bit_image", "start_char_set_def", "stop_bit_image",
+    "stop_char_set_def", "subscript_characters", "superscript_characters", "these_cause_cr",
+    "zero_motion", "char_set_names", "key_mouse", "mouse_info", "req_mouse_pos", "get_mouse",
+    "set_a_foreground", "set_a_background", "pkey_plab", "device_type", "code_set_init",
+    "set0_des_seq", "set1_des_seq", "set2_des_seq", "set3_des_seq", "set_lr_margin",
+    "set_tb_margin", "bit_image_repeat", "bit_image_newline", "bit_image_carriage_return",
+    "color_names", "define_bit_image_region", "end_bit_image_region", "set_color_band",
+    "set_page_length", "display_pc_char", "enter_pc_charset_mode", "exit_pc_charset_mode",
+    "enter_scancode_mode", "exit_scancode_mode", "pc_term_options", "scancode_escape",
+    "alt_scancode_esc", "enter_horizontal_hl_mode", "enter_left_hl_mode", "enter_low_hl_mode",
+    "enter_right_hl_mode", "enter_top_hl_mode", "enter_vertical_hl_mode", "set_a_attributes",
+    "set_pglen_inch", "termcap_init2", "termcap_reset", "linefeed_if_not_lf", "backspace_if_not_bs",
+    "other_non_function_keys", "arrow_key_map", "acs_ulcorner", "acs_llcorner", "acs_urcorner",
+    "acs_lrcorner", "acs_ltee", "acs_rtee", "acs_btee", "acs_ttee", "acs_hline", "acs_vline",
+    "acs_plus", "memory_lock", "memory_unlock", "box_chars_1"];
+
+#[rustfmt::skip]
+pub static stringnames: &[&str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear",
+    "_", "_", "hpa", "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1",
+    "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl", "hd", "smacs", "blink", "bold", "smcup", "smdc",
+    "dim", "smir", "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", "rmcup", "rmdc",
+    "rmir", "rmso", "rmul", "flash", "ff", "fsl", "is1", "is2", "is3", "if", "ich1", "il1", "ip",
+    "kbs", "ktbc", "kclr", "kctab", "_", "_", "kcud1", "_", "_", "_", "_", "_", "_", "_", "_", "_",
+    "_", "_", "_", "_", "_", "khome", "_", "_", "kcub1", "_", "knp", "kpp", "kcuf1", "_", "_",
+    "khts", "_", "rmkx", "smkx", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "rmm", "_",
+    "_", "pad", "dch", "dl", "cud", "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey",
+    "pfloc", "pfx", "mc0", "mc4", "_", "rep", "rs1", "rs2", "rs3", "rf", "rc", "vpa", "sc", "ind",
+    "ri", "sgr", "_", "wind", "_", "tsl", "uc", "hu", "iprog", "_", "_", "_", "_", "_", "mc5p",
+    "rmp", "acsc", "pln", "kcbt", "smxon", "rmxon", "smam", "rmam", "xonc", "xoffc", "_", "smln",
+    "rmln", "_", "kcan", "kclo", "kcmd", "kcpy", "kcrt", "_", "kent", "kext", "kfnd", "khlp",
+    "kmrk", "kmsg", "kmov", "knxt", "kopn", "kopt", "kprv", "kprt", "krdo", "kref", "krfr", "krpl",
+    "krst", "kres", "ksav", "kspd", "kund", "kBEG", "kCAN", "kCMD", "kCPY", "kCRT", "_", "_",
+    "kslt", "kEND", "kEOL", "kEXT", "kFND", "kHLP", "kHOM", "_", "kLFT", "kMSG", "kMOV", "kNXT",
+    "kOPT", "kPRV", "kPRT", "kRDO", "kRPL", "kRIT", "kRES", "kSAV", "kSPD", "kUND", "rfi", "_", "_",
+    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
+    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
+    "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_",
+    "dclk", "rmclk", "cwin", "wingo", "_", "dial", "qdial", "_", "_", "hook", "pause", "wait", "_",
+    "_", "_", "_", "_", "_", "_", "_", "_", "_", "op", "oc", "initc", "initp", "scp", "setf",
+    "setb", "cpi", "lpi", "chr", "cvr", "defc", "swidm", "sdrfq", "sitm", "slm", "smicm", "snlq",
+    "snrmq", "sshm", "ssubm", "ssupm", "sum", "rwidm", "ritm", "rlm", "rmicm", "rshm", "rsubm",
+    "rsupm", "rum", "mhpa", "mcud1", "mcub1", "mcuf1", "mvpa", "mcuu1", "porder", "mcud", "mcub",
+    "mcuf", "mcuu", "scs", "smgb", "smgbp", "smglp", "smgrp", "smgt", "smgtp", "sbim", "scsd",
+    "rbim", "rcsd", "subcs", "supcs", "docr", "zerom", "csnm", "kmous", "minfo", "reqmp", "getm",
+    "setaf", "setab", "pfxl", "devt", "csin", "s0ds", "s1ds", "s2ds", "s3ds", "smglr", "smgtb",
+    "birep", "binel", "bicr", "colornm", "defbi", "endbi", "setcolor", "slines", "dispc", "smpch",
+    "rmpch", "smsc", "rmsc", "pctrm", "scesc", "scesa", "ehhlm", "elhlm", "elohlm", "erhlm",
+    "ethlm", "evhlm", "sgr1", "slength", "OTi2", "OTrs", "OTnl", "OTbs", "OTko", "OTma", "OTG2",
+    "OTG3", "OTG1", "OTG4", "OTGR", "OTGL", "OTGU", "OTGD", "OTGH", "OTGV", "OTGC", "meml", "memu",
+    "box1"];
+
+fn read_le_u16(r: &mut dyn io::Read) -> io::Result<u16> {
+    let mut b = [0; 2];
+    let mut amt = 0;
+    while amt < b.len() {
+        match r.read(&mut b[amt..])? {
+            0 => return Err(io::Error::new(io::ErrorKind::Other, "end of file")),
+            n => amt += n,
+        }
+    }
+    Ok((b[0] as u16) | ((b[1] as u16) << 8))
+}
+
+fn read_byte(r: &mut dyn io::Read) -> io::Result<u8> {
+    match r.bytes().next() {
+        Some(s) => s,
+        None => Err(io::Error::new(io::ErrorKind::Other, "end of file")),
+    }
+}
+
+/// Parse a compiled terminfo entry, using long capability names if `longnames`
+/// is true
+pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result<TermInfo, String> {
+    macro_rules! t( ($e:expr) => (
+        match $e {
+            Ok(e) => e,
+            Err(e) => return Err(e.to_string())
+        }
+    ) );
+
+    let (bnames, snames, nnames) = if longnames {
+        (boolfnames, stringfnames, numfnames)
+    } else {
+        (boolnames, stringnames, numnames)
+    };
+
+    // Check magic number
+    let magic = t!(read_le_u16(file));
+    if magic != 0x011A {
+        return Err(format!("invalid magic number: expected {:x}, found {:x}",
+                           0x011A,
+                           magic));
+    }
+
+    // According to the spec, these fields must be >= -1 where -1 means that the feature is not
+    // supported. Using 0 instead of -1 works because we skip sections with length 0.
+    macro_rules! read_nonneg {
+        () => {{
+            match t!(read_le_u16(file)) as i16 {
+                n if n >= 0 => n as usize,
+                -1 => 0,
+                _ => return Err("incompatible file: length fields must be  >= -1".to_string()),
+            }
+        }}
+    }
+
+    let names_bytes = read_nonneg!();
+    let bools_bytes = read_nonneg!();
+    let numbers_count = read_nonneg!();
+    let string_offsets_count = read_nonneg!();
+    let string_table_bytes = read_nonneg!();
+
+    if names_bytes == 0 {
+        return Err("incompatible file: names field must be at least 1 byte wide".to_string());
+    }
+
+    if bools_bytes > boolnames.len() {
+        return Err("incompatible file: more booleans than expected".to_string());
+    }
+
+    if numbers_count > numnames.len() {
+        return Err("incompatible file: more numbers than expected".to_string());
+    }
+
+    if string_offsets_count > stringnames.len() {
+        return Err("incompatible file: more string offsets than expected".to_string());
+    }
+
+    // don't read NUL
+    let mut bytes = Vec::new();
+    t!(file.take((names_bytes - 1) as u64).read_to_end(&mut bytes));
+    let names_str = match String::from_utf8(bytes) {
+        Ok(s) => s,
+        Err(_) => return Err("input not utf-8".to_string()),
+    };
+
+    let term_names: Vec<String> = names_str.split('|')
+                                           .map(|s| s.to_string())
+                                           .collect();
+    // consume NUL
+    if t!(read_byte(file)) != b'\0' {
+        return Err("incompatible file: missing null terminator for names section".to_string());
+    }
+
+    let bools_map: HashMap<String, bool> = t! {
+        (0..bools_bytes).filter_map(|i| match read_byte(file) {
+            Err(e) => Some(Err(e)),
+            Ok(1) => Some(Ok((bnames[i].to_string(), true))),
+            Ok(_) => None
+        }).collect()
+    };
+
+    if (bools_bytes + names_bytes) % 2 == 1 {
+        t!(read_byte(file)); // compensate for padding
+    }
+
+    let numbers_map: HashMap<String, u16> = t! {
+        (0..numbers_count).filter_map(|i| match read_le_u16(file) {
+            Ok(0xFFFF) => None,
+            Ok(n) => Some(Ok((nnames[i].to_string(), n))),
+            Err(e) => Some(Err(e))
+        }).collect()
+    };
+
+    let string_map: HashMap<String, Vec<u8>> = if string_offsets_count > 0 {
+        let string_offsets: Vec<u16> = t!((0..string_offsets_count)
+                                                .map(|_| read_le_u16(file))
+                                                .collect());
+
+        let mut string_table = Vec::new();
+        t!(file.take(string_table_bytes as u64).read_to_end(&mut string_table));
+
+        t!(string_offsets.into_iter().enumerate().filter(|&(_, offset)| {
+            // non-entry
+            offset != 0xFFFF
+        }).map(|(i, offset)| {
+            let offset = offset as usize;
+
+            let name = if snames[i] == "_" {
+                stringfnames[i]
+            } else {
+                snames[i]
+            };
+
+            if offset == 0xFFFE {
+                // undocumented: FFFE indicates cap@, which means the capability is not present
+                // unsure if the handling for this is correct
+                return Ok((name.to_string(), Vec::new()));
+            }
+
+            // Find the offset of the NUL we want to go to
+            let nulpos = string_table[offset..string_table_bytes].iter().position(|&b| b == 0);
+            match nulpos {
+                Some(len) => Ok((name.to_string(), string_table[offset..offset + len].to_vec())),
+                None => Err("invalid file: missing NUL in string_table".to_string()),
+            }
+        }).collect())
+    } else {
+        HashMap::new()
+    };
+
+    // And that's all there is to it
+    Ok(TermInfo {
+        names: term_names,
+        bools: bools_map,
+        numbers: numbers_map,
+        strings: string_map,
+    })
+}
+
+/// Creates a dummy TermInfo struct for msys terminals
+pub fn msys_terminfo() -> TermInfo {
+    let mut strings = HashMap::new();
+    strings.insert("sgr0".to_string(), b"\x1B[0m".to_vec());
+    strings.insert("bold".to_string(), b"\x1B[1m".to_vec());
+    strings.insert("setaf".to_string(), b"\x1B[3%p1%dm".to_vec());
+    strings.insert("setab".to_string(), b"\x1B[4%p1%dm".to_vec());
+
+    let mut numbers = HashMap::new();
+    numbers.insert("colors".to_string(), 8u16);
+
+    TermInfo {
+        names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version
+        bools: HashMap::new(),
+        numbers,
+        strings,
+    }
+}
+
+#[cfg(test)]
+mod test {
+
+    use super::{boolnames, boolfnames, numnames, numfnames, stringnames, stringfnames};
+
+    #[test]
+    fn test_veclens() {
+        assert_eq!(boolfnames.len(), boolnames.len());
+        assert_eq!(numfnames.len(), numnames.len());
+        assert_eq!(stringfnames.len(), stringnames.len());
+    }
+}
diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs
new file mode 100644
index 00000000000..0b17ed36fc8
--- /dev/null
+++ b/src/libterm/terminfo/searcher.rs
@@ -0,0 +1,84 @@
+//! ncurses-compatible database discovery.
+//!
+//! Does not support hashed database, only filesystem!
+
+use std::env;
+use std::fs;
+use std::path::PathBuf;
+
+/// Return path to database entry for `term`
+#[allow(deprecated)]
+pub fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
+    let mut dirs_to_search = Vec::new();
+    let first_char = term.chars().next()?;
+
+    // Find search directory
+    if let Some(dir) = env::var_os("TERMINFO") {
+        dirs_to_search.push(PathBuf::from(dir));
+    }
+
+    if let Ok(dirs) = env::var("TERMINFO_DIRS") {
+        for i in dirs.split(':') {
+            if i == "" {
+                dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
+            } else {
+                dirs_to_search.push(PathBuf::from(i));
+            }
+        }
+    } else {
+        // Found nothing in TERMINFO_DIRS, use the default paths:
+        // According to  /etc/terminfo/README, after looking at
+        // ~/.terminfo, ncurses will search /etc/terminfo, then
+        // /lib/terminfo, and eventually /usr/share/terminfo.
+        // On Haiku the database can be found at /boot/system/data/terminfo
+        if let Some(mut homedir) = env::home_dir() {
+            homedir.push(".terminfo");
+            dirs_to_search.push(homedir)
+        }
+
+        dirs_to_search.push(PathBuf::from("/etc/terminfo"));
+        dirs_to_search.push(PathBuf::from("/lib/terminfo"));
+        dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
+        dirs_to_search.push(PathBuf::from("/boot/system/data/terminfo"));
+    }
+
+    // Look for the terminal in all of the search directories
+    for mut p in dirs_to_search {
+        if fs::metadata(&p).is_ok() {
+            p.push(&first_char.to_string());
+            p.push(&term);
+            if fs::metadata(&p).is_ok() {
+                return Some(p);
+            }
+            p.pop();
+            p.pop();
+
+            // on some installations the dir is named after the hex of the char
+            // (e.g., macOS)
+            p.push(&format!("{:x}", first_char as usize));
+            p.push(term);
+            if fs::metadata(&p).is_ok() {
+                return Some(p);
+            }
+        }
+    }
+    None
+}
+
+#[test]
+#[ignore = "buildbots don't have ncurses installed and I can't mock everything I need"]
+fn test_get_dbpath_for_term() {
+    // woefully inadequate test coverage
+    // note: current tests won't work with non-standard terminfo hierarchies (e.g., macOS's)
+    use std::env;
+    // FIXME (#9639): This needs to handle non-utf8 paths
+    fn x(t: &str) -> String {
+        let p = get_dbpath_for_term(t).expect("no terminfo entry found");
+        p.to_str().unwrap().to_string()
+    }
+    assert!(x("screen") == "/usr/share/terminfo/s/screen");
+    assert!(get_dbpath_for_term("") == None);
+    env::set_var("TERMINFO_DIRS", ":");
+    assert!(x("screen") == "/usr/share/terminfo/s/screen");
+    env::remove_var("TERMINFO_DIRS");
+}
diff --git a/src/libterm/win.rs b/src/libterm/win.rs
new file mode 100644
index 00000000000..6d42b01337e
--- /dev/null
+++ b/src/libterm/win.rs
@@ -0,0 +1,203 @@
+//! Windows console handling
+
+// FIXME (#13400): this is only a tiny fraction of the Windows console api
+
+extern crate libc;
+
+use std::io;
+use std::io::prelude::*;
+
+use crate::Attr;
+use crate::color;
+use crate::Terminal;
+
+/// A Terminal implementation that uses the Win32 Console API.
+pub struct WinConsole<T> {
+    buf: T,
+    def_foreground: color::Color,
+    def_background: color::Color,
+    foreground: color::Color,
+    background: color::Color,
+}
+
+type WORD = u16;
+type DWORD = u32;
+type BOOL = i32;
+type HANDLE = *mut u8;
+
+#[allow(non_snake_case)]
+#[repr(C)]
+struct CONSOLE_SCREEN_BUFFER_INFO {
+    dwSize: [libc::c_short; 2],
+    dwCursorPosition: [libc::c_short; 2],
+    wAttributes: WORD,
+    srWindow: [libc::c_short; 4],
+    dwMaximumWindowSize: [libc::c_short; 2],
+}
+
+#[allow(non_snake_case)]
+#[link(name = "kernel32")]
+extern "system" {
+    fn SetConsoleTextAttribute(handle: HANDLE, attr: WORD) -> BOOL;
+    fn GetStdHandle(which: DWORD) -> HANDLE;
+    fn GetConsoleScreenBufferInfo(handle: HANDLE, info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> BOOL;
+}
+
+fn color_to_bits(color: color::Color) -> u16 {
+    // magic numbers from mingw-w64's wincon.h
+
+    let bits = match color % 8 {
+        color::BLACK => 0,
+        color::BLUE => 0x1,
+        color::GREEN => 0x2,
+        color::RED => 0x4,
+        color::YELLOW => 0x2 | 0x4,
+        color::MAGENTA => 0x1 | 0x4,
+        color::CYAN => 0x1 | 0x2,
+        color::WHITE => 0x1 | 0x2 | 0x4,
+        _ => unreachable!(),
+    };
+
+    if color >= 8 {
+        bits | 0x8
+    } else {
+        bits
+    }
+}
+
+fn bits_to_color(bits: u16) -> color::Color {
+    let color = match bits & 0x7 {
+        0 => color::BLACK,
+        0x1 => color::BLUE,
+        0x2 => color::GREEN,
+        0x4 => color::RED,
+        0x6 => color::YELLOW,
+        0x5 => color::MAGENTA,
+        0x3 => color::CYAN,
+        0x7 => color::WHITE,
+        _ => unreachable!(),
+    };
+
+    color | (bits & 0x8) // copy the hi-intensity bit
+}
+
+impl<T: Write + Send + 'static> WinConsole<T> {
+    fn apply(&mut self) {
+        let _unused = self.buf.flush();
+        let mut accum: WORD = 0;
+        accum |= color_to_bits(self.foreground);
+        accum |= color_to_bits(self.background) << 4;
+
+        unsafe {
+            // Magic -11 means stdout, from
+            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
+            //
+            // You may be wondering, "but what about stderr?", and the answer
+            // to that is that setting terminal attributes on the stdout
+            // handle also sets them for stderr, since they go to the same
+            // terminal! Admittedly, this is fragile, since stderr could be
+            // redirected to a different console. This is good enough for
+            // rustc though. See #13400.
+            let out = GetStdHandle(-11i32 as DWORD);
+            SetConsoleTextAttribute(out, accum);
+        }
+    }
+
+    /// Returns `None` whenever the terminal cannot be created for some reason.
+    pub fn new(out: T) -> io::Result<WinConsole<T>> {
+        let fg;
+        let bg;
+        unsafe {
+            let mut buffer_info = ::std::mem::uninitialized();
+            if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), &mut buffer_info) != 0 {
+                fg = bits_to_color(buffer_info.wAttributes);
+                bg = bits_to_color(buffer_info.wAttributes >> 4);
+            } else {
+                fg = color::WHITE;
+                bg = color::BLACK;
+            }
+        }
+        Ok(WinConsole {
+            buf: out,
+            def_foreground: fg,
+            def_background: bg,
+            foreground: fg,
+            background: bg,
+        })
+    }
+}
+
+impl<T: Write> Write for WinConsole<T> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.buf.write(buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        self.buf.flush()
+    }
+}
+
+impl<T: Write + Send + 'static> Terminal for WinConsole<T> {
+    type Output = T;
+
+    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
+        self.foreground = color;
+        self.apply();
+
+        Ok(true)
+    }
+
+    fn bg(&mut self, color: color::Color) -> io::Result<bool> {
+        self.background = color;
+        self.apply();
+
+        Ok(true)
+    }
+
+    fn attr(&mut self, attr: Attr) -> io::Result<bool> {
+        match attr {
+            Attr::ForegroundColor(f) => {
+                self.foreground = f;
+                self.apply();
+                Ok(true)
+            }
+            Attr::BackgroundColor(b) => {
+                self.background = b;
+                self.apply();
+                Ok(true)
+            }
+            _ => Ok(false),
+        }
+    }
+
+    fn supports_attr(&self, attr: Attr) -> bool {
+        // it claims support for underscore and reverse video, but I can't get
+        // it to do anything -cmr
+        match attr {
+            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true,
+            _ => false,
+        }
+    }
+
+    fn reset(&mut self) -> io::Result<bool> {
+        self.foreground = self.def_foreground;
+        self.background = self.def_background;
+        self.apply();
+
+        Ok(true)
+    }
+
+    fn get_ref(&self) -> &T {
+        &self.buf
+    }
+
+    fn get_mut(&mut self) -> &mut T {
+        &mut self.buf
+    }
+
+    fn into_inner(self) -> T
+        where Self: Sized
+    {
+        self.buf
+    }
+}
diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml
index 26ac7888184..10bdd6e877c 100644
--- a/src/libtest/Cargo.toml
+++ b/src/libtest/Cargo.toml
@@ -10,7 +10,8 @@ path = "lib.rs"
 crate-type = ["dylib", "rlib"]
 
 [dependencies]
-libtest = { version = "0.0.1" }
+getopts = "0.2"
+term = { path = "../libterm" }
 
 # not actually used but needed to always have proc_macro in the sysroot
 proc_macro = { path = "../libproc_macro" }
diff --git a/src/libtest/README.md b/src/libtest/README.md
deleted file mode 100644
index 6d9fe30dcad..00000000000
--- a/src/libtest/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-WIP - stable libtest
-===
-
-The migration of libtest to stable Rust is currently in progress.
-
-You can find libtest at: https://github.com/rust-lang/libtest . If you need to
-make a change:
-
-* perform the change there, 
-* do a new crates.io release, and
-* send a PR to rust-lang/rust bumping the libtest version.
-
-The roadmap of the migration is being tracked here: https://github.com/rust-lang/libtest/issues/2
diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs
new file mode 100644
index 00000000000..a06497f9862
--- /dev/null
+++ b/src/libtest/formatters/json.rs
@@ -0,0 +1,208 @@
+use super::*;
+
+pub(crate) struct JsonFormatter<T> {
+    out: OutputLocation<T>,
+}
+
+impl<T: Write> JsonFormatter<T> {
+    pub fn new(out: OutputLocation<T>) -> Self {
+        Self { out }
+    }
+
+    fn write_message(&mut self, s: &str) -> io::Result<()> {
+        assert!(!s.contains('\n'));
+
+        self.out.write_all(s.as_ref())?;
+        self.out.write_all(b"\n")
+    }
+
+    fn write_event(
+        &mut self,
+        ty: &str,
+        name: &str,
+        evt: &str,
+        extra: Option<String>,
+    ) -> io::Result<()> {
+        if let Some(extras) = extra {
+            self.write_message(&*format!(
+                r#"{{ "type": "{}", "name": "{}", "event": "{}", {} }}"#,
+                ty, name, evt, extras
+            ))
+        } else {
+            self.write_message(&*format!(
+                r#"{{ "type": "{}", "name": "{}", "event": "{}" }}"#,
+                ty, name, evt
+            ))
+        }
+    }
+}
+
+impl<T: Write> OutputFormatter for JsonFormatter<T> {
+    fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
+        self.write_message(&*format!(
+            r#"{{ "type": "suite", "event": "started", "test_count": {} }}"#,
+            test_count
+        ))
+    }
+
+    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
+        self.write_message(&*format!(
+            r#"{{ "type": "test", "event": "started", "name": "{}" }}"#,
+            desc.name
+        ))
+    }
+
+    fn write_result(
+        &mut self,
+        desc: &TestDesc,
+        result: &TestResult,
+        stdout: &[u8],
+    ) -> io::Result<()> {
+        match *result {
+            TrOk => self.write_event("test", desc.name.as_slice(), "ok", None),
+
+            TrFailed => {
+                let extra_data = if stdout.len() > 0 {
+                    Some(format!(
+                        r#""stdout": "{}""#,
+                        EscapedString(String::from_utf8_lossy(stdout))
+                    ))
+                } else {
+                    None
+                };
+
+                self.write_event("test", desc.name.as_slice(), "failed", extra_data)
+            }
+
+            TrFailedMsg(ref m) => self.write_event(
+                "test",
+                desc.name.as_slice(),
+                "failed",
+                Some(format!(r#""message": "{}""#, EscapedString(m))),
+            ),
+
+            TrIgnored => self.write_event("test", desc.name.as_slice(), "ignored", None),
+
+            TrAllowedFail => {
+                self.write_event("test", desc.name.as_slice(), "allowed_failure", None)
+            }
+
+            TrBench(ref bs) => {
+                let median = bs.ns_iter_summ.median as usize;
+                let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
+
+                let mbps = if bs.mb_s == 0 {
+                    String::new()
+                } else {
+                    format!(r#", "mib_per_second": {}"#, bs.mb_s)
+                };
+
+                let line = format!(
+                    "{{ \"type\": \"bench\", \
+                     \"name\": \"{}\", \
+                     \"median\": {}, \
+                     \"deviation\": {}{} }}",
+                    desc.name, median, deviation, mbps
+                );
+
+                self.write_message(&*line)
+            }
+        }
+    }
+
+    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
+        self.write_message(&*format!(
+            r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#,
+            desc.name
+        ))
+    }
+
+    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
+        self.write_message(&*format!(
+            "{{ \"type\": \"suite\", \
+             \"event\": \"{}\", \
+             \"passed\": {}, \
+             \"failed\": {}, \
+             \"allowed_fail\": {}, \
+             \"ignored\": {}, \
+             \"measured\": {}, \
+             \"filtered_out\": {} }}",
+            if state.failed == 0 { "ok" } else { "failed" },
+            state.passed,
+            state.failed + state.allowed_fail,
+            state.allowed_fail,
+            state.ignored,
+            state.measured,
+            state.filtered_out
+        ))?;
+
+        Ok(state.failed == 0)
+    }
+}
+
+/// A formatting utility used to print strings with characters in need of escaping.
+/// Base code taken form `libserialize::json::escape_str`
+struct EscapedString<S: AsRef<str>>(S);
+
+impl<S: AsRef<str>> ::std::fmt::Display for EscapedString<S> {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        let mut start = 0;
+
+        for (i, byte) in self.0.as_ref().bytes().enumerate() {
+            let escaped = match byte {
+                b'"' => "\\\"",
+                b'\\' => "\\\\",
+                b'\x00' => "\\u0000",
+                b'\x01' => "\\u0001",
+                b'\x02' => "\\u0002",
+                b'\x03' => "\\u0003",
+                b'\x04' => "\\u0004",
+                b'\x05' => "\\u0005",
+                b'\x06' => "\\u0006",
+                b'\x07' => "\\u0007",
+                b'\x08' => "\\b",
+                b'\t' => "\\t",
+                b'\n' => "\\n",
+                b'\x0b' => "\\u000b",
+                b'\x0c' => "\\f",
+                b'\r' => "\\r",
+                b'\x0e' => "\\u000e",
+                b'\x0f' => "\\u000f",
+                b'\x10' => "\\u0010",
+                b'\x11' => "\\u0011",
+                b'\x12' => "\\u0012",
+                b'\x13' => "\\u0013",
+                b'\x14' => "\\u0014",
+                b'\x15' => "\\u0015",
+                b'\x16' => "\\u0016",
+                b'\x17' => "\\u0017",
+                b'\x18' => "\\u0018",
+                b'\x19' => "\\u0019",
+                b'\x1a' => "\\u001a",
+                b'\x1b' => "\\u001b",
+                b'\x1c' => "\\u001c",
+                b'\x1d' => "\\u001d",
+                b'\x1e' => "\\u001e",
+                b'\x1f' => "\\u001f",
+                b'\x7f' => "\\u007f",
+                _ => {
+                    continue;
+                }
+            };
+
+            if start < i {
+                f.write_str(&self.0.as_ref()[start..i])?;
+            }
+
+            f.write_str(escaped)?;
+
+            start = i + 1;
+        }
+
+        if start != self.0.as_ref().len() {
+            f.write_str(&self.0.as_ref()[start..])?;
+        }
+
+        Ok(())
+    }
+}
diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs
new file mode 100644
index 00000000000..be5f6a65039
--- /dev/null
+++ b/src/libtest/formatters/mod.rs
@@ -0,0 +1,22 @@
+use super::*;
+
+mod pretty;
+mod json;
+mod terse;
+
+pub(crate) use self::pretty::PrettyFormatter;
+pub(crate) use self::json::JsonFormatter;
+pub(crate) use self::terse::TerseFormatter;
+
+pub(crate) trait OutputFormatter {
+    fn write_run_start(&mut self, test_count: usize) -> io::Result<()>;
+    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()>;
+    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()>;
+    fn write_result(
+        &mut self,
+        desc: &TestDesc,
+        result: &TestResult,
+        stdout: &[u8],
+    ) -> io::Result<()>;
+    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool>;
+}
diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs
new file mode 100644
index 00000000000..4af00428ca8
--- /dev/null
+++ b/src/libtest/formatters/pretty.rs
@@ -0,0 +1,232 @@
+use super::*;
+
+pub(crate) struct PrettyFormatter<T> {
+    out: OutputLocation<T>,
+    use_color: bool,
+
+    /// Number of columns to fill when aligning names
+    max_name_len: usize,
+
+    is_multithreaded: bool,
+}
+
+impl<T: Write> PrettyFormatter<T> {
+    pub fn new(
+        out: OutputLocation<T>,
+        use_color: bool,
+        max_name_len: usize,
+        is_multithreaded: bool,
+    ) -> Self {
+        PrettyFormatter {
+            out,
+            use_color,
+            max_name_len,
+            is_multithreaded,
+        }
+    }
+
+    #[cfg(test)]
+    pub fn output_location(&self) -> &OutputLocation<T> {
+        &self.out
+    }
+
+    pub fn write_ok(&mut self) -> io::Result<()> {
+        self.write_short_result("ok", term::color::GREEN)
+    }
+
+    pub fn write_failed(&mut self) -> io::Result<()> {
+        self.write_short_result("FAILED", term::color::RED)
+    }
+
+    pub fn write_ignored(&mut self) -> io::Result<()> {
+        self.write_short_result("ignored", term::color::YELLOW)
+    }
+
+    pub fn write_allowed_fail(&mut self) -> io::Result<()> {
+        self.write_short_result("FAILED (allowed)", term::color::YELLOW)
+    }
+
+    pub fn write_bench(&mut self) -> io::Result<()> {
+        self.write_pretty("bench", term::color::CYAN)
+    }
+
+    pub fn write_short_result(
+        &mut self,
+        result: &str,
+        color: term::color::Color,
+    ) -> io::Result<()> {
+        self.write_pretty(result, color)?;
+        self.write_plain("\n")
+    }
+
+    pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
+        match self.out {
+            Pretty(ref mut term) => {
+                if self.use_color {
+                    term.fg(color)?;
+                }
+                term.write_all(word.as_bytes())?;
+                if self.use_color {
+                    term.reset()?;
+                }
+                term.flush()
+            }
+            Raw(ref mut stdout) => {
+                stdout.write_all(word.as_bytes())?;
+                stdout.flush()
+            }
+        }
+    }
+
+    pub fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> {
+        let s = s.as_ref();
+        self.out.write_all(s.as_bytes())?;
+        self.out.flush()
+    }
+
+    pub fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> {
+        self.write_plain("\nsuccesses:\n")?;
+        let mut successes = Vec::new();
+        let mut stdouts = String::new();
+        for &(ref f, ref stdout) in &state.not_failures {
+            successes.push(f.name.to_string());
+            if !stdout.is_empty() {
+                stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
+                let output = String::from_utf8_lossy(stdout);
+                stdouts.push_str(&output);
+                stdouts.push_str("\n");
+            }
+        }
+        if !stdouts.is_empty() {
+            self.write_plain("\n")?;
+            self.write_plain(&stdouts)?;
+        }
+
+        self.write_plain("\nsuccesses:\n")?;
+        successes.sort();
+        for name in &successes {
+            self.write_plain(&format!("    {}\n", name))?;
+        }
+        Ok(())
+    }
+
+    pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
+        self.write_plain("\nfailures:\n")?;
+        let mut failures = Vec::new();
+        let mut fail_out = String::new();
+        for &(ref f, ref stdout) in &state.failures {
+            failures.push(f.name.to_string());
+            if !stdout.is_empty() {
+                fail_out.push_str(&format!("---- {} stdout ----\n", f.name));
+                let output = String::from_utf8_lossy(stdout);
+                fail_out.push_str(&output);
+                fail_out.push_str("\n");
+            }
+        }
+        if !fail_out.is_empty() {
+            self.write_plain("\n")?;
+            self.write_plain(&fail_out)?;
+        }
+
+        self.write_plain("\nfailures:\n")?;
+        failures.sort();
+        for name in &failures {
+            self.write_plain(&format!("    {}\n", name))?;
+        }
+        Ok(())
+    }
+
+    fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
+        let name = desc.padded_name(self.max_name_len, desc.name.padding());
+        self.write_plain(&format!("test {} ... ", name))?;
+
+        Ok(())
+    }
+}
+
+impl<T: Write> OutputFormatter for PrettyFormatter<T> {
+    fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
+        let noun = if test_count != 1 { "tests" } else { "test" };
+        self.write_plain(&format!("\nrunning {} {}\n", test_count, noun))
+    }
+
+    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
+        // When running tests concurrently, we should not print
+        // the test's name as the result will be mis-aligned.
+        // When running the tests serially, we print the name here so
+        // that the user can see which test hangs.
+        if !self.is_multithreaded {
+            self.write_test_name(desc)?;
+        }
+
+        Ok(())
+    }
+
+    fn write_result(&mut self, desc: &TestDesc, result: &TestResult, _: &[u8]) -> io::Result<()> {
+        if self.is_multithreaded {
+            self.write_test_name(desc)?;
+        }
+
+        match *result {
+            TrOk => self.write_ok(),
+            TrFailed | TrFailedMsg(_) => self.write_failed(),
+            TrIgnored => self.write_ignored(),
+            TrAllowedFail => self.write_allowed_fail(),
+            TrBench(ref bs) => {
+                self.write_bench()?;
+                self.write_plain(&format!(": {}\n", fmt_bench_samples(bs)))
+            }
+        }
+    }
+
+    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
+        if self.is_multithreaded {
+            self.write_test_name(desc)?;
+        }
+
+        self.write_plain(&format!(
+            "test {} has been running for over {} seconds\n",
+            desc.name, TEST_WARN_TIMEOUT_S
+        ))
+    }
+
+    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
+        if state.options.display_output {
+            self.write_successes(state)?;
+        }
+        let success = state.failed == 0;
+        if !success {
+            self.write_failures(state)?;
+        }
+
+        self.write_plain("\ntest result: ")?;
+
+        if success {
+            // There's no parallelism at this point so it's safe to use color
+            self.write_pretty("ok", term::color::GREEN)?;
+        } else {
+            self.write_pretty("FAILED", term::color::RED)?;
+        }
+
+        let s = if state.allowed_fail > 0 {
+            format!(
+                ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n",
+                state.passed,
+                state.failed + state.allowed_fail,
+                state.allowed_fail,
+                state.ignored,
+                state.measured,
+                state.filtered_out
+            )
+        } else {
+            format!(
+                ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
+                state.passed, state.failed, state.ignored, state.measured, state.filtered_out
+            )
+        };
+
+        self.write_plain(&s)?;
+
+        Ok(success)
+    }
+}
diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs
new file mode 100644
index 00000000000..1400fba5d60
--- /dev/null
+++ b/src/libtest/formatters/terse.rs
@@ -0,0 +1,235 @@
+use super::*;
+
+pub(crate) struct TerseFormatter<T> {
+    out: OutputLocation<T>,
+    use_color: bool,
+    is_multithreaded: bool,
+    /// Number of columns to fill when aligning names
+    max_name_len: usize,
+
+    test_count: usize,
+    total_test_count: usize,
+}
+
+impl<T: Write> TerseFormatter<T> {
+    pub fn new(
+        out: OutputLocation<T>,
+        use_color: bool,
+        max_name_len: usize,
+        is_multithreaded: bool,
+    ) -> Self {
+        TerseFormatter {
+            out,
+            use_color,
+            max_name_len,
+            is_multithreaded,
+            test_count: 0,
+            total_test_count: 0, // initialized later, when write_run_start is called
+        }
+    }
+
+    pub fn write_ok(&mut self) -> io::Result<()> {
+        self.write_short_result(".", term::color::GREEN)
+    }
+
+    pub fn write_failed(&mut self) -> io::Result<()> {
+        self.write_short_result("F", term::color::RED)
+    }
+
+    pub fn write_ignored(&mut self) -> io::Result<()> {
+        self.write_short_result("i", term::color::YELLOW)
+    }
+
+    pub fn write_allowed_fail(&mut self) -> io::Result<()> {
+        self.write_short_result("a", term::color::YELLOW)
+    }
+
+    pub fn write_bench(&mut self) -> io::Result<()> {
+        self.write_pretty("bench", term::color::CYAN)
+    }
+
+    pub fn write_short_result(
+        &mut self,
+        result: &str,
+        color: term::color::Color,
+    ) -> io::Result<()> {
+        self.write_pretty(result, color)?;
+        if self.test_count % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 {
+            // we insert a new line every 100 dots in order to flush the
+            // screen when dealing with line-buffered output (e.g., piping to
+            // `stamp` in the rust CI).
+            let out = format!(" {}/{}\n", self.test_count+1, self.total_test_count);
+            self.write_plain(&out)?;
+        }
+
+        self.test_count += 1;
+        Ok(())
+    }
+
+    pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
+        match self.out {
+            Pretty(ref mut term) => {
+                if self.use_color {
+                    term.fg(color)?;
+                }
+                term.write_all(word.as_bytes())?;
+                if self.use_color {
+                    term.reset()?;
+                }
+                term.flush()
+            }
+            Raw(ref mut stdout) => {
+                stdout.write_all(word.as_bytes())?;
+                stdout.flush()
+            }
+        }
+    }
+
+    pub fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> {
+        let s = s.as_ref();
+        self.out.write_all(s.as_bytes())?;
+        self.out.flush()
+    }
+
+    pub fn write_outputs(&mut self, state: &ConsoleTestState) -> io::Result<()> {
+        self.write_plain("\nsuccesses:\n")?;
+        let mut successes = Vec::new();
+        let mut stdouts = String::new();
+        for &(ref f, ref stdout) in &state.not_failures {
+            successes.push(f.name.to_string());
+            if !stdout.is_empty() {
+                stdouts.push_str(&format!("---- {} stdout ----\n", f.name));
+                let output = String::from_utf8_lossy(stdout);
+                stdouts.push_str(&output);
+                stdouts.push_str("\n");
+            }
+        }
+        if !stdouts.is_empty() {
+            self.write_plain("\n")?;
+            self.write_plain(&stdouts)?;
+        }
+
+        self.write_plain("\nsuccesses:\n")?;
+        successes.sort();
+        for name in &successes {
+            self.write_plain(&format!("    {}\n", name))?;
+        }
+        Ok(())
+    }
+
+    pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
+        self.write_plain("\nfailures:\n")?;
+        let mut failures = Vec::new();
+        let mut fail_out = String::new();
+        for &(ref f, ref stdout) in &state.failures {
+            failures.push(f.name.to_string());
+            if !stdout.is_empty() {
+                fail_out.push_str(&format!("---- {} stdout ----\n", f.name));
+                let output = String::from_utf8_lossy(stdout);
+                fail_out.push_str(&output);
+                fail_out.push_str("\n");
+            }
+        }
+        if !fail_out.is_empty() {
+            self.write_plain("\n")?;
+            self.write_plain(&fail_out)?;
+        }
+
+        self.write_plain("\nfailures:\n")?;
+        failures.sort();
+        for name in &failures {
+            self.write_plain(&format!("    {}\n", name))?;
+        }
+        Ok(())
+    }
+
+    fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
+        let name = desc.padded_name(self.max_name_len, desc.name.padding());
+        self.write_plain(&format!("test {} ... ", name))?;
+
+        Ok(())
+    }
+}
+
+impl<T: Write> OutputFormatter for TerseFormatter<T> {
+    fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
+        self.total_test_count = test_count;
+        let noun = if test_count != 1 { "tests" } else { "test" };
+        self.write_plain(&format!("\nrunning {} {}\n", test_count, noun))
+    }
+
+    fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
+        // Remnants from old libtest code that used the padding value
+        // in order to indicate benchmarks.
+        // When running benchmarks, terse-mode should still print their name as if
+        // it is the Pretty formatter.
+        if !self.is_multithreaded && desc.name.padding() == PadOnRight {
+            self.write_test_name(desc)?;
+        }
+
+        Ok(())
+    }
+
+    fn write_result(&mut self, desc: &TestDesc, result: &TestResult, _: &[u8]) -> io::Result<()> {
+        match *result {
+            TrOk => self.write_ok(),
+            TrFailed | TrFailedMsg(_) => self.write_failed(),
+            TrIgnored => self.write_ignored(),
+            TrAllowedFail => self.write_allowed_fail(),
+            TrBench(ref bs) => {
+                if self.is_multithreaded {
+                    self.write_test_name(desc)?;
+                }
+                self.write_bench()?;
+                self.write_plain(&format!(": {}\n", fmt_bench_samples(bs)))
+            }
+        }
+    }
+
+    fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
+        self.write_plain(&format!(
+            "test {} has been running for over {} seconds\n",
+            desc.name, TEST_WARN_TIMEOUT_S
+        ))
+    }
+
+    fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
+        if state.options.display_output {
+            self.write_outputs(state)?;
+        }
+        let success = state.failed == 0;
+        if !success {
+            self.write_failures(state)?;
+        }
+
+        self.write_plain("\ntest result: ")?;
+
+        if success {
+            // There's no parallelism at this point so it's safe to use color
+            self.write_pretty("ok", term::color::GREEN)?;
+        } else {
+            self.write_pretty("FAILED", term::color::RED)?;
+        }
+
+        let s = if state.allowed_fail > 0 {
+            format!(
+                ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n",
+                state.passed,
+                state.failed + state.allowed_fail,
+                state.allowed_fail,
+                state.ignored,
+                state.measured,
+                state.filtered_out
+            )
+        } else {
+            format!(
+                ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
+                state.passed, state.failed, state.ignored, state.measured, state.filtered_out
+            )
+        };
+
+        self.write_plain(&s)?;
+
+        Ok(success)
+    }
+}
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 5c91c0ec43b..26612964c30 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -8,48 +8,2224 @@
 //!
 //! See the [Testing Chapter](../book/ch11-00-testing.html) of the book for more details.
 
+// Currently, not much of this is meant for users. It is intended to
+// support the simplest interface possible for representing and
+// running tests while providing a base that other test frameworks may
+// build off of.
+
+// N.B., this is also specified in this crate's Cargo.toml, but libsyntax contains logic specific to
+// this crate, which relies on this attribute (rather than the value of `--crate-name` passed by
+// cargo) to detect this crate.
+
+#![deny(rust_2018_idioms)]
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "27812")]
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
-       test(attr(deny(warnings))))]
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
 #![feature(asm)]
+#![feature(fnbox)]
+#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc, rustc_private))]
+#![feature(nll)]
+#![feature(set_stdio)]
+#![feature(panic_unwind)]
 #![feature(staged_api)]
+#![feature(termination_trait_lib)]
 #![feature(test)]
 
-extern crate libtest;
+use getopts;
+#[cfg(any(unix, target_os = "cloudabi"))]
+extern crate libc;
+use term;
+
+// FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind
+//                on aarch64-pc-windows-msvc, so we don't link libtest against
+//                libunwind (for the time being), even though it means that
+//                libtest won't be fully functional on this platform.
+//
+// See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437
+#[cfg(not(all(windows, target_arch = "aarch64")))]
+extern crate panic_unwind;
+
+pub use self::ColorConfig::*;
+use self::NamePadding::*;
+use self::OutputLocation::*;
+use self::TestEvent::*;
+pub use self::TestFn::*;
+pub use self::TestName::*;
+pub use self::TestResult::*;
+
+use std::any::Any;
+use std::borrow::Cow;
+use std::boxed::FnBox;
+use std::cmp;
+use std::collections::BTreeMap;
+use std::env;
+use std::fmt;
+use std::fs::File;
+use std::io;
+use std::io::prelude::*;
+use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::path::PathBuf;
+use std::process;
+use std::process::Termination;
+use std::sync::mpsc::{channel, Sender};
+use std::sync::{Arc, Mutex};
+use std::thread;
+use std::time::{Duration, Instant};
+
+const TEST_WARN_TIMEOUT_S: u64 = 60;
+const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in quiet mode
+
+// to be used by rustc to compile tests in libtest
+pub mod test {
+    pub use crate::{
+        assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static,
+        Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, ShouldPanic,
+        StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, TestOpts,
+        TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk,
+    };
+}
+
+mod formatters;
+pub mod stats;
+
+use crate::formatters::{JsonFormatter, OutputFormatter, PrettyFormatter, TerseFormatter};
+
+/// Whether to execute tests concurrently or not
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Concurrent {
+    Yes,
+    No,
+}
+
+// The name of a test. By convention this follows the rules for rust
+// paths; i.e., it should be a series of identifiers separated by double
+// colons. This way if some test runner wants to arrange the tests
+// hierarchically it may.
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum TestName {
+    StaticTestName(&'static str),
+    DynTestName(String),
+    AlignedTestName(Cow<'static, str>, NamePadding),
+}
+impl TestName {
+    fn as_slice(&self) -> &str {
+        match *self {
+            StaticTestName(s) => s,
+            DynTestName(ref s) => s,
+            AlignedTestName(ref s, _) => &*s,
+        }
+    }
+
+    fn padding(&self) -> NamePadding {
+        match self {
+            &AlignedTestName(_, p) => p,
+            _ => PadNone,
+        }
+    }
+
+    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(),
+        };
+
+        TestName::AlignedTestName(name, padding)
+    }
+}
+impl fmt::Display for TestName {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self.as_slice(), f)
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub enum NamePadding {
+    PadNone,
+    PadOnRight,
+}
+
+impl TestDesc {
+    fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
+        let mut name = String::from(self.name.as_slice());
+        let fill = column_count.saturating_sub(name.len());
+        let pad = " ".repeat(fill);
+        match align {
+            PadNone => name,
+            PadOnRight => {
+                name.push_str(&pad);
+                name
+            }
+        }
+    }
+}
+
+/// Represents a benchmark function.
+pub trait TDynBenchFn: Send {
+    fn run(&self, harness: &mut Bencher);
+}
+
+// A function that runs a test. If the function returns successfully,
+// the test succeeds; if the function panics then the test fails. We
+// may need to come up with a more clever definition of test in order
+// to support isolation of tests into threads.
+pub enum TestFn {
+    StaticTestFn(fn()),
+    StaticBenchFn(fn(&mut Bencher)),
+    DynTestFn(Box<dyn FnBox() + Send>),
+    DynBenchFn(Box<dyn TDynBenchFn + 'static>),
+}
+
+impl TestFn {
+    fn padding(&self) -> NamePadding {
+        match *self {
+            StaticTestFn(..) => PadNone,
+            StaticBenchFn(..) => PadOnRight,
+            DynTestFn(..) => PadNone,
+            DynBenchFn(..) => PadOnRight,
+        }
+    }
+}
+
+impl fmt::Debug for TestFn {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(match *self {
+            StaticTestFn(..) => "StaticTestFn(..)",
+            StaticBenchFn(..) => "StaticBenchFn(..)",
+            DynTestFn(..) => "DynTestFn(..)",
+            DynBenchFn(..) => "DynBenchFn(..)",
+        })
+    }
+}
+
+/// Manager of the benchmarking runs.
+///
+/// This is fed into functions marked with `#[bench]` to allow for
+/// set-up & tear-down before running a piece of code repeatedly via a
+/// call to `iter`.
+#[derive(Clone)]
+pub struct Bencher {
+    mode: BenchMode,
+    summary: Option<stats::Summary>,
+    pub bytes: u64,
+}
+
+#[derive(Clone, PartialEq, Eq)]
+pub enum BenchMode {
+    Auto,
+    Single,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum ShouldPanic {
+    No,
+    Yes,
+    YesWithMessage(&'static str),
+}
+
+// The definition of a single test. A test runner will run a list of
+// these.
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct TestDesc {
+    pub name: TestName,
+    pub ignore: bool,
+    pub should_panic: ShouldPanic,
+    pub allow_fail: bool,
+}
+
+#[derive(Debug)]
+pub struct TestDescAndFn {
+    pub desc: TestDesc,
+    pub testfn: TestFn,
+}
+
+#[derive(Clone, PartialEq, Debug, Copy)]
+pub struct Metric {
+    value: f64,
+    noise: f64,
+}
+
+impl Metric {
+    pub fn new(value: f64, noise: f64) -> Metric {
+        Metric { value, noise }
+    }
+}
+
+/// In case we want to add other options as well, just add them in this struct.
+#[derive(Copy, Clone, Debug)]
+pub struct Options {
+    display_output: bool,
+}
+
+impl Options {
+    pub fn new() -> Options {
+        Options {
+            display_output: false,
+        }
+    }
+
+    pub fn display_output(mut self, display_output: bool) -> Options {
+        self.display_output = display_output;
+        self
+    }
+}
+
+// The default console test runner. It accepts the command line
+// arguments and a vector of test_descs.
+pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Options) {
+    let mut opts = match parse_opts(args) {
+        Some(Ok(o)) => o,
+        Some(Err(msg)) => {
+            eprintln!("error: {}", msg);
+            process::exit(101);
+        }
+        None => return,
+    };
+
+    opts.options = options;
+    if opts.list {
+        if let Err(e) = list_tests_console(&opts, tests) {
+            eprintln!("error: io error when listing tests: {:?}", e);
+            process::exit(101);
+        }
+    } else {
+        match run_tests_console(&opts, tests) {
+            Ok(true) => {}
+            Ok(false) => process::exit(101),
+            Err(e) => {
+                eprintln!("error: io error when listing tests: {:?}", e);
+                process::exit(101);
+            }
+        }
+    }
+}
+
+// A variant optimized for invocation with a static test vector.
+// This will panic (intentionally) when fed any dynamic tests, because
+// it is copying the static values out into a dynamic vector and cannot
+// copy dynamic values. It is doing this because from this point on
+// a Vec<TestDescAndFn> is used in order to effect ownership-transfer
+// semantics into parallel test runners, which in turn requires a Vec<>
+// rather than a &[].
+pub fn test_main_static(tests: &[&TestDescAndFn]) {
+    let args = env::args().collect::<Vec<_>>();
+    let owned_tests = tests
+        .iter()
+        .map(|t| match t.testfn {
+            StaticTestFn(f) => TestDescAndFn {
+                testfn: StaticTestFn(f),
+                desc: t.desc.clone(),
+            },
+            StaticBenchFn(f) => TestDescAndFn {
+                testfn: StaticBenchFn(f),
+                desc: t.desc.clone(),
+            },
+            _ => panic!("non-static tests passed to test::test_main_static"),
+        })
+        .collect();
+    test_main(&args, owned_tests, Options::new())
+}
+
+/// Invoked when unit tests terminate. Should panic if the unit
+/// Tests is considered a failure. By default, invokes `report()`
+/// and checks for a `0` result.
+pub fn assert_test_result<T: Termination>(result: T) {
+    let code = result.report();
+    assert_eq!(
+        code, 0,
+        "the test returned a termination value with a non-zero status code ({}) \
+         which indicates a failure",
+        code
+    );
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum ColorConfig {
+    AutoColor,
+    AlwaysColor,
+    NeverColor,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum OutputFormat {
+    Pretty,
+    Terse,
+    Json,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum RunIgnored {
+    Yes,
+    No,
+    Only,
+}
+
+#[derive(Debug)]
+pub struct TestOpts {
+    pub list: bool,
+    pub filter: Option<String>,
+    pub filter_exact: bool,
+    pub exclude_should_panic: bool,
+    pub run_ignored: RunIgnored,
+    pub run_tests: bool,
+    pub bench_benchmarks: bool,
+    pub logfile: Option<PathBuf>,
+    pub nocapture: bool,
+    pub color: ColorConfig,
+    pub format: OutputFormat,
+    pub test_threads: Option<usize>,
+    pub skip: Vec<String>,
+    pub options: Options,
+}
+
+impl TestOpts {
+    #[cfg(test)]
+    fn new() -> TestOpts {
+        TestOpts {
+            list: false,
+            filter: None,
+            filter_exact: false,
+            exclude_should_panic: false,
+            run_ignored: RunIgnored::No,
+            run_tests: false,
+            bench_benchmarks: false,
+            logfile: None,
+            nocapture: false,
+            color: AutoColor,
+            format: OutputFormat::Pretty,
+            test_threads: None,
+            skip: vec![],
+            options: Options::new(),
+        }
+    }
+}
+
+/// Result of parsing the options.
+pub type OptRes = Result<TestOpts, String>;
+
+fn optgroups() -> getopts::Options {
+    let mut opts = getopts::Options::new();
+    opts.optflag("", "include-ignored", "Run ignored and not ignored tests")
+        .optflag("", "ignored", "Run only ignored tests")
+        .optflag("", "exclude-should-panic", "Excludes tests marked as should_panic")
+        .optflag("", "test", "Run tests and not benchmarks")
+        .optflag("", "bench", "Run benchmarks instead of tests")
+        .optflag("", "list", "List all tests and benchmarks")
+        .optflag("h", "help", "Display this message (longer with --help)")
+        .optopt(
+            "",
+            "logfile",
+            "Write logs to the specified file instead \
+             of stdout",
+            "PATH",
+        )
+        .optflag(
+            "",
+            "nocapture",
+            "don't capture stdout/stderr of each \
+             task, allow printing directly",
+        )
+        .optopt(
+            "",
+            "test-threads",
+            "Number of threads used for running tests \
+             in parallel",
+            "n_threads",
+        )
+        .optmulti(
+            "",
+            "skip",
+            "Skip tests whose names contain FILTER (this flag can \
+             be used multiple times)",
+            "FILTER",
+        )
+        .optflag(
+            "q",
+            "quiet",
+            "Display one character per test instead of one line. \
+             Alias to --format=terse",
+        )
+        .optflag(
+            "",
+            "exact",
+            "Exactly match filters rather than by substring",
+        )
+        .optopt(
+            "",
+            "color",
+            "Configure coloring of output:
+            auto   = colorize if stdout is a tty and tests are run on serially (default);
+            always = always colorize output;
+            never  = never colorize output;",
+            "auto|always|never",
+        )
+        .optopt(
+            "",
+            "format",
+            "Configure formatting of output:
+            pretty = Print verbose output;
+            terse  = Display one character per test;
+            json   = Output a json document",
+            "pretty|terse|json",
+        )
+        .optopt(
+            "Z",
+            "",
+            "Enable nightly-only flags:
+            unstable-options = Allow use of experimental features",
+            "unstable-options",
+        );
+    return opts;
+}
+
+fn usage(binary: &str, options: &getopts::Options) {
+    let message = format!("Usage: {} [OPTIONS] [FILTER]", binary);
+    println!(
+        r#"{usage}
+
+The FILTER string is tested against the name of all tests, and only those
+tests whose names contain the filter are run.
+
+By default, all tests are run in parallel. This can be altered with the
+--test-threads flag or the RUST_TEST_THREADS environment variable when running
+tests (set it to 1).
+
+All tests have their standard output and standard error captured by default.
+This can be overridden with the --nocapture flag or setting RUST_TEST_NOCAPTURE
+environment variable to a value other than "0". Logging is not captured by default.
+
+Test Attributes:
+
+    #[test]        - Indicates a function is a test to be run. This function
+                     takes no arguments.
+    #[bench]       - Indicates a function is a benchmark to be run. This
+                     function takes one argument (test::Bencher).
+    #[should_panic] - This function (also labeled with #[test]) will only pass if
+                     the code causes a panic (an assertion failure or panic!)
+                     A message may be provided, which the failure string must
+                     contain: #[should_panic(expected = "foo")].
+    #[ignore]      - When applied to a function which is already attributed as a
+                     test, then the test runner will ignore these tests during
+                     normal test runs. Running with --ignored or --include-ignored will run
+                     these tests."#,
+        usage = options.usage(&message)
+    );
+}
+
+// FIXME: Copied from libsyntax until linkage errors are resolved. Issue #47566
+fn is_nightly() -> bool {
+    // Whether this is a feature-staged build, i.e., on the beta or stable channel
+    let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
+    // Whether we should enable unstable features for bootstrapping
+    let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
+
+    bootstrap || !disable_unstable_features
+}
+
+// Parses command line arguments into test options
+pub fn parse_opts(args: &[String]) -> Option<OptRes> {
+    let mut allow_unstable = false;
+    let opts = optgroups();
+    let args = args.get(1..).unwrap_or(args);
+    let matches = match opts.parse(args) {
+        Ok(m) => m,
+        Err(f) => return Some(Err(f.to_string())),
+    };
+
+    if let Some(opt) = matches.opt_str("Z") {
+        if !is_nightly() {
+            return Some(Err(
+                "the option `Z` is only accepted on the nightly compiler".into(),
+            ));
+        }
+
+        match &*opt {
+            "unstable-options" => {
+                allow_unstable = true;
+            }
+            _ => {
+                return Some(Err("Unrecognized option to `Z`".into()));
+            }
+        }
+    };
+
+    if matches.opt_present("h") {
+        usage(&args[0], &opts);
+        return None;
+    }
+
+    let filter = if !matches.free.is_empty() {
+        Some(matches.free[0].clone())
+    } else {
+        None
+    };
+
+    let exclude_should_panic = matches.opt_present("exclude-should-panic");
+    if !allow_unstable && exclude_should_panic {
+        return Some(Err(
+            "The \"exclude-should-panic\" flag is only accepted on the nightly compiler".into(),
+        ));
+    }
+
+    let include_ignored = matches.opt_present("include-ignored");
+    if !allow_unstable && include_ignored {
+        return Some(Err(
+            "The \"include-ignored\" flag is only accepted on the nightly compiler".into(),
+        ));
+    }
+
+    let run_ignored = match (include_ignored, matches.opt_present("ignored")) {
+        (true, true) => {
+            return Some(Err(
+                "the options --include-ignored and --ignored are mutually exclusive".into(),
+            ));
+        }
+        (true, false) => RunIgnored::Yes,
+        (false, true) => RunIgnored::Only,
+        (false, false) => RunIgnored::No,
+    };
+    let quiet = matches.opt_present("quiet");
+    let exact = matches.opt_present("exact");
+    let list = matches.opt_present("list");
+
+    let logfile = matches.opt_str("logfile");
+    let logfile = logfile.map(|s| PathBuf::from(&s));
+
+    let bench_benchmarks = matches.opt_present("bench");
+    let run_tests = !bench_benchmarks || matches.opt_present("test");
+
+    let mut nocapture = matches.opt_present("nocapture");
+    if !nocapture {
+        nocapture = match env::var("RUST_TEST_NOCAPTURE") {
+            Ok(val) => &val != "0",
+            Err(_) => false,
+        };
+    }
+
+    let test_threads = match matches.opt_str("test-threads") {
+        Some(n_str) => match n_str.parse::<usize>() {
+            Ok(0) => return Some(Err("argument for --test-threads must not be 0".to_string())),
+            Ok(n) => Some(n),
+            Err(e) => {
+                return Some(Err(format!(
+                    "argument for --test-threads must be a number > 0 \
+                     (error: {})",
+                    e
+                )));
+            }
+        },
+        None => None,
+    };
+
+    let color = match matches.opt_str("color").as_ref().map(|s| &**s) {
+        Some("auto") | None => AutoColor,
+        Some("always") => AlwaysColor,
+        Some("never") => NeverColor,
+
+        Some(v) => {
+            return Some(Err(format!(
+                "argument for --color must be auto, always, or never (was \
+                 {})",
+                v
+            )));
+        }
+    };
+
+    let format = match matches.opt_str("format").as_ref().map(|s| &**s) {
+        None if quiet => OutputFormat::Terse,
+        Some("pretty") | None => OutputFormat::Pretty,
+        Some("terse") => OutputFormat::Terse,
+        Some("json") => {
+            if !allow_unstable {
+                return Some(Err(
+                    "The \"json\" format is only accepted on the nightly compiler".into(),
+                ));
+            }
+            OutputFormat::Json
+        }
+
+        Some(v) => {
+            return Some(Err(format!(
+                "argument for --format must be pretty, terse, or json (was \
+                 {})",
+                v
+            )));
+        }
+    };
+
+    let test_opts = TestOpts {
+        list,
+        filter,
+        filter_exact: exact,
+        exclude_should_panic,
+        run_ignored,
+        run_tests,
+        bench_benchmarks,
+        logfile,
+        nocapture,
+        color,
+        format,
+        test_threads,
+        skip: matches.opt_strs("skip"),
+        options: Options::new(),
+    };
+
+    Some(Ok(test_opts))
+}
+
+#[derive(Clone, PartialEq)]
+pub struct BenchSamples {
+    ns_iter_summ: stats::Summary,
+    mb_s: usize,
+}
+
+#[derive(Clone, PartialEq)]
+pub enum TestResult {
+    TrOk,
+    TrFailed,
+    TrFailedMsg(String),
+    TrIgnored,
+    TrAllowedFail,
+    TrBench(BenchSamples),
+}
+
+unsafe impl Send for TestResult {}
+
+enum OutputLocation<T> {
+    Pretty(Box<term::StdoutTerminal>),
+    Raw(T),
+}
+
+impl<T: Write> Write for OutputLocation<T> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        match *self {
+            Pretty(ref mut term) => term.write(buf),
+            Raw(ref mut stdout) => stdout.write(buf),
+        }
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        match *self {
+            Pretty(ref mut term) => term.flush(),
+            Raw(ref mut stdout) => stdout.flush(),
+        }
+    }
+}
+
+struct ConsoleTestState {
+    log_out: Option<File>,
+    total: usize,
+    passed: usize,
+    failed: usize,
+    ignored: usize,
+    allowed_fail: usize,
+    filtered_out: usize,
+    measured: usize,
+    metrics: MetricMap,
+    failures: Vec<(TestDesc, Vec<u8>)>,
+    not_failures: Vec<(TestDesc, Vec<u8>)>,
+    options: Options,
+}
+
+impl ConsoleTestState {
+    pub fn new(opts: &TestOpts) -> io::Result<ConsoleTestState> {
+        let log_out = match opts.logfile {
+            Some(ref path) => Some(File::create(path)?),
+            None => None,
+        };
+
+        Ok(ConsoleTestState {
+            log_out,
+            total: 0,
+            passed: 0,
+            failed: 0,
+            ignored: 0,
+            allowed_fail: 0,
+            filtered_out: 0,
+            measured: 0,
+            metrics: MetricMap::new(),
+            failures: Vec::new(),
+            not_failures: Vec::new(),
+            options: opts.options,
+        })
+    }
+
+    pub fn write_log<S: AsRef<str>>(&mut self, msg: S) -> io::Result<()> {
+        let msg = msg.as_ref();
+        match self.log_out {
+            None => Ok(()),
+            Some(ref mut o) => o.write_all(msg.as_bytes()),
+        }
+    }
+
+    pub fn write_log_result(&mut self, test: &TestDesc, result: &TestResult) -> io::Result<()> {
+        self.write_log(format!(
+            "{} {}\n",
+            match *result {
+                TrOk => "ok".to_owned(),
+                TrFailed => "failed".to_owned(),
+                TrFailedMsg(ref msg) => format!("failed: {}", msg),
+                TrIgnored => "ignored".to_owned(),
+                TrAllowedFail => "failed (allowed)".to_owned(),
+                TrBench(ref bs) => fmt_bench_samples(bs),
+            },
+            test.name
+        ))
+    }
+
+    fn current_test_count(&self) -> usize {
+        self.passed + self.failed + self.ignored + self.measured + self.allowed_fail
+    }
+}
+
+// Format a number with thousands separators
+fn fmt_thousands_sep(mut n: usize, sep: char) -> String {
+    use std::fmt::Write;
+    let mut output = String::new();
+    let mut trailing = false;
+    for &pow in &[9, 6, 3, 0] {
+        let base = 10_usize.pow(pow);
+        if pow == 0 || trailing || n / base != 0 {
+            if !trailing {
+                output.write_fmt(format_args!("{}", n / base)).unwrap();
+            } else {
+                output.write_fmt(format_args!("{:03}", n / base)).unwrap();
+            }
+            if pow != 0 {
+                output.push(sep);
+            }
+            trailing = true;
+        }
+        n %= base;
+    }
+
+    output
+}
+
+pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
+    use std::fmt::Write;
+    let mut output = String::new();
+
+    let median = bs.ns_iter_summ.median as usize;
+    let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
+
+    output
+        .write_fmt(format_args!(
+            "{:>11} ns/iter (+/- {})",
+            fmt_thousands_sep(median, ','),
+            fmt_thousands_sep(deviation, ',')
+        ))
+        .unwrap();
+    if bs.mb_s != 0 {
+        output
+            .write_fmt(format_args!(" = {} MB/s", bs.mb_s))
+            .unwrap();
+    }
+    output
+}
+
+// List the tests to console, and optionally to logfile. Filters are honored.
+pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<()> {
+    let mut output = match term::stdout() {
+        None => Raw(io::stdout()),
+        Some(t) => Pretty(t),
+    };
+
+    let quiet = opts.format == OutputFormat::Terse;
+    let mut st = ConsoleTestState::new(opts)?;
+
+    let mut ntest = 0;
+    let mut nbench = 0;
+
+    for test in filter_tests(&opts, tests) {
+        use crate::TestFn::*;
+
+        let TestDescAndFn {
+            desc: TestDesc { name, .. },
+            testfn,
+        } = test;
+
+        let fntype = match testfn {
+            StaticTestFn(..) | DynTestFn(..) => {
+                ntest += 1;
+                "test"
+            }
+            StaticBenchFn(..) | DynBenchFn(..) => {
+                nbench += 1;
+                "benchmark"
+            }
+        };
+
+        writeln!(output, "{}: {}", name, fntype)?;
+        st.write_log(format!("{} {}\n", fntype, name))?;
+    }
+
+    fn plural(count: u32, s: &str) -> String {
+        match count {
+            1 => format!("{} {}", 1, s),
+            n => format!("{} {}s", n, s),
+        }
+    }
+
+    if !quiet {
+        if ntest != 0 || nbench != 0 {
+            writeln!(output, "")?;
+        }
+
+        writeln!(
+            output,
+            "{}, {}",
+            plural(ntest, "test"),
+            plural(nbench, "benchmark")
+        )?;
+    }
+
+    Ok(())
+}
+
+// A simple console test runner
+pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<bool> {
+    fn callback(
+        event: &TestEvent,
+        st: &mut ConsoleTestState,
+        out: &mut dyn OutputFormatter,
+    ) -> io::Result<()> {
+        match (*event).clone() {
+            TeFiltered(ref filtered_tests) => {
+                st.total = filtered_tests.len();
+                out.write_run_start(filtered_tests.len())
+            }
+            TeFilteredOut(filtered_out) => Ok(st.filtered_out = filtered_out),
+            TeWait(ref test) => out.write_test_start(test),
+            TeTimeout(ref test) => out.write_timeout(test),
+            TeResult(test, result, stdout) => {
+                st.write_log_result(&test, &result)?;
+                out.write_result(&test, &result, &*stdout)?;
+                match result {
+                    TrOk => {
+                        st.passed += 1;
+                        st.not_failures.push((test, stdout));
+                    }
+                    TrIgnored => st.ignored += 1,
+                    TrAllowedFail => st.allowed_fail += 1,
+                    TrBench(bs) => {
+                        st.metrics.insert_metric(
+                            test.name.as_slice(),
+                            bs.ns_iter_summ.median,
+                            bs.ns_iter_summ.max - bs.ns_iter_summ.min,
+                        );
+                        st.measured += 1
+                    }
+                    TrFailed => {
+                        st.failed += 1;
+                        st.failures.push((test, stdout));
+                    }
+                    TrFailedMsg(msg) => {
+                        st.failed += 1;
+                        let mut stdout = stdout;
+                        stdout.extend_from_slice(format!("note: {}", msg).as_bytes());
+                        st.failures.push((test, stdout));
+                    }
+                }
+                Ok(())
+            }
+        }
+    }
+
+    let output = match term::stdout() {
+        None => Raw(io::stdout()),
+        Some(t) => Pretty(t),
+    };
+
+    let max_name_len = tests
+        .iter()
+        .max_by_key(|t| len_if_padded(*t))
+        .map(|t| t.desc.name.as_slice().len())
+        .unwrap_or(0);
+
+    let is_multithreaded = opts.test_threads.unwrap_or_else(get_concurrency) > 1;
+
+    let mut out: Box<dyn OutputFormatter> = match opts.format {
+        OutputFormat::Pretty => Box::new(PrettyFormatter::new(
+            output,
+            use_color(opts),
+            max_name_len,
+            is_multithreaded,
+        )),
+        OutputFormat::Terse => Box::new(TerseFormatter::new(
+            output,
+            use_color(opts),
+            max_name_len,
+            is_multithreaded,
+        )),
+        OutputFormat::Json => Box::new(JsonFormatter::new(output)),
+    };
+    let mut st = ConsoleTestState::new(opts)?;
+    fn len_if_padded(t: &TestDescAndFn) -> usize {
+        match t.testfn.padding() {
+            PadNone => 0,
+            PadOnRight => t.desc.name.as_slice().len(),
+        }
+    }
+
+    run_tests(opts, tests, |x| callback(&x, &mut st, &mut *out))?;
+
+    assert!(st.current_test_count() == st.total);
+
+    return out.write_run_finish(&st);
+}
+
+#[test]
+fn should_sort_failures_before_printing_them() {
+    let test_a = TestDesc {
+        name: StaticTestName("a"),
+        ignore: false,
+        should_panic: ShouldPanic::No,
+        allow_fail: false,
+    };
+
+    let test_b = TestDesc {
+        name: StaticTestName("b"),
+        ignore: false,
+        should_panic: ShouldPanic::No,
+        allow_fail: false,
+    };
+
+    let mut out = PrettyFormatter::new(Raw(Vec::new()), false, 10, false);
+
+    let st = ConsoleTestState {
+        log_out: None,
+        total: 0,
+        passed: 0,
+        failed: 0,
+        ignored: 0,
+        allowed_fail: 0,
+        filtered_out: 0,
+        measured: 0,
+        metrics: MetricMap::new(),
+        failures: vec![(test_b, Vec::new()), (test_a, Vec::new())],
+        options: Options::new(),
+        not_failures: Vec::new(),
+    };
+
+    out.write_failures(&st).unwrap();
+    let s = match out.output_location() {
+        &Raw(ref m) => String::from_utf8_lossy(&m[..]),
+        &Pretty(_) => unreachable!(),
+    };
+
+    let apos = s.find("a").unwrap();
+    let bpos = s.find("b").unwrap();
+    assert!(apos < bpos);
+}
+
+fn use_color(opts: &TestOpts) -> bool {
+    match opts.color {
+        AutoColor => !opts.nocapture && stdout_isatty(),
+        AlwaysColor => true,
+        NeverColor => false,
+    }
+}
+
+#[cfg(any(
+    target_os = "cloudabi",
+    target_os = "redox",
+    all(target_arch = "wasm32", not(target_os = "emscripten")),
+    all(target_vendor = "fortanix", target_env = "sgx")
+))]
+fn stdout_isatty() -> bool {
+    // FIXME: Implement isatty on Redox and SGX
+    false
+}
+#[cfg(unix)]
+fn stdout_isatty() -> bool {
+    unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
+}
+#[cfg(windows)]
+fn stdout_isatty() -> bool {
+    type DWORD = u32;
+    type BOOL = i32;
+    type HANDLE = *mut u8;
+    type LPDWORD = *mut u32;
+    const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
+    extern "system" {
+        fn GetStdHandle(which: DWORD) -> HANDLE;
+        fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
+    }
+    unsafe {
+        let handle = GetStdHandle(STD_OUTPUT_HANDLE);
+        let mut out = 0;
+        GetConsoleMode(handle, &mut out) != 0
+    }
+}
+
+#[derive(Clone)]
+pub enum TestEvent {
+    TeFiltered(Vec<TestDesc>),
+    TeWait(TestDesc),
+    TeResult(TestDesc, TestResult, Vec<u8>),
+    TeTimeout(TestDesc),
+    TeFilteredOut(usize),
+}
+
+pub type MonitorMsg = (TestDesc, TestResult, Vec<u8>);
 
-// FIXME: we should be more explicit about the exact APIs that we
-// export to users.
-pub use libtest::{
-    assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static,
-    Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, ShouldPanic,
-    StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, TestOpts,
-    TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk, stats::Summary
-};
+struct Sink(Arc<Mutex<Vec<u8>>>);
+impl Write for Sink {
+    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+        Write::write(&mut *self.0.lock().unwrap(), data)
+    }
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+pub fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) -> io::Result<()>
+where
+    F: FnMut(TestEvent) -> io::Result<()>,
+{
+    use std::collections::{self, HashMap};
+    use std::hash::BuildHasherDefault;
+    use std::sync::mpsc::RecvTimeoutError;
+    // Use a deterministic hasher
+    type TestMap =
+        HashMap<TestDesc, Instant, BuildHasherDefault<collections::hash_map::DefaultHasher>>;
+
+    let tests_len = tests.len();
+
+    let mut filtered_tests = filter_tests(opts, tests);
+    if !opts.bench_benchmarks {
+        filtered_tests = convert_benchmarks_to_tests(filtered_tests);
+    }
+
+    let filtered_tests = {
+        let mut filtered_tests = filtered_tests;
+        for test in filtered_tests.iter_mut() {
+            test.desc.name = test.desc.name.with_padding(test.testfn.padding());
+        }
+
+        filtered_tests
+    };
+
+    let filtered_out = tests_len - filtered_tests.len();
+    callback(TeFilteredOut(filtered_out))?;
+
+    let filtered_descs = filtered_tests.iter().map(|t| t.desc.clone()).collect();
+
+    callback(TeFiltered(filtered_descs))?;
+
+    let (filtered_tests, filtered_benchs): (Vec<_>, _) =
+        filtered_tests.into_iter().partition(|e| match e.testfn {
+            StaticTestFn(_) | DynTestFn(_) => true,
+            _ => false,
+        });
+
+    let concurrency = opts.test_threads.unwrap_or_else(get_concurrency);
+
+    let mut remaining = filtered_tests;
+    remaining.reverse();
+    let mut pending = 0;
+
+    let (tx, rx) = channel::<MonitorMsg>();
+
+    let mut running_tests: TestMap = HashMap::default();
+
+    fn get_timed_out_tests(running_tests: &mut TestMap) -> Vec<TestDesc> {
+        let now = Instant::now();
+        let timed_out = running_tests
+            .iter()
+            .filter_map(|(desc, timeout)| {
+                if &now >= timeout {
+                    Some(desc.clone())
+                } else {
+                    None
+                }
+            })
+            .collect();
+        for test in &timed_out {
+            running_tests.remove(test);
+        }
+        timed_out
+    };
+
+    fn calc_timeout(running_tests: &TestMap) -> Option<Duration> {
+        running_tests.values().min().map(|next_timeout| {
+            let now = Instant::now();
+            if *next_timeout >= now {
+                *next_timeout - now
+            } else {
+                Duration::new(0, 0)
+            }
+        })
+    };
+
+    if concurrency == 1 {
+        while !remaining.is_empty() {
+            let test = remaining.pop().unwrap();
+            callback(TeWait(test.desc.clone()))?;
+            run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::No);
+            let (test, result, stdout) = rx.recv().unwrap();
+            callback(TeResult(test, result, stdout))?;
+        }
+    } else {
+        while pending > 0 || !remaining.is_empty() {
+            while pending < concurrency && !remaining.is_empty() {
+                let test = remaining.pop().unwrap();
+                let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
+                running_tests.insert(test.desc.clone(), timeout);
+                callback(TeWait(test.desc.clone()))?; //here no pad
+                run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::Yes);
+                pending += 1;
+            }
+
+            let mut res;
+            loop {
+                if let Some(timeout) = calc_timeout(&running_tests) {
+                    res = rx.recv_timeout(timeout);
+                    for test in get_timed_out_tests(&mut running_tests) {
+                        callback(TeTimeout(test))?;
+                    }
+                    if res != Err(RecvTimeoutError::Timeout) {
+                        break;
+                    }
+                } else {
+                    res = rx.recv().map_err(|_| RecvTimeoutError::Disconnected);
+                    break;
+                }
+            }
+
+            let (desc, result, stdout) = res.unwrap();
+            running_tests.remove(&desc);
+
+            callback(TeResult(desc, result, stdout))?;
+            pending -= 1;
+        }
+    }
+
+    if opts.bench_benchmarks {
+        // All benchmarks run at the end, in serial.
+        for b in filtered_benchs {
+            callback(TeWait(b.desc.clone()))?;
+            run_test(opts, false, b, tx.clone(), Concurrent::No);
+            let (test, result, stdout) = rx.recv().unwrap();
+            callback(TeResult(test, result, stdout))?;
+        }
+    }
+    Ok(())
+}
+
+#[allow(deprecated)]
+fn get_concurrency() -> usize {
+    return match env::var("RUST_TEST_THREADS") {
+        Ok(s) => {
+            let opt_n: Option<usize> = s.parse().ok();
+            match opt_n {
+                Some(n) if n > 0 => n,
+                _ => panic!(
+                    "RUST_TEST_THREADS is `{}`, should be a positive integer.",
+                    s
+                ),
+            }
+        }
+        Err(..) => num_cpus(),
+    };
+
+    #[cfg(windows)]
+    #[allow(nonstandard_style)]
+    fn num_cpus() -> usize {
+        #[repr(C)]
+        struct SYSTEM_INFO {
+            wProcessorArchitecture: u16,
+            wReserved: u16,
+            dwPageSize: u32,
+            lpMinimumApplicationAddress: *mut u8,
+            lpMaximumApplicationAddress: *mut u8,
+            dwActiveProcessorMask: *mut u8,
+            dwNumberOfProcessors: u32,
+            dwProcessorType: u32,
+            dwAllocationGranularity: u32,
+            wProcessorLevel: u16,
+            wProcessorRevision: u16,
+        }
+        extern "system" {
+            fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32;
+        }
+        unsafe {
+            let mut sysinfo = std::mem::zeroed();
+            GetSystemInfo(&mut sysinfo);
+            sysinfo.dwNumberOfProcessors as usize
+        }
+    }
+
+    #[cfg(target_os = "redox")]
+    fn num_cpus() -> usize {
+        // FIXME: Implement num_cpus on Redox
+        1
+    }
+
+    #[cfg(any(
+        all(target_arch = "wasm32", not(target_os = "emscripten")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    ))]
+    fn num_cpus() -> usize {
+        1
+    }
+
+    #[cfg(any(
+        target_os = "android",
+        target_os = "cloudabi",
+        target_os = "emscripten",
+        target_os = "fuchsia",
+        target_os = "ios",
+        target_os = "linux",
+        target_os = "macos",
+        target_os = "solaris"
+    ))]
+    fn num_cpus() -> usize {
+        unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize }
+    }
+
+    #[cfg(any(
+        target_os = "freebsd",
+        target_os = "dragonfly",
+        target_os = "bitrig",
+        target_os = "netbsd"
+    ))]
+    fn num_cpus() -> usize {
+        use std::ptr;
+
+        let mut cpus: libc::c_uint = 0;
+        let mut cpus_size = std::mem::size_of_val(&cpus);
+
+        unsafe {
+            cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
+        }
+        if cpus < 1 {
+            let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
+            unsafe {
+                libc::sysctl(
+                    mib.as_mut_ptr(),
+                    2,
+                    &mut cpus as *mut _ as *mut _,
+                    &mut cpus_size as *mut _ as *mut _,
+                    ptr::null_mut(),
+                    0,
+                );
+            }
+            if cpus < 1 {
+                cpus = 1;
+            }
+        }
+        cpus as usize
+    }
+
+    #[cfg(target_os = "openbsd")]
+    fn num_cpus() -> usize {
+        use std::ptr;
+
+        let mut cpus: libc::c_uint = 0;
+        let mut cpus_size = std::mem::size_of_val(&cpus);
+        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
+
+        unsafe {
+            libc::sysctl(
+                mib.as_mut_ptr(),
+                2,
+                &mut cpus as *mut _ as *mut _,
+                &mut cpus_size as *mut _ as *mut _,
+                ptr::null_mut(),
+                0,
+            );
+        }
+        if cpus < 1 {
+            cpus = 1;
+        }
+        cpus as usize
+    }
+
+    #[cfg(target_os = "haiku")]
+    fn num_cpus() -> usize {
+        // FIXME: implement
+        1
+    }
+
+    #[cfg(target_os = "l4re")]
+    fn num_cpus() -> usize {
+        // FIXME: implement
+        1
+    }
+}
+
+pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
+    let mut filtered = tests;
+    let matches_filter = |test: &TestDescAndFn, filter: &str| {
+        let test_name = test.desc.name.as_slice();
+
+        match opts.filter_exact {
+            true => test_name == filter,
+            false => test_name.contains(filter),
+        }
+    };
+
+    // Remove tests that don't match the test filter
+    if let Some(ref filter) = opts.filter {
+        filtered.retain(|test| matches_filter(test, filter));
+    }
+
+    // Skip tests that match any of the skip filters
+    filtered.retain(|test| !opts.skip.iter().any(|sf| matches_filter(test, sf)));
+
+    // Excludes #[should_panic] tests
+    if opts.exclude_should_panic {
+        filtered.retain(|test| test.desc.should_panic == ShouldPanic::No);
+    }
+
+    // maybe unignore tests
+    match opts.run_ignored {
+        RunIgnored::Yes => {
+            filtered
+                .iter_mut()
+                .for_each(|test| test.desc.ignore = false);
+        }
+        RunIgnored::Only => {
+            filtered.retain(|test| test.desc.ignore);
+            filtered
+                .iter_mut()
+                .for_each(|test| test.desc.ignore = false);
+        }
+        RunIgnored::No => {}
+    }
+
+    // Sort the tests alphabetically
+    filtered.sort_by(|t1, t2| t1.desc.name.as_slice().cmp(t2.desc.name.as_slice()));
+
+    filtered
+}
+
+pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
+    // convert benchmarks to tests, if we're not benchmarking them
+    tests
+        .into_iter()
+        .map(|x| {
+            let testfn = match x.testfn {
+                DynBenchFn(bench) => DynTestFn(Box::new(move || {
+                    bench::run_once(|b| __rust_begin_short_backtrace(|| bench.run(b)))
+                })),
+                StaticBenchFn(benchfn) => DynTestFn(Box::new(move || {
+                    bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b)))
+                })),
+                f => f,
+            };
+            TestDescAndFn {
+                desc: x.desc,
+                testfn,
+            }
+        })
+        .collect()
+}
+
+pub fn run_test(
+    opts: &TestOpts,
+    force_ignore: bool,
+    test: TestDescAndFn,
+    monitor_ch: Sender<MonitorMsg>,
+    concurrency: Concurrent,
+) {
+    let TestDescAndFn { desc, testfn } = test;
+
+    let ignore_because_panic_abort = cfg!(target_arch = "wasm32")
+        && !cfg!(target_os = "emscripten")
+        && desc.should_panic != ShouldPanic::No;
+
+    if force_ignore || desc.ignore || ignore_because_panic_abort {
+        monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap();
+        return;
+    }
+
+    fn run_test_inner(
+        desc: TestDesc,
+        monitor_ch: Sender<MonitorMsg>,
+        nocapture: bool,
+        testfn: Box<dyn FnBox() + Send>,
+        concurrency: Concurrent,
+    ) {
+        // Buffer for capturing standard I/O
+        let data = Arc::new(Mutex::new(Vec::new()));
+        let data2 = data.clone();
+
+        let name = desc.name.clone();
+        let runtest = move || {
+            let oldio = if !nocapture {
+                Some((
+                    io::set_print(Some(Box::new(Sink(data2.clone())))),
+                    io::set_panic(Some(Box::new(Sink(data2)))),
+                ))
+            } else {
+                None
+            };
+
+            let result = catch_unwind(AssertUnwindSafe(testfn));
+
+            if let Some((printio, panicio)) = oldio {
+                io::set_print(printio);
+                io::set_panic(panicio);
+            };
+
+            let test_result = calc_result(&desc, result);
+            let stdout = data.lock().unwrap().to_vec();
+            monitor_ch
+                .send((desc.clone(), test_result, stdout))
+                .unwrap();
+        };
+
+        // If the platform is single-threaded we're just going to run
+        // the test synchronously, regardless of the concurrency
+        // level.
+        let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_arch = "wasm32");
+        if concurrency == Concurrent::Yes && supports_threads {
+            let cfg = thread::Builder::new().name(name.as_slice().to_owned());
+            cfg.spawn(runtest).unwrap();
+        } else {
+            runtest();
+        }
+    }
+
+    match testfn {
+        DynBenchFn(bencher) => {
+            crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| {
+                bencher.run(harness)
+            });
+        }
+        StaticBenchFn(benchfn) => {
+            crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| {
+                (benchfn.clone())(harness)
+            });
+        }
+        DynTestFn(f) => {
+            let cb = move || __rust_begin_short_backtrace(f);
+            run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb), concurrency)
+        }
+        StaticTestFn(f) => run_test_inner(
+            desc,
+            monitor_ch,
+            opts.nocapture,
+            Box::new(move || __rust_begin_short_backtrace(f)),
+            concurrency,
+        ),
+    }
+}
+
+/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
+#[inline(never)]
+fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
+    f()
+}
+
+fn calc_result(desc: &TestDesc, task_result: Result<(), Box<dyn Any + Send>>) -> TestResult {
+    match (&desc.should_panic, task_result) {
+        (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk,
+        (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => {
+            if err
+                .downcast_ref::<String>()
+                .map(|e| &**e)
+                .or_else(|| err.downcast_ref::<&'static str>().map(|e| *e))
+                .map(|e| e.contains(msg))
+                .unwrap_or(false)
+            {
+                TrOk
+            } else {
+                if desc.allow_fail {
+                    TrAllowedFail
+                } else {
+                    TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
+                }
+            }
+        }
+        _ if desc.allow_fail => TrAllowedFail,
+        _ => TrFailed,
+    }
+}
+
+#[derive(Clone, PartialEq)]
+pub struct MetricMap(BTreeMap<String, Metric>);
+
+impl MetricMap {
+    pub fn new() -> MetricMap {
+        MetricMap(BTreeMap::new())
+    }
+
+    /// Insert a named `value` (+/- `noise`) metric into the map. The value
+    /// must be non-negative. The `noise` indicates the uncertainty of the
+    /// metric, which doubles as the "noise range" of acceptable
+    /// pairwise-regressions on this named value, when comparing from one
+    /// metric to the next using `compare_to_old`.
+    ///
+    /// If `noise` is positive, then it means this metric is of a value
+    /// you want to see grow smaller, so a change larger than `noise` in the
+    /// positive direction represents a regression.
+    ///
+    /// If `noise` is negative, then it means this metric is of a value
+    /// you want to see grow larger, so a change larger than `noise` in the
+    /// negative direction represents a regression.
+    pub fn insert_metric(&mut self, name: &str, value: f64, noise: f64) {
+        let m = Metric { value, noise };
+        self.0.insert(name.to_owned(), m);
+    }
+
+    pub fn fmt_metrics(&self) -> String {
+        let v = self
+            .0
+            .iter()
+            .map(|(k, v)| format!("{}: {} (+/- {})", *k, v.value, v.noise))
+            .collect::<Vec<_>>();
+        v.join(", ")
+    }
+}
+
+// Benchmarking
 
 pub use std::hint::black_box;
 
+impl Bencher {
+    /// Callback for benchmark functions to run in their body.
+    pub fn iter<T, F>(&mut self, mut inner: F)
+    where
+        F: FnMut() -> T,
+    {
+        if self.mode == BenchMode::Single {
+            ns_iter_inner(&mut inner, 1);
+            return;
+        }
+
+        self.summary = Some(iter(&mut inner));
+    }
+
+    pub fn bench<F>(&mut self, mut f: F) -> Option<stats::Summary>
+    where
+        F: FnMut(&mut Bencher),
+    {
+        f(self);
+        return self.summary;
+    }
+}
+
+fn ns_from_dur(dur: Duration) -> u64 {
+    dur.as_secs() * 1_000_000_000 + (dur.subsec_nanos() as u64)
+}
+
+fn ns_iter_inner<T, F>(inner: &mut F, k: u64) -> u64
+where
+    F: FnMut() -> T,
+{
+    let start = Instant::now();
+    for _ in 0..k {
+        black_box(inner());
+    }
+    return ns_from_dur(start.elapsed());
+}
+
+pub fn iter<T, F>(inner: &mut F) -> stats::Summary
+where
+    F: FnMut() -> T,
+{
+    // Initial bench run to get ballpark figure.
+    let ns_single = ns_iter_inner(inner, 1);
+
+    // Try to estimate iter count for 1ms falling back to 1m
+    // iterations if first run took < 1ns.
+    let ns_target_total = 1_000_000; // 1ms
+    let mut n = ns_target_total / cmp::max(1, ns_single);
+
+    // if the first run took more than 1ms we don't want to just
+    // be left doing 0 iterations on every loop. The unfortunate
+    // side effect of not being able to do as many runs is
+    // automatically handled by the statistical analysis below
+    // (i.e., larger error bars).
+    n = cmp::max(1, n);
+
+    let mut total_run = Duration::new(0, 0);
+    let samples: &mut [f64] = &mut [0.0_f64; 50];
+    loop {
+        let loop_start = Instant::now();
+
+        for p in &mut *samples {
+            *p = ns_iter_inner(inner, n) as f64 / n as f64;
+        }
+
+        stats::winsorize(samples, 5.0);
+        let summ = stats::Summary::new(samples);
+
+        for p in &mut *samples {
+            let ns = ns_iter_inner(inner, 5 * n);
+            *p = ns as f64 / (5 * n) as f64;
+        }
+
+        stats::winsorize(samples, 5.0);
+        let summ5 = stats::Summary::new(samples);
+
+        let loop_run = loop_start.elapsed();
+
+        // If we've run for 100ms and seem to have converged to a
+        // stable median.
+        if loop_run > Duration::from_millis(100)
+            && summ.median_abs_dev_pct < 1.0
+            && summ.median - summ5.median < summ5.median_abs_dev
+        {
+            return summ5;
+        }
+
+        total_run = total_run + loop_run;
+        // Longest we ever run for is 3s.
+        if total_run > Duration::from_secs(3) {
+            return summ5;
+        }
+
+        // If we overflow here just return the results so far. We check a
+        // multiplier of 10 because we're about to multiply by 2 and the
+        // next iteration of the loop will also multiply by 5 (to calculate
+        // the summ5 result)
+        n = match n.checked_mul(10) {
+            Some(_) => n * 2,
+            None => {
+                return summ5;
+            }
+        };
+    }
+}
+
+pub mod bench {
+    use super::{BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestResult};
+    use crate::stats;
+    use std::cmp;
+    use std::io;
+    use std::panic::{catch_unwind, AssertUnwindSafe};
+    use std::sync::{Arc, Mutex};
+
+    pub fn benchmark<F>(desc: TestDesc, monitor_ch: Sender<MonitorMsg>, nocapture: bool, f: F)
+    where
+        F: FnMut(&mut Bencher),
+    {
+        let mut bs = Bencher {
+            mode: BenchMode::Auto,
+            summary: None,
+            bytes: 0,
+        };
+
+        let data = Arc::new(Mutex::new(Vec::new()));
+        let data2 = data.clone();
+
+        let oldio = if !nocapture {
+            Some((
+                io::set_print(Some(Box::new(Sink(data2.clone())))),
+                io::set_panic(Some(Box::new(Sink(data2)))),
+            ))
+        } else {
+            None
+        };
+
+        let result = catch_unwind(AssertUnwindSafe(|| bs.bench(f)));
+
+        if let Some((printio, panicio)) = oldio {
+            io::set_print(printio);
+            io::set_panic(panicio);
+        };
+
+        let test_result = match result {
+            //bs.bench(f) {
+            Ok(Some(ns_iter_summ)) => {
+                let ns_iter = cmp::max(ns_iter_summ.median as u64, 1);
+                let mb_s = bs.bytes * 1000 / ns_iter;
+
+                let bs = BenchSamples {
+                    ns_iter_summ,
+                    mb_s: mb_s as usize,
+                };
+                TestResult::TrBench(bs)
+            }
+            Ok(None) => {
+                // iter not called, so no data.
+                // FIXME: error in this case?
+                let samples: &mut [f64] = &mut [0.0_f64; 1];
+                let bs = BenchSamples {
+                    ns_iter_summ: stats::Summary::new(samples),
+                    mb_s: 0,
+                };
+                TestResult::TrBench(bs)
+            }
+            Err(_) => TestResult::TrFailed,
+        };
+
+        let stdout = data.lock().unwrap().to_vec();
+        monitor_ch.send((desc, test_result, stdout)).unwrap();
+    }
+
+    pub fn run_once<F>(f: F)
+    where
+        F: FnMut(&mut Bencher),
+    {
+        let mut bs = Bencher {
+            mode: BenchMode::Single,
+            summary: None,
+            bytes: 0,
+        };
+        bs.bench(f);
+    }
+}
+
 #[cfg(test)]
 mod tests {
+    use crate::bench;
+    use crate::test::{
+        filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored,
+        ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg,
+        TrIgnored, TrOk,
+    };
     use crate::Bencher;
-    use libtest::stats::Stats;
+    use crate::Concurrent;
+    use std::sync::mpsc::channel;
 
-    #[bench]
-    pub fn sum_three_items(b: &mut Bencher) {
-        b.iter(|| {
-            [1e20f64, 1.5f64, -1e20f64].sum();
-        })
+    fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
+        vec![
+            TestDescAndFn {
+                desc: TestDesc {
+                    name: StaticTestName("1"),
+                    ignore: true,
+                    should_panic: ShouldPanic::No,
+                    allow_fail: false,
+                },
+                testfn: DynTestFn(Box::new(move || {})),
+            },
+            TestDescAndFn {
+                desc: TestDesc {
+                    name: StaticTestName("2"),
+                    ignore: false,
+                    should_panic: ShouldPanic::No,
+                    allow_fail: false,
+                },
+                testfn: DynTestFn(Box::new(move || {})),
+            },
+        ]
     }
 
-    #[bench]
-    pub fn sum_many_f64(b: &mut Bencher) {
-        let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60];
-        let v = (0..500).map(|i| nums[i % 5]).collect::<Vec<_>>();
-        b.iter(|| {
-            v.sum();
-        })
+    #[test]
+    pub fn do_not_run_ignored_tests() {
+        fn f() {
+            panic!();
+        }
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("whatever"),
+                ignore: true,
+                should_panic: ShouldPanic::No,
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(f)),
+        };
+        let (tx, rx) = channel();
+        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+        let (_, res, _) = rx.recv().unwrap();
+        assert!(res != TrOk);
+    }
+
+    #[test]
+    pub fn ignored_tests_result_in_ignored() {
+        fn f() {}
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("whatever"),
+                ignore: true,
+                should_panic: ShouldPanic::No,
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(f)),
+        };
+        let (tx, rx) = channel();
+        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+        let (_, res, _) = rx.recv().unwrap();
+        assert!(res == TrIgnored);
+    }
+
+    #[test]
+    fn test_should_panic() {
+        fn f() {
+            panic!();
+        }
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("whatever"),
+                ignore: false,
+                should_panic: ShouldPanic::Yes,
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(f)),
+        };
+        let (tx, rx) = channel();
+        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+        let (_, res, _) = rx.recv().unwrap();
+        assert!(res == TrOk);
+    }
+
+    #[test]
+    fn test_should_panic_good_message() {
+        fn f() {
+            panic!("an error message");
+        }
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("whatever"),
+                ignore: false,
+                should_panic: ShouldPanic::YesWithMessage("error message"),
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(f)),
+        };
+        let (tx, rx) = channel();
+        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+        let (_, res, _) = rx.recv().unwrap();
+        assert!(res == TrOk);
+    }
+
+    #[test]
+    fn test_should_panic_bad_message() {
+        fn f() {
+            panic!("an error message");
+        }
+        let expected = "foobar";
+        let failed_msg = "Panic did not include expected string";
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("whatever"),
+                ignore: false,
+                should_panic: ShouldPanic::YesWithMessage(expected),
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(f)),
+        };
+        let (tx, rx) = channel();
+        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+        let (_, res, _) = rx.recv().unwrap();
+        assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected)));
+    }
+
+    #[test]
+    fn test_should_panic_but_succeeds() {
+        fn f() {}
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("whatever"),
+                ignore: false,
+                should_panic: ShouldPanic::Yes,
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(f)),
+        };
+        let (tx, rx) = channel();
+        run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
+        let (_, res, _) = rx.recv().unwrap();
+        assert!(res == TrFailed);
+    }
+
+    #[test]
+    fn parse_ignored_flag() {
+        let args = vec![
+            "progname".to_string(),
+            "filter".to_string(),
+            "--ignored".to_string(),
+        ];
+        let opts = parse_opts(&args).unwrap().unwrap();
+        assert_eq!(opts.run_ignored, RunIgnored::Only);
+    }
+
+    #[test]
+    fn parse_include_ignored_flag() {
+        let args = vec![
+            "progname".to_string(),
+            "filter".to_string(),
+            "-Zunstable-options".to_string(),
+            "--include-ignored".to_string(),
+        ];
+        let opts = parse_opts(&args).unwrap().unwrap();
+        assert_eq!(opts.run_ignored, RunIgnored::Yes);
+    }
+
+    #[test]
+    pub fn filter_for_ignored_option() {
+        // When we run ignored tests the test filter should filter out all the
+        // unignored tests and flip the ignore flag on the rest to false
+
+        let mut opts = TestOpts::new();
+        opts.run_tests = true;
+        opts.run_ignored = RunIgnored::Only;
+
+        let tests = one_ignored_one_unignored_test();
+        let filtered = filter_tests(&opts, tests);
+
+        assert_eq!(filtered.len(), 1);
+        assert_eq!(filtered[0].desc.name.to_string(), "1");
+        assert!(!filtered[0].desc.ignore);
     }
 
-    #[bench]
-    pub fn no_iter(_: &mut Bencher) {}
+    #[test]
+    pub fn run_include_ignored_option() {
+        // When we "--include-ignored" tests, the ignore flag should be set to false on
+        // all tests and no test filtered out
+
+        let mut opts = TestOpts::new();
+        opts.run_tests = true;
+        opts.run_ignored = RunIgnored::Yes;
+
+        let tests = one_ignored_one_unignored_test();
+        let filtered = filter_tests(&opts, tests);
+
+        assert_eq!(filtered.len(), 2);
+        assert!(!filtered[0].desc.ignore);
+        assert!(!filtered[1].desc.ignore);
+    }
+
+    #[test]
+    pub fn exclude_should_panic_option() {
+        let mut opts = TestOpts::new();
+        opts.run_tests = true;
+        opts.exclude_should_panic = true;
+
+        let mut tests = one_ignored_one_unignored_test();
+        tests.push(TestDescAndFn {
+            desc: TestDesc {
+                name: StaticTestName("3"),
+                ignore: false,
+                should_panic: ShouldPanic::Yes,
+                allow_fail: false,
+            },
+            testfn: DynTestFn(Box::new(move || {})),
+        });
+
+        let filtered = filter_tests(&opts, tests);
+
+        assert_eq!(filtered.len(), 2);
+        assert!(filtered.iter().all(|test| test.desc.should_panic == ShouldPanic::No));
+    }
+
+    #[test]
+    pub fn exact_filter_match() {
+        fn tests() -> Vec<TestDescAndFn> {
+            vec!["base", "base::test", "base::test1", "base::test2"]
+                .into_iter()
+                .map(|name| TestDescAndFn {
+                    desc: TestDesc {
+                        name: StaticTestName(name),
+                        ignore: false,
+                        should_panic: ShouldPanic::No,
+                        allow_fail: false,
+                    },
+                    testfn: DynTestFn(Box::new(move || {})),
+                })
+                .collect()
+        }
+
+        let substr = filter_tests(
+            &TestOpts {
+                filter: Some("base".into()),
+                ..TestOpts::new()
+            },
+            tests(),
+        );
+        assert_eq!(substr.len(), 4);
+
+        let substr = filter_tests(
+            &TestOpts {
+                filter: Some("bas".into()),
+                ..TestOpts::new()
+            },
+            tests(),
+        );
+        assert_eq!(substr.len(), 4);
+
+        let substr = filter_tests(
+            &TestOpts {
+                filter: Some("::test".into()),
+                ..TestOpts::new()
+            },
+            tests(),
+        );
+        assert_eq!(substr.len(), 3);
+
+        let substr = filter_tests(
+            &TestOpts {
+                filter: Some("base::test".into()),
+                ..TestOpts::new()
+            },
+            tests(),
+        );
+        assert_eq!(substr.len(), 3);
+
+        let exact = filter_tests(
+            &TestOpts {
+                filter: Some("base".into()),
+                filter_exact: true,
+                ..TestOpts::new()
+            },
+            tests(),
+        );
+        assert_eq!(exact.len(), 1);
+
+        let exact = filter_tests(
+            &TestOpts {
+                filter: Some("bas".into()),
+                filter_exact: true,
+                ..TestOpts::new()
+            },
+            tests(),
+        );
+        assert_eq!(exact.len(), 0);
+
+        let exact = filter_tests(
+            &TestOpts {
+                filter: Some("::test".into()),
+                filter_exact: true,
+                ..TestOpts::new()
+            },
+            tests(),
+        );
+        assert_eq!(exact.len(), 0);
+
+        let exact = filter_tests(
+            &TestOpts {
+                filter: Some("base::test".into()),
+                filter_exact: true,
+                ..TestOpts::new()
+            },
+            tests(),
+        );
+        assert_eq!(exact.len(), 1);
+    }
+
+    #[test]
+    pub fn sort_tests() {
+        let mut opts = TestOpts::new();
+        opts.run_tests = true;
+
+        let names = vec![
+            "sha1::test".to_string(),
+            "isize::test_to_str".to_string(),
+            "isize::test_pow".to_string(),
+            "test::do_not_run_ignored_tests".to_string(),
+            "test::ignored_tests_result_in_ignored".to_string(),
+            "test::first_free_arg_should_be_a_filter".to_string(),
+            "test::parse_ignored_flag".to_string(),
+            "test::parse_include_ignored_flag".to_string(),
+            "test::filter_for_ignored_option".to_string(),
+            "test::run_include_ignored_option".to_string(),
+            "test::sort_tests".to_string(),
+        ];
+        let tests = {
+            fn testfn() {}
+            let mut tests = Vec::new();
+            for name in &names {
+                let test = TestDescAndFn {
+                    desc: TestDesc {
+                        name: DynTestName((*name).clone()),
+                        ignore: false,
+                        should_panic: ShouldPanic::No,
+                        allow_fail: false,
+                    },
+                    testfn: DynTestFn(Box::new(testfn)),
+                };
+                tests.push(test);
+            }
+            tests
+        };
+        let filtered = filter_tests(&opts, tests);
+
+        let expected = vec![
+            "isize::test_pow".to_string(),
+            "isize::test_to_str".to_string(),
+            "sha1::test".to_string(),
+            "test::do_not_run_ignored_tests".to_string(),
+            "test::filter_for_ignored_option".to_string(),
+            "test::first_free_arg_should_be_a_filter".to_string(),
+            "test::ignored_tests_result_in_ignored".to_string(),
+            "test::parse_ignored_flag".to_string(),
+            "test::parse_include_ignored_flag".to_string(),
+            "test::run_include_ignored_option".to_string(),
+            "test::sort_tests".to_string(),
+        ];
+
+        for (a, b) in expected.iter().zip(filtered) {
+            assert!(*a == b.desc.name.to_string());
+        }
+    }
+
+    #[test]
+    pub fn test_metricmap_compare() {
+        let mut m1 = MetricMap::new();
+        let mut m2 = MetricMap::new();
+        m1.insert_metric("in-both-noise", 1000.0, 200.0);
+        m2.insert_metric("in-both-noise", 1100.0, 200.0);
+
+        m1.insert_metric("in-first-noise", 1000.0, 2.0);
+        m2.insert_metric("in-second-noise", 1000.0, 2.0);
+
+        m1.insert_metric("in-both-want-downwards-but-regressed", 1000.0, 10.0);
+        m2.insert_metric("in-both-want-downwards-but-regressed", 2000.0, 10.0);
+
+        m1.insert_metric("in-both-want-downwards-and-improved", 2000.0, 10.0);
+        m2.insert_metric("in-both-want-downwards-and-improved", 1000.0, 10.0);
+
+        m1.insert_metric("in-both-want-upwards-but-regressed", 2000.0, -10.0);
+        m2.insert_metric("in-both-want-upwards-but-regressed", 1000.0, -10.0);
+
+        m1.insert_metric("in-both-want-upwards-and-improved", 1000.0, -10.0);
+        m2.insert_metric("in-both-want-upwards-and-improved", 2000.0, -10.0);
+    }
+
+    #[test]
+    pub fn test_bench_once_no_iter() {
+        fn f(_: &mut Bencher) {}
+        bench::run_once(f);
+    }
+
+    #[test]
+    pub fn test_bench_once_iter() {
+        fn f(b: &mut Bencher) {
+            b.iter(|| {})
+        }
+        bench::run_once(f);
+    }
+
+    #[test]
+    pub fn test_bench_no_iter() {
+        fn f(_: &mut Bencher) {}
+
+        let (tx, rx) = channel();
+
+        let desc = TestDesc {
+            name: StaticTestName("f"),
+            ignore: false,
+            should_panic: ShouldPanic::No,
+            allow_fail: false,
+        };
+
+        crate::bench::benchmark(desc, tx, true, f);
+        rx.recv().unwrap();
+    }
+
+    #[test]
+    pub fn test_bench_iter() {
+        fn f(b: &mut Bencher) {
+            b.iter(|| {})
+        }
+
+        let (tx, rx) = channel();
+
+        let desc = TestDesc {
+            name: StaticTestName("f"),
+            ignore: false,
+            should_panic: ShouldPanic::No,
+            allow_fail: false,
+        };
+
+        crate::bench::benchmark(desc, tx, true, f);
+        rx.recv().unwrap();
+    }
 }
diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs
new file mode 100644
index 00000000000..5c9421d5ea4
--- /dev/null
+++ b/src/libtest/stats.rs
@@ -0,0 +1,922 @@
+#![allow(missing_docs)]
+#![allow(deprecated)] // Float
+
+use std::cmp::Ordering::{self, Equal, Greater, Less};
+use std::mem;
+
+fn local_cmp(x: f64, y: f64) -> Ordering {
+    // arbitrarily decide that NaNs are larger than everything.
+    if y.is_nan() {
+        Less
+    } else if x.is_nan() {
+        Greater
+    } else if x < y {
+        Less
+    } else if x == y {
+        Equal
+    } else {
+        Greater
+    }
+}
+
+fn local_sort(v: &mut [f64]) {
+    v.sort_by(|x: &f64, y: &f64| local_cmp(*x, *y));
+}
+
+/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
+pub trait Stats {
+    /// Sum of the samples.
+    ///
+    /// Note: this method sacrifices performance at the altar of accuracy
+    /// Depends on IEEE-754 arithmetic guarantees. See proof of correctness at:
+    /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric
+    /// Predicates"][paper]
+    ///
+    /// [paper]: http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps
+    fn sum(&self) -> f64;
+
+    /// Minimum value of the samples.
+    fn min(&self) -> f64;
+
+    /// Maximum value of the samples.
+    fn max(&self) -> f64;
+
+    /// Arithmetic mean (average) of the samples: sum divided by sample-count.
+    ///
+    /// See: <https://en.wikipedia.org/wiki/Arithmetic_mean>
+    fn mean(&self) -> f64;
+
+    /// Median of the samples: value separating the lower half of the samples from the higher half.
+    /// Equal to `self.percentile(50.0)`.
+    ///
+    /// See: <https://en.wikipedia.org/wiki/Median>
+    fn median(&self) -> f64;
+
+    /// Variance of the samples: bias-corrected mean of the squares of the differences of each
+    /// sample from the sample mean. Note that this calculates the _sample variance_ rather than the
+    /// population variance, which is assumed to be unknown. It therefore corrects the `(n-1)/n`
+    /// bias that would appear if we calculated a population variance, by dividing by `(n-1)` rather
+    /// than `n`.
+    ///
+    /// See: <https://en.wikipedia.org/wiki/Variance>
+    fn var(&self) -> f64;
+
+    /// Standard deviation: the square root of the sample variance.
+    ///
+    /// Note: this is not a robust statistic for non-normal distributions. Prefer the
+    /// `median_abs_dev` for unknown distributions.
+    ///
+    /// See: <https://en.wikipedia.org/wiki/Standard_deviation>
+    fn std_dev(&self) -> f64;
+
+    /// Standard deviation as a percent of the mean value. See `std_dev` and `mean`.
+    ///
+    /// Note: this is not a robust statistic for non-normal distributions. Prefer the
+    /// `median_abs_dev_pct` for unknown distributions.
+    fn std_dev_pct(&self) -> f64;
+
+    /// Scaled median of the absolute deviations of each sample from the sample median. This is a
+    /// robust (distribution-agnostic) estimator of sample variability. Use this in preference to
+    /// `std_dev` if you cannot assume your sample is normally distributed. Note that this is scaled
+    /// by the constant `1.4826` to allow its use as a consistent estimator for the standard
+    /// deviation.
+    ///
+    /// See: <http://en.wikipedia.org/wiki/Median_absolute_deviation>
+    fn median_abs_dev(&self) -> f64;
+
+    /// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
+    fn median_abs_dev_pct(&self) -> f64;
+
+    /// Percentile: the value below which `pct` percent of the values in `self` fall. For example,
+    /// percentile(95.0) will return the value `v` such that 95% of the samples `s` in `self`
+    /// satisfy `s <= v`.
+    ///
+    /// Calculated by linear interpolation between closest ranks.
+    ///
+    /// See: <http://en.wikipedia.org/wiki/Percentile>
+    fn percentile(&self, pct: f64) -> f64;
+
+    /// Quartiles of the sample: three values that divide the sample into four equal groups, each
+    /// with 1/4 of the data. The middle value is the median. See `median` and `percentile`. This
+    /// function may calculate the 3 quartiles more efficiently than 3 calls to `percentile`, but
+    /// is otherwise equivalent.
+    ///
+    /// See also: <https://en.wikipedia.org/wiki/Quartile>
+    fn quartiles(&self) -> (f64, f64, f64);
+
+    /// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th
+    /// percentile (3rd quartile). See `quartiles`.
+    ///
+    /// See also: <https://en.wikipedia.org/wiki/Interquartile_range>
+    fn iqr(&self) -> f64;
+}
+
+/// Extracted collection of all the summary statistics of a sample set.
+#[derive(Clone, PartialEq, Copy)]
+#[allow(missing_docs)]
+pub struct Summary {
+    pub sum: f64,
+    pub min: f64,
+    pub max: f64,
+    pub mean: f64,
+    pub median: f64,
+    pub var: f64,
+    pub std_dev: f64,
+    pub std_dev_pct: f64,
+    pub median_abs_dev: f64,
+    pub median_abs_dev_pct: f64,
+    pub quartiles: (f64, f64, f64),
+    pub iqr: f64,
+}
+
+impl Summary {
+    /// Construct a new summary of a sample set.
+    pub fn new(samples: &[f64]) -> Summary {
+        Summary {
+            sum: samples.sum(),
+            min: samples.min(),
+            max: samples.max(),
+            mean: samples.mean(),
+            median: samples.median(),
+            var: samples.var(),
+            std_dev: samples.std_dev(),
+            std_dev_pct: samples.std_dev_pct(),
+            median_abs_dev: samples.median_abs_dev(),
+            median_abs_dev_pct: samples.median_abs_dev_pct(),
+            quartiles: samples.quartiles(),
+            iqr: samples.iqr(),
+        }
+    }
+}
+
+impl Stats for [f64] {
+    // FIXME #11059 handle NaN, inf and overflow
+    fn sum(&self) -> f64 {
+        let mut partials = vec![];
+
+        for &x in self {
+            let mut x = x;
+            let mut j = 0;
+            // This inner loop applies `hi`/`lo` summation to each
+            // partial so that the list of partial sums remains exact.
+            for i in 0..partials.len() {
+                let mut y: f64 = partials[i];
+                if x.abs() < y.abs() {
+                    mem::swap(&mut x, &mut y);
+                }
+                // Rounded `x+y` is stored in `hi` with round-off stored in
+                // `lo`. Together `hi+lo` are exactly equal to `x+y`.
+                let hi = x + y;
+                let lo = y - (hi - x);
+                if lo != 0.0 {
+                    partials[j] = lo;
+                    j += 1;
+                }
+                x = hi;
+            }
+            if j >= partials.len() {
+                partials.push(x);
+            } else {
+                partials[j] = x;
+                partials.truncate(j + 1);
+            }
+        }
+        let zero: f64 = 0.0;
+        partials.iter().fold(zero, |p, q| p + *q)
+    }
+
+    fn min(&self) -> f64 {
+        assert!(!self.is_empty());
+        self.iter().fold(self[0], |p, q| p.min(*q))
+    }
+
+    fn max(&self) -> f64 {
+        assert!(!self.is_empty());
+        self.iter().fold(self[0], |p, q| p.max(*q))
+    }
+
+    fn mean(&self) -> f64 {
+        assert!(!self.is_empty());
+        self.sum() / (self.len() as f64)
+    }
+
+    fn median(&self) -> f64 {
+        self.percentile(50 as f64)
+    }
+
+    fn var(&self) -> f64 {
+        if self.len() < 2 {
+            0.0
+        } else {
+            let mean = self.mean();
+            let mut v: f64 = 0.0;
+            for s in self {
+                let x = *s - mean;
+                v = v + x * x;
+            }
+            // N.B., this is _supposed to be_ len-1, not len. If you
+            // change it back to len, you will be calculating a
+            // population variance, not a sample variance.
+            let denom = (self.len() - 1) as f64;
+            v / denom
+        }
+    }
+
+    fn std_dev(&self) -> f64 {
+        self.var().sqrt()
+    }
+
+    fn std_dev_pct(&self) -> f64 {
+        let hundred = 100 as f64;
+        (self.std_dev() / self.mean()) * hundred
+    }
+
+    fn median_abs_dev(&self) -> f64 {
+        let med = self.median();
+        let abs_devs: Vec<f64> = self.iter().map(|&v| (med - v).abs()).collect();
+        // This constant is derived by smarter statistics brains than me, but it is
+        // consistent with how R and other packages treat the MAD.
+        let number = 1.4826;
+        abs_devs.median() * number
+    }
+
+    fn median_abs_dev_pct(&self) -> f64 {
+        let hundred = 100 as f64;
+        (self.median_abs_dev() / self.median()) * hundred
+    }
+
+    fn percentile(&self, pct: f64) -> f64 {
+        let mut tmp = self.to_vec();
+        local_sort(&mut tmp);
+        percentile_of_sorted(&tmp, pct)
+    }
+
+    fn quartiles(&self) -> (f64, f64, f64) {
+        let mut tmp = self.to_vec();
+        local_sort(&mut tmp);
+        let first = 25f64;
+        let a = percentile_of_sorted(&tmp, first);
+        let second = 50f64;
+        let b = percentile_of_sorted(&tmp, second);
+        let third = 75f64;
+        let c = percentile_of_sorted(&tmp, third);
+        (a, b, c)
+    }
+
+    fn iqr(&self) -> f64 {
+        let (a, _, c) = self.quartiles();
+        c - a
+    }
+}
+
+// Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using
+// linear interpolation. If samples are not sorted, return nonsensical value.
+fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 {
+    assert!(!sorted_samples.is_empty());
+    if sorted_samples.len() == 1 {
+        return sorted_samples[0];
+    }
+    let zero: f64 = 0.0;
+    assert!(zero <= pct);
+    let hundred = 100f64;
+    assert!(pct <= hundred);
+    if pct == hundred {
+        return sorted_samples[sorted_samples.len() - 1];
+    }
+    let length = (sorted_samples.len() - 1) as f64;
+    let rank = (pct / hundred) * length;
+    let lrank = rank.floor();
+    let d = rank - lrank;
+    let n = lrank as usize;
+    let lo = sorted_samples[n];
+    let hi = sorted_samples[n + 1];
+    lo + (hi - lo) * d
+}
+
+/// Winsorize a set of samples, replacing values above the `100-pct` percentile
+/// and below the `pct` percentile with those percentiles themselves. This is a
+/// way of minimizing the effect of outliers, at the cost of biasing the sample.
+/// It differs from trimming in that it does not change the number of samples,
+/// just changes the values of those that are outliers.
+///
+/// See: <http://en.wikipedia.org/wiki/Winsorising>
+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 hi = percentile_of_sorted(&tmp, hundred - pct);
+    for samp in samples {
+        if *samp > hi {
+            *samp = hi
+        } else if *samp < lo {
+            *samp = lo
+        }
+    }
+}
+
+// Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
+
+#[cfg(test)]
+mod tests {
+    use crate::stats::Stats;
+    use crate::stats::Summary;
+    use std::f64;
+    use std::io::prelude::*;
+    use std::io;
+
+    macro_rules! assert_approx_eq {
+        ($a: expr, $b: expr) => {{
+            let (a, b) = (&$a, &$b);
+            assert!(
+                (*a - *b).abs() < 1.0e-6,
+                "{} is not approximately equal to {}",
+                *a,
+                *b
+            );
+        }};
+    }
+
+    fn check(samples: &[f64], summ: &Summary) {
+        let summ2 = Summary::new(samples);
+
+        let mut w = io::sink();
+        let w = &mut w;
+        (write!(w, "\n")).unwrap();
+
+        assert_eq!(summ.sum, summ2.sum);
+        assert_eq!(summ.min, summ2.min);
+        assert_eq!(summ.max, summ2.max);
+        assert_eq!(summ.mean, summ2.mean);
+        assert_eq!(summ.median, summ2.median);
+
+        // We needed a few more digits to get exact equality on these
+        // but they're within float epsilon, which is 1.0e-6.
+        assert_approx_eq!(summ.var, summ2.var);
+        assert_approx_eq!(summ.std_dev, summ2.std_dev);
+        assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct);
+        assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev);
+        assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct);
+
+        assert_eq!(summ.quartiles, summ2.quartiles);
+        assert_eq!(summ.iqr, summ2.iqr);
+    }
+
+    #[test]
+    fn test_min_max_nan() {
+        let xs = &[1.0, 2.0, f64::NAN, 3.0, 4.0];
+        let summary = Summary::new(xs);
+        assert_eq!(summary.min, 1.0);
+        assert_eq!(summary.max, 4.0);
+    }
+
+    #[test]
+    fn test_norm2() {
+        let val = &[958.0000000000, 924.0000000000];
+        let summ = &Summary {
+            sum: 1882.0000000000,
+            min: 924.0000000000,
+            max: 958.0000000000,
+            mean: 941.0000000000,
+            median: 941.0000000000,
+            var: 578.0000000000,
+            std_dev: 24.0416305603,
+            std_dev_pct: 2.5549022912,
+            median_abs_dev: 25.2042000000,
+            median_abs_dev_pct: 2.6784484591,
+            quartiles: (932.5000000000, 941.0000000000, 949.5000000000),
+            iqr: 17.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_norm10narrow() {
+        let val = &[
+            966.0000000000,
+            985.0000000000,
+            1110.0000000000,
+            848.0000000000,
+            821.0000000000,
+            975.0000000000,
+            962.0000000000,
+            1157.0000000000,
+            1217.0000000000,
+            955.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 9996.0000000000,
+            min: 821.0000000000,
+            max: 1217.0000000000,
+            mean: 999.6000000000,
+            median: 970.5000000000,
+            var: 16050.7111111111,
+            std_dev: 126.6914010938,
+            std_dev_pct: 12.6742097933,
+            median_abs_dev: 102.2994000000,
+            median_abs_dev_pct: 10.5408964451,
+            quartiles: (956.7500000000, 970.5000000000, 1078.7500000000),
+            iqr: 122.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_norm10medium() {
+        let val = &[
+            954.0000000000,
+            1064.0000000000,
+            855.0000000000,
+            1000.0000000000,
+            743.0000000000,
+            1084.0000000000,
+            704.0000000000,
+            1023.0000000000,
+            357.0000000000,
+            869.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 8653.0000000000,
+            min: 357.0000000000,
+            max: 1084.0000000000,
+            mean: 865.3000000000,
+            median: 911.5000000000,
+            var: 48628.4555555556,
+            std_dev: 220.5186059170,
+            std_dev_pct: 25.4846418487,
+            median_abs_dev: 195.7032000000,
+            median_abs_dev_pct: 21.4704552935,
+            quartiles: (771.0000000000, 911.5000000000, 1017.2500000000),
+            iqr: 246.2500000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_norm10wide() {
+        let val = &[
+            505.0000000000,
+            497.0000000000,
+            1591.0000000000,
+            887.0000000000,
+            1026.0000000000,
+            136.0000000000,
+            1580.0000000000,
+            940.0000000000,
+            754.0000000000,
+            1433.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 9349.0000000000,
+            min: 136.0000000000,
+            max: 1591.0000000000,
+            mean: 934.9000000000,
+            median: 913.5000000000,
+            var: 239208.9888888889,
+            std_dev: 489.0899599142,
+            std_dev_pct: 52.3146817750,
+            median_abs_dev: 611.5725000000,
+            median_abs_dev_pct: 66.9482758621,
+            quartiles: (567.2500000000, 913.5000000000, 1331.2500000000),
+            iqr: 764.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_norm25verynarrow() {
+        let val = &[
+            991.0000000000,
+            1018.0000000000,
+            998.0000000000,
+            1013.0000000000,
+            974.0000000000,
+            1007.0000000000,
+            1014.0000000000,
+            999.0000000000,
+            1011.0000000000,
+            978.0000000000,
+            985.0000000000,
+            999.0000000000,
+            983.0000000000,
+            982.0000000000,
+            1015.0000000000,
+            1002.0000000000,
+            977.0000000000,
+            948.0000000000,
+            1040.0000000000,
+            974.0000000000,
+            996.0000000000,
+            989.0000000000,
+            1015.0000000000,
+            994.0000000000,
+            1024.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 24926.0000000000,
+            min: 948.0000000000,
+            max: 1040.0000000000,
+            mean: 997.0400000000,
+            median: 998.0000000000,
+            var: 393.2066666667,
+            std_dev: 19.8294393937,
+            std_dev_pct: 1.9888308788,
+            median_abs_dev: 22.2390000000,
+            median_abs_dev_pct: 2.2283567134,
+            quartiles: (983.0000000000, 998.0000000000, 1013.0000000000),
+            iqr: 30.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_exp10a() {
+        let val = &[
+            23.0000000000,
+            11.0000000000,
+            2.0000000000,
+            57.0000000000,
+            4.0000000000,
+            12.0000000000,
+            5.0000000000,
+            29.0000000000,
+            3.0000000000,
+            21.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 167.0000000000,
+            min: 2.0000000000,
+            max: 57.0000000000,
+            mean: 16.7000000000,
+            median: 11.5000000000,
+            var: 287.7888888889,
+            std_dev: 16.9643416875,
+            std_dev_pct: 101.5828843560,
+            median_abs_dev: 13.3434000000,
+            median_abs_dev_pct: 116.0295652174,
+            quartiles: (4.2500000000, 11.5000000000, 22.5000000000),
+            iqr: 18.2500000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_exp10b() {
+        let val = &[
+            24.0000000000,
+            17.0000000000,
+            6.0000000000,
+            38.0000000000,
+            25.0000000000,
+            7.0000000000,
+            51.0000000000,
+            2.0000000000,
+            61.0000000000,
+            32.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 263.0000000000,
+            min: 2.0000000000,
+            max: 61.0000000000,
+            mean: 26.3000000000,
+            median: 24.5000000000,
+            var: 383.5666666667,
+            std_dev: 19.5848580967,
+            std_dev_pct: 74.4671410520,
+            median_abs_dev: 22.9803000000,
+            median_abs_dev_pct: 93.7971428571,
+            quartiles: (9.5000000000, 24.5000000000, 36.5000000000),
+            iqr: 27.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_exp10c() {
+        let val = &[
+            71.0000000000,
+            2.0000000000,
+            32.0000000000,
+            1.0000000000,
+            6.0000000000,
+            28.0000000000,
+            13.0000000000,
+            37.0000000000,
+            16.0000000000,
+            36.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 242.0000000000,
+            min: 1.0000000000,
+            max: 71.0000000000,
+            mean: 24.2000000000,
+            median: 22.0000000000,
+            var: 458.1777777778,
+            std_dev: 21.4050876611,
+            std_dev_pct: 88.4507754589,
+            median_abs_dev: 21.4977000000,
+            median_abs_dev_pct: 97.7168181818,
+            quartiles: (7.7500000000, 22.0000000000, 35.0000000000),
+            iqr: 27.2500000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_exp25() {
+        let val = &[
+            3.0000000000,
+            24.0000000000,
+            1.0000000000,
+            19.0000000000,
+            7.0000000000,
+            5.0000000000,
+            30.0000000000,
+            39.0000000000,
+            31.0000000000,
+            13.0000000000,
+            25.0000000000,
+            48.0000000000,
+            1.0000000000,
+            6.0000000000,
+            42.0000000000,
+            63.0000000000,
+            2.0000000000,
+            12.0000000000,
+            108.0000000000,
+            26.0000000000,
+            1.0000000000,
+            7.0000000000,
+            44.0000000000,
+            25.0000000000,
+            11.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 593.0000000000,
+            min: 1.0000000000,
+            max: 108.0000000000,
+            mean: 23.7200000000,
+            median: 19.0000000000,
+            var: 601.0433333333,
+            std_dev: 24.5161851301,
+            std_dev_pct: 103.3565983562,
+            median_abs_dev: 19.2738000000,
+            median_abs_dev_pct: 101.4410526316,
+            quartiles: (6.0000000000, 19.0000000000, 31.0000000000),
+            iqr: 25.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_binom25() {
+        let val = &[
+            18.0000000000,
+            17.0000000000,
+            27.0000000000,
+            15.0000000000,
+            21.0000000000,
+            25.0000000000,
+            17.0000000000,
+            24.0000000000,
+            25.0000000000,
+            24.0000000000,
+            26.0000000000,
+            26.0000000000,
+            23.0000000000,
+            15.0000000000,
+            23.0000000000,
+            17.0000000000,
+            18.0000000000,
+            18.0000000000,
+            21.0000000000,
+            16.0000000000,
+            15.0000000000,
+            31.0000000000,
+            20.0000000000,
+            17.0000000000,
+            15.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 514.0000000000,
+            min: 15.0000000000,
+            max: 31.0000000000,
+            mean: 20.5600000000,
+            median: 20.0000000000,
+            var: 20.8400000000,
+            std_dev: 4.5650848842,
+            std_dev_pct: 22.2037202539,
+            median_abs_dev: 5.9304000000,
+            median_abs_dev_pct: 29.6520000000,
+            quartiles: (17.0000000000, 20.0000000000, 24.0000000000),
+            iqr: 7.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_pois25lambda30() {
+        let val = &[
+            27.0000000000,
+            33.0000000000,
+            34.0000000000,
+            34.0000000000,
+            24.0000000000,
+            39.0000000000,
+            28.0000000000,
+            27.0000000000,
+            31.0000000000,
+            28.0000000000,
+            38.0000000000,
+            21.0000000000,
+            33.0000000000,
+            36.0000000000,
+            29.0000000000,
+            37.0000000000,
+            32.0000000000,
+            34.0000000000,
+            31.0000000000,
+            39.0000000000,
+            25.0000000000,
+            31.0000000000,
+            32.0000000000,
+            40.0000000000,
+            24.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 787.0000000000,
+            min: 21.0000000000,
+            max: 40.0000000000,
+            mean: 31.4800000000,
+            median: 32.0000000000,
+            var: 26.5933333333,
+            std_dev: 5.1568724372,
+            std_dev_pct: 16.3814245145,
+            median_abs_dev: 5.9304000000,
+            median_abs_dev_pct: 18.5325000000,
+            quartiles: (28.0000000000, 32.0000000000, 34.0000000000),
+            iqr: 6.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_pois25lambda40() {
+        let val = &[
+            42.0000000000,
+            50.0000000000,
+            42.0000000000,
+            46.0000000000,
+            34.0000000000,
+            45.0000000000,
+            34.0000000000,
+            49.0000000000,
+            39.0000000000,
+            28.0000000000,
+            40.0000000000,
+            35.0000000000,
+            37.0000000000,
+            39.0000000000,
+            46.0000000000,
+            44.0000000000,
+            32.0000000000,
+            45.0000000000,
+            42.0000000000,
+            37.0000000000,
+            48.0000000000,
+            42.0000000000,
+            33.0000000000,
+            42.0000000000,
+            48.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 1019.0000000000,
+            min: 28.0000000000,
+            max: 50.0000000000,
+            mean: 40.7600000000,
+            median: 42.0000000000,
+            var: 34.4400000000,
+            std_dev: 5.8685603004,
+            std_dev_pct: 14.3978417577,
+            median_abs_dev: 5.9304000000,
+            median_abs_dev_pct: 14.1200000000,
+            quartiles: (37.0000000000, 42.0000000000, 45.0000000000),
+            iqr: 8.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_pois25lambda50() {
+        let val = &[
+            45.0000000000,
+            43.0000000000,
+            44.0000000000,
+            61.0000000000,
+            51.0000000000,
+            53.0000000000,
+            59.0000000000,
+            52.0000000000,
+            49.0000000000,
+            51.0000000000,
+            51.0000000000,
+            50.0000000000,
+            49.0000000000,
+            56.0000000000,
+            42.0000000000,
+            52.0000000000,
+            51.0000000000,
+            43.0000000000,
+            48.0000000000,
+            48.0000000000,
+            50.0000000000,
+            42.0000000000,
+            43.0000000000,
+            42.0000000000,
+            60.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 1235.0000000000,
+            min: 42.0000000000,
+            max: 61.0000000000,
+            mean: 49.4000000000,
+            median: 50.0000000000,
+            var: 31.6666666667,
+            std_dev: 5.6273143387,
+            std_dev_pct: 11.3913245723,
+            median_abs_dev: 4.4478000000,
+            median_abs_dev_pct: 8.8956000000,
+            quartiles: (44.0000000000, 50.0000000000, 52.0000000000),
+            iqr: 8.0000000000,
+        };
+        check(val, summ);
+    }
+    #[test]
+    fn test_unif25() {
+        let val = &[
+            99.0000000000,
+            55.0000000000,
+            92.0000000000,
+            79.0000000000,
+            14.0000000000,
+            2.0000000000,
+            33.0000000000,
+            49.0000000000,
+            3.0000000000,
+            32.0000000000,
+            84.0000000000,
+            59.0000000000,
+            22.0000000000,
+            86.0000000000,
+            76.0000000000,
+            31.0000000000,
+            29.0000000000,
+            11.0000000000,
+            41.0000000000,
+            53.0000000000,
+            45.0000000000,
+            44.0000000000,
+            98.0000000000,
+            98.0000000000,
+            7.0000000000,
+        ];
+        let summ = &Summary {
+            sum: 1242.0000000000,
+            min: 2.0000000000,
+            max: 99.0000000000,
+            mean: 49.6800000000,
+            median: 45.0000000000,
+            var: 1015.6433333333,
+            std_dev: 31.8691595957,
+            std_dev_pct: 64.1488719719,
+            median_abs_dev: 45.9606000000,
+            median_abs_dev_pct: 102.1346666667,
+            quartiles: (29.0000000000, 45.0000000000, 79.0000000000),
+            iqr: 50.0000000000,
+        };
+        check(val, summ);
+    }
+
+    #[test]
+    fn test_sum_f64s() {
+        assert_eq!([0.5f64, 3.2321f64, 1.5678f64].sum(), 5.2999);
+    }
+    #[test]
+    fn test_sum_f64_between_ints_that_sum_to_0() {
+        assert_eq!([1e30f64, 1.2f64, -1e30f64].sum(), 1.2);
+    }
+}
+
+#[cfg(test)]
+mod bench {
+    extern crate test;
+    use self::test::Bencher;
+    use crate::stats::Stats;
+
+    #[bench]
+    pub fn sum_three_items(b: &mut Bencher) {
+        b.iter(|| {
+            [1e20f64, 1.5f64, -1e20f64].sum();
+        })
+    }
+    #[bench]
+    pub fn sum_many_f64(b: &mut Bencher) {
+        let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60];
+        let v = (0..500).map(|i| nums[i % 5]).collect::<Vec<_>>();
+
+        b.iter(|| {
+            v.sum();
+        })
+    }
+
+    #[bench]
+    pub fn no_iter(_: &mut Bencher) {}
+}
diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml
index 2378b0a315a..4ddc878997e 100644
--- a/src/libunwind/Cargo.toml
+++ b/src/libunwind/Cargo.toml
@@ -4,6 +4,9 @@ name = "unwind"
 version = "0.0.0"
 build = "build.rs"
 edition = "2018"
+include = [
+  '/libunwind/*',
+]
 
 [lib]
 name = "unwind"
@@ -16,3 +19,9 @@ doc = false
 core = { path = "../libcore" }
 libc = { version = "0.2.43", features = ['rustc-dep-of-std'], default-features = false }
 compiler_builtins = "0.1.0"
+
+[build-dependencies]
+cc = { optional = true, version = "1.0.1" }
+
+[features]
+llvm-libunwind = ["cc"]
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index b50a11fa03a..f3fda9eaa75 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -4,7 +4,13 @@ fn main() {
     println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
 
-    if target.contains("linux") {
+    if cfg!(feature = "llvm-libunwind") &&
+        (target.contains("linux") ||
+         target.contains("fuchsia")) {
+        // Build the unwinding from libunwind C/C++ source code.
+        #[cfg(feature = "llvm-libunwind")]
+        llvm_libunwind::compile();
+    } else if target.contains("linux") {
         if target.contains("musl") {
             // musl is handled in lib.rs
         } else if !target.contains("android") {
@@ -37,3 +43,62 @@ fn main() {
         println!("cargo:rustc-link-lib=unwind");
     }
 }
+
+#[cfg(feature = "llvm-libunwind")]
+mod llvm_libunwind {
+    use std::env;
+    use std::path::Path;
+
+    /// Compile the libunwind C/C++ source code.
+    pub fn compile() {
+        let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
+        let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
+        let cfg = &mut cc::Build::new();
+
+        cfg.cpp(true);
+        cfg.cpp_set_stdlib(None);
+        cfg.warnings(false);
+
+        if target_env == "msvc" {
+            // Don't pull in extra libraries on MSVC
+            cfg.flag("/Zl");
+            cfg.flag("/EHsc");
+            cfg.define("_CRT_SECURE_NO_WARNINGS", None);
+            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
+        } else {
+            cfg.flag("-std=c99");
+            cfg.flag("-std=c++11");
+            cfg.flag("-nostdinc++");
+            if cfg.is_flag_supported("-funwind-tables").unwrap_or_default() &&
+               cfg.is_flag_supported("-fno-exceptions").unwrap_or_default() {
+                cfg.flag("-funwind-tables");
+                cfg.flag("-fno-exceptions");
+            }
+            cfg.flag("-fno-rtti");
+            cfg.flag("-fstrict-aliasing");
+        }
+
+        let mut unwind_sources = vec![
+            "Unwind-EHABI.cpp",
+            "Unwind-seh.cpp",
+            "Unwind-sjlj.c",
+            "UnwindLevel1-gcc-ext.c",
+            "UnwindLevel1.c",
+            "UnwindRegistersRestore.S",
+            "UnwindRegistersSave.S",
+            "libunwind.cpp",
+        ];
+
+        if target_vendor == "apple" {
+            unwind_sources.push("Unwind_AppleExtras.cpp");
+        }
+
+        let root = Path::new("../llvm-project/libunwind");
+        cfg.include(root.join("include"));
+        for src in unwind_sources {
+            cfg.file(root.join("src").join(src));
+        }
+
+        cfg.compile("unwind");
+    }
+}
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 1f484cbe0e863e9e215f1b3d7198063444d6087
+Subproject 84abffda0e03b03c62bdfc3cfeda1c2cf1f88c8
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 65975ec574c..dd0111d3f2c 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -24,9 +24,14 @@ struct RustArchiveIterator {
   bool First;
   Archive::child_iterator Cur;
   Archive::child_iterator End;
-  Error Err;
-
-  RustArchiveIterator() : First(true), Err(Error::success()) {}
+  std::unique_ptr<Error> Err;
+
+  RustArchiveIterator(Archive::child_iterator Cur, Archive::child_iterator End,
+      std::unique_ptr<Error> Err)
+    : First(true),
+      Cur(Cur),
+      End(End),
+      Err(std::move(Err)) {}
 };
 
 enum class LLVMRustArchiveKind {
@@ -84,15 +89,14 @@ extern "C" void LLVMRustDestroyArchive(LLVMRustArchiveRef RustArchive) {
 extern "C" LLVMRustArchiveIteratorRef
 LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) {
   Archive *Archive = RustArchive->getBinary();
-  RustArchiveIterator *RAI = new RustArchiveIterator();
-  RAI->Cur = Archive->child_begin(RAI->Err);
-  if (RAI->Err) {
-    LLVMRustSetLastError(toString(std::move(RAI->Err)).c_str());
-    delete RAI;
+  std::unique_ptr<Error> Err = llvm::make_unique<Error>(Error::success());
+  auto Cur = Archive->child_begin(*Err);
+  if (*Err) {
+    LLVMRustSetLastError(toString(std::move(*Err)).c_str());
     return nullptr;
   }
-  RAI->End = Archive->child_end();
-  return RAI;
+  auto End = Archive->child_end();
+  return new RustArchiveIterator(Cur, End, std::move(Err));
 }
 
 extern "C" LLVMRustArchiveChildConstRef
@@ -108,8 +112,8 @@ LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef RAI) {
   // but instead advance it *before* fetching the child in all later calls.
   if (!RAI->First) {
     ++RAI->Cur;
-    if (RAI->Err) {
-      LLVMRustSetLastError(toString(std::move(RAI->Err)).c_str());
+    if (*RAI->Err) {
+      LLVMRustSetLastError(toString(std::move(*RAI->Err)).c_str());
       return nullptr;
     }
   } else {
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 25595e14982..319c66a21f1 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -646,8 +646,9 @@ char RustPrintModulePass::ID = 0;
 INITIALIZE_PASS(RustPrintModulePass, "print-rust-module",
                 "Print rust module to stderr", false, false)
 
-extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
-                                    const char *Path, DemangleFn Demangle) {
+extern "C" LLVMRustResult
+LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
+                    const char *Path, DemangleFn Demangle) {
   llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
   std::string ErrorInfo;
 
@@ -655,12 +656,18 @@ extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
   raw_fd_ostream OS(Path, EC, sys::fs::F_None);
   if (EC)
     ErrorInfo = EC.message();
+  if (ErrorInfo != "") {
+    LLVMRustSetLastError(ErrorInfo.c_str());
+    return LLVMRustResult::Failure;
+  }
 
   formatted_raw_ostream FOS(OS);
 
   PM->add(new RustPrintModulePass(FOS, Demangle));
 
   PM->run(*unwrap(M));
+
+  return LLVMRustResult::Success;
 }
 
 extern "C" void LLVMRustPrintPasses() {
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index a00417a3629..437e2d482ef 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -117,7 +117,11 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
                                                     const char *Name,
                                                     LLVMTypeRef FunctionTy) {
   return wrap(
-      unwrap(M)->getOrInsertFunction(Name, unwrap<FunctionType>(FunctionTy)));
+      unwrap(M)->getOrInsertFunction(Name, unwrap<FunctionType>(FunctionTy))
+#if LLVM_VERSION_GE(9, 0)
+      .getCallee()
+#endif
+      );
 }
 
 extern "C" LLVMValueRef
@@ -417,7 +421,6 @@ enum class LLVMRustDIFlags : uint32_t {
   FlagIntroducedVirtual = (1 << 18),
   FlagBitField = (1 << 19),
   FlagNoReturn = (1 << 20),
-  FlagMainSubprogram = (1 << 21),
   // Do not add values that are not supported by the minimum LLVM
   // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
 };
@@ -508,9 +511,6 @@ static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
   if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
     Result |= DINode::DIFlags::FlagNoReturn;
   }
-  if (isSet(Flags & LLVMRustDIFlags::FlagMainSubprogram)) {
-    Result |= DINode::DIFlags::FlagMainSubprogram;
-  }
 
   return Result;
 }
@@ -525,6 +525,7 @@ enum class LLVMRustDISPFlags : uint32_t {
   SPFlagLocalToUnit = (1 << 2),
   SPFlagDefinition = (1 << 3),
   SPFlagOptimized = (1 << 4),
+  SPFlagMainSubprogram = (1 << 5),
   // Do not add values that are not supported by the minimum LLVM
   // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
   // (In LLVM < 8, createFunction supported these as separate bool arguments.)
@@ -575,6 +576,11 @@ static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
   if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
     Result |= DISubprogram::DISPFlags::SPFlagOptimized;
   }
+#if LLVM_VERSION_GE(9, 0)
+  if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
+    Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
+  }
+#endif
 
   return Result;
 }
@@ -671,18 +677,27 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
   DITemplateParameterArray TParams =
       DITemplateParameterArray(unwrap<MDTuple>(TParam));
 #if LLVM_VERSION_GE(8, 0)
+  DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
+  DINode::DIFlags llvmFlags = fromRust(Flags);
+#if LLVM_VERSION_LT(9, 0)
+  if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram))
+    llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
+#endif
   DISubprogram *Sub = Builder->createFunction(
       unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
-      LineNo, unwrapDI<DISubroutineType>(Ty), ScopeLine, fromRust(Flags),
-      fromRust(SPFlags), TParams, unwrapDIPtr<DISubprogram>(Decl));
+      LineNo, unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
+      llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
 #else
   bool IsLocalToUnit = isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit);
   bool IsDefinition = isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition);
   bool IsOptimized = isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized);
+  DINode::DIFlags llvmFlags = fromRust(Flags);
+  if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram))
+    llvmFlags |= DINode::DIFlags::FlagMainSubprogram;
   DISubprogram *Sub = Builder->createFunction(
       unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
       LineNo, unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
-      ScopeLine, fromRust(Flags), IsOptimized, TParams,
+      ScopeLine, llvmFlags, IsOptimized, TParams,
       unwrapDIPtr<DISubprogram>(Decl));
 #endif
   unwrap<Function>(Fn)->setSubprogram(Sub);
diff --git a/src/stdsimd b/src/stdsimd
-Subproject 12bdc2ed6b32653866d02b42f0885d9cd8bd295
+Subproject 2792b45c975880038240d477adb0d66f760ac04
diff --git a/src/test/codegen/fn-impl-trait-self.rs b/src/test/codegen/fn-impl-trait-self.rs
new file mode 100644
index 00000000000..f9113d50197
--- /dev/null
+++ b/src/test/codegen/fn-impl-trait-self.rs
@@ -0,0 +1,15 @@
+// compile-flags: -g
+//
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}}
+//
+// CHECK: {{.*}}DISubroutineType{{.*}}
+// CHECK: {{.*}}DIBasicType(name: "<recur_type>", encoding: DW_ATE_unsigned)
+
+pub fn foo() -> impl Copy {
+    foo
+}
+
+fn main() {
+    let my_res = foo();
+}
diff --git a/src/test/codegen/noreturn-uninhabited.rs b/src/test/codegen/noreturn-uninhabited.rs
new file mode 100644
index 00000000000..1b65da9f287
--- /dev/null
+++ b/src/test/codegen/noreturn-uninhabited.rs
@@ -0,0 +1,32 @@
+// compile-flags: -g -C no-prepopulate-passes
+// ignore-tidy-linelength
+
+#![crate_type = "lib"]
+
+#[derive(Clone, Copy)]
+pub enum EmptyEnum {}
+
+#[no_mangle]
+pub fn empty(x: &EmptyEnum) -> EmptyEnum {
+    // CHECK: @empty({{.*}}) unnamed_addr #0
+    // CHECK-NOT: ret void
+    // CHECK: call void @llvm.trap()
+    // CHECK: unreachable
+    *x
+}
+
+pub struct Foo(String, EmptyEnum);
+
+#[no_mangle]
+pub fn foo(x: String, y: &EmptyEnum) -> Foo {
+    // CHECK: @foo({{.*}}) unnamed_addr #0
+    // CHECK-NOT: ret %Foo
+    // CHECK: call void @llvm.trap()
+    // CHECK: unreachable
+    Foo(x, *y)
+}
+
+// CHECK: attributes #0 = {{{.*}} noreturn {{.*}}}
+
+// CHECK: DISubprogram(name: "empty", {{.*}} DIFlagNoReturn
+// CHECK: DISubprogram(name: "foo", {{.*}} DIFlagNoReturn
diff --git a/src/test/compile-fail/must_use-in-stdlib-traits.rs b/src/test/compile-fail/must_use-in-stdlib-traits.rs
index b4f07ab3321..503b39e181a 100644
--- a/src/test/compile-fail/must_use-in-stdlib-traits.rs
+++ b/src/test/compile-fail/must_use-in-stdlib-traits.rs
@@ -4,7 +4,7 @@
 use std::iter::Iterator;
 use std::future::Future;
 
-use std::task::{Poll, Waker};
+use std::task::{Context, Poll};
 use std::pin::Pin;
 use std::unimplemented;
 
@@ -13,7 +13,7 @@ struct MyFuture;
 impl Future for MyFuture {
    type Output = u32;
 
-   fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<u32> {
+   fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<u32> {
       Poll::Pending
    }
 }
diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
index 0e17a29dea0..13daa72a4d1 100644
--- a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
+++ b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
@@ -24,7 +24,7 @@ extern crate point;
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -35,7 +35,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_free_fn {
     use point::{self, Point};
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         point::distance_squared(&x);
@@ -46,7 +46,7 @@ pub mod fn_calls_free_fn {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -56,7 +56,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -66,7 +66,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/callee_caller_cross_crate/b.rs b/src/test/incremental/callee_caller_cross_crate/b.rs
index 95285b7a03c..b49731b26e7 100644
--- a/src/test/incremental/callee_caller_cross_crate/b.rs
+++ b/src/test/incremental/callee_caller_cross_crate/b.rs
@@ -6,12 +6,12 @@
 
 extern crate a;
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
 pub fn call_function0() {
     a::function0(77);
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
 pub fn call_function1() {
     a::function1(77);
 }
diff --git a/src/test/incremental/change_add_field/struct_point.rs b/src/test/incremental/change_add_field/struct_point.rs
index 182e6cb45be..9e34aedbed3 100644
--- a/src/test/incremental/change_add_field/struct_point.rs
+++ b/src/test/incremental/change_add_field/struct_point.rs
@@ -70,7 +70,7 @@ pub mod point {
 pub mod fn_with_type_in_sig {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+    #[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
     pub fn boop(p: Option<&Point>) -> f32 {
         p.map(|p| p.total()).unwrap_or(0.0)
     }
@@ -86,7 +86,7 @@ pub mod fn_with_type_in_sig {
 pub mod call_fn_with_type_in_sig {
     use fn_with_type_in_sig;
 
-    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+    #[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
     pub fn bip() -> f32 {
         fn_with_type_in_sig::boop(None)
     }
@@ -102,7 +102,7 @@ pub mod call_fn_with_type_in_sig {
 pub mod fn_with_type_in_body {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+    #[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
     pub fn boop() -> f32 {
         Point::origin().total()
     }
@@ -115,7 +115,7 @@ pub mod fn_with_type_in_body {
 pub mod call_fn_with_type_in_body {
     use fn_with_type_in_body;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn bip() -> f32 {
         fn_with_type_in_body::boop()
     }
@@ -125,7 +125,7 @@ pub mod call_fn_with_type_in_body {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+    #[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
     pub fn make_origin(p: Point) -> Point {
         Point { ..p }
     }
@@ -135,7 +135,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+    #[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -145,7 +145,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+    #[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_crate_order/main.rs b/src/test/incremental/change_crate_order/main.rs
index e514c8519f8..c167cf6e035 100644
--- a/src/test/incremental/change_crate_order/main.rs
+++ b/src/test/incremental/change_crate_order/main.rs
@@ -18,7 +18,7 @@ extern crate a;
 use a::A;
 use b::B;
 
-//? #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+//? #[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
 pub fn main() {
     A + B;
 }
diff --git a/src/test/incremental/change_private_fn/struct_point.rs b/src/test/incremental/change_private_fn/struct_point.rs
index f9f83169ef4..be287b86bbc 100644
--- a/src/test/incremental/change_private_fn/struct_point.rs
+++ b/src/test/incremental/change_private_fn/struct_point.rs
@@ -51,7 +51,7 @@ pub mod point {
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -62,7 +62,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -73,7 +73,7 @@ pub mod fn_calls_methods_in_another_impl {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -83,7 +83,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -93,7 +93,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_private_fn_cc/struct_point.rs b/src/test/incremental/change_private_fn_cc/struct_point.rs
index 827eb8105b2..521fe99ebc2 100644
--- a/src/test/incremental/change_private_fn_cc/struct_point.rs
+++ b/src/test/incremental/change_private_fn_cc/struct_point.rs
@@ -23,7 +23,7 @@ extern crate point;
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -34,7 +34,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -45,7 +45,7 @@ pub mod fn_calls_methods_in_another_impl {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -55,7 +55,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -65,7 +65,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_private_impl_method/struct_point.rs b/src/test/incremental/change_private_impl_method/struct_point.rs
index e3073b170df..c2796b5e3c9 100644
--- a/src/test/incremental/change_private_impl_method/struct_point.rs
+++ b/src/test/incremental/change_private_impl_method/struct_point.rs
@@ -51,7 +51,7 @@ pub mod point {
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -62,7 +62,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -73,7 +73,7 @@ pub mod fn_calls_methods_in_another_impl {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -83,7 +83,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -93,7 +93,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_private_impl_method_cc/struct_point.rs b/src/test/incremental/change_private_impl_method_cc/struct_point.rs
index bd5e9636d48..731dcdf78c9 100644
--- a/src/test/incremental/change_private_impl_method_cc/struct_point.rs
+++ b/src/test/incremental/change_private_impl_method_cc/struct_point.rs
@@ -24,7 +24,7 @@ extern crate point;
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -35,7 +35,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn dirty() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -46,7 +46,7 @@ pub mod fn_calls_methods_in_another_impl {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -56,7 +56,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -66,7 +66,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_pub_inherent_method_body/struct_point.rs b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
index 8e87fde54ef..76dcff848ca 100644
--- a/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
+++ b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
@@ -42,7 +42,7 @@ pub mod point {
 pub mod fn_calls_changed_method {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.distance_from_origin();
@@ -53,7 +53,7 @@ pub mod fn_calls_changed_method {
 pub mod fn_calls_another_method {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.x();
@@ -64,7 +64,7 @@ pub mod fn_calls_another_method {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -74,7 +74,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -84,7 +84,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
index 7ea64a08472..9c95d4cc2a9 100644
--- a/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
+++ b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
@@ -52,7 +52,7 @@ pub mod point {
 pub mod fn_calls_changed_method {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+    #[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.distance_from_point(None);
@@ -63,7 +63,7 @@ pub mod fn_calls_changed_method {
 pub mod fn_calls_another_method {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.x();
@@ -74,7 +74,7 @@ pub mod fn_calls_another_method {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -84,7 +84,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -94,7 +94,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs
index f4248dbdd6d..b9a1846b37d 100644
--- a/src/test/incremental/dirty_clean.rs
+++ b/src/test/incremental/dirty_clean.rs
@@ -25,16 +25,16 @@ mod x {
 mod y {
     use x;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     pub fn y() {
-        //[cfail2]~^ ERROR `TypeckTables(y::y)` should be clean but is not
+        //[cfail2]~^ ERROR `typeck_tables_of(y::y)` should be clean but is not
         x::x();
     }
 }
 
 mod z {
-    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+    #[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
     pub fn z() {
-        //[cfail2]~^ ERROR `TypeckTables(z::z)` should be dirty but is not
+        //[cfail2]~^ ERROR `typeck_tables_of(z::z)` should be dirty but is not
     }
 }
diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs
index 05cc945bbaf..55dd3745123 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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_function() {
     callee2(1, 2)
@@ -81,7 +81,7 @@ pub fn change_callee_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_ufcs_callee_method() {
     let s = Struct;
@@ -149,7 +149,7 @@ pub fn change_to_ufcs() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,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.
@@ -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,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,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 b8e84173ec0..5bfd540eca6 100644
--- a/src/test/incremental/hashes/closure_expressions.rs
+++ b/src/test/incremental/hashes/closure_expressions.rs
@@ -37,7 +37,7 @@ pub fn add_parameter() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, 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, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_parameter_pattern() {
     let _ = |&x: &u32| x;
@@ -84,7 +84,7 @@ pub fn add_type_ascription_to_parameter() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_type_ascription_to_parameter() {
     let closure = |x: u32| x + 1u32;
@@ -101,7 +101,7 @@ pub fn change_parameter_type() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, 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/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs
index d3f96c9947b..f553b2d1b51 100644
--- a/src/test/incremental/hashes/enum_constructors.rs
+++ b/src/test/incremental/hashes/enum_constructors.rs
@@ -57,7 +57,7 @@ pub fn change_field_order_struct_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_struct_like() {
     let _ = Enum2::Struct {
@@ -139,8 +139,8 @@ pub mod change_constructor_path_indirectly_struct_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="FnSignature,Hir,HirBody,optimized_mir,mir_built,\
-                TypeckTables"
+        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\
+                typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> TheEnum {
@@ -197,7 +197,7 @@ pub fn change_constructor_path_tuple_like() {
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg="cfail2",
-    except="HirBody,optimized_mir,mir_built,TypeckTables"
+    except="HirBody,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,TypeckTables"
+    except="HirBody,optimized_mir,mir_built,typeck_tables_of"
 )]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_tuple_like() {
@@ -232,8 +232,8 @@ pub mod change_constructor_path_indirectly_tuple_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="FnSignature,Hir,HirBody,optimized_mir,mir_built,\
-                TypeckTables"
+        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\
+                typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> TheEnum {
@@ -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,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_c_like() {
     let _ = Clike2::B;
@@ -309,8 +309,8 @@ pub mod change_constructor_path_indirectly_c_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="FnSignature,Hir,HirBody,optimized_mir,mir_built,\
-                TypeckTables"
+        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\
+                typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> TheEnum {
diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs
index 91abca3312b..503cb8732ef 100644
--- a/src/test/incremental/hashes/for_loops.rs
+++ b/src/test/incremental/hashes/for_loops.rs
@@ -71,7 +71,7 @@ pub fn change_iteration_variable_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iteration_variable_pattern() {
     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, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index db8fa9ced11..7850291fc56 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -24,7 +24,7 @@ pub fn add_parameter() {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn add_parameter(p: i32) {}
 
@@ -47,7 +47,7 @@ pub fn type_of_parameter(p: i32) {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter(p: i64) {}
 
@@ -59,7 +59,7 @@ pub fn type_of_parameter_ref(p: &i32) {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter_ref(p: &mut i32) {}
 
@@ -71,7 +71,7 @@ pub fn order_of_parameters(p1: i32, p2: i64) {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn order_of_parameters(p2: i64, p1: i32) {}
 
@@ -83,7 +83,7 @@ pub fn make_unsafe() {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub unsafe fn make_unsafe() {}
 
@@ -94,7 +94,7 @@ pub unsafe fn make_unsafe() {}
 pub fn make_extern() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, mir_built, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, mir_built, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub extern "C" fn make_extern() {}
 
@@ -105,7 +105,7 @@ pub extern "C" fn make_extern() {}
 pub extern "C" fn make_intrinsic() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub extern "rust-intrinsic" fn make_intrinsic() {}
 
@@ -258,7 +258,7 @@ pub fn return_impl_trait() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn return_impl_trait() -> impl Clone {
     0
@@ -292,7 +292,7 @@ pub mod change_return_type_indirectly {
     use super::ReferencedType2 as ReturnType;
 
     #[rustc_clean(cfg = "cfail2",
-                  except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
+                  except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_return_type() -> ReturnType {
         ReturnType {}
@@ -309,7 +309,7 @@ pub mod change_parameter_type_indirectly {
     use super::ReferencedType2 as ParameterType;
 
     #[rustc_clean(cfg = "cfail2",
-                  except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
+                  except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_parameter_type(p: ParameterType) {}
 }
diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs
index 32a0c8b6b7e..fba7869af42 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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_condition(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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")]
 #[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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,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 {
@@ -191,7 +191,7 @@ pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")]
 #[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/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index 1b6b41ce05b..268c37508a7 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,AssociatedItemDefIds")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_clean(cfg="cfail3")]
@@ -42,7 +42,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_body() {
         println!("Hello, world!");
@@ -63,7 +63,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     #[inline]
     pub fn method_body_inlined() {
@@ -82,7 +82,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="AssociatedItems,Hir,HirBody")]
+    #[rustc_clean(cfg="cfail2", except="associated_item,Hir,HirBody")]
     #[rustc_clean(cfg="cfail3")]
     fn method_privacy() { }
 }
@@ -114,7 +114,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,FnSignature,TypeckTables,optimized_mir,mir_built"
+        except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_selfmutness(&mut self) { }
@@ -129,7 +129,7 @@ impl Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="Hir,HirBody,AssociatedItemDefIds")]
+#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
     #[rustc_clean(cfg="cfail2")]
@@ -154,7 +154,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,FnSignature,TypeckTables,optimized_mir,mir_built"
+        except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_method_parameter(&self, _: i32) { }
@@ -191,7 +191,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,FnSignature,optimized_mir,mir_built,TypeckTables")]
+        except="Hir,HirBody,fn_sig,optimized_mir,mir_built,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_return_type(&self) -> u8 { 0 }
 }
@@ -245,7 +245,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,FnSignature,TypeckTables,optimized_mir,mir_built"
+        except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub unsafe fn make_method_unsafe(&self) { }
@@ -263,7 +263,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,mir_built,FnSignature,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,mir_built,fn_sig,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub extern fn make_method_extern(&self) { }
 }
@@ -280,7 +280,7 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,FnSignature,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub extern "system" fn change_method_calling_convention(&self) { }
 }
@@ -297,15 +297,15 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    // Warning: Note that `TypeckTables` are coming up clean here.
+    // Warning: Note that `typeck_tables_of` are coming up clean here.
     // The addition or removal of lifetime parameters that don't
     // appear in the arguments or fn body in any way does not, in
-    // fact, affect the `TypeckTables` in any semantic way (at least
+    // fact, affect the `typeck_tables_of` in any semantic way (at least
     // as of this writing). **However,** altering the order of
-    // lowering **can** cause it appear to affect the `TypeckTables`:
+    // lowering **can** cause it appear to affect the `typeck_tables_of`:
     // if we lower generics before the body, then the `HirId` for
     // things in the body will be affected. So if you start to see
-    // `TypeckTables` appear dirty, that might be the cause. -nmatsakis
+    // `typeck_tables_of` appear dirty, that might be the cause. -nmatsakis
     #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_parameter_to_method<'a>(&self) { }
@@ -323,14 +323,14 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    // Warning: Note that `TypeckTables` are coming up clean here.
+    // Warning: Note that `typeck_tables_of` are coming up clean here.
     // The addition or removal of type parameters that don't appear in
     // the arguments or fn body in any way does not, in fact, affect
-    // the `TypeckTables` in any semantic way (at least as of this
+    // the `typeck_tables_of` in any semantic way (at least as of this
     // writing). **However,** altering the order of lowering **can**
-    // cause it appear to affect the `TypeckTables`: if we lower
+    // cause it appear to affect the `typeck_tables_of`: if we lower
     // generics before the body, then the `HirId` for things in the
-    // body will be affected. So if you start to see `TypeckTables`
+    // 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",
@@ -354,7 +354,7 @@ impl Foo {
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,generics_of,predicates_of,type_of,TypeckTables"
+        except="Hir,HirBody,generics_of,predicates_of,type_of,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
@@ -372,14 +372,14 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    // Warning: Note that `TypeckTables` are coming up clean here.
+    // Warning: Note that `typeck_tables_of` are coming up clean here.
     // The addition or removal of bounds that don't appear in the
     // arguments or fn body in any way does not, in fact, affect the
-    // `TypeckTables` in any semantic way (at least as of this
+    // `typeck_tables_of` in any semantic way (at least as of this
     // writing). **However,** altering the order of lowering **can**
-    // cause it appear to affect the `TypeckTables`: if we lower
+    // cause it appear to affect the `typeck_tables_of`: if we lower
     // generics before the body, then the `HirId` for things in the
-    // body will be affected. So if you start to see `TypeckTables`
+    // 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,\
                                         type_of")]
@@ -399,14 +399,14 @@ impl Foo {
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    // Warning: Note that `TypeckTables` are coming up clean here.
+    // Warning: Note that `typeck_tables_of` are coming up clean here.
     // The addition or removal of bounds that don't appear in the
     // arguments or fn body in any way does not, in fact, affect the
-    // `TypeckTables` in any semantic way (at least as of this
+    // `typeck_tables_of` in any semantic way (at least as of this
     // writing). **However,** altering the order of lowering **can**
-    // cause it appear to affect the `TypeckTables`: if we lower
+    // cause it appear to affect the `typeck_tables_of`: if we lower
     // generics before the body, then the `HirId` for things in the
-    // body will be affected. So if you start to see `TypeckTables`
+    // 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="cfail3")]
@@ -447,7 +447,7 @@ impl Bar<u32> {
 impl<T> Bar<T> {
     #[rustc_clean(
         cfg="cfail2",
-        except="generics_of,FnSignature,TypeckTables,type_of,optimized_mir,mir_built"
+        except="generics_of,fn_sig,typeck_tables_of,type_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_type_parameter_to_impl(&self) { }
@@ -465,7 +465,7 @@ impl Bar<u32> {
 #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
 #[rustc_clean(cfg="cfail3")]
 impl Bar<u64> {
-    #[rustc_clean(cfg="cfail2", except="FnSignature,optimized_mir,mir_built,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,mir_built,typeck_tables_of")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_impl_self_type(&self) { }
 }
diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs
index 76be2ccbf60..e016b92a9eb 100644
--- a/src/test/incremental/hashes/let_expressions.rs
+++ b/src/test/incremental/hashes/let_expressions.rs
@@ -38,7 +38,7 @@ pub fn add_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,mir_built,optimized_mir")]
+    except="HirBody,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,TypeckTables,mir_built,optimized_mir")]
+    except="HirBody,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,TypeckTables,mir_built,optimized_mir")]
+    except="HirBody,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,TypeckTables,mir_built,optimized_mir")]
+    except="HirBody,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,TypeckTables,mir_built,optimized_mir")]
+    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_simple_binding_to_pattern() {
     let (_a, _b) = (0u8, 'x');
@@ -134,7 +134,7 @@ pub fn add_ref_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,mir_built,optimized_mir")]
+    except="HirBody,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,TypeckTables,mir_built,optimized_mir")]
+    except="HirBody,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,TypeckTables,mir_built,optimized_mir")]
+    except="HirBody,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,TypeckTables,mir_built,optimized_mir")]
+    except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_initializer() {
     let _x: i16 = 3i16;
diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs
index 63cf1e9d5e8..c04bdd43a95 100644
--- a/src/test/incremental/hashes/loop_expressions.rs
+++ b/src/test/incremental/hashes/loop_expressions.rs
@@ -47,7 +47,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_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, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -168,7 +168,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, 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, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, 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 37f6aa9ee9b..02f2cd6634d 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,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_arm(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,TypeckTables")]
+    except="HirBody,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,TypeckTables")]
+    except="HirBody,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,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_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,TypeckTables")]
+    except="HirBody,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) {
@@ -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,TypeckTables")]
+    except="HirBody,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,TypeckTables")]
+    except="HirBody,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,TypeckTables")]
+except="HirBody,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) {
@@ -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,TypeckTables")]
+    except="HirBody,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/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
index 3190f65a817..e478ff96c32 100644
--- a/src/test/incremental/hashes/struct_constructors.rs
+++ b/src/test/incremental/hashes/struct_constructors.rs
@@ -54,7 +54,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,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,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,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,optimized_mir,mir_built,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,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="FnSignature,Hir,HirBody,optimized_mir,mir_built,TypeckTables"
+        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
@@ -213,7 +213,7 @@ pub fn change_constructor_path_tuple_struct() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,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="FnSignature,Hir,HirBody,optimized_mir,mir_built,TypeckTables"
+        except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs
index f3331ec61cb..8c53ae6a038 100644
--- a/src/test/incremental/hashes/unary_and_binary_exprs.rs
+++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs
@@ -81,7 +81,7 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built,TypeckTables", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_deref(x: &i32, y: &i32) -> i32 {
     *y
@@ -368,7 +368,7 @@ pub fn type_cast(a: u8) -> u64 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,optimized_mir,mir_built,TypeckTables", cfg="cfail2")]
+#[rustc_clean(except="HirBody,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;
diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs
index 7e866ae925e..2d48707561c 100644
--- a/src/test/incremental/hashes/while_let_loops.rs
+++ b/src/test/incremental/hashes/while_let_loops.rs
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_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, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -191,7 +191,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs
index cbd1341fdd4..79a3bc9b205 100644
--- a/src/test/incremental/hashes/while_loops.rs
+++ b/src/test/incremental/hashes/while_loops.rs
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
diff --git a/src/test/incremental/hello_world.rs b/src/test/incremental/hello_world.rs
index e2e15eb958f..e4d8c56752c 100644
--- a/src/test/incremental/hello_world.rs
+++ b/src/test/incremental/hello_world.rs
@@ -21,7 +21,7 @@ mod x {
 mod y {
     use x;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
     pub fn yyyy() {
         x::xxxx();
     }
@@ -30,7 +30,7 @@ mod y {
 mod z {
     use y;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
     pub fn z() {
         y::yyyy();
     }
diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs
index d4b170bd277..9dfd2ae2511 100644
--- a/src/test/incremental/ich_method_call_trait_scope.rs
+++ b/src/test/incremental/ich_method_call_trait_scope.rs
@@ -28,14 +28,14 @@ mod mod3 {
 
     #[rustc_clean(label="Hir", cfg="rpass2")]
     #[rustc_clean(label="HirBody", cfg="rpass2")]
-    #[rustc_dirty(label="TypeckTables", 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="TypeckTables", 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/rlib_cross_crate/b.rs b/src/test/incremental/rlib_cross_crate/b.rs
index 7c3dcf3a815..81b84ba741d 100644
--- a/src/test/incremental/rlib_cross_crate/b.rs
+++ b/src/test/incremental/rlib_cross_crate/b.rs
@@ -12,15 +12,15 @@
 
 extern crate a;
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
-#[rustc_clean(label="TypeckTables", cfg="rpass3")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass3")]
 pub fn use_X() -> u32 {
     let x: a::X = 22;
     x as u32
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
-#[rustc_clean(label="TypeckTables", cfg="rpass3")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass3")]
 pub fn use_Y() {
     let x: a::Y = 'c';
 }
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
index db2660bb661..c39d4145b58 100644
--- a/src/test/incremental/string_constant.rs
+++ b/src/test/incremental/string_constant.rs
@@ -28,7 +28,7 @@ pub mod x {
 pub mod y {
     use x;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     #[rustc_clean(label="optimized_mir", cfg="cfail2")]
     pub fn y() {
         x::x();
@@ -38,7 +38,7 @@ pub mod y {
 pub mod z {
     use y;
 
-    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
     #[rustc_clean(label="optimized_mir", cfg="cfail2")]
     pub fn z() {
         y::y();
diff --git a/src/test/incremental/struct_add_field.rs b/src/test/incremental/struct_add_field.rs
index d019a3d2ab8..d2e1e7decf5 100644
--- a/src/test/incremental/struct_add_field.rs
+++ b/src/test/incremental/struct_add_field.rs
@@ -21,17 +21,17 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_X(x: X) -> u32 {
     x.x as u32
 }
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_EmbedX(embed: EmbedX) -> u32 {
     embed.x.x as u32
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_change_field_name.rs b/src/test/incremental/struct_change_field_name.rs
index 28011efed9c..68356f703bc 100644
--- a/src/test/incremental/struct_change_field_name.rs
+++ b/src/test/incremental/struct_change_field_name.rs
@@ -24,7 +24,7 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
 pub fn use_X() -> u32 {
     let x: X = X { x: 22 };
     //[cfail2]~^ ERROR struct `X` has no field named `x`
@@ -32,13 +32,13 @@ pub fn use_X() -> u32 {
     //[cfail2]~^ ERROR no field `x` on type `X`
 }
 
-#[rustc_dirty(label="TypeckTables", cfg="cfail2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="cfail2")]
 pub fn use_EmbedX(embed: EmbedX) -> u32 {
     embed.x.x as u32
     //[cfail2]~^ ERROR no field `x` on type `X`
 }
 
-#[rustc_clean(label="TypeckTables", cfg="cfail2")]
+#[rustc_clean(label="typeck_tables_of", cfg="cfail2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_change_field_type.rs b/src/test/incremental/struct_change_field_type.rs
index cb4a83c2f9a..308ec84fa72 100644
--- a/src/test/incremental/struct_change_field_type.rs
+++ b/src/test/incremental/struct_change_field_type.rs
@@ -24,19 +24,19 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_X() -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_EmbedX(x: EmbedX) -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_change_field_type_cross_crate/b.rs b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
index ecfd24cbaf4..9d84c2cf773 100644
--- a/src/test/incremental/struct_change_field_type_cross_crate/b.rs
+++ b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
@@ -8,18 +8,18 @@ extern crate a;
 
 use a::*;
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_X() -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_EmbedX(embed: EmbedX) -> u32 {
     embed.x.x as u32
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_change_nothing.rs b/src/test/incremental/struct_change_nothing.rs
index e62c004a83d..bbded1da216 100644
--- a/src/test/incremental/struct_change_nothing.rs
+++ b/src/test/incremental/struct_change_nothing.rs
@@ -24,19 +24,19 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_X() -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_EmbedX(x: EmbedX) -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_remove_field.rs b/src/test/incremental/struct_remove_field.rs
index 572a2c640e6..4c4028bbe5b 100644
--- a/src/test/incremental/struct_remove_field.rs
+++ b/src/test/incremental/struct_remove_field.rs
@@ -25,17 +25,17 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_X(x: X) -> u32 {
     x.x as u32
 }
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_EmbedX(embed: EmbedX) -> u32 {
     embed.x.x as u32
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/type_alias_cross_crate/b.rs b/src/test/incremental/type_alias_cross_crate/b.rs
index 9261a0fb290..cef2e4bab12 100644
--- a/src/test/incremental/type_alias_cross_crate/b.rs
+++ b/src/test/incremental/type_alias_cross_crate/b.rs
@@ -6,15 +6,15 @@
 
 extern crate a;
 
-#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
-#[rustc_clean(label="TypeckTables", cfg="rpass3")]
+#[rustc_dirty(label="typeck_tables_of", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass3")]
 pub fn use_X() -> u32 {
     let x: a::X = 22;
     x as u32
 }
 
-#[rustc_clean(label="TypeckTables", cfg="rpass2")]
-#[rustc_clean(label="TypeckTables", cfg="rpass3")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass2")]
+#[rustc_clean(label="typeck_tables_of", cfg="rpass3")]
 pub fn use_Y() {
     let x: a::Y = 'c';
 }
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs
index 0cbf048697a..7ac36a22274 100644
--- a/src/test/mir-opt/match_false_edges.rs
+++ b/src/test/mir-opt/match_false_edges.rs
@@ -70,8 +70,8 @@ fn main() {
 //  }
 //  bb8: { // binding1 and guard
 //      StorageLive(_6);
-//      _6 = &(((promoted[1]: std::option::Option<i32>) as Some).0: i32);
-//      _4 = &shallow (promoted[0]: std::option::Option<i32>);
+//      _6 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32);
+//      _4 = &shallow _2;
 //      StorageLive(_7);
 //      _7 = const guard() -> [return: bb9, unwind: bb1];
 //  }
diff --git a/src/test/run-make-fulldeps/lto-dylib-dep/Makefile b/src/test/run-make-fulldeps/lto-dylib-dep/Makefile
new file mode 100644
index 00000000000..ab8ee6c2ef7
--- /dev/null
+++ b/src/test/run-make-fulldeps/lto-dylib-dep/Makefile
@@ -0,0 +1,10 @@
+-include ../tools.mk
+
+# Test that we don't run into an assertion when using a Rust dylib dependency
+# while compiling with full LTO.
+# See https://github.com/rust-lang/rust/issues/59137
+
+all:
+	$(RUSTC) a_dylib.rs --crate-type=dylib -C prefer-dynamic
+	$(RUSTC) main.rs -C lto
+	$(call RUN,main)
diff --git a/src/test/run-make-fulldeps/lto-dylib-dep/a_dylib.rs b/src/test/run-make-fulldeps/lto-dylib-dep/a_dylib.rs
new file mode 100644
index 00000000000..c5a35296f89
--- /dev/null
+++ b/src/test/run-make-fulldeps/lto-dylib-dep/a_dylib.rs
@@ -0,0 +1,4 @@
+
+pub fn foo() {
+    println!("bar");
+}
diff --git a/src/test/run-make-fulldeps/lto-dylib-dep/main.rs b/src/test/run-make-fulldeps/lto-dylib-dep/main.rs
new file mode 100644
index 00000000000..af0955e7f35
--- /dev/null
+++ b/src/test/run-make-fulldeps/lto-dylib-dep/main.rs
@@ -0,0 +1,6 @@
+
+extern crate a_dylib;
+
+fn main() {
+    a_dylib::foo();
+}
diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile
index e358314c0d0..7c19961b1e4 100644
--- a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile
+++ b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile
@@ -1,10 +1,8 @@
 -include ../tools.mk
 
-# ignore-windows
-
 all:
 ifeq ($(PROFILER_SUPPORT),1)
-	$(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
+	$(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)" test.rs
 	$(call RUN,test) || exit 1
-	[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
+	[ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1)
 endif
diff --git a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile
new file mode 100644
index 00000000000..dc52e91317a
--- /dev/null
+++ b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile
@@ -0,0 +1,11 @@
+-include ../tools.mk
+
+all:
+ifeq ($(PROFILER_SUPPORT),1)
+	$(RUSTC) -O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)/test.profraw" --emit=llvm-ir test.rs
+	# We expect symbols starting with "__llvm_profile_".
+	$(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll
+	# We do NOT expect the "__imp_" version of these symbols.
+	$(CGREP) -v "__imp___llvm_profile_" < $(TMPDIR)/test.ll # 64 bit
+	$(CGREP) -v "__imp____llvm_profile_" < $(TMPDIR)/test.ll # 32 bit
+endif
diff --git a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/test.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/src/test/run-make-fulldeps/pgo-gen/Makefile b/src/test/run-make-fulldeps/pgo-gen/Makefile
index 1961dff8d78..0469c4443d8 100644
--- a/src/test/run-make-fulldeps/pgo-gen/Makefile
+++ b/src/test/run-make-fulldeps/pgo-gen/Makefile
@@ -1,10 +1,8 @@
 -include ../tools.mk
 
-# ignore-windows
-
 all:
 ifeq ($(PROFILER_SUPPORT),1)
-	$(RUSTC) -g -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
+	$(RUSTC) -g -Z pgo-gen="$(TMPDIR)" test.rs
 	$(call RUN,test) || exit 1
-	[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
+	[ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1)
 endif
diff --git a/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py
index e0fa4e8f5de..855b6421cf8 100644
--- a/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py
+++ b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py
@@ -7,8 +7,8 @@ from subprocess import PIPE, Popen
 
 # This is a whitelist of files which are stable crates or simply are not crates,
 # we don't check for the instability of these crates as they're all stable!
-STABLE_CRATES = ['std', 'core', 'proc_macro', 'rsbegin.o', 'rsend.o', 'dllcrt2.o', 'crt2.o',
-                 'clang_rt']
+STABLE_CRATES = ['std', 'alloc', 'core', 'proc_macro',
+                 'rsbegin.o', 'rsend.o', 'dllcrt2.o', 'crt2.o', 'clang_rt']
 
 
 def convert_to_string(s):
diff --git a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs
index 09aa106ebbd..76d0906f97c 100644
--- a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -26,21 +26,14 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_attribute("whitelisted_attr".to_string(), Whitelisted);
 }
 
-declare_lint!(MISSING_WHITELISTED_ATTR, Deny,
-              "Checks for missing `whitelisted_attr` attribute");
-
-struct MissingWhitelistedAttrPass;
-
-impl LintPass for MissingWhitelistedAttrPass {
-    fn name(&self) -> &'static str {
-        "MissingWhitelistedAttrPass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_WHITELISTED_ATTR)
-    }
+declare_lint! {
+    MISSING_WHITELISTED_ATTR,
+    Deny,
+    "Checks for missing `whitelisted_attr` attribute"
 }
 
+declare_lint_pass!(MissingWhitelistedAttrPass => [MISSING_WHITELISTED_ATTR]);
+
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass {
     fn check_fn(&mut self,
                 cx: &LateContext<'a, 'tcx>,
diff --git a/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs b/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs
index 7f7f1e43315..443895f7c48 100644
--- a/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs
+++ b/src/test/run-pass/array-slice-vec/vec-macro-no-std.rs
@@ -2,7 +2,7 @@
 
 // ignore-emscripten no no_std executables
 
-#![feature(lang_items, start, rustc_private, alloc)]
+#![feature(lang_items, start, rustc_private)]
 #![no_std]
 
 extern crate std as other;
diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs
index 1843feed927..518452aefc1 100644
--- a/src/test/run-pass/async-await.rs
+++ b/src/test/run-pass/async-await.rs
@@ -1,7 +1,7 @@
 // edition:2018
 // aux-build:arc_wake.rs
 
-#![feature(arbitrary_self_types, async_await, await_macro, futures_api)]
+#![feature(async_await, await_macro, futures_api)]
 
 extern crate arc_wake;
 
@@ -11,9 +11,7 @@ use std::sync::{
     Arc,
     atomic::{self, AtomicUsize},
 };
-use std::task::{
-    Poll, Waker,
-};
+use std::task::{Context, Poll};
 use arc_wake::ArcWake;
 
 struct Counter {
@@ -21,7 +19,10 @@ struct Counter {
 }
 
 impl ArcWake for Counter {
-    fn wake(arc_self: &Arc<Self>) {
+    fn wake(self: Arc<Self>) {
+        Self::wake_by_ref(&self)
+    }
+    fn wake_by_ref(arc_self: &Arc<Self>) {
         arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
     }
 }
@@ -32,11 +33,11 @@ fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) }
 
 impl Future for WakeOnceThenComplete {
     type Output = ();
-    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<()> {
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
         if self.0 {
             Poll::Ready(())
         } else {
-            waker.wake();
+            cx.waker().wake_by_ref();
             self.0 = true;
             Poll::Pending
         }
@@ -79,6 +80,11 @@ async fn async_fn(x: u8) -> u8 {
     x
 }
 
+async fn generic_async_fn<T>(x: T) -> T {
+    await!(wake_and_yield_once());
+    x
+}
+
 async fn async_fn_with_borrow(x: &u8) -> u8 {
     await!(wake_and_yield_once());
     *x
@@ -96,14 +102,21 @@ fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future<Output
     }
 }
 
-async fn async_fn_with_named_lifetime_multiple_args<'a>(x: &'a u8, _y: &'a u8) -> u8 {
+/* FIXME(cramertj) support when `existential type T<'a, 'b>:;` works
+async fn async_fn_multiple_args(x: &u8, _y: &u8) -> u8 {
+    await!(wake_and_yield_once());
+    *x
+}
+*/
+
+async fn async_fn_multiple_args_named_lifetime<'a>(x: &'a u8, _y: &'a u8) -> u8 {
     await!(wake_and_yield_once());
     *x
 }
 
 fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
     async move {
-        await!(async_fn_with_borrow(&y))
+        await!(async_fn_with_borrow_named_lifetime(&y))
     }
 }
 
@@ -134,10 +147,11 @@ where
     let mut fut = Box::pin(f(9));
     let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
     let waker = ArcWake::into_waker(counter.clone());
+    let mut cx = Context::from_waker(&waker);
     assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
-    assert_eq!(Poll::Pending, fut.as_mut().poll(&waker));
+    assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx));
     assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst));
-    assert_eq!(Poll::Ready(9), fut.as_mut().poll(&waker));
+    assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx));
 }
 
 fn main() {
@@ -162,6 +176,7 @@ fn main() {
         async_nonmove_block,
         async_closure,
         async_fn,
+        generic_async_fn,
         async_fn_with_internal_borrow,
         Foo::async_method,
         |x| {
@@ -170,7 +185,6 @@ fn main() {
             }
         },
     }
-
     test_with_borrow! {
         async_block_with_borrow_named_lifetime,
         async_fn_with_borrow,
@@ -178,7 +192,7 @@ fn main() {
         async_fn_with_impl_future_named_lifetime,
         |x| {
             async move {
-                await!(async_fn_with_named_lifetime_multiple_args(x, x))
+                await!(async_fn_multiple_args_named_lifetime(x, x))
             }
         },
     }
diff --git a/src/test/run-pass/auxiliary/arc_wake.rs b/src/test/run-pass/auxiliary/arc_wake.rs
index 034e378af7f..93e074e7ee5 100644
--- a/src/test/run-pass/auxiliary/arc_wake.rs
+++ b/src/test/run-pass/auxiliary/arc_wake.rs
@@ -1,36 +1,41 @@
 // edition:2018
 
-#![feature(arbitrary_self_types, futures_api)]
+#![feature(futures_api)]
 
 use std::sync::Arc;
 use std::task::{
-    Poll, Waker, RawWaker, RawWakerVTable,
+    Waker, RawWaker, RawWakerVTable,
 };
 
 macro_rules! waker_vtable {
     ($ty:ident) => {
-        &RawWakerVTable {
-            clone: clone_arc_raw::<$ty>,
-            drop: drop_arc_raw::<$ty>,
-            wake: wake_arc_raw::<$ty>,
-        }
+        &RawWakerVTable::new(
+            clone_arc_raw::<$ty>,
+            wake_arc_raw::<$ty>,
+            wake_by_ref_arc_raw::<$ty>,
+            drop_arc_raw::<$ty>,
+        )
     };
 }
 
 pub trait ArcWake {
-    fn wake(arc_self: &Arc<Self>);
+    fn wake(self: Arc<Self>);
+
+    fn wake_by_ref(arc_self: &Arc<Self>) {
+        arc_self.clone().wake()
+    }
 
     fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
     {
-        let ptr = Arc::into_raw(wake) as *const();
+        let ptr = Arc::into_raw(wake) as *const ();
 
         unsafe {
-            Waker::new_unchecked(RawWaker::new(ptr, waker_vtable!(Self)))
+            Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
         }
     }
 }
 
-unsafe fn increase_refcount<T: ArcWake>(data: *const()) {
+unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
     // Retain Arc by creating a copy
     let arc: Arc<T> = Arc::from_raw(data as *const T);
     let arc_clone = arc.clone();
@@ -39,18 +44,23 @@ unsafe fn increase_refcount<T: ArcWake>(data: *const()) {
     let _ = Arc::into_raw(arc_clone);
 }
 
-unsafe fn clone_arc_raw<T: ArcWake>(data: *const()) -> RawWaker {
+unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
     increase_refcount::<T>(data);
     RawWaker::new(data, waker_vtable!(T))
 }
 
-unsafe fn drop_arc_raw<T: ArcWake>(data: *const()) {
+unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
     // Drop Arc
     let _: Arc<T> = Arc::from_raw(data as *const T);
 }
 
-unsafe fn wake_arc_raw<T: ArcWake>(data: *const()) {
+unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
+    let arc: Arc<T> = Arc::from_raw(data as *const T);
+    ArcWake::wake(arc);
+}
+
+unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
     let arc: Arc<T> = Arc::from_raw(data as *const T);
-    ArcWake::wake(&arc);
+    ArcWake::wake_by_ref(&arc);
     let _ = Arc::into_raw(arc);
 }
diff --git a/src/test/run-pass/extern/extern-prelude-core.rs b/src/test/run-pass/extern/extern-prelude-core.rs
index a5d31009f9c..f0d43404b00 100644
--- a/src/test/run-pass/extern/extern-prelude-core.rs
+++ b/src/test/run-pass/extern/extern-prelude-core.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![feature(extern_prelude, lang_items, start, alloc)]
+#![feature(extern_prelude, lang_items, start)]
 #![no_std]
 
 extern crate std as other;
diff --git a/src/test/run-pass/extern/extern-prelude-core.stderr b/src/test/run-pass/extern/extern-prelude-core.stderr
index 417483af707..8d2a0b7425f 100644
--- a/src/test/run-pass/extern/extern-prelude-core.stderr
+++ b/src/test/run-pass/extern/extern-prelude-core.stderr
@@ -1,7 +1,7 @@
 warning: the feature `extern_prelude` has been stable since 1.30.0 and no longer requires an attribute to enable
   --> $DIR/extern-prelude-core.rs:2:12
    |
-LL | #![feature(extern_prelude, lang_items, start, alloc)]
+LL | #![feature(extern_prelude, lang_items, start)]
    |            ^^^^^^^^^^^^^^
    |
    = note: #[warn(stable_features)] on by default
diff --git a/src/test/run-pass/for-loop-while/for-loop-no-std.rs b/src/test/run-pass/for-loop-while/for-loop-no-std.rs
index 877429f5d39..65a33c5f16f 100644
--- a/src/test/run-pass/for-loop-while/for-loop-no-std.rs
+++ b/src/test/run-pass/for-loop-while/for-loop-no-std.rs
@@ -1,6 +1,6 @@
 // run-pass
 #![allow(unused_imports)]
-#![feature(lang_items, start, alloc)]
+#![feature(lang_items, start)]
 #![no_std]
 
 extern crate std as other;
diff --git a/src/test/run-pass/format-no-std.rs b/src/test/run-pass/format-no-std.rs
index 0f3a5c277b4..32f7a4a07c4 100644
--- a/src/test/run-pass/format-no-std.rs
+++ b/src/test/run-pass/format-no-std.rs
@@ -1,6 +1,6 @@
 // ignore-emscripten no no_std executables
 
-#![feature(lang_items, start, alloc)]
+#![feature(lang_items, start)]
 #![no_std]
 
 extern crate std as other;
diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs
index fd4b585d345..6094f15569b 100644
--- a/src/test/run-pass/futures-api.rs
+++ b/src/test/run-pass/futures-api.rs
@@ -1,7 +1,6 @@
 // aux-build:arc_wake.rs
 
-#![feature(arbitrary_self_types, futures_api)]
-#![allow(unused)]
+#![feature(futures_api)]
 
 extern crate arc_wake;
 
@@ -12,7 +11,7 @@ use std::sync::{
     atomic::{self, AtomicUsize},
 };
 use std::task::{
-    Poll, Waker,
+    Context, Poll,
 };
 use arc_wake::ArcWake;
 
@@ -21,7 +20,10 @@ struct Counter {
 }
 
 impl ArcWake for Counter {
-    fn wake(arc_self: &Arc<Self>) {
+    fn wake(self: Arc<Self>) {
+        Self::wake_by_ref(&self)
+    }
+    fn wake_by_ref(arc_self: &Arc<Self>) {
         arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
     }
 }
@@ -30,10 +32,11 @@ struct MyFuture;
 
 impl Future for MyFuture {
     type Output = ();
-    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
         // Wake twice
-        waker.wake();
-        waker.wake();
+        let waker = cx.waker();
+        waker.wake_by_ref();
+        waker.wake_by_ref();
         Poll::Ready(())
     }
 }
@@ -44,10 +47,11 @@ fn test_waker() {
     });
     let waker = ArcWake::into_waker(counter.clone());
     assert_eq!(2, Arc::strong_count(&counter));
-
-    assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(&waker));
-    assert_eq!(2, counter.wakes.load(atomic::Ordering::SeqCst));
-
+    {
+        let mut context = Context::from_waker(&waker);
+        assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(&mut context));
+        assert_eq!(2, counter.wakes.load(atomic::Ordering::SeqCst));
+    }
     drop(waker);
     assert_eq!(1, Arc::strong_count(&counter));
 }
diff --git a/src/test/run-pass/issue-59020.rs b/src/test/run-pass/issue-59020.rs
new file mode 100644
index 00000000000..a2b11764a2f
--- /dev/null
+++ b/src/test/run-pass/issue-59020.rs
@@ -0,0 +1,27 @@
+// edition:2018
+// run-pass
+// ignore-emscripten no threads support
+
+use std::thread;
+use std::time::Duration;
+
+fn main() {
+    let t1 = thread::spawn(|| {
+        let sleep = Duration::new(0,100_000);
+        for _ in 0..100 {
+            println!("Parking1");
+            thread::park_timeout(sleep);
+        }
+    });
+
+    let t2 = thread::spawn(|| {
+        let sleep = Duration::new(0,100_000);
+        for _ in 0..100 {
+            println!("Parking2");
+            thread::park_timeout(sleep);
+        }
+    });
+
+    t1.join().expect("Couldn't join thread 1");
+    t2.join().expect("Couldn't join thread 2");
+}
diff --git a/src/test/run-pass/issues/issue-58463.rs b/src/test/run-pass/issues/issue-58463.rs
new file mode 100644
index 00000000000..8ab845366b7
--- /dev/null
+++ b/src/test/run-pass/issues/issue-58463.rs
@@ -0,0 +1,8 @@
+// run-pass
+// compile-flags:-C debuginfo=2
+fn foo() -> impl Copy {
+    foo
+}
+fn main() {
+    foo();
+}
diff --git a/src/test/run-pass/structs-enums/unit-like-struct-drop-run.rs b/src/test/run-pass/structs-enums/unit-like-struct-drop-run.rs
index dfe73875215..980fd97e2c6 100644
--- a/src/test/run-pass/structs-enums/unit-like-struct-drop-run.rs
+++ b/src/test/run-pass/structs-enums/unit-like-struct-drop-run.rs
@@ -3,9 +3,6 @@
 
 // Make sure the destructor is run for unit-like structs.
 
-
-#![feature(alloc)]
-
 use std::thread;
 
 struct Foo;
diff --git a/src/test/run-pass/traits/auxiliary/trait_alias.rs b/src/test/run-pass/traits/auxiliary/trait_alias.rs
new file mode 100644
index 00000000000..9e412215512
--- /dev/null
+++ b/src/test/run-pass/traits/auxiliary/trait_alias.rs
@@ -0,0 +1,13 @@
+#![feature(trait_alias)]
+
+pub trait Hello {
+    fn hello(&self);
+}
+
+pub struct Hi;
+
+impl Hello for Hi {
+    fn hello(&self) {}
+}
+
+pub trait Greet = Hello;
diff --git a/src/test/run-pass/traits/trait-alias-import-cross-crate.rs b/src/test/run-pass/traits/trait-alias-import-cross-crate.rs
new file mode 100644
index 00000000000..975542ab49b
--- /dev/null
+++ b/src/test/run-pass/traits/trait-alias-import-cross-crate.rs
@@ -0,0 +1,14 @@
+// run-pass
+// aux-build:trait_alias.rs
+
+#![feature(trait_alias)]
+
+extern crate trait_alias;
+
+// Import only the alias, not the real trait.
+use trait_alias::{Greet, Hi};
+
+fn main() {
+    let hi = Hi;
+    hi.hello(); // From `Hello`, via `Greet` alias.
+}
diff --git a/src/test/run-pass/traits/trait-alias-import.rs b/src/test/run-pass/traits/trait-alias-import.rs
new file mode 100644
index 00000000000..7d63320b9aa
--- /dev/null
+++ b/src/test/run-pass/traits/trait-alias-import.rs
@@ -0,0 +1,38 @@
+#![feature(trait_alias)]
+
+mod inner {
+    pub trait Foo {
+        fn foo(&self);
+    }
+
+    pub struct Qux;
+
+    impl Foo for Qux {
+        fn foo(&self) {}
+    }
+
+    pub trait Bar = Foo;
+}
+
+mod two {
+    pub trait A {
+        fn foo();
+    }
+
+    impl A for u8 {
+        fn foo() {}
+    }
+}
+
+// Import only the alias, not the `Foo` trait.
+use inner::{Bar, Qux};
+
+// Declaring an alias also brings in aliased methods.
+trait Two = two::A;
+
+fn main() {
+    let q = Qux;
+    q.foo(); // From Bar.
+
+    u8::foo(); // From A.
+}
diff --git a/src/test/run-pass/unsized-locals/box-fnonce.rs b/src/test/run-pass/unsized-locals/box-fnonce.rs
new file mode 100644
index 00000000000..16bdeae4fad
--- /dev/null
+++ b/src/test/run-pass/unsized-locals/box-fnonce.rs
@@ -0,0 +1,8 @@
+fn call_it<T>(f: Box<dyn FnOnce() -> T>) -> T {
+    f()
+}
+
+fn main() {
+    let s = "hello".to_owned();
+    assert_eq!(&call_it(Box::new(|| s)) as &str, "hello");
+}
diff --git a/src/test/run-pass/unsized-locals/fnbox-compat.rs b/src/test/run-pass/unsized-locals/fnbox-compat.rs
new file mode 100644
index 00000000000..5ec54ada13b
--- /dev/null
+++ b/src/test/run-pass/unsized-locals/fnbox-compat.rs
@@ -0,0 +1,12 @@
+#![feature(fnbox)]
+
+use std::boxed::FnBox;
+
+fn call_it<T>(f: Box<dyn FnBox() -> T>) -> T {
+    f()
+}
+
+fn main() {
+    let s = "hello".to_owned();
+    assert_eq!(&call_it(Box::new(|| s)) as &str, "hello");
+}
diff --git a/src/test/rustdoc-js/search-short-types.js b/src/test/rustdoc-js/search-short-types.js
new file mode 100644
index 00000000000..0ebf4860cfa
--- /dev/null
+++ b/src/test/rustdoc-js/search-short-types.js
@@ -0,0 +1,8 @@
+const QUERY = 'P';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'search_short_types', 'name': 'P' },
+        { 'path': 'search_short_types', 'name': 'Ap' },
+    ],
+};
diff --git a/src/test/rustdoc-js/search-short-types.rs b/src/test/rustdoc-js/search-short-types.rs
new file mode 100644
index 00000000000..2eacc0a3582
--- /dev/null
+++ b/src/test/rustdoc-js/search-short-types.rs
@@ -0,0 +1,68 @@
+macro_rules! imp {
+    ($name:ident) => {
+        pub struct $name {
+            pub op: usize,
+        }
+        impl $name {
+            pub fn op() {}
+            pub fn cmp() {}
+            pub fn map() {}
+            pub fn pop() {}
+            pub fn ptr() {}
+            pub fn rpo() {}
+            pub fn drop() {}
+            pub fn copy() {}
+            pub fn zip() {}
+            pub fn sup() {}
+            pub fn pa() {}
+            pub fn pb() {}
+            pub fn pc() {}
+            pub fn pd() {}
+            pub fn pe() {}
+            pub fn pf() {}
+            pub fn pg() {}
+            pub fn ph() {}
+            pub fn pi() {}
+            pub fn pj() {}
+            pub fn pk() {}
+            pub fn pl() {}
+            pub fn pm() {}
+            pub fn pn() {}
+            pub fn po() {}
+        }
+    };
+    ($name:ident, $($names:ident),*) => {
+        imp!($name);
+        imp!($($names),*);
+    };
+}
+macro_rules! en {
+    ($name:ident) => {
+        pub enum $name {
+            Ptr,
+            Rp,
+            Rpo,
+            Pt,
+            Drop,
+            Dr,
+            Dro,
+            Sup,
+            Op,
+            Cmp,
+            Map,
+            Mp,
+        }
+    };
+    ($name:ident, $($names:ident),*) => {
+        en!($name);
+        en!($($names),*);
+    };
+}
+
+imp!(Ot, Foo, Cmp, Map, Loc, Lac, Toc, Si, Sig, Sip, Psy, Psi, Py, Pi, Pa, Pb, Pc, Pd);
+imp!(Pe, Pf, Pg, Ph, Pj, Pk, Pl, Pm, Pn, Po, Pq, Pr, Ps, Pt, Pu, Pv, Pw, Px, Pz, Ap, Bp, Cp);
+imp!(Dp, Ep, Fp, Gp, Hp, Ip, Jp, Kp, Lp, Mp, Np, Op, Pp, Qp, Rp, Sp, Tp, Up, Vp, Wp, Xp, Yp, Zp);
+
+en!(Place, Plac, Plae, Plce, Pace, Scalar, Scalr, Scaar, Sclar, Salar);
+
+pub struct P;
diff --git a/src/test/rustdoc-js/substring.js b/src/test/rustdoc-js/substring.js
new file mode 100644
index 00000000000..af05cd1ad34
--- /dev/null
+++ b/src/test/rustdoc-js/substring.js
@@ -0,0 +1,8 @@
+const QUERY = 'waker_from';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'substring::SuperWaker', 'name': 'local_waker_from_nonlocal' },
+        { 'path': 'substring::SuperWakerTask', 'name': 'local_waker_from_nonlocal' },
+    ],
+};
diff --git a/src/test/rustdoc-js/substring.rs b/src/test/rustdoc-js/substring.rs
new file mode 100644
index 00000000000..e729c722c79
--- /dev/null
+++ b/src/test/rustdoc-js/substring.rs
@@ -0,0 +1,21 @@
+pub struct SuperWaker;
+
+impl SuperWaker {
+    pub fn local_waker_from_nonlocal() {}
+    pub fn local_waker_frm_nonlocal() {}
+    pub fn some_method() {}
+    pub fn some_other_method() {}
+    pub fn waker_non_local() {}
+    pub fn from_non_local() {}
+}
+
+pub struct SuperWakerTask;
+
+impl SuperWakerTask {
+    pub fn local_waker_from_nonlocal() {}
+    pub fn local_waker_frm_nonlocal() {}
+    pub fn some_method() {}
+    pub fn some_other_method() {}
+    pub fn waker_non_local() {}
+    pub fn from_non_local() {}
+}
diff --git a/src/test/rustdoc/auxiliary/intra-links-external-traits.rs b/src/test/rustdoc/auxiliary/intra-links-external-traits.rs
new file mode 100644
index 00000000000..6142dcda986
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/intra-links-external-traits.rs
@@ -0,0 +1,6 @@
+pub trait ThisTrait {
+    fn asdf(&self);
+
+    /// let's link to [`asdf`](ThisTrait::asdf)
+    fn qwop(&self);
+}
diff --git a/src/test/rustdoc/intra-links-external-traits.rs b/src/test/rustdoc/intra-links-external-traits.rs
new file mode 100644
index 00000000000..d6b4a8ad58a
--- /dev/null
+++ b/src/test/rustdoc/intra-links-external-traits.rs
@@ -0,0 +1,12 @@
+// aux-build:intra-links-external-traits.rs
+// ignore-cross-compile
+
+#![crate_name = "outer"]
+#![deny(intra_doc_link_resolution_failure)]
+
+// using a trait that has intra-doc links on it from another crate (whether re-exporting or just
+// implementing it) used to give spurious resolution failure warnings
+
+extern crate intra_links_external_traits;
+
+pub use intra_links_external_traits::ThisTrait;
diff --git a/src/test/rustdoc/useless_lifetime_bound.rs b/src/test/rustdoc/useless_lifetime_bound.rs
new file mode 100644
index 00000000000..f530d8a654f
--- /dev/null
+++ b/src/test/rustdoc/useless_lifetime_bound.rs
@@ -0,0 +1,13 @@
+use std::marker::PhantomData;
+
+// @has useless_lifetime_bound/struct.Scope.html
+// @!has - '//*[@class="rust struct"]' "'env: 'env"
+pub struct Scope<'env> {
+    _marker: PhantomData<&'env mut &'env ()>,
+}
+
+// @has useless_lifetime_bound/struct.Scope.html
+// @!has - '//*[@class="rust struct"]' "T: 'a + 'a"
+pub struct SomeStruct<'a, T: 'a> {
+    _marker: PhantomData<&'a T>,
+}
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index 82aa28b26b6..e8f1d2eedf5 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -12,20 +12,14 @@ use rustc_plugin::Registry;
 use rustc::hir;
 use syntax::attr;
 
-declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]");
-
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(CRATE_NOT_OKAY)
-    }
+declare_lint! {
+    CRATE_NOT_OKAY,
+    Warn,
+    "crate not marked with #![crate_okay]"
 }
 
+declare_lint_pass!(Pass => [CRATE_NOT_OKAY]);
+
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
         if !attr::contains_name(&krate.attrs, "crate_okay") {
diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
index 16630e2b312..941fe25b14c 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
@@ -16,17 +16,7 @@ declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
 declare_lint!(PLEASE_LINT, Warn, "Warn about items named 'pleaselintme'");
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT, PLEASE_LINT)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT, PLEASE_LINT]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
index 4e45189b424..1d204e7bfcf 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
@@ -16,17 +16,7 @@ use rustc_plugin::Registry;
 use syntax::ast;
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT]);
 
 impl EarlyLintPass for Pass {
     fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
index d25a5ea3746..182d2899da1 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
@@ -19,17 +19,7 @@ declare_tool_lint!(
     Warn, "Warn about other stuff"
 );
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT, TEST_GROUP)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT, TEST_GROUP]);
 
 impl EarlyLintPass for Pass {
     fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
diff --git a/src/test/ui-fulldeps/gated-plugin.stderr b/src/test/ui-fulldeps/gated-plugin.stderr
index 37c2b443247..4f8bcda9020 100644
--- a/src/test/ui-fulldeps/gated-plugin.stderr
+++ b/src/test/ui-fulldeps/gated-plugin.stderr
@@ -1,9 +1,10 @@
-error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
+error[E0658]: compiler plugins are experimental and possibly buggy
   --> $DIR/gated-plugin.rs:3:1
    |
 LL | #![plugin(attr_plugin_test)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29597
    = help: add #![feature(plugin)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr
index e7007204d38..b598c86c0e0 100644
--- a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr
+++ b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr
@@ -2,44 +2,49 @@ error[E0601]: `main` function not found in crate `hash_stable_is_unstable`
    |
    = note: consider adding a `main` function to `$DIR/hash-stable-is-unstable.rs`
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/hash-stable-is-unstable.rs:3:1
    |
 LL | extern crate rustc_data_structures;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27812
    = help: add #![feature(rustc_private)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/hash-stable-is-unstable.rs:5:1
    |
 LL | extern crate rustc;
    | ^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27812
    = help: add #![feature(rustc_private)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/hash-stable-is-unstable.rs:7:1
    |
 LL | extern crate rustc_macros;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27812
    = help: add #![feature(rustc_private)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/hash-stable-is-unstable.rs:10:5
    |
 LL | use rustc_macros::HashStable;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27812
    = help: add #![feature(rustc_private)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/hash-stable-is-unstable.rs:13:10
    |
 LL | #[derive(HashStable)]
    |          ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27812
    = help: add #![feature(rustc_private)] to the crate attributes to enable
 
 error: aborting due to 6 previous errors
diff --git a/src/test/ui-fulldeps/internal-lints/default_hash_types.rs b/src/test/ui-fulldeps/internal-lints/default_hash_types.rs
new file mode 100644
index 00000000000..3264099c876
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/default_hash_types.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Z unstable-options
+
+#![feature(rustc_private)]
+
+extern crate rustc_data_structures;
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use std::collections::{HashMap, HashSet};
+
+#[deny(default_hash_types)]
+fn main() {
+    let _map: HashMap<String, String> = HashMap::default();
+    //~^ ERROR Prefer FxHashMap over HashMap, it has better performance
+    //~^^ ERROR Prefer FxHashMap over HashMap, it has better performance
+    let _set: HashSet<String> = HashSet::default();
+    //~^ ERROR Prefer FxHashSet over HashSet, it has better performance
+    //~^^ ERROR Prefer FxHashSet over HashSet, it has better performance
+
+    // test that the lint doesn't also match the Fx variants themselves
+    let _fx_map: FxHashMap<String, String> = FxHashMap::default();
+    let _fx_set: FxHashSet<String> = FxHashSet::default();
+}
diff --git a/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr b/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr
new file mode 100644
index 00000000000..64f322cb0c1
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr
@@ -0,0 +1,39 @@
+error: Prefer FxHashMap over HashMap, it has better performance
+  --> $DIR/default_hash_types.rs:12:15
+   |
+LL |     let _map: HashMap<String, String> = HashMap::default();
+   |               ^^^^^^^ help: use: `FxHashMap`
+   |
+note: lint level defined here
+  --> $DIR/default_hash_types.rs:10:8
+   |
+LL | #[deny(default_hash_types)]
+   |        ^^^^^^^^^^^^^^^^^^
+   = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
+
+error: Prefer FxHashMap over HashMap, it has better performance
+  --> $DIR/default_hash_types.rs:12:41
+   |
+LL |     let _map: HashMap<String, String> = HashMap::default();
+   |                                         ^^^^^^^ help: use: `FxHashMap`
+   |
+   = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
+
+error: Prefer FxHashSet over HashSet, it has better performance
+  --> $DIR/default_hash_types.rs:15:15
+   |
+LL |     let _set: HashSet<String> = HashSet::default();
+   |               ^^^^^^^ help: use: `FxHashSet`
+   |
+   = note: a `use rustc_data_structures::fx::FxHashSet` may be necessary
+
+error: Prefer FxHashSet over HashSet, it has better performance
+  --> $DIR/default_hash_types.rs:15:33
+   |
+LL |     let _set: HashSet<String> = HashSet::default();
+   |                                 ^^^^^^^ help: use: `FxHashSet`
+   |
+   = note: a `use rustc_data_structures::fx::FxHashSet` may be necessary
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
new file mode 100644
index 00000000000..dba0db69b7f
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
@@ -0,0 +1,49 @@
+// compile-flags: -Z unstable-options
+
+#![feature(rustc_private)]
+
+extern crate rustc;
+
+use rustc::ty::{self, Ty, TyKind};
+
+#[deny(usage_of_ty_tykind)]
+fn main() {
+    let sty = TyKind::Bool; //~ ERROR usage of `ty::TyKind::<kind>`
+
+    match sty {
+        TyKind::Bool => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Char => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Int(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Uint(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Float(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Adt(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Foreign(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Str => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Array(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Slice(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::RawPtr(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Ref(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::FnDef(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::FnPtr(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Dynamic(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Closure(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Generator(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::GeneratorWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Never => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Tuple(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Projection(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::UnnormalizedProjection(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Opaque(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Param(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Bound(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Placeholder(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Infer(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Error => (), //~ ERROR usage of `ty::TyKind::<kind>`
+    }
+
+    if let ty::Int(int_ty) = sty {}
+
+    if let TyKind::Int(int_ty) = sty {} //~ ERROR usage of `ty::TyKind::<kind>`
+
+    fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} //~ ERROR usage of `ty::TyKind`
+}
diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
new file mode 100644
index 00000000000..4e94af12453
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
@@ -0,0 +1,196 @@
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:11:15
+   |
+LL |     let sty = TyKind::Bool;
+   |               ^^^^^^ help: try using ty::<kind> directly: `ty`
+   |
+note: lint level defined here
+  --> $DIR/ty_tykind_usage.rs:9:8
+   |
+LL | #[deny(usage_of_ty_tykind)]
+   |        ^^^^^^^^^^^^^^^^^^
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:14:9
+   |
+LL |         TyKind::Bool => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:15:9
+   |
+LL |         TyKind::Char => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:16:9
+   |
+LL |         TyKind::Int(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:17:9
+   |
+LL |         TyKind::Uint(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:18:9
+   |
+LL |         TyKind::Float(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:19:9
+   |
+LL |         TyKind::Adt(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:20:9
+   |
+LL |         TyKind::Foreign(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:21:9
+   |
+LL |         TyKind::Str => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:22:9
+   |
+LL |         TyKind::Array(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:23:9
+   |
+LL |         TyKind::Slice(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:24:9
+   |
+LL |         TyKind::RawPtr(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:25:9
+   |
+LL |         TyKind::Ref(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:26:9
+   |
+LL |         TyKind::FnDef(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:27:9
+   |
+LL |         TyKind::FnPtr(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:28:9
+   |
+LL |         TyKind::Dynamic(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:29:9
+   |
+LL |         TyKind::Closure(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:30:9
+   |
+LL |         TyKind::Generator(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:31:9
+   |
+LL |         TyKind::GeneratorWitness(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:32:9
+   |
+LL |         TyKind::Never => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:33:9
+   |
+LL |         TyKind::Tuple(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:34:9
+   |
+LL |         TyKind::Projection(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:35:9
+   |
+LL |         TyKind::UnnormalizedProjection(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:36:9
+   |
+LL |         TyKind::Opaque(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:37:9
+   |
+LL |         TyKind::Param(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:38:9
+   |
+LL |         TyKind::Bound(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:39:9
+   |
+LL |         TyKind::Placeholder(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:40:9
+   |
+LL |         TyKind::Infer(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:41:9
+   |
+LL |         TyKind::Error => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:46:12
+   |
+LL |     if let TyKind::Int(int_ty) = sty {}
+   |            ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind`
+  --> $DIR/ty_tykind_usage.rs:48:24
+   |
+LL |     fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
+   |                        ^^^^^^^^^^
+   |
+   = help: try using `ty::Ty` instead
+
+error: aborting due to 31 previous errors
+
diff --git a/src/test/ui/allocator-submodule.rs b/src/test/ui/allocator-submodule.rs
index a1cca50ba98..7a8d86b8da1 100644
--- a/src/test/ui/allocator-submodule.rs
+++ b/src/test/ui/allocator-submodule.rs
@@ -1,8 +1,6 @@
 // Tests that it is possible to create a global allocator in a submodule, rather than in the crate
 // root.
 
-#![feature(alloc, allocator_api, global_allocator)]
-
 extern crate alloc;
 
 use std::{
diff --git a/src/test/ui/allocator-submodule.stderr b/src/test/ui/allocator-submodule.stderr
index 26d7aa80eee..91c7c0f6b8e 100644
--- a/src/test/ui/allocator-submodule.stderr
+++ b/src/test/ui/allocator-submodule.stderr
@@ -1,5 +1,5 @@
 error: `global_allocator` cannot be used in submodules
-  --> $DIR/allocator-submodule.rs:27:5
+  --> $DIR/allocator-submodule.rs:25:5
    |
 LL |     static MY_HEAP: MyAlloc = MyAlloc;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/associated-item/associated-item-enum.rs b/src/test/ui/associated-item/associated-item-enum.rs
new file mode 100644
index 00000000000..30ba258155b
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-enum.rs
@@ -0,0 +1,20 @@
+enum Enum { Variant }
+
+impl Enum {
+    const MISSPELLABLE: i32 = 0;
+    fn misspellable() {}
+}
+
+trait Trait {
+    fn misspellable_trait() {}
+}
+
+impl Trait for Enum {
+    fn misspellable_trait() {}
+}
+
+fn main() {
+    Enum::mispellable(); //~ ERROR no variant or associated item
+    Enum::mispellable_trait(); //~ ERROR no variant or associated item
+    Enum::MISPELLABLE; //~ ERROR no variant or associated item
+}
diff --git a/src/test/ui/associated-item/associated-item-enum.stderr b/src/test/ui/associated-item/associated-item-enum.stderr
new file mode 100644
index 00000000000..5a62b9736de
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-enum.stderr
@@ -0,0 +1,36 @@
+error[E0599]: no variant or associated item named `mispellable` found for type `Enum` in the current scope
+  --> $DIR/associated-item-enum.rs:17:11
+   |
+LL | enum Enum { Variant }
+   | --------- variant or associated item `mispellable` not found here
+...
+LL |     Enum::mispellable();
+   |           ^^^^^^^^^^^
+   |           |
+   |           variant or associated item not found in `Enum`
+   |           help: there is a method with a similar name: `misspellable`
+
+error[E0599]: no variant or associated item named `mispellable_trait` found for type `Enum` in the current scope
+  --> $DIR/associated-item-enum.rs:18:11
+   |
+LL | enum Enum { Variant }
+   | --------- variant or associated item `mispellable_trait` not found here
+...
+LL |     Enum::mispellable_trait();
+   |           ^^^^^^^^^^^^^^^^^ variant or associated item not found in `Enum`
+
+error[E0599]: no variant or associated item named `MISPELLABLE` found for type `Enum` in the current scope
+  --> $DIR/associated-item-enum.rs:19:11
+   |
+LL | enum Enum { Variant }
+   | --------- variant or associated item `MISPELLABLE` not found here
+...
+LL |     Enum::MISPELLABLE;
+   |           ^^^^^^^^^^^
+   |           |
+   |           variant or associated item not found in `Enum`
+   |           help: there is an associated constant with a similar name: `MISSPELLABLE`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/async-fn-multiple-lifetimes.rs b/src/test/ui/async-fn-multiple-lifetimes.rs
index 6156617c4da..fccc4fdb917 100644
--- a/src/test/ui/async-fn-multiple-lifetimes.rs
+++ b/src/test/ui/async-fn-multiple-lifetimes.rs
@@ -5,7 +5,7 @@
 use std::ops::Add;
 
 async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
-//~^ ERROR multiple different lifetimes used in arguments of `async fn`
+//~^ ERROR ambiguous lifetime bound in `async fn`
 
 async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
     _: impl for<'a> Add<&'a u8>,
@@ -14,7 +14,6 @@ async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
 ) {}
 
 async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
-//~^ ERROR multiple elided lifetimes used
-//~^^ ERROR missing lifetime specifier
+//~^ ambiguous lifetime bound in `async fn`
 
 fn main() {}
diff --git a/src/test/ui/async-fn-multiple-lifetimes.stderr b/src/test/ui/async-fn-multiple-lifetimes.stderr
index 071349b23fa..8c3ee2bed83 100644
--- a/src/test/ui/async-fn-multiple-lifetimes.stderr
+++ b/src/test/ui/async-fn-multiple-lifetimes.stderr
@@ -1,32 +1,20 @@
-error[E0709]: multiple different lifetimes used in arguments of `async fn`
-  --> $DIR/async-fn-multiple-lifetimes.rs:7:47
+error: ambiguous lifetime bound in `async fn`
+  --> $DIR/async-fn-multiple-lifetimes.rs:7:65
    |
 LL | async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
-   |                                               ^^         ^^ different lifetime here
-   |                                               |
-   |                                               first lifetime here
+   |                                                                 ^ neither `'a` nor `'b` outlives the other
    |
-   = help: `async fn` can only accept borrowed values with identical lifetimes
+   = note: multiple unrelated lifetimes are not allowed in `async fn`.
+   = note: if you're using argument-position elided lifetimes, consider switching to a single named lifetime.
 
-error[E0707]: multiple elided lifetimes used in arguments of `async fn`
-  --> $DIR/async-fn-multiple-lifetimes.rs:16:39
+error: ambiguous lifetime bound in `async fn`
+  --> $DIR/async-fn-multiple-lifetimes.rs:16:52
    |
 LL | async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
-   |                                       ^       ^ different lifetime here
-   |                                       |
-   |                                       first lifetime here
+   |                                                    ^ the elided lifetimes here do not outlive one another
    |
-   = help: consider giving these arguments named lifetimes
+   = note: multiple unrelated lifetimes are not allowed in `async fn`.
+   = note: if you're using argument-position elided lifetimes, consider switching to a single named lifetime.
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/async-fn-multiple-lifetimes.rs:16:39
-   |
-LL | async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
-   |                                       ^ expected lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_` or `_`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0106, E0707, E0709.
-For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr
index 97b9cd961a0..f2e0d379d1b 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 type `std::vec::Vec<{integer}
   --> $DIR/auto-ref-slice-plus-ref.rs:7:7
    |
 LL |     a.test_mut();
-   |       ^^^^^^^^ help: did you mean: `get_mut`
+   |       ^^^^^^^^ help: there is a method with a similar name: `get_mut`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `test_mut`, perhaps you need to implement it:
diff --git a/src/test/ui/auxiliary/issue-59764.rs b/src/test/ui/auxiliary/issue-59764.rs
new file mode 100644
index 00000000000..a92eed968d0
--- /dev/null
+++ b/src/test/ui/auxiliary/issue-59764.rs
@@ -0,0 +1,18 @@
+pub mod foo {
+    #[macro_export]
+    macro_rules! makro {
+        ($foo:ident) => {
+            fn $foo() { }
+        }
+    }
+
+    pub fn baz() {}
+
+    pub fn foobar() {}
+
+    pub mod barbaz {
+        pub fn barfoo() {}
+    }
+}
+
+pub fn foobaz() {}
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
index a6346a5233f..237b8c54ce3 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 type `&Self` in the current scope
   --> $DIR/issue-3563.rs:3:17
    |
 LL |         || self.b()
-   |                 ^ help: did you mean: `a`
+   |                 ^ help: there is a method with a similar name: `a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr
index 0bf0d4b14ee..890f6800c22 100644
--- a/src/test/ui/bogus-tag.stderr
+++ b/src/test/ui/bogus-tag.stderr
@@ -1,11 +1,11 @@
-error[E0599]: no variant named `Hsl` found for type `Color` in the current scope
+error[E0599]: no variant or associated item named `Hsl` found for type `Color` in the current scope
   --> $DIR/bogus-tag.rs:7:16
    |
 LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
-   | ---------- variant `Hsl` not found here
+   | ---------- variant or associated item `Hsl` not found here
 ...
 LL |         Color::Hsl(h, s, l) => { println!("hsl"); }
-   |                ^^^ variant not found in `Color`
+   |                ^^^ variant or associated item not found in `Color`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr b/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr
index 9123e1890fe..9bfd8b994bf 100644
--- a/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr
+++ b/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr
@@ -7,7 +7,7 @@ LL |     vec.get({
    |     immutable borrow occurs here
 LL | 
 LL |         vec.push(2);
-   |         ^^^^^^^^^^^ mutable borrow occurs here
+   |         ^^^ mutable borrow occurs here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr
index d026f81b7aa..223de36f0df 100644
--- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr
+++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr
@@ -7,17 +7,15 @@ LL |         f(f(10));
    |         first mutable borrow occurs here
    |         first borrow later used by call
 
-error[E0382]: use of moved value: `*f`
+error[E0382]: use of moved value: `f`
   --> $DIR/two-phase-nonrecv-autoref.rs:69:11
    |
 LL |     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
-   |                     - consider adding a `Copy` constraint to this type argument
+   |                                            - move occurs because `f` has type `std::boxed::Box<F>`, which does not implement the `Copy` trait
 LL |         f(f(10));
    |         - ^ value used here after move
    |         |
    |         value moved here
-   |
-   = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait
 
 error[E0499]: cannot borrow `*f` as mutable more than once at a time
   --> $DIR/two-phase-nonrecv-autoref.rs:76:11
@@ -28,30 +26,18 @@ LL |         f(f(10));
    |         first mutable borrow occurs here
    |         first borrow later used by call
 
-error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined
-  --> $DIR/two-phase-nonrecv-autoref.rs:85:9
-   |
-LL |         f(f(10));
-   |         ^
-
-error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined
-  --> $DIR/two-phase-nonrecv-autoref.rs:85:11
-   |
-LL |         f(f(10));
-   |           ^
-
-error[E0382]: use of moved value: `*f`
+error[E0382]: use of moved value: `f`
   --> $DIR/two-phase-nonrecv-autoref.rs:85:11
    |
+LL |     fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
+   |                     - move occurs because `f` has type `std::boxed::Box<dyn std::ops::FnOnce(i32) -> i32>`, which does not implement the `Copy` trait
 LL |         f(f(10));
    |         - ^ value used here after move
    |         |
    |         value moved here
-   |
-   = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:129:27
+  --> $DIR/two-phase-nonrecv-autoref.rs:125:27
    |
 LL |     double_access(&mut a, &a);
    |     ------------- ------  ^^ immutable borrow occurs here
@@ -60,7 +46,7 @@ LL |     double_access(&mut a, &a);
    |     mutable borrow later used by call
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:157:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:153:7
    |
 LL |     i[i[3]] = 4;
    |     --^----
@@ -70,7 +56,7 @@ LL |     i[i[3]] = 4;
    |     mutable borrow later used here
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:163:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:159:7
    |
 LL |     i[i[3]] = i[4];
    |     --^----
@@ -79,7 +65,7 @@ LL |     i[i[3]] = i[4];
    |     mutable borrow occurs here
    |     mutable borrow later used here
 
-error: aborting due to 9 previous errors
+error: aborting due to 7 previous errors
 
-Some errors occurred: E0161, E0382, E0499, E0502.
-For more information about an error, try `rustc --explain E0161`.
+Some errors occurred: E0382, E0499, E0502.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr
index 426939f371c..d98b272944f 100644
--- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr
+++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr
@@ -15,7 +15,7 @@ LL |         f(f(10));
    |         | second mutable borrow occurs here
    |         first mutable borrow occurs here
 
-error[E0382]: use of moved value: `*f`
+error[E0382]: use of moved value: `f`
   --> $DIR/two-phase-nonrecv-autoref.rs:69:11
    |
 LL |         f(f(10));
@@ -23,7 +23,7 @@ LL |         f(f(10));
    |         |
    |         value moved here
    |
-   = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait
+   = note: move occurs because `f` has type `std::boxed::Box<F>`, which does not implement the `Copy` trait
 
 error[E0499]: cannot borrow `*f` as mutable more than once at a time
   --> $DIR/two-phase-nonrecv-autoref.rs:76:11
@@ -34,7 +34,7 @@ LL |         f(f(10));
    |         | second mutable borrow occurs here
    |         first mutable borrow occurs here
 
-error[E0382]: use of moved value: `*f`
+error[E0382]: use of moved value: `f`
   --> $DIR/two-phase-nonrecv-autoref.rs:85:11
    |
 LL |         f(f(10));
@@ -42,10 +42,10 @@ LL |         f(f(10));
    |         |
    |         value moved here
    |
-   = note: move occurs because `*f` has type `(dyn std::ops::FnOnce(i32) -> i32 + 'static)`, which does not implement the `Copy` trait
+   = note: move occurs because `f` has type `std::boxed::Box<(dyn std::ops::FnOnce(i32) -> i32 + 'static)>`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:129:28
+  --> $DIR/two-phase-nonrecv-autoref.rs:125:28
    |
 LL |     double_access(&mut a, &a);
    |                        -   ^- mutable borrow ends here
@@ -54,7 +54,7 @@ LL |     double_access(&mut a, &a);
    |                        mutable borrow occurs here
 
 error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:135:9
+  --> $DIR/two-phase-nonrecv-autoref.rs:131:9
    |
 LL |     a.m(a.i(10));
    |     -   ^      - mutable borrow ends here
@@ -63,7 +63,7 @@ LL |     a.m(a.i(10));
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:157:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:153:7
    |
 LL |     i[i[3]] = 4;
    |     - ^   - mutable borrow ends here
@@ -72,7 +72,7 @@ LL |     i[i[3]] = 4;
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:163:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:159:7
    |
 LL |     i[i[3]] = i[4];
    |     - ^   - mutable borrow ends here
@@ -81,7 +81,7 @@ LL |     i[i[3]] = i[4];
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:172:12
+  --> $DIR/two-phase-nonrecv-autoref.rs:168:12
    |
 LL |     v.push(v.len());
    |     -      ^      - mutable borrow ends here
@@ -90,7 +90,7 @@ LL |     v.push(v.len());
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:183:9
+  --> $DIR/two-phase-nonrecv-autoref.rs:179:9
    |
 LL |     s.m(s.i(10));
    |     -   ^      - mutable borrow ends here
@@ -99,7 +99,7 @@ LL |     s.m(s.i(10));
    |     mutable borrow occurs here
 
 error[E0502]: cannot borrow `t` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:188:9
+  --> $DIR/two-phase-nonrecv-autoref.rs:184:9
    |
 LL |     t.m(t.i(10));
    |     -   ^      - mutable borrow ends here
diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr
index d026f81b7aa..223de36f0df 100644
--- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr
+++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr
@@ -7,17 +7,15 @@ LL |         f(f(10));
    |         first mutable borrow occurs here
    |         first borrow later used by call
 
-error[E0382]: use of moved value: `*f`
+error[E0382]: use of moved value: `f`
   --> $DIR/two-phase-nonrecv-autoref.rs:69:11
    |
 LL |     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
-   |                     - consider adding a `Copy` constraint to this type argument
+   |                                            - move occurs because `f` has type `std::boxed::Box<F>`, which does not implement the `Copy` trait
 LL |         f(f(10));
    |         - ^ value used here after move
    |         |
    |         value moved here
-   |
-   = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait
 
 error[E0499]: cannot borrow `*f` as mutable more than once at a time
   --> $DIR/two-phase-nonrecv-autoref.rs:76:11
@@ -28,30 +26,18 @@ LL |         f(f(10));
    |         first mutable borrow occurs here
    |         first borrow later used by call
 
-error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined
-  --> $DIR/two-phase-nonrecv-autoref.rs:85:9
-   |
-LL |         f(f(10));
-   |         ^
-
-error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined
-  --> $DIR/two-phase-nonrecv-autoref.rs:85:11
-   |
-LL |         f(f(10));
-   |           ^
-
-error[E0382]: use of moved value: `*f`
+error[E0382]: use of moved value: `f`
   --> $DIR/two-phase-nonrecv-autoref.rs:85:11
    |
+LL |     fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
+   |                     - move occurs because `f` has type `std::boxed::Box<dyn std::ops::FnOnce(i32) -> i32>`, which does not implement the `Copy` trait
 LL |         f(f(10));
    |         - ^ value used here after move
    |         |
    |         value moved here
-   |
-   = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:129:27
+  --> $DIR/two-phase-nonrecv-autoref.rs:125:27
    |
 LL |     double_access(&mut a, &a);
    |     ------------- ------  ^^ immutable borrow occurs here
@@ -60,7 +46,7 @@ LL |     double_access(&mut a, &a);
    |     mutable borrow later used by call
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:157:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:153:7
    |
 LL |     i[i[3]] = 4;
    |     --^----
@@ -70,7 +56,7 @@ LL |     i[i[3]] = 4;
    |     mutable borrow later used here
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
-  --> $DIR/two-phase-nonrecv-autoref.rs:163:7
+  --> $DIR/two-phase-nonrecv-autoref.rs:159:7
    |
 LL |     i[i[3]] = i[4];
    |     --^----
@@ -79,7 +65,7 @@ LL |     i[i[3]] = i[4];
    |     mutable borrow occurs here
    |     mutable borrow later used here
 
-error: aborting due to 9 previous errors
+error: aborting due to 7 previous errors
 
-Some errors occurred: E0161, E0382, E0499, E0502.
-For more information about an error, try `rustc --explain E0161`.
+Some errors occurred: E0382, E0499, E0502.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs b/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs
index 1a14cb90f38..1005da05297 100644
--- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs
+++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs
@@ -67,9 +67,9 @@ fn overloaded_call_traits() {
     }
     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
         f(f(10));
-        //[nll]~^   ERROR use of moved value: `*f`
-        //[g2p]~^^  ERROR use of moved value: `*f`
-        //[ast]~^^^ ERROR use of moved value: `*f`
+        //[nll]~^   ERROR use of moved value: `f`
+        //[g2p]~^^  ERROR use of moved value: `f`
+        //[ast]~^^^ ERROR use of moved value: `f`
     }
 
     fn twice_ten_om(f: &mut FnMut(i32) -> i32) {
@@ -83,13 +83,9 @@ fn overloaded_call_traits() {
     }
     fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
         f(f(10));
-        //[nll]~^          ERROR cannot move a value of type
-        //[nll]~^^         ERROR cannot move a value of type
-        //[nll]~^^^        ERROR use of moved value: `*f`
-        //[g2p]~^^^^       ERROR cannot move a value of type
-        //[g2p]~^^^^^      ERROR cannot move a value of type
-        //[g2p]~^^^^^^     ERROR use of moved value: `*f`
-        //[ast]~^^^^^^^    ERROR use of moved value: `*f`
+        //[nll]~^   ERROR use of moved value: `f`
+        //[g2p]~^^  ERROR use of moved value: `f`
+        //[ast]~^^^ ERROR use of moved value: `f`
     }
 
     twice_ten_sm(&mut |x| x + 1);
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.ast.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.ast.stderr
new file mode 100644
index 00000000000..28c997efc8a
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.ast.stderr
@@ -0,0 +1,36 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                   - immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:15
+   |
+LL |     v.extend(&v);
+   |     -         ^- mutable borrow ends here
+   |     |         |
+   |     |         immutable borrow occurs here
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                   - immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr
new file mode 100644
index 00000000000..bb11b2e4f0f
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr
@@ -0,0 +1,40 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^^------^^^^^^^^
+   |     | |
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:5
+   |
+LL |     v.extend(&v);
+   |     ^^------^--^
+   |     | |      |
+   |     | |      immutable borrow occurs here
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+warning: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^      ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+   |
+   = note: #[warn(mutable_borrow_reservation_conflict)] on by default
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr
new file mode 100644
index 00000000000..bb11b2e4f0f
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr
@@ -0,0 +1,40 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^^------^^^^^^^^
+   |     | |
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:5
+   |
+LL |     v.extend(&v);
+   |     ^^------^--^
+   |     | |      |
+   |     | |      immutable borrow occurs here
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+warning: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^      ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+   |
+   = note: #[warn(mutable_borrow_reservation_conflict)] on by default
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr
new file mode 100644
index 00000000000..fb3a1fda631
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr
@@ -0,0 +1,35 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^        ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:5
+   |
+LL |     v.extend(&v);
+   |     ^^------^--^
+   |     | |      |
+   |     | |      immutable borrow occurs here
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^      ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr
new file mode 100644
index 00000000000..fb3a1fda631
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr
@@ -0,0 +1,35 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:19:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.extend(shared);
+   |     ^        ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:30:5
+   |
+LL |     v.extend(&v);
+   |     ^^------^--^
+   |     | |      |
+   |     | |      immutable borrow occurs here
+   |     | immutable borrow later used by call
+   |     mutable borrow occurs here
+
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-2.rs:42:5
+   |
+LL |     let shared = &v;
+   |                  -- immutable borrow occurs here
+LL | 
+LL |     v.push(shared.len());
+   |     ^      ------ immutable borrow later used here
+   |     |
+   |     mutable borrow occurs here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs
index 13c1df7db2b..54fad9f66b8 100644
--- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.rs
@@ -1,24 +1,54 @@
-// compile-flags: -Z borrowck=mir -Z two-phase-borrows
-
-// This is similar to two-phase-reservation-sharing-interference.rs
-// in that it shows a reservation that overlaps with a shared borrow.
-//
-// Currently, this test fails with lexical lifetimes, but succeeds
-// with non-lexical lifetimes. (The reason is because the activation
-// of the mutable borrow ends up overlapping with a lexically-scoped
-// shared borrow; but a non-lexical shared borrow can end before the
-// activation occurs.)
-//
-// So this test is just making a note of the current behavior.
-
-#![feature(rustc_attrs)]
-
-#[rustc_error]
-fn main() { //~ ERROR compilation successful
+// Test for #56254, we previously allowed the last example on the 2018
+// editiion. Make sure that we now emit a warning in that case and an error for
+// everyone else.
+
+//ignore-compare-mode-nll
+
+//revisions: ast migrate2015 migrate2018 nll2015 nll2018
+
+//[migrate2015] compile-flags: -Zborrowck=migrate -Ztwo-phase-borrows
+//[migrate2018] edition:2018
+//[nll2018] edition:2018
+
+#![cfg_attr(any(nll2015, nll2018), feature(nll))]
+
+fn double_conflicts() {
+    let mut v = vec![0, 1, 2];
+    let shared = &v;
+
+    v.extend(shared);
+    //[migrate2015]~^ ERROR cannot borrow `v` as mutable
+    //[nll2015]~^^ ERROR cannot borrow `v` as mutable
+    //[migrate2018]~^^^ ERROR cannot borrow `v` as mutable
+    //[nll2018]~^^^^ ERROR cannot borrow `v` as mutable
+    //[ast]~^^^^^ ERROR cannot borrow `v` as mutable
+}
+
+fn activation_conflict() {
+    let mut v = vec![0, 1, 2];
+
+    v.extend(&v);
+    //[migrate2015]~^ ERROR cannot borrow `v` as mutable
+    //[nll2015]~^^ ERROR cannot borrow `v` as mutable
+    //[migrate2018]~^^^ ERROR cannot borrow `v` as mutable
+    //[nll2018]~^^^^ ERROR cannot borrow `v` as mutable
+    //[ast]~^^^^^ ERROR cannot borrow `v` as immutable
+}
+
+fn reservation_conflict() {
     let mut v = vec![0, 1, 2];
     let shared = &v;
 
     v.push(shared.len());
+    //[nll2015]~^ ERROR cannot borrow `v` as mutable
+    //[nll2018]~^^ ERROR cannot borrow `v` as mutable
+    //[migrate2015]~^^^ WARNING cannot borrow `v` as mutable
+    //[migrate2015]~| WARNING may become a hard error in the future
 
-    assert_eq!(v, [0, 1, 2, 3]);
+    //[migrate2018]~^^^^^^ WARNING cannot borrow `v` as mutable
+    //[migrate2018]~| WARNING may become a hard error in the future
+
+    //[ast]~^^^^^^^^^ ERROR cannot borrow `v` as mutable
 }
+
+fn main() {}
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.stderr
deleted file mode 100644
index bcd743f47c5..00000000000
--- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: compilation successful
-  --> $DIR/two-phase-reservation-sharing-interference-2.rs:17:1
-   |
-LL | / fn main() {
-LL | |     let mut v = vec![0, 1, 2];
-LL | |     let shared = &v;
-LL | |
-...  |
-LL | |     assert_eq!(v, [0, 1, 2, 3]);
-LL | | }
-   | |_^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.rs b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.rs
new file mode 100644
index 00000000000..0e1d77ace3f
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.rs
@@ -0,0 +1,43 @@
+// Check that the future-compat-lint for the reservation conflict is
+// handled like any other lint.
+
+// edition:2018
+
+mod future_compat_allow {
+    #![allow(mutable_borrow_reservation_conflict)]
+
+    fn reservation_conflict() {
+        let mut v = vec![0, 1, 2];
+        let shared = &v;
+
+        v.push(shared.len());
+    }
+}
+
+mod future_compat_warn {
+    #![warn(mutable_borrow_reservation_conflict)]
+
+    fn reservation_conflict() {
+        let mut v = vec![0, 1, 2];
+        let shared = &v;
+
+        v.push(shared.len());
+        //~^ WARNING cannot borrow `v` as mutable
+        //~| WARNING may become a hard error in the future
+    }
+}
+
+mod future_compat_deny {
+    #![deny(mutable_borrow_reservation_conflict)]
+
+    fn reservation_conflict() {
+        let mut v = vec![0, 1, 2];
+        let shared = &v;
+
+        v.push(shared.len());
+        //~^ ERROR cannot borrow `v` as mutable
+        //~| WARNING may become a hard error in the future
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr
new file mode 100644
index 00000000000..77fbfb37add
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr
@@ -0,0 +1,40 @@
+warning: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-future-compat-lint.rs:24:9
+   |
+LL |         let shared = &v;
+   |                      -- immutable borrow occurs here
+LL | 
+LL |         v.push(shared.len());
+   |         ^      ------ immutable borrow later used here
+   |         |
+   |         mutable borrow occurs here
+   |
+note: lint level defined here
+  --> $DIR/two-phase-reservation-sharing-interference-future-compat-lint.rs:18:13
+   |
+LL |     #![warn(mutable_borrow_reservation_conflict)]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+error: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/two-phase-reservation-sharing-interference-future-compat-lint.rs:37:9
+   |
+LL |         let shared = &v;
+   |                      -- immutable borrow occurs here
+LL | 
+LL |         v.push(shared.len());
+   |         ^      ------ immutable borrow later used here
+   |         |
+   |         mutable borrow occurs here
+   |
+note: lint level defined here
+  --> $DIR/two-phase-reservation-sharing-interference-future-compat-lint.rs:31:13
+   |
+LL |     #![deny(mutable_borrow_reservation_conflict)]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.stderr b/src/test/ui/cast/cast-ptr-to-int-const.stderr
index 0d4397c2e2d..c40accfd7c4 100644
--- a/src/test/ui/cast/cast-ptr-to-int-const.stderr
+++ b/src/test/ui/cast/cast-ptr-to-int-const.stderr
@@ -1,17 +1,19 @@
-error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+error[E0658]: casting pointers to integers in constants is unstable
   --> $DIR/cast-ptr-to-int-const.rs:5:9
    |
 LL |         main as u32
    |         ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51910
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
-error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+error[E0658]: casting pointers to integers in constants is unstable
   --> $DIR/cast-ptr-to-int-const.rs:9:9
    |
 LL |         &Y as *const u32 as u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51910
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr
index 8d308f0c96f..ec77789449a 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr
@@ -1,9 +1,10 @@
-error[E0658]: no_core is experimental (see issue #29639)
+error[E0658]: no_core is experimental
   --> $DIR/cfg-attr-crate-2.rs:6:21
    |
 LL | #![cfg_attr(broken, no_core)]
    |                     ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29639
    = help: add #![feature(no_core)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr
index 8485459ca6b..ad5177dc9c0 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr
@@ -1,9 +1,10 @@
-error[E0658]: no_core is experimental (see issue #29639)
+error[E0658]: no_core is experimental
   --> $DIR/cfg-attr-multi-invalid-1.rs:4:21
    |
 LL | #![cfg_attr(broken, no_core, no_std)]
    |                     ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29639
    = help: add #![feature(no_core)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr
index 2a673ea8131..675997758e6 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr
@@ -1,9 +1,10 @@
-error[E0658]: no_core is experimental (see issue #29639)
+error[E0658]: no_core is experimental
   --> $DIR/cfg-attr-multi-invalid-2.rs:4:29
    |
 LL | #![cfg_attr(broken, no_std, no_core)]
    |                             ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29639
    = help: add #![feature(no_core)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
index d0b59c3994c..ca3e3d9eff1 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
@@ -1,4 +1,4 @@
-error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:3:27
    |
 LL |         #[cfg_attr(all(), unknown)]
@@ -7,6 +7,7 @@ LL |         #[cfg_attr(all(), unknown)]
 LL | foo!();
    | ------- in this macro invocation
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/consts/const-deref-ptr.stderr b/src/test/ui/consts/const-deref-ptr.stderr
index 8de0f6c1514..23ac3b85ee6 100644
--- a/src/test/ui/consts/const-deref-ptr.stderr
+++ b/src/test/ui/consts/const-deref-ptr.stderr
@@ -1,9 +1,10 @@
-error[E0658]: dereferencing raw pointers in statics is unstable (see issue #51911)
+error[E0658]: dereferencing raw pointers in statics is unstable
   --> $DIR/const-deref-ptr.rs:4:29
    |
 LL |     static C: u64 = unsafe {*(0xdeadbeef as *const u64)};
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr
index 5a72c8205b6..069a8bfd4e7 100644
--- a/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr
+++ b/src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr
@@ -1,9 +1,10 @@
-error[E0658]: unions in const fn are unstable (see issue #51909)
+error[E0658]: unions in const fn are unstable
   --> $DIR/feature-gate-const_fn_union.rs:11:5
    |
 LL |     Foo { u }.i
    |     ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51909
    = help: add #![feature(const_fn_union)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr b/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr
index 08103413556..5d3e88e4e58 100644
--- a/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr
+++ b/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr
@@ -1,27 +1,30 @@
-error[E0658]: panicking in constants is unstable (see issue #51999)
+error[E0658]: panicking in constants is unstable
   --> $DIR/feature-gate-const_panic.rs:3:15
    |
 LL | const Z: () = panic!("cheese");
    |               ^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51999
    = help: add #![feature(const_panic)] to the crate attributes to enable
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
-error[E0658]: panicking in constants is unstable (see issue #51999)
+error[E0658]: panicking in constants is unstable
   --> $DIR/feature-gate-const_panic.rs:9:15
    |
 LL | const X: () = unimplemented!();
    |               ^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51999
    = help: add #![feature(const_panic)] to the crate attributes to enable
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
-error[E0658]: panicking in constants is unstable (see issue #51999)
+error[E0658]: panicking in constants is unstable
   --> $DIR/feature-gate-const_panic.rs:6:15
    |
 LL | const Y: () = unreachable!();
    |               ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51999
    = help: add #![feature(const_panic)] to the crate attributes to enable
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.rs b/src/test/ui/consts/const-eval/match-test-ptr-null.rs
index b27b816cf50..e0af01aeef4 100644
--- a/src/test/ui/consts/const-eval/match-test-ptr-null.rs
+++ b/src/test/ui/consts/const-eval/match-test-ptr-null.rs
@@ -3,7 +3,9 @@ fn main() {
     // that pointer comparison is disallowed, not that parts of a pointer are accessed as raw
     // bytes.
     let _: [u8; 0] = [4; {
-        match &1 as *const i32 as usize { //~ ERROR casting pointers to integers in constants
+        match &1 as *const i32 as usize {
+            //~^ ERROR casting pointers to integers in constants
+            //~| NOTE for more information, see
             0 => 42, //~ ERROR constant contains unimplemented expression type
             //~^ NOTE "pointer arithmetic or comparison" needs an rfc before being allowed
             //~| ERROR evaluation of constant value failed
diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr
index fd5647c9af3..79e278f68ad 100644
--- a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr
+++ b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr
@@ -1,19 +1,20 @@
-error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+error[E0658]: casting pointers to integers in constants is unstable
   --> $DIR/match-test-ptr-null.rs:6:15
    |
 LL |         match &1 as *const i32 as usize {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51910
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/match-test-ptr-null.rs:7:13
+  --> $DIR/match-test-ptr-null.rs:9:13
    |
 LL |             0 => 42,
    |             ^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/match-test-ptr-null.rs:7:13
+  --> $DIR/match-test-ptr-null.rs:9:13
    |
 LL |             0 => 42,
    |             ^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
diff --git a/src/test/ui/consts/const_arg_local.rs b/src/test/ui/consts/const_arg_local.rs
new file mode 100644
index 00000000000..0da4b44a968
--- /dev/null
+++ b/src/test/ui/consts/const_arg_local.rs
@@ -0,0 +1,13 @@
+// only-x86_64
+
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+unsafe fn pclmul(a: __m128i, b: __m128i) -> __m128i {
+    let imm8 = 3;
+    _mm_clmulepi64_si128(a, b, imm8) //~ ERROR argument 3 is required to be a constant
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const_arg_local.stderr b/src/test/ui/consts/const_arg_local.stderr
new file mode 100644
index 00000000000..197b2f082e5
--- /dev/null
+++ b/src/test/ui/consts/const_arg_local.stderr
@@ -0,0 +1,8 @@
+error: argument 3 is required to be a constant
+  --> $DIR/const_arg_local.rs:10:5
+   |
+LL |     _mm_clmulepi64_si128(a, b, imm8)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const_arg_promotable.rs b/src/test/ui/consts/const_arg_promotable.rs
new file mode 100644
index 00000000000..25f45104d6a
--- /dev/null
+++ b/src/test/ui/consts/const_arg_promotable.rs
@@ -0,0 +1,12 @@
+// only-x86_64
+
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+unsafe fn pclmul(a: __m128i, b: __m128i) -> __m128i {
+    _mm_clmulepi64_si128(a, b, *&mut 42) //~ ERROR argument 3 is required to be a constant
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const_arg_promotable.stderr b/src/test/ui/consts/const_arg_promotable.stderr
new file mode 100644
index 00000000000..5de3ee6654a
--- /dev/null
+++ b/src/test/ui/consts/const_arg_promotable.stderr
@@ -0,0 +1,8 @@
+error: argument 3 is required to be a constant
+  --> $DIR/const_arg_promotable.rs:9:5
+   |
+LL |     _mm_clmulepi64_si128(a, b, *&mut 42)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const_arg_wrapper.rs b/src/test/ui/consts/const_arg_wrapper.rs
new file mode 100644
index 00000000000..92ff264cd2b
--- /dev/null
+++ b/src/test/ui/consts/const_arg_wrapper.rs
@@ -0,0 +1,12 @@
+// only-x86_64
+
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+unsafe fn pclmul(a: __m128i, b: __m128i, imm8: i32) -> __m128i {
+    _mm_clmulepi64_si128(a, b, imm8) //~ ERROR argument 3 is required to be a constant
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const_arg_wrapper.stderr b/src/test/ui/consts/const_arg_wrapper.stderr
new file mode 100644
index 00000000000..4acf2f0f4d1
--- /dev/null
+++ b/src/test/ui/consts/const_arg_wrapper.stderr
@@ -0,0 +1,8 @@
+error: argument 3 is required to be a constant
+  --> $DIR/const_arg_wrapper.rs:9:5
+   |
+LL |     _mm_clmulepi64_si128(a, b, imm8)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
index 48c260644a7..5c1bbc6ba31 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
@@ -1,33 +1,37 @@
-error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+error[E0658]: dereferencing raw pointers in constant functions is unstable
   --> $DIR/min_const_fn_unsafe.rs:50:77
    |
 LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } }
    |                                                                             ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
-error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+error[E0658]: dereferencing raw pointers in constant functions is unstable
   --> $DIR/min_const_fn_unsafe.rs:53:70
    |
 LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x }
    |                                                                      ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
-error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+error[E0658]: dereferencing raw pointers in constant functions is unstable
   --> $DIR/min_const_fn_unsafe.rs:56:83
    |
 LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x }
    |                                                                                   ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
-error[E0658]: unions in const fn are unstable (see issue #51909)
+error[E0658]: unions in const fn are unstable
   --> $DIR/min_const_fn_unsafe.rs:63:5
    |
 LL |     Foo { x: () }.y
    |     ^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51909
    = help: add #![feature(const_fn_union)] to the crate attributes to enable
 
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr
index 45679e3b962..15d332aba1f 100644
--- a/src/test/ui/consts/projection_qualif.stderr
+++ b/src/test/ui/consts/projection_qualif.stderr
@@ -10,12 +10,13 @@ error[E0019]: constant contains unimplemented expression type
 LL |         unsafe { *b = 5; }
    |                  ^^^^^^
 
-error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
+error[E0658]: dereferencing raw pointers in constants is unstable
   --> $DIR/projection_qualif.rs:7:18
    |
 LL |         unsafe { *b = 5; }
    |                  ^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/custom_attribute.stderr b/src/test/ui/custom_attribute.stderr
index 6608fb53c30..adb05e3fb2a 100644
--- a/src/test/ui/custom_attribute.stderr
+++ b/src/test/ui/custom_attribute.stderr
@@ -1,25 +1,28 @@
-error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/custom_attribute.rs:3:3
    |
 LL | #[foo]
    |   ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/custom_attribute.rs:5:7
    |
 LL |     #[foo]
    |       ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/custom_attribute.rs:7:7
    |
 LL |     #[foo]
    |       ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs
index f3df57e6ff9..bcf7e3e6608 100644
--- a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs
+++ b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs
@@ -25,7 +25,7 @@ mod x {
 mod y {
     use Foo;
 
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     pub fn use_char_assoc() {
         // Careful here: in the representation, <char as Foo>::T gets
         // normalized away, so at a certain point we had no edge to
diff --git a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr
index db6ee98bb7b..a603d71596b 100644
--- a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr
+++ b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr
@@ -1,8 +1,8 @@
 error: OK
   --> $DIR/dep-graph-assoc-type-codegen.rs:28:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/dep-graph/dep-graph-caller-callee.rs b/src/test/ui/dep-graph/dep-graph-caller-callee.rs
index f8276ea3ad6..18b4252a06b 100644
--- a/src/test/ui/dep-graph/dep-graph-caller-callee.rs
+++ b/src/test/ui/dep-graph/dep-graph-caller-callee.rs
@@ -17,7 +17,7 @@ mod y {
     use x;
 
     // These dependencies SHOULD exist:
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     pub fn y() {
         x::x();
     }
@@ -28,7 +28,7 @@ mod z {
 
     // These are expected to yield errors, because changes to `x`
     // affect the BODY of `y`, but not its signature.
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
     pub fn z() {
         y::y();
     }
diff --git a/src/test/ui/dep-graph/dep-graph-caller-callee.stderr b/src/test/ui/dep-graph/dep-graph-caller-callee.stderr
index 2b1b7fe9a56..de041e60067 100644
--- a/src/test/ui/dep-graph/dep-graph-caller-callee.stderr
+++ b/src/test/ui/dep-graph/dep-graph-caller-callee.stderr
@@ -1,14 +1,14 @@
 error: OK
   --> $DIR/dep-graph-caller-callee.rs:20:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `x::x` to `TypeckTables`
+error: no path from `x::x` to `typeck_tables_of`
   --> $DIR/dep-graph-caller-callee.rs:31:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.rs b/src/test/ui/dep-graph/dep-graph-struct-signature.rs
index bd6d3a7e56f..8b78d39ecae 100644
--- a/src/test/ui/dep-graph/dep-graph-struct-signature.rs
+++ b/src/test/ui/dep-graph/dep-graph-struct-signature.rs
@@ -25,34 +25,34 @@ mod signatures {
     use WillChange;
 
     #[rustc_then_this_would_need(type_of)] //~ ERROR no path
-    #[rustc_then_this_would_need(AssociatedItems)] //~ ERROR no path
-    #[rustc_then_this_would_need(TraitDefOfItem)] //~ ERROR no path
+    #[rustc_then_this_would_need(associated_item)] //~ ERROR no path
+    #[rustc_then_this_would_need(trait_def)] //~ ERROR no path
     trait Bar {
-        #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
+        #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
         fn do_something(x: WillChange);
     }
 
-    #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     fn some_fn(x: WillChange) { }
 
-    #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     fn new_foo(x: u32, y: u32) -> WillChange {
         WillChange { x: x, y: y }
     }
 
     #[rustc_then_this_would_need(type_of)] //~ ERROR OK
     impl WillChange {
-        #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
-        #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+        #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+        #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
         fn new(x: u32, y: u32) -> WillChange { loop { } }
     }
 
     #[rustc_then_this_would_need(type_of)] //~ ERROR OK
     impl WillChange {
-        #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
-        #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+        #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+        #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
         fn method(&self, x: u32) { }
     }
 
@@ -73,14 +73,14 @@ mod invalid_signatures {
 
     #[rustc_then_this_would_need(type_of)] //~ ERROR no path
     trait A {
-        #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path
+        #[rustc_then_this_would_need(fn_sig)] //~ ERROR no path
         fn do_something_else_twice(x: WontChange);
     }
 
-    #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR no path
     fn b(x: WontChange) { }
 
-    #[rustc_then_this_would_need(FnSignature)] //~ ERROR no path from `WillChange`
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path from `WillChange`
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR no path from `WillChange`
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path from `WillChange`
     fn c(x: u32) { }
 }
diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.stderr b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr
index 7aa4251752e..2e00e5a2cbd 100644
--- a/src/test/ui/dep-graph/dep-graph-struct-signature.stderr
+++ b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr
@@ -4,41 +4,41 @@ error: no path from `WillChange` to `type_of`
 LL |     #[rustc_then_this_would_need(type_of)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `WillChange` to `AssociatedItems`
+error: no path from `WillChange` to `associated_item`
   --> $DIR/dep-graph-struct-signature.rs:28:5
    |
-LL |     #[rustc_then_this_would_need(AssociatedItems)]
+LL |     #[rustc_then_this_would_need(associated_item)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `WillChange` to `TraitDefOfItem`
+error: no path from `WillChange` to `trait_def`
   --> $DIR/dep-graph-struct-signature.rs:29:5
    |
-LL |     #[rustc_then_this_would_need(TraitDefOfItem)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(trait_def)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:35:5
    |
-LL |     #[rustc_then_this_would_need(FnSignature)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:36:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:39:5
    |
-LL |     #[rustc_then_this_would_need(FnSignature)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:40:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:45:5
@@ -76,59 +76,59 @@ error: no path from `WillChange` to `type_of`
 LL |     #[rustc_then_this_would_need(type_of)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `WillChange` to `FnSignature`
+error: no path from `WillChange` to `fn_sig`
   --> $DIR/dep-graph-struct-signature.rs:80:5
    |
-LL |     #[rustc_then_this_would_need(FnSignature)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `WillChange` to `FnSignature`
+error: no path from `WillChange` to `fn_sig`
   --> $DIR/dep-graph-struct-signature.rs:83:5
    |
-LL |     #[rustc_then_this_would_need(FnSignature)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `WillChange` to `TypeckTables`
+error: no path from `WillChange` to `typeck_tables_of`
   --> $DIR/dep-graph-struct-signature.rs:84:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:31:9
    |
-LL |         #[rustc_then_this_would_need(FnSignature)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `WillChange` to `FnSignature`
+error: no path from `WillChange` to `fn_sig`
   --> $DIR/dep-graph-struct-signature.rs:76:9
    |
-LL |         #[rustc_then_this_would_need(FnSignature)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:47:9
    |
-LL |         #[rustc_then_this_would_need(FnSignature)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:48:9
    |
-LL |         #[rustc_then_this_would_need(TypeckTables)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_then_this_would_need(typeck_tables_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:54:9
    |
-LL |         #[rustc_then_this_would_need(FnSignature)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_then_this_would_need(fn_sig)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-struct-signature.rs:55:9
    |
-LL |         #[rustc_then_this_would_need(TypeckTables)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         #[rustc_then_this_would_need(typeck_tables_of)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 22 previous errors
 
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs
index 16e5a705d25..38622a754dd 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs
@@ -29,7 +29,7 @@ mod x {
 mod y {
     use {Foo, Bar};
 
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     pub fn with_char() {
         char::method('a');
     }
@@ -38,7 +38,7 @@ mod y {
 mod z {
     use y;
 
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
     pub fn z() {
         y::with_char();
     }
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr
index 2df4b9ec39d..3384fd7b4ac 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr
@@ -1,14 +1,14 @@
 error: OK
   --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:32:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `x::<impl Foo for u32>` to `TypeckTables`
+error: no path from `x::<impl Foo for u32>` to `typeck_tables_of`
   --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:41:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
index 064302c9c80..82306b6539c 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
@@ -28,7 +28,7 @@ mod x {
 mod y {
     use {Foo, Bar};
 
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
     pub fn call_bar() {
         char::bar('a');
     }
@@ -37,7 +37,7 @@ mod y {
 mod z {
     use y;
 
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
     pub fn z() {
         y::call_bar();
     }
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr
index 54125367f90..d8a1f05dcaa 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr
@@ -1,14 +1,14 @@
-error: no path from `x::<impl Foo for char>` to `TypeckTables`
+error: no path from `x::<impl Foo for char>` to `typeck_tables_of`
   --> $DIR/dep-graph-trait-impl-two-traits.rs:31:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `x::<impl Foo for char>` to `TypeckTables`
+error: no path from `x::<impl Foo for char>` to `typeck_tables_of`
   --> $DIR/dep-graph-trait-impl-two-traits.rs:40:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl.rs b/src/test/ui/dep-graph/dep-graph-trait-impl.rs
index 7d088082c7a..e4483b9f71d 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl.rs
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl.rs
@@ -24,22 +24,22 @@ mod x {
 mod y {
     use Foo;
 
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     pub fn with_char() {
         char::method('a');
     }
 
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     pub fn take_foo_with_char() {
         take_foo::<char>('a');
     }
 
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     pub fn with_u32() {
         u32::method(22);
     }
 
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     pub fn take_foo_with_u32() {
         take_foo::<u32>(22);
     }
@@ -52,7 +52,7 @@ mod z {
 
     // These are expected to yield errors, because changes to `x`
     // affect the BODY of `y`, but not its signature.
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR no path
     pub fn z() {
         y::with_char();
         y::with_u32();
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl.stderr
index 97072e74f42..ca9676a9478 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl.stderr
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl.stderr
@@ -1,32 +1,32 @@
 error: OK
   --> $DIR/dep-graph-trait-impl.rs:27:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-trait-impl.rs:32:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-trait-impl.rs:37:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-trait-impl.rs:42:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: no path from `x::<impl Foo for char>` to `TypeckTables`
+error: no path from `x::<impl Foo for char>` to `typeck_tables_of`
   --> $DIR/dep-graph-trait-impl.rs:55:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.rs b/src/test/ui/dep-graph/dep-graph-type-alias.rs
index 5621284fb18..2d4a18f2818 100644
--- a/src/test/ui/dep-graph/dep-graph-type-alias.rs
+++ b/src/test/ui/dep-graph/dep-graph-type-alias.rs
@@ -32,7 +32,7 @@ enum Enum {
 
 #[rustc_then_this_would_need(type_of)] //~ ERROR no path
 trait Trait {
-    #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
     fn method(&self, _: TypeAlias);
 }
 
@@ -40,16 +40,16 @@ struct SomeType;
 
 #[rustc_then_this_would_need(type_of)] //~ ERROR no path
 impl SomeType {
-    #[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
-    #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+    #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+    #[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
     fn method(&self, _: TypeAlias) {}
 }
 
 #[rustc_then_this_would_need(type_of)] //~ ERROR OK
 type TypeAlias2 = TypeAlias;
 
-#[rustc_then_this_would_need(FnSignature)] //~ ERROR OK
-#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
+#[rustc_then_this_would_need(fn_sig)] //~ ERROR OK
+#[rustc_then_this_would_need(typeck_tables_of)] //~ ERROR OK
 fn function(_: TypeAlias) {
 
 }
diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.stderr b/src/test/ui/dep-graph/dep-graph-type-alias.stderr
index 520c2a5ed21..393e4badc16 100644
--- a/src/test/ui/dep-graph/dep-graph-type-alias.stderr
+++ b/src/test/ui/dep-graph/dep-graph-type-alias.stderr
@@ -43,32 +43,32 @@ LL | #[rustc_then_this_would_need(type_of)]
 error: OK
   --> $DIR/dep-graph-type-alias.rs:51:1
    |
-LL | #[rustc_then_this_would_need(FnSignature)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_then_this_would_need(fn_sig)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-type-alias.rs:52:1
    |
-LL | #[rustc_then_this_would_need(TypeckTables)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_then_this_would_need(typeck_tables_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-type-alias.rs:35:5
    |
-LL |     #[rustc_then_this_would_need(FnSignature)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-type-alias.rs:43:5
    |
-LL |     #[rustc_then_this_would_need(FnSignature)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(fn_sig)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: OK
   --> $DIR/dep-graph-type-alias.rs:44:5
    |
-LL |     #[rustc_then_this_would_need(TypeckTables)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_then_this_would_need(typeck_tables_of)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/dep-graph/dep-graph-variance-alias.rs b/src/test/ui/dep-graph/dep-graph-variance-alias.rs
index 0a70bfd08bf..95645687307 100644
--- a/src/test/ui/dep-graph/dep-graph-variance-alias.rs
+++ b/src/test/ui/dep-graph/dep-graph-variance-alias.rs
@@ -16,7 +16,7 @@ struct Foo<T> {
 #[rustc_if_this_changed(Krate)]
 type TypeAlias<T> = Foo<T>;
 
-#[rustc_then_this_would_need(ItemVariances)] //~ ERROR OK
+#[rustc_then_this_would_need(variances_of)] //~ ERROR OK
 struct Use<T> {
     x: TypeAlias<T>
 }
diff --git a/src/test/ui/dep-graph/dep-graph-variance-alias.stderr b/src/test/ui/dep-graph/dep-graph-variance-alias.stderr
index 86cb0f9fe32..554ff455a20 100644
--- a/src/test/ui/dep-graph/dep-graph-variance-alias.stderr
+++ b/src/test/ui/dep-graph/dep-graph-variance-alias.stderr
@@ -1,8 +1,8 @@
 error: OK
   --> $DIR/dep-graph-variance-alias.rs:19:1
    |
-LL | #[rustc_then_this_would_need(ItemVariances)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_then_this_would_need(variances_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/empty/empty-struct-braces-expr.rs b/src/test/ui/empty/empty-struct-braces-expr.rs
index 2f2f41ae8c1..e33fcb70db7 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.rs
+++ b/src/test/ui/empty/empty-struct-braces-expr.rs
@@ -19,6 +19,8 @@ fn main() {
 
     let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
     let xe1 = XEmpty1(); //~ ERROR expected function, found struct `XEmpty1`
-    let xe3 = XE::Empty3; //~ ERROR no variant named `Empty3` found for type
-    let xe3 = XE::Empty3(); //~ ERROR no variant named `Empty3` found for type
+    let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for type
+    let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for type
+
+    XE::Empty1 {}; //~ ERROR no variant `Empty1` in enum `empty_struct::XE`
 }
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index 57c8c1c85dd..f5609c8e1bf 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -46,25 +46,31 @@ LL |     let xe1 = XEmpty1();
    |               did you mean `XEmpty1 { /* fields */ }`?
    |               help: a unit struct with a similar name exists: `XEmpty2`
 
-error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:22:19
    |
 LL |     let xe3 = XE::Empty3;
    |                   ^^^^^^
    |                   |
-   |                   variant not found in `empty_struct::XE`
-   |                   help: did you mean: `XEmpty3`
+   |                   variant or associated item not found in `empty_struct::XE`
+   |                   help: there is a variant with a similar name: `XEmpty3`
 
-error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:23:19
    |
 LL |     let xe3 = XE::Empty3();
    |                   ^^^^^^
    |                   |
-   |                   variant not found in `empty_struct::XE`
-   |                   help: did you mean: `XEmpty3`
+   |                   variant or associated item not found in `empty_struct::XE`
+   |                   help: there is a variant with a similar name: `XEmpty3`
 
-error: aborting due to 8 previous errors
+error: no variant `Empty1` in enum `empty_struct::XE`
+  --> $DIR/empty-struct-braces-expr.rs:25:9
+   |
+LL |     XE::Empty1 {};
+   |         ^^^^^^ help: there is a variant with a similar name: `XEmpty3`
+
+error: aborting due to 9 previous errors
 
 Some errors occurred: E0423, E0599.
 For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/error-codes/E0254.rs b/src/test/ui/error-codes/E0254.rs
index 706cd347e13..d166aff5657 100644
--- a/src/test/ui/error-codes/E0254.rs
+++ b/src/test/ui/error-codes/E0254.rs
@@ -1,4 +1,3 @@
-#![feature(alloc)]
 #![allow(unused_extern_crates, non_camel_case_types)]
 
 extern crate alloc;
diff --git a/src/test/ui/error-codes/E0254.stderr b/src/test/ui/error-codes/E0254.stderr
index c2d013da417..10456fd5a5d 100644
--- a/src/test/ui/error-codes/E0254.stderr
+++ b/src/test/ui/error-codes/E0254.stderr
@@ -1,5 +1,5 @@
 error[E0254]: the name `alloc` is defined multiple times
-  --> $DIR/E0254.rs:12:5
+  --> $DIR/E0254.rs:11:5
    |
 LL | extern crate alloc;
    | ------------------- previous import of the extern crate `alloc` here
diff --git a/src/test/ui/error-codes/E0259.rs b/src/test/ui/error-codes/E0259.rs
index cda3db34dfc..c83561be9c6 100644
--- a/src/test/ui/error-codes/E0259.rs
+++ b/src/test/ui/error-codes/E0259.rs
@@ -1,4 +1,4 @@
-#![feature(alloc, rustc_private)]
+#![feature(rustc_private)]
 #![allow(unused_extern_crates)]
 
 extern crate alloc;
diff --git a/src/test/ui/error-codes/E0260.rs b/src/test/ui/error-codes/E0260.rs
index 80382c0d2fc..73b8934159f 100644
--- a/src/test/ui/error-codes/E0260.rs
+++ b/src/test/ui/error-codes/E0260.rs
@@ -1,4 +1,3 @@
-#![feature(alloc)]
 #![allow(unused_extern_crates)]
 
 extern crate alloc;
diff --git a/src/test/ui/error-codes/E0260.stderr b/src/test/ui/error-codes/E0260.stderr
index bfe2ed0cfc7..7d0b3022914 100644
--- a/src/test/ui/error-codes/E0260.stderr
+++ b/src/test/ui/error-codes/E0260.stderr
@@ -1,5 +1,5 @@
 error[E0260]: the name `alloc` is defined multiple times
-  --> $DIR/E0260.rs:6:1
+  --> $DIR/E0260.rs:5:1
    |
 LL | extern crate alloc;
    | ------------------- previous import of the extern crate `alloc` here
diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs
index 9657bbdeadc..bbefff27d7f 100644
--- a/src/test/ui/error-codes/E0395.rs
+++ b/src/test/ui/error-codes/E0395.rs
@@ -3,6 +3,8 @@
 static FOO: i32 = 42;
 static BAR: i32 = 42;
 
-static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
+static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
+//~^ ERROR comparing raw pointers inside static
+
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr
index 9d80acb515d..30a4d4815ff 100644
--- a/src/test/ui/error-codes/E0395.stderr
+++ b/src/test/ui/error-codes/E0395.stderr
@@ -1,9 +1,10 @@
-error[E0658]: comparing raw pointers inside static (see issue #53020)
+error[E0658]: comparing raw pointers inside static
   --> $DIR/E0395.rs:6:29
    |
 LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53020
    = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0396.stderr b/src/test/ui/error-codes/E0396.stderr
index 1006ff6dc54..6d2d121e91c 100644
--- a/src/test/ui/error-codes/E0396.stderr
+++ b/src/test/ui/error-codes/E0396.stderr
@@ -1,9 +1,10 @@
-error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
+error[E0658]: dereferencing raw pointers in constants is unstable
   --> $DIR/E0396.rs:5:28
    |
 LL | const VALUE: u8 = unsafe { *REG_ADDR };
    |                            ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0658.stderr b/src/test/ui/error-codes/E0658.stderr
index 292c49fa84e..ff3f74addd2 100644
--- a/src/test/ui/error-codes/E0658.stderr
+++ b/src/test/ui/error-codes/E0658.stderr
@@ -1,4 +1,4 @@
-error[E0658]: repr with 128-bit type is unstable (see issue #35118)
+error[E0658]: repr with 128-bit type is unstable
   --> $DIR/E0658.rs:2:1
    |
 LL | / enum Foo {
@@ -6,6 +6,7 @@ LL | |     Bar(u64),
 LL | | }
    | |_^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/35118
    = help: add #![feature(repr128)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/explore-issue-38412.stderr b/src/test/ui/explore-issue-38412.stderr
index 5e5d952bcec..eb28ad410fa 100644
--- a/src/test/ui/explore-issue-38412.stderr
+++ b/src/test/ui/explore-issue-38412.stderr
@@ -1,17 +1,19 @@
-error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+error[E0658]: use of unstable library feature 'unstable_undeclared'
   --> $DIR/explore-issue-38412.rs:21:63
    |
 LL |     let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } =
    |                                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38412
    = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+error[E0658]: use of unstable library feature 'unstable_undeclared'
   --> $DIR/explore-issue-38412.rs:30:5
    |
 LL |     r.a_unstable_undeclared_pub;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38412
    = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
 
 error[E0616]: field `b_crate` of struct `pub_and_stability::Record` is private
@@ -32,12 +34,13 @@ error[E0616]: field `d_priv` of struct `pub_and_stability::Record` is private
 LL |     r.d_priv;
    |     ^^^^^^^^
 
-error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+error[E0658]: use of unstable library feature 'unstable_undeclared'
   --> $DIR/explore-issue-38412.rs:37:5
    |
 LL |     t.2;
    |     ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38412
    = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
 
 error[E0616]: field `3` of struct `pub_and_stability::Tuple` is private
@@ -58,20 +61,22 @@ error[E0616]: field `5` of struct `pub_and_stability::Tuple` is private
 LL |     t.5;
    |     ^^^
 
-error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+error[E0658]: use of unstable library feature 'unstable_undeclared'
   --> $DIR/explore-issue-38412.rs:44:7
    |
 LL |     r.unstable_undeclared_trait_method();
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38412
    = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+error[E0658]: use of unstable library feature 'unstable_undeclared'
   --> $DIR/explore-issue-38412.rs:48:7
    |
 LL |     r.unstable_undeclared();
    |       ^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38412
    = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
 
 error[E0624]: method `pub_crate` is private
@@ -92,20 +97,22 @@ error[E0624]: method `private` is private
 LL |     r.private();
    |       ^^^^^^^
 
-error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+error[E0658]: use of unstable library feature 'unstable_undeclared'
   --> $DIR/explore-issue-38412.rs:57:7
    |
 LL |     t.unstable_undeclared_trait_method();
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38412
    = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'unstable_undeclared' (see issue #38412)
+error[E0658]: use of unstable library feature 'unstable_undeclared'
   --> $DIR/explore-issue-38412.rs:61:7
    |
 LL |     t.unstable_undeclared();
    |       ^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38412
    = help: add #![feature(unstable_undeclared)] to the crate attributes to enable
 
 error[E0624]: method `pub_crate` is private
diff --git a/src/test/ui/feature-gate-optimize_attribute.rs b/src/test/ui/feature-gate-optimize_attribute.rs
index c1f75100141..f252a3c153d 100644
--- a/src/test/ui/feature-gate-optimize_attribute.rs
+++ b/src/test/ui/feature-gate-optimize_attribute.rs
@@ -1,17 +1,17 @@
 #![crate_type="rlib"]
-#![optimize(speed)] //~ ERROR #54882
+#![optimize(speed)] //~ ERROR #[optimize] attribute is an unstable feature
 
-#[optimize(size)] //~ ERROR #54882
+#[optimize(size)] //~ ERROR #[optimize] attribute is an unstable feature
 mod module {
 
-#[optimize(size)] //~ ERROR #54882
+#[optimize(size)] //~ ERROR #[optimize] attribute is an unstable feature
 fn size() {}
 
-#[optimize(speed)] //~ ERROR #54882
+#[optimize(speed)] //~ ERROR #[optimize] attribute is an unstable feature
 fn speed() {}
 
 #[optimize(banana)]
-//~^ ERROR #54882
+//~^ ERROR #[optimize] attribute is an unstable feature
 //~| ERROR E0722
 fn not_known() {}
 
diff --git a/src/test/ui/feature-gate-optimize_attribute.stderr b/src/test/ui/feature-gate-optimize_attribute.stderr
index 7635af6ce46..b4ba3fded15 100644
--- a/src/test/ui/feature-gate-optimize_attribute.stderr
+++ b/src/test/ui/feature-gate-optimize_attribute.stderr
@@ -1,41 +1,46 @@
-error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+error[E0658]: #[optimize] attribute is an unstable feature
   --> $DIR/feature-gate-optimize_attribute.rs:7:1
    |
 LL | #[optimize(size)]
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54882
    = help: add #![feature(optimize_attribute)] to the crate attributes to enable
 
-error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+error[E0658]: #[optimize] attribute is an unstable feature
   --> $DIR/feature-gate-optimize_attribute.rs:10:1
    |
 LL | #[optimize(speed)]
    | ^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54882
    = help: add #![feature(optimize_attribute)] to the crate attributes to enable
 
-error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+error[E0658]: #[optimize] attribute is an unstable feature
   --> $DIR/feature-gate-optimize_attribute.rs:13:1
    |
 LL | #[optimize(banana)]
    | ^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54882
    = help: add #![feature(optimize_attribute)] to the crate attributes to enable
 
-error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+error[E0658]: #[optimize] attribute is an unstable feature
   --> $DIR/feature-gate-optimize_attribute.rs:4:1
    |
 LL | #[optimize(size)]
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54882
    = help: add #![feature(optimize_attribute)] to the crate attributes to enable
 
-error[E0658]: #[optimize] attribute is an unstable feature (see issue #54882)
+error[E0658]: #[optimize] attribute is an unstable feature
   --> $DIR/feature-gate-optimize_attribute.rs:2:1
    |
 LL | #![optimize(speed)]
    | ^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54882
    = help: add #![feature(optimize_attribute)] to the crate attributes to enable
 
 error[E0722]: invalid argument
diff --git a/src/test/ui/feature-gate/feature-gate-c_variadic.stderr b/src/test/ui/feature-gate/feature-gate-c_variadic.stderr
index a876e16fdea..a1362901862 100644
--- a/src/test/ui/feature-gate/feature-gate-c_variadic.stderr
+++ b/src/test/ui/feature-gate/feature-gate-c_variadic.stderr
@@ -1,9 +1,10 @@
-error[E0658]: C-varaidic functions are unstable (see issue #44930)
+error[E0658]: C-varaidic functions are unstable
   --> $DIR/feature-gate-c_variadic.rs:3:1
    |
 LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44930
    = help: add #![feature(c_variadic)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
index 419c21901a0..4a653265f16 100644
--- a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
+++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
@@ -1,5 +1,6 @@
-error[E0658]: kind="static-nobundle" is feature gated (see issue #37403)
+error[E0658]: kind="static-nobundle" is feature gated
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/37403
    = help: add #![feature(static_nobundle)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr
index 6b3c169c99d..0eb26ec8291 100644
--- a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr
+++ b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr
@@ -1,9 +1,10 @@
-error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-msp430-interrupt.rs:4:1
    |
 LL | extern "msp430-interrupt" fn foo() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38487
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr
index 7417f310921..e20ab0cb2f5 100644
--- a/src/test/ui/feature-gates/feature-gate-abi.stderr
+++ b/src/test/ui/feature-gates/feature-gate-abi.stderr
@@ -6,12 +6,13 @@ LL | extern "rust-intrinsic" fn f1() {}
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy
   --> $DIR/feature-gate-abi.rs:13:1
    |
 LL | extern "platform-intrinsic" fn f2() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
@@ -22,36 +23,40 @@ LL | extern "vectorcall" fn f3() {}
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:15:1
    |
 LL | extern "rust-call" fn f4() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:16:1
    |
 LL | extern "msp430-interrupt" fn f5() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38487
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:17:1
    |
 LL | extern "ptx-kernel" fn f6() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38788
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:18:1
    |
 LL | extern "x86-interrupt" fn f7() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/40180
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
@@ -62,12 +67,13 @@ LL | extern "thiscall" fn f8() {}
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:20:1
    |
 LL | extern "amdgpu-kernel" fn f9() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51575
    = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
@@ -78,12 +84,13 @@ LL |     extern "rust-intrinsic" fn m1();
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy
   --> $DIR/feature-gate-abi.rs:25:5
    |
 LL |     extern "platform-intrinsic" fn m2();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
@@ -94,36 +101,40 @@ LL |     extern "vectorcall" fn m3();
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:27:5
    |
 LL |     extern "rust-call" fn m4();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:28:5
    |
 LL |     extern "msp430-interrupt" fn m5();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38487
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:29:5
    |
 LL |     extern "ptx-kernel" fn m6();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38788
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:30:5
    |
 LL |     extern "x86-interrupt" fn m7();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/40180
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
@@ -134,12 +145,13 @@ LL |     extern "thiscall" fn m8();
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:32:5
    |
 LL |     extern "amdgpu-kernel" fn m9();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51575
    = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
@@ -150,12 +162,13 @@ LL |     extern "rust-intrinsic" fn dm1() {}
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy
   --> $DIR/feature-gate-abi.rs:35:5
    |
 LL |     extern "platform-intrinsic" fn dm2() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
@@ -166,36 +179,40 @@ LL |     extern "vectorcall" fn dm3() {}
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:37:5
    |
 LL |     extern "rust-call" fn dm4() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:38:5
    |
 LL |     extern "msp430-interrupt" fn dm5() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38487
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:39:5
    |
 LL |     extern "ptx-kernel" fn dm6() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38788
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:40:5
    |
 LL |     extern "x86-interrupt" fn dm7() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/40180
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
@@ -206,12 +223,13 @@ LL |     extern "thiscall" fn dm8() {}
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:42:5
    |
 LL |     extern "amdgpu-kernel" fn dm9() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51575
    = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
@@ -222,12 +240,13 @@ LL |     extern "rust-intrinsic" fn m1() {}
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy
   --> $DIR/feature-gate-abi.rs:50:5
    |
 LL |     extern "platform-intrinsic" fn m2() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
@@ -238,36 +257,40 @@ LL |     extern "vectorcall" fn m3() {}
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:52:5
    |
 LL |     extern "rust-call" fn m4() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:53:5
    |
 LL |     extern "msp430-interrupt" fn m5() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38487
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:54:5
    |
 LL |     extern "ptx-kernel" fn m6() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38788
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:55:5
    |
 LL |     extern "x86-interrupt" fn m7() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/40180
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
@@ -278,12 +301,13 @@ LL |     extern "thiscall" fn m8() {}
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:57:5
    |
 LL |     extern "amdgpu-kernel" fn m9() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51575
    = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
@@ -294,12 +318,13 @@ LL |     extern "rust-intrinsic" fn im1() {}
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy
   --> $DIR/feature-gate-abi.rs:63:5
    |
 LL |     extern "platform-intrinsic" fn im2() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
@@ -310,36 +335,40 @@ LL |     extern "vectorcall" fn im3() {}
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:65:5
    |
 LL |     extern "rust-call" fn im4() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:66:5
    |
 LL |     extern "msp430-interrupt" fn im5() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38487
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:67:5
    |
 LL |     extern "ptx-kernel" fn im6() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38788
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:68:5
    |
 LL |     extern "x86-interrupt" fn im7() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/40180
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
@@ -350,12 +379,13 @@ LL |     extern "thiscall" fn im8() {}
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:70:5
    |
 LL |     extern "amdgpu-kernel" fn im9() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51575
    = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
@@ -366,12 +396,13 @@ LL | type A1 = extern "rust-intrinsic" fn();
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy
   --> $DIR/feature-gate-abi.rs:75:11
    |
 LL | type A2 = extern "platform-intrinsic" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
@@ -382,36 +413,40 @@ LL | type A3 = extern "vectorcall" fn();
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:77:11
    |
 LL | type A4 = extern "rust-call" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:78:11
    |
 LL | type A5 = extern "msp430-interrupt" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38487
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:79:11
    |
 LL | type A6 = extern "ptx-kernel" fn ();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38788
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:80:11
    |
 LL | type A7 = extern "x86-interrupt" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/40180
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
@@ -422,12 +457,13 @@ LL | type A8 = extern "thiscall" fn();
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:82:11
    |
 LL | type A9 = extern "amdgpu-kernel" fn();
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51575
    = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
 
 error[E0658]: intrinsics are subject to change
@@ -438,12 +474,13 @@ LL | extern "rust-intrinsic" {}
    |
    = help: add #![feature(intrinsics)] to the crate attributes to enable
 
-error[E0658]: platform intrinsics are experimental and possibly buggy (see issue #27731)
+error[E0658]: platform intrinsics are experimental and possibly buggy
   --> $DIR/feature-gate-abi.rs:86:1
    |
 LL | extern "platform-intrinsic" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
 
 error[E0658]: vectorcall is experimental and subject to change
@@ -454,36 +491,40 @@ LL | extern "vectorcall" {}
    |
    = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:88:1
    |
 LL | extern "rust-call" {}
    | ^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:89:1
    |
 LL | extern "msp430-interrupt" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38487
    = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
 
-error[E0658]: PTX ABIs are experimental and subject to change (see issue #38788)
+error[E0658]: PTX ABIs are experimental and subject to change
   --> $DIR/feature-gate-abi.rs:90:1
    |
 LL | extern "ptx-kernel" {}
    | ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/38788
    = help: add #![feature(abi_ptx)] to the crate attributes to enable
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+error[E0658]: x86-interrupt ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:91:1
    |
 LL | extern "x86-interrupt" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/40180
    = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
 
 error[E0658]: thiscall is experimental and subject to change
@@ -494,12 +535,13 @@ LL | extern "thiscall" {}
    |
    = help: add #![feature(abi_thiscall)] to the crate attributes to enable
 
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change (see issue #51575)
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:93:1
    |
 LL | extern "amdgpu-kernel" {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51575
    = help: add #![feature(abi_amdgpu_kernel)] to the crate attributes to enable
 
 error: aborting due to 63 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs
index daa2bb5d6fa..df7c3ad6b3d 100644
--- a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs
+++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.rs
@@ -5,7 +5,7 @@
 
 use core::alloc::Layout;
 
-#[alloc_error_handler] //~ ERROR #[alloc_error_handler] is an unstable feature (see issue #51540)
+#[alloc_error_handler] //~ ERROR #[alloc_error_handler] is an unstable feature
 fn oom(info: Layout) -> ! {
     loop {}
 }
diff --git a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr
index 5e64ac50c3c..cb01b5caf85 100644
--- a/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr
+++ b/src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr
@@ -1,9 +1,10 @@
-error[E0658]: #[alloc_error_handler] is an unstable feature (see issue #51540)
+error[E0658]: #[alloc_error_handler] is an unstable feature
   --> $DIR/feature-gate-alloc-error-handler.rs:8:1
    |
 LL | #[alloc_error_handler]
    | ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51540
    = help: add #![feature(alloc_error_handler)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-allow_fail.stderr b/src/test/ui/feature-gates/feature-gate-allow_fail.stderr
index 5de1706dd4a..af7c8de61d5 100644
--- a/src/test/ui/feature-gates/feature-gate-allow_fail.stderr
+++ b/src/test/ui/feature-gates/feature-gate-allow_fail.stderr
@@ -1,9 +1,10 @@
-error[E0658]: allow_fail attribute is currently unstable (see issue #46488)
+error[E0658]: allow_fail attribute is currently unstable
   --> $DIR/feature-gate-allow_fail.rs:3:1
    |
 LL | #[allow_fail]
    | ^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/46488
    = help: add #![feature(allow_fail)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
index e1089bc345e..8d061a95676 100644
--- a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
@@ -1,27 +1,30 @@
-error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary-self-types.rs:16:18
    |
 LL |     fn foo(self: Ptr<Self>);
    |                  ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44874
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0658]: `Ptr<Bar>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+error[E0658]: `Ptr<Bar>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary-self-types.rs:22:18
    |
 LL |     fn foo(self: Ptr<Self>) {}
    |                  ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44874
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0658]: `std::boxed::Box<Ptr<Bar>>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+error[E0658]: `std::boxed::Box<Ptr<Bar>>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary-self-types.rs:26:18
    |
 LL |     fn bar(self: Box<Ptr<Self>>) {}
    |                  ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44874
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
index f35438f42f4..eda2403e057 100644
--- a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
@@ -1,27 +1,30 @@
-error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18
    |
 LL |     fn bar(self: *const Self);
    |                  ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44874
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:4:18
    |
 LL |     fn foo(self: *const Self) {}
    |                  ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44874
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
    |
 LL |     fn bar(self: *const Self) {}
    |                  ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44874
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
diff --git a/src/test/ui/feature-gates/feature-gate-asm.stderr b/src/test/ui/feature-gates/feature-gate-asm.stderr
index 6ad0ea67313..ccaf34f0169 100644
--- a/src/test/ui/feature-gates/feature-gate-asm.stderr
+++ b/src/test/ui/feature-gates/feature-gate-asm.stderr
@@ -1,9 +1,10 @@
-error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+error[E0658]: inline assembly is not stable enough for use and is subject to change
   --> $DIR/feature-gate-asm.rs:3:9
    |
 LL |         asm!("");
    |         ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29722
    = help: add #![feature(asm)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-asm2.stderr b/src/test/ui/feature-gates/feature-gate-asm2.stderr
index 466f2028198..cafe2be9d0b 100644
--- a/src/test/ui/feature-gates/feature-gate-asm2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-asm2.stderr
@@ -1,9 +1,10 @@
-error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+error[E0658]: inline assembly is not stable enough for use and is subject to change
   --> $DIR/feature-gate-asm2.rs:5:26
    |
 LL |         println!("{:?}", asm!(""));
    |                          ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29722
    = help: add #![feature(asm)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.stderr b/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.stderr
index fe206d3dfca..16b37cf29ca 100644
--- a/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.stderr
+++ b/src/test/ui/feature-gates/feature-gate-assoc-type-defaults.stderr
@@ -1,9 +1,10 @@
-error[E0658]: associated type defaults are unstable (see issue #29661)
+error[E0658]: associated type defaults are unstable
   --> $DIR/feature-gate-assoc-type-defaults.rs:4:5
    |
 LL |     type Bar = u8;
    |     ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29661
    = help: add #![feature(associated_type_defaults)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
index b67949b6155..77dc6a486a1 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
+++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
@@ -16,12 +16,13 @@ error[E0425]: cannot find value `async` in this scope
 LL |     let _ = async || { true };
    |             ^^^^^ not found in this scope
 
-error[E0658]: async fn is unstable (see issue #50547)
+error[E0658]: async fn is unstable
   --> $DIR/feature-gate-async-await-2015-edition.rs:5:1
    |
 LL | async fn foo() {}
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/50547
    = help: add #![feature(async_await)] to the crate attributes to enable
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-async-await.stderr b/src/test/ui/feature-gates/feature-gate-async-await.stderr
index beec28765c8..6bff254607f 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await.stderr
+++ b/src/test/ui/feature-gates/feature-gate-async-await.stderr
@@ -1,25 +1,28 @@
-error[E0658]: async fn is unstable (see issue #50547)
+error[E0658]: async fn is unstable
   --> $DIR/feature-gate-async-await.rs:5:1
    |
 LL | async fn foo() {}
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/50547
    = help: add #![feature(async_await)] to the crate attributes to enable
 
-error[E0658]: async blocks are unstable (see issue #50547)
+error[E0658]: async blocks are unstable
   --> $DIR/feature-gate-async-await.rs:8:13
    |
 LL |     let _ = async {};
    |             ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/50547
    = help: add #![feature(async_await)] to the crate attributes to enable
 
-error[E0658]: async closures are unstable (see issue #50547)
+error[E0658]: async closures are unstable
   --> $DIR/feature-gate-async-await.rs:9:13
    |
 LL |     let _ = async || {};
    |             ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/50547
    = help: add #![feature(async_await)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-box-expr.stderr b/src/test/ui/feature-gates/feature-gate-box-expr.stderr
index 7b202042878..9666793313e 100644
--- a/src/test/ui/feature-gates/feature-gate-box-expr.stderr
+++ b/src/test/ui/feature-gates/feature-gate-box-expr.stderr
@@ -1,9 +1,10 @@
-error[E0658]: box expression syntax is experimental; you can call `Box::new` instead. (see issue #49733)
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead
   --> $DIR/feature-gate-box-expr.rs:12:13
    |
 LL |     let x = box 'c';
    |             ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49733
    = help: add #![feature(box_syntax)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-box_patterns.stderr b/src/test/ui/feature-gates/feature-gate-box_patterns.stderr
index 39404aa39c8..765b929de8a 100644
--- a/src/test/ui/feature-gates/feature-gate-box_patterns.stderr
+++ b/src/test/ui/feature-gates/feature-gate-box_patterns.stderr
@@ -1,9 +1,10 @@
-error[E0658]: box pattern syntax is experimental (see issue #29641)
+error[E0658]: box pattern syntax is experimental
   --> $DIR/feature-gate-box_patterns.rs:2:9
    |
 LL |     let box x = Box::new('c');
    |         ^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29641
    = help: add #![feature(box_patterns)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-box_syntax.rs b/src/test/ui/feature-gates/feature-gate-box_syntax.rs
index df0c604b2a8..778660cc0b5 100644
--- a/src/test/ui/feature-gates/feature-gate-box_syntax.rs
+++ b/src/test/ui/feature-gates/feature-gate-box_syntax.rs
@@ -2,5 +2,5 @@
 
 fn main() {
     let x = box 3;
-    //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead.
+    //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead
 }
diff --git a/src/test/ui/feature-gates/feature-gate-box_syntax.stderr b/src/test/ui/feature-gates/feature-gate-box_syntax.stderr
index f144d11d89b..a9cac7686ea 100644
--- a/src/test/ui/feature-gates/feature-gate-box_syntax.stderr
+++ b/src/test/ui/feature-gates/feature-gate-box_syntax.stderr
@@ -1,9 +1,10 @@
-error[E0658]: box expression syntax is experimental; you can call `Box::new` instead. (see issue #49733)
+error[E0658]: box expression syntax is experimental; you can call `Box::new` instead
   --> $DIR/feature-gate-box_syntax.rs:4:13
    |
 LL |     let x = box 3;
    |             ^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49733
    = help: add #![feature(box_syntax)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
index db1a7dad06b..827ac3af8f1 100644
--- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
@@ -13,78 +13,78 @@ trait Sized {}
 trait Copy {}
 
 #[cfg(target_has_atomic = "8")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_u8(x: *mut u8) {
     atomic_xadd(x, 1);
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "8")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_i8(x: *mut i8) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "16")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_u16(x: *mut u16) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "16")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_i16(x: *mut i16) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "32")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_u32(x: *mut u32) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "32")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_i32(x: *mut i32) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "64")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_u64(x: *mut u64) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "64")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_i64(x: *mut i64) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "128")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_u128(x: *mut u128) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "128")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_i128(x: *mut i128) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "ptr")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_usize(x: *mut usize) {
     atomic_xadd(x, 1);
 }
 #[cfg(target_has_atomic = "ptr")]
-//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+//~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 pub unsafe fn atomic_isize(x: *mut isize) {
     atomic_xadd(x, 1);
 }
 
 fn main() {
     cfg!(target_has_atomic = "8");
-    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
     cfg!(target_has_atomic = "16");
-    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
     cfg!(target_has_atomic = "32");
-    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
     cfg!(target_has_atomic = "64");
-    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
     cfg!(target_has_atomic = "128");
-    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
     cfg!(target_has_atomic = "ptr");
-    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+    //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 }
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr
index a2d5669bcdc..995528efdd3 100644
--- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr
@@ -1,145 +1,163 @@
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:15:7
    |
 LL | #[cfg(target_has_atomic = "8")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:21:7
    |
 LL | #[cfg(target_has_atomic = "8")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:26:7
    |
 LL | #[cfg(target_has_atomic = "16")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:31:7
    |
 LL | #[cfg(target_has_atomic = "16")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:36:7
    |
 LL | #[cfg(target_has_atomic = "32")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:41:7
    |
 LL | #[cfg(target_has_atomic = "32")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:46:7
    |
 LL | #[cfg(target_has_atomic = "64")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:51:7
    |
 LL | #[cfg(target_has_atomic = "64")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:56:7
    |
 LL | #[cfg(target_has_atomic = "128")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:61:7
    |
 LL | #[cfg(target_has_atomic = "128")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:66:7
    |
 LL | #[cfg(target_has_atomic = "ptr")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:71:7
    |
 LL | #[cfg(target_has_atomic = "ptr")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:78:10
    |
 LL |     cfg!(target_has_atomic = "8");
    |          ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:80:10
    |
 LL |     cfg!(target_has_atomic = "16");
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:82:10
    |
 LL |     cfg!(target_has_atomic = "32");
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:84:10
    |
 LL |     cfg!(target_has_atomic = "64");
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:86:10
    |
 LL |     cfg!(target_has_atomic = "128");
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
-error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-has-atomic.rs:88:10
    |
 LL |     cfg!(target_has_atomic = "ptr");
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32976
    = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
 
 error: aborting due to 18 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs
index 54db7500583..d44f78d4fab 100644
--- a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.rs
@@ -7,7 +7,7 @@ extern crate cfg_target_thread_local;
 
 extern {
     #[cfg_attr(target_thread_local, thread_local)]
-    //~^ `cfg(target_thread_local)` is experimental and subject to change (see issue #29594)
+    //~^ `cfg(target_thread_local)` is experimental and subject to change
 
     static FOO: u32;
 }
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr
index 672fb14871a..3d24b218253 100644
--- a/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `cfg(target_thread_local)` is experimental and subject to change (see issue #29594)
+error[E0658]: `cfg(target_thread_local)` is experimental and subject to change
   --> $DIR/feature-gate-cfg-target-thread-local.rs:9:16
    |
 LL |     #[cfg_attr(target_thread_local, thread_local)]
    |                ^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29594
    = help: add #![feature(cfg_target_thread_local)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents.stderr
index 3f4ce6d3b94..be8c727e2be 100644
--- a/src/test/ui/feature-gates/feature-gate-concat_idents.stderr
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents.stderr
@@ -1,17 +1,19 @@
-error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents.rs:5:13
    |
 LL |     let a = concat_idents!(X, Y_1);
    |             ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add #![feature(concat_idents)] to the crate attributes to enable
 
-error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents.rs:6:13
    |
 LL |     let b = concat_idents!(X, Y_2);
    |             ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add #![feature(concat_idents)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr
index 105b3d5cff5..1ef45115bd1 100644
--- a/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents2.rs:4:5
    |
 LL |     concat_idents!(a, b);
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add #![feature(concat_idents)] to the crate attributes to enable
 
 error[E0425]: cannot find value `ab` in this scope
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr
index 9568b1d8801..cb8725ab566 100644
--- a/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr
@@ -1,17 +1,19 @@
-error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents3.rs:7:20
    |
 LL |     assert_eq!(10, concat_idents!(X, Y_1));
    |                    ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add #![feature(concat_idents)] to the crate attributes to enable
 
-error[E0658]: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+error[E0658]: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents3.rs:8:20
    |
 LL |     assert_eq!(20, concat_idents!(X, Y_2));
    |                    ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add #![feature(concat_idents)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.stderr b/src/test/ui/feature-gates/feature-gate-const_fn.stderr
index 7f88d30acc6..0edd4eb7ab0 100644
--- a/src/test/ui/feature-gates/feature-gate-const_fn.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_fn.stderr
@@ -16,20 +16,22 @@ error[E0379]: trait fns cannot be declared const
 LL |     const fn foo() -> u32 { 0 }
    |     ^^^^^ trait fns cannot be const
 
-error[E0658]: const fn is unstable (see issue #57563)
+error[E0658]: const fn is unstable
   --> $DIR/feature-gate-const_fn.rs:6:5
    |
 LL |     const fn foo() -> u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57563
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
-error[E0658]: const fn is unstable (see issue #57563)
+error[E0658]: const fn is unstable
   --> $DIR/feature-gate-const_fn.rs:8:5
    |
 LL |     const fn bar() -> u32 { 0 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57563
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
index dce40002535..9ea04a1e204 100644
--- a/src/test/ui/feature-gates/feature-gate-const_generics.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
@@ -1,17 +1,19 @@
-error[E0658]: const generics are unstable (see issue #44580)
+error[E0658]: const generics are unstable
   --> $DIR/feature-gate-const_generics.rs:1:14
    |
 LL | fn foo<const X: ()>() {}
    |              ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add #![feature(const_generics)] to the crate attributes to enable
 
-error[E0658]: const generics are unstable (see issue #44580)
+error[E0658]: const generics are unstable
   --> $DIR/feature-gate-const_generics.rs:3:18
    |
 LL | struct Foo<const X: usize>([(); X]);
    |                  ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add #![feature(const_generics)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.rs b/src/test/ui/feature-gates/feature-gate-const_transmute.rs
index 3c4e6de0b1e..6a5bbec77fd 100644
--- a/src/test/ui/feature-gates/feature-gate-const_transmute.rs
+++ b/src/test/ui/feature-gates/feature-gate-const_transmute.rs
@@ -4,6 +4,6 @@ use std::mem;
 struct Foo(u32);
 
 const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
-//~^ ERROR The use of std::mem::transmute() is gated in constants (see issue #53605)
+//~^ ERROR The use of std::mem::transmute() is gated in constants
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_transmute.stderr b/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
index 2e07a9e7ddb..c3cd3131342 100644
--- a/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_transmute.stderr
@@ -1,9 +1,10 @@
-error[E0658]: The use of std::mem::transmute() is gated in constants (see issue #53605)
+error[E0658]: The use of std::mem::transmute() is gated in constants
   --> $DIR/feature-gate-const_transmute.rs:6:38
    |
 LL | const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
    |                                      ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53605
    = help: add #![feature(const_transmute)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr
index 25b26de60ef..4e70870ae72 100644
--- a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr
+++ b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `crate` visibility modifier is experimental (see issue #53120)
+error[E0658]: `crate` visibility modifier is experimental
   --> $DIR/feature-gate-crate_visibility_modifier.rs:1:1
    |
 LL | crate struct Bender {
    | ^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53120
    = help: add #![feature(crate_visibility_modifier)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
index 8b79c752e45..9b81c38f86b 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
@@ -1,105 +1,118 @@
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:7:3
    |
 LL | #[fake_attr]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:8:3
    |
 LL | #[fake_attr(100)]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:9:3
    |
 LL | #[fake_attr(1, 2, 3)]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:10:3
    |
 LL | #[fake_attr("hello")]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:11:3
    |
 LL | #[fake_attr(name = "hello")]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:12:3
    |
 LL | #[fake_attr(1, "hi", key = 12, true, false)]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:13:3
    |
 LL | #[fake_attr(key = "hello", val = 10)]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:14:3
    |
 LL | #[fake_attr(key("hello"), val(10))]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:15:3
    |
 LL | #[fake_attr(enabled = true, disabled = false)]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:16:3
    |
 LL | #[fake_attr(true)]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:17:3
    |
 LL | #[fake_attr(pi = 3.14159)]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:18:3
    |
 LL | #[fake_attr(b"hi")]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute.rs:19:3
    |
 LL | #[fake_doc(r"doc")]
    |   ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to 13 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
index 560ceda3486..8c8ac1233a0 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
@@ -1,137 +1,154 @@
-error[E0658]: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:6:13
    |
 LL | struct StLt<#[lt_struct] 'a>(&'a u32);
    |             ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:8:13
    |
 LL | struct StTy<#[ty_struct] I>(I);
    |             ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:11:11
    |
 LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
    |           ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:13:11
    |
 LL | enum EnTy<#[ty_enum] J> { A(J), B }
    |           ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:16:12
    |
 LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
    |            ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:18:12
    |
 LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
    |            ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:21:11
    |
 LL | type TyLt<#[lt_type] 'd> = &'d u32;
    |           ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:23:11
    |
 LL | type TyTy<#[ty_type] L> = (L, );
    |           ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:26:6
    |
 LL | impl<#[lt_inherent] 'e> StLt<'e> { }
    |      ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:28:6
    |
 LL | impl<#[ty_inherent] M> StTy<M> { }
    |      ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:31:6
    |
 LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
    |      ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:35:6
    |
 LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
    |      ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:40:9
    |
 LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
    |         ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:42:9
    |
 LL | fn f_ty<#[ty_fn] O>(_: O) { }
    |         ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:46:13
    |
 LL |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
    |             ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:48:13
    |
 LL |     fn m_ty<#[ty_meth] P>(_: P) { }
    |             ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/feature-gate-custom_attribute2.rs:53:19
    |
 LL |     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
    |                   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to 17 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr b/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
index bac23b3a60d..e288af54cb2 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
@@ -1,9 +1,10 @@
-error[E0658]: custom test frameworks are an unstable feature (see issue #50297)
+error[E0658]: custom test frameworks are an unstable feature
   --> $DIR/feature-gate-custom_test_frameworks.rs:1:1
    |
 LL | #![test_runner(main)]
    | ^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/50297
    = help: add #![feature(custom_test_frameworks)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-decl_macro.rs b/src/test/ui/feature-gates/feature-gate-decl_macro.rs
index ca0dafd0bf7..d002c5dbbd2 100644
--- a/src/test/ui/feature-gates/feature-gate-decl_macro.rs
+++ b/src/test/ui/feature-gates/feature-gate-decl_macro.rs
@@ -1,5 +1,5 @@
 #![allow(unused_macros)]
 
-macro m() {} //~ ERROR `macro` is experimental (see issue #39412)
+macro m() {} //~ ERROR `macro` is experimental
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-decl_macro.stderr b/src/test/ui/feature-gates/feature-gate-decl_macro.stderr
index 2d4b622843d..808363a0048 100644
--- a/src/test/ui/feature-gates/feature-gate-decl_macro.stderr
+++ b/src/test/ui/feature-gates/feature-gate-decl_macro.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `macro` is experimental (see issue #39412)
+error[E0658]: `macro` is experimental
   --> $DIR/feature-gate-decl_macro.rs:3:1
    |
 LL | macro m() {}
    | ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/39412
    = help: add #![feature(decl_macro)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-doc_alias.stderr b/src/test/ui/feature-gates/feature-gate-doc_alias.stderr
index c585a96adf6..be85ae4b137 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_alias.stderr
+++ b/src/test/ui/feature-gates/feature-gate-doc_alias.stderr
@@ -1,9 +1,10 @@
-error[E0658]: #[doc(alias = "...")] is experimental (see issue #50146)
+error[E0658]: #[doc(alias = "...")] is experimental
   --> $DIR/feature-gate-doc_alias.rs:1:1
    |
 LL | #[doc(alias = "foo")]
    | ^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/50146
    = help: add #![feature(doc_alias)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr
index f018ff4a9d7..0f84a1b11f0 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr
+++ b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `cfg(rustdoc)` is experimental and subject to change (see issue #43781)
+error[E0658]: `cfg(rustdoc)` is experimental and subject to change
   --> $DIR/feature-gate-doc_cfg-cfg-rustdoc.rs:1:7
    |
 LL | #[cfg(rustdoc)]
    |       ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/43781
    = help: add #![feature(doc_cfg)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr b/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr
index 2a0aa4ff3c2..9e4aa6c7a07 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr
+++ b/src/test/ui/feature-gates/feature-gate-doc_cfg.stderr
@@ -1,9 +1,10 @@
-error[E0658]: #[doc(cfg(...))] is experimental (see issue #43781)
+error[E0658]: #[doc(cfg(...))] is experimental
   --> $DIR/feature-gate-doc_cfg.rs:1:1
    |
 LL | #[doc(cfg(unix))]
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/43781
    = help: add #![feature(doc_cfg)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr b/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr
index c2cc1dceda3..6e464781721 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr
+++ b/src/test/ui/feature-gates/feature-gate-doc_keyword.stderr
@@ -1,9 +1,10 @@
-error[E0658]: #[doc(keyword = "...")] is experimental (see issue #51315)
+error[E0658]: #[doc(keyword = "...")] is experimental
   --> $DIR/feature-gate-doc_keyword.rs:1:1
    |
 LL | #[doc(keyword = "match")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51315
    = help: add #![feature(doc_keyword)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-doc_masked.stderr b/src/test/ui/feature-gates/feature-gate-doc_masked.stderr
index 77d3a6f6fb3..d778d4d994c 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_masked.stderr
+++ b/src/test/ui/feature-gates/feature-gate-doc_masked.stderr
@@ -1,9 +1,10 @@
-error[E0658]: #[doc(masked)] is experimental (see issue #44027)
+error[E0658]: #[doc(masked)] is experimental
   --> $DIR/feature-gate-doc_masked.rs:1:1
    |
 LL | #[doc(masked)]
    | ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44027
    = help: add #![feature(doc_masked)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
index 60f5c082188..2bf201f4907 100644
--- a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
+++ b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr
@@ -1,9 +1,10 @@
-error[E0658]: #[doc(spotlight)] is experimental (see issue #45040)
+error[E0658]: #[doc(spotlight)] is experimental
   --> $DIR/feature-gate-doc_spotlight.rs:1:1
    |
 LL | #[doc(spotlight)]
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/45040
    = help: add #![feature(doc_spotlight)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-dropck-ugeh.stderr b/src/test/ui/feature-gates/feature-gate-dropck-ugeh.stderr
index bc62fc01b44..9c7f7b2178d 100644
--- a/src/test/ui/feature-gates/feature-gate-dropck-ugeh.stderr
+++ b/src/test/ui/feature-gates/feature-gate-dropck-ugeh.stderr
@@ -1,9 +1,10 @@
-error[E0658]: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future (see issue #28498)
+error[E0658]: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future
   --> $DIR/feature-gate-dropck-ugeh.rs:16:5
    |
 LL |     #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/28498
    = help: add #![feature(dropck_parametricity)] to the crate attributes to enable
 
 warning: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future. See https://github.com/rust-lang/rust/issues/34761
diff --git a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
index afb402174fb..0eb6da3b125 100644
--- a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
+++ b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
@@ -1,9 +1,10 @@
-error[E0658]: exclusive range pattern syntax is experimental (see issue #37854)
+error[E0658]: exclusive range pattern syntax is experimental
   --> $DIR/feature-gate-exclusive-range-pattern.rs:3:9
    |
 LL |         0 .. 3 => {}
    |         ^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
    = help: add #![feature(exclusive_range_pattern)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-existential-type.stderr b/src/test/ui/feature-gates/feature-gate-existential-type.stderr
index 6b8b850b5cc..efaf29c00da 100644
--- a/src/test/ui/feature-gates/feature-gate-existential-type.stderr
+++ b/src/test/ui/feature-gates/feature-gate-existential-type.stderr
@@ -1,17 +1,19 @@
-error[E0658]: existential types are unstable (see issue #34511)
+error[E0658]: existential types are unstable
   --> $DIR/feature-gate-existential-type.rs:3:1
    |
 LL | existential type Foo: std::fmt::Debug;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/34511
    = help: add #![feature(existential_type)] to the crate attributes to enable
 
-error[E0658]: existential types are unstable (see issue #34511)
+error[E0658]: existential types are unstable
   --> $DIR/feature-gate-existential-type.rs:11:5
    |
 LL |     existential type Baa: std::fmt::Debug;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/34511
    = help: add #![feature(existential_type)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-extern_types.stderr b/src/test/ui/feature-gates/feature-gate-extern_types.stderr
index 7035d85ec2a..18c0bae2c4b 100644
--- a/src/test/ui/feature-gates/feature-gate-extern_types.stderr
+++ b/src/test/ui/feature-gates/feature-gate-extern_types.stderr
@@ -1,9 +1,10 @@
-error[E0658]: extern types are experimental (see issue #43467)
+error[E0658]: extern types are experimental
   --> $DIR/feature-gate-extern_types.rs:2:5
    |
 LL |     type T;
    |     ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/43467
    = help: add #![feature(extern_types)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.stderr b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
index 16507bf596f..79e4f8e9b62 100644
--- a/src/test/ui/feature-gates/feature-gate-external_doc.stderr
+++ b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
@@ -1,9 +1,10 @@
-error[E0658]: #[doc(include = "...")] is experimental (see issue #44732)
+error[E0658]: #[doc(include = "...")] is experimental
   --> $DIR/feature-gate-external_doc.rs:1:1
    |
 LL | #[doc(include="asdf.md")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44732
    = help: add #![feature(external_doc)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs
index d3df6e5a852..2ea60029492 100644
--- a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs
+++ b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.rs
@@ -2,6 +2,6 @@
 #![crate_type = "lib"]
 
 extern {
-    #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
+    #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature
     pub fn foo();
 }
diff --git a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr
index f85ce8eeeac..c28d45df7cd 100644
--- a/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr
+++ b/src/test/ui/feature-gates/feature-gate-ffi_returns_twice.stderr
@@ -1,9 +1,10 @@
-error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature (see issue #58314)
+error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature
   --> $DIR/feature-gate-ffi_returns_twice.rs:5:5
    |
 LL |     #[ffi_returns_twice]
    |     ^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/58314
    = help: add #![feature(ffi_returns_twice)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-fundamental.stderr b/src/test/ui/feature-gates/feature-gate-fundamental.stderr
index 9faf2a88a6b..265b576bc79 100644
--- a/src/test/ui/feature-gates/feature-gate-fundamental.stderr
+++ b/src/test/ui/feature-gates/feature-gate-fundamental.stderr
@@ -1,9 +1,10 @@
-error[E0658]: the `#[fundamental]` attribute is an experimental feature (see issue #29635)
+error[E0658]: the `#[fundamental]` attribute is an experimental feature
   --> $DIR/feature-gate-fundamental.rs:1:1
    |
 LL | #[fundamental]
    | ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29635
    = help: add #![feature(fundamental)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr
index 554eeae8dec..b29fe7094f3 100644
--- a/src/test/ui/feature-gates/feature-gate-generators.stderr
+++ b/src/test/ui/feature-gates/feature-gate-generators.stderr
@@ -1,9 +1,10 @@
-error[E0658]: yield syntax is experimental (see issue #43122)
+error[E0658]: yield syntax is experimental
   --> $DIR/feature-gate-generators.rs:2:5
    |
 LL |     yield true;
    |     ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/43122
    = help: add #![feature(generators)] to the crate attributes to enable
 
 error[E0627]: yield statement outside of generator literal
diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
index 8a207c966cd..d37dd93983c 100644
--- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
+++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
@@ -1,57 +1,64 @@
-error[E0658]: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable
   --> $DIR/feature-gate-generic_associated_types.rs:4:5
    |
 LL |     type Pointer<T>: Deref<Target = T>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error[E0658]: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable
   --> $DIR/feature-gate-generic_associated_types.rs:6:5
    |
 LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error[E0658]: where clauses on associated types are unstable (see issue #44265)
+error[E0658]: where clauses on associated types are unstable
   --> $DIR/feature-gate-generic_associated_types.rs:6:5
    |
 LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error[E0658]: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable
   --> $DIR/feature-gate-generic_associated_types.rs:14:5
    |
 LL |     type Pointer<Usize> = Box<Usize>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error[E0658]: generic associated types are unstable (see issue #44265)
+error[E0658]: generic associated types are unstable
   --> $DIR/feature-gate-generic_associated_types.rs:16:5
    |
 LL |     type Pointer2<U32> = Box<U32>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error[E0658]: where clauses on associated types are unstable (see issue #44265)
+error[E0658]: where clauses on associated types are unstable
   --> $DIR/feature-gate-generic_associated_types.rs:21:5
    |
 LL |     type Assoc where Self: Sized;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error[E0658]: where clauses on associated types are unstable (see issue #44265)
+error[E0658]: where clauses on associated types are unstable
   --> $DIR/feature-gate-generic_associated_types.rs:26:5
    |
 LL |     type Assoc where Self: Sized = Foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44265
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
 error: aborting due to 7 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-global_asm.stderr b/src/test/ui/feature-gates/feature-gate-global_asm.stderr
index fb9b47bd49c..7d8abac3990 100644
--- a/src/test/ui/feature-gates/feature-gate-global_asm.stderr
+++ b/src/test/ui/feature-gates/feature-gate-global_asm.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `global_asm!` is not stable enough for use and is subject to change (see issue #35119)
+error[E0658]: `global_asm!` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-global_asm.rs:1:1
    |
 LL | global_asm!("");
    | ^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/35119
    = help: add #![feature(global_asm)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.stderr b/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
index 8230c1e3a38..1d5998641be 100644
--- a/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
+++ b/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
@@ -1,33 +1,37 @@
-error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+error[E0658]: use of unstable library feature 'is_sorted': new API
   --> $DIR/feature-gate-is_sorted.rs:3:33
    |
 LL |     assert!([1, 2, 2, 9].iter().is_sorted());
    |                                 ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53485
    = help: add #![feature(is_sorted)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+error[E0658]: use of unstable library feature 'is_sorted': new API
   --> $DIR/feature-gate-is_sorted.rs:5:39
    |
 LL |     assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
    |                                       ^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53485
    = help: add #![feature(is_sorted)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+error[E0658]: use of unstable library feature 'is_sorted': new API
   --> $DIR/feature-gate-is_sorted.rs:9:26
    |
 LL |     assert!([1, 2, 2, 9].is_sorted());
    |                          ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53485
    = help: add #![feature(is_sorted)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+error[E0658]: use of unstable library feature 'is_sorted': new API
   --> $DIR/feature-gate-is_sorted.rs:11:32
    |
 LL |     assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
    |                                ^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53485
    = help: add #![feature(is_sorted)] to the crate attributes to enable
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr
index b23db3c216d..40efc4dec4b 100644
--- a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr
+++ b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr
@@ -1,9 +1,10 @@
-error[E0658]: labels on blocks are unstable (see issue #48594)
+error[E0658]: labels on blocks are unstable
   --> $DIR/feature-gate-label_break_value.rs:2:5
    |
 LL |     'a: {
    |     ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/48594
    = help: add #![feature(label_break_value)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-link_args.stderr b/src/test/ui/feature-gates/feature-gate-link_args.stderr
index c43377fe630..5267b56253f 100644
--- a/src/test/ui/feature-gates/feature-gate-link_args.stderr
+++ b/src/test/ui/feature-gates/feature-gate-link_args.stderr
@@ -1,25 +1,28 @@
-error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead
   --> $DIR/feature-gate-link_args.rs:12:1
    |
 LL | #[link_args = "-l expected_use_case"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29596
    = help: add #![feature(link_args)] to the crate attributes to enable
 
-error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead
   --> $DIR/feature-gate-link_args.rs:16:1
    |
 LL | #[link_args = "-l unexected_use_on_non_extern_item"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29596
    = help: add #![feature(link_args)] to the crate attributes to enable
 
-error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+error[E0658]: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead
   --> $DIR/feature-gate-link_args.rs:9:1
    |
 LL | #![link_args = "-l unexpected_use_as_inner_attr_on_mod"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29596
    = help: add #![feature(link_args)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
index b5ac5fdb86a..1648245d0b8 100644
--- a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
+++ b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
@@ -1,9 +1,10 @@
-error[E0658]: is feature gated (see issue #37406)
+error[E0658]: is feature gated
   --> $DIR/feature-gate-link_cfg.rs:1:1
    |
 LL | #[link(name = "foo", cfg(foo))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/37406
    = help: add #![feature(link_cfg)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr b/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr
index a6cfc99ecd2..903696dc7c2 100644
--- a/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr
+++ b/src/test/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr
@@ -1,9 +1,10 @@
-error[E0658]: linking to LLVM intrinsics is experimental (see issue #29602)
+error[E0658]: linking to LLVM intrinsics is experimental
   --> $DIR/feature-gate-link_llvm_intrinsics.rs:3:5
    |
 LL |     fn sqrt(x: f32) -> f32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29602
    = help: add #![feature(link_llvm_intrinsics)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-linkage.stderr b/src/test/ui/feature-gates/feature-gate-linkage.stderr
index 1399a84faf6..872c695120a 100644
--- a/src/test/ui/feature-gates/feature-gate-linkage.stderr
+++ b/src/test/ui/feature-gates/feature-gate-linkage.stderr
@@ -1,9 +1,10 @@
-error[E0658]: the `linkage` attribute is experimental and not portable across platforms (see issue #29603)
+error[E0658]: the `linkage` attribute is experimental and not portable across platforms
   --> $DIR/feature-gate-linkage.rs:2:5
    |
 LL |     #[linkage = "extern_weak"] static foo: isize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29603
    = help: add #![feature(linkage)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
index 6a36d9fd5a8..9e814a20d6d 100644
--- a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
+++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr
@@ -1,9 +1,10 @@
-error[E0658]: lint reasons are experimental (see issue #54503)
+error[E0658]: lint reasons are experimental
   --> $DIR/feature-gate-lint-reasons.rs:1:28
    |
 LL | #![warn(nonstandard_style, reason = "the standard should be respected")]
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54503
    = help: add #![feature(lint_reasons)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax.stderr b/src/test/ui/feature-gates/feature-gate-log_syntax.stderr
index f29ee0b5a78..67bd48d3bed 100644
--- a/src/test/ui/feature-gates/feature-gate-log_syntax.stderr
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `log_syntax!` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-log_syntax.rs:2:5
    |
 LL |     log_syntax!()
    |     ^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add #![feature(log_syntax)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr b/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr
index c5a9b493728..ff0fa343c84 100644
--- a/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `log_syntax!` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-log_syntax2.rs:4:22
    |
 LL |     println!("{:?}", log_syntax!());
    |                      ^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add #![feature(log_syntax)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr b/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr
index affef0fe7d3..891ed81107f 100644
--- a/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr
+++ b/src/test/ui/feature-gates/feature-gate-macros_in_extern.stderr
@@ -1,25 +1,28 @@
-error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental
   --> $DIR/feature-gate-macros_in_extern.rs:19:5
    |
 LL |     returns_isize!(rust_get_test_int);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49476
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental
   --> $DIR/feature-gate-macros_in_extern.rs:21:5
    |
 LL |     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49476
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental
   --> $DIR/feature-gate-macros_in_extern.rs:23:5
    |
 LL |     emits_nothing!();
    |     ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49476
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-main.stderr b/src/test/ui/feature-gates/feature-gate-main.stderr
index 870cf1aa286..4d2d01b49f3 100644
--- a/src/test/ui/feature-gates/feature-gate-main.stderr
+++ b/src/test/ui/feature-gates/feature-gate-main.stderr
@@ -1,9 +1,10 @@
-error[E0658]: declaration of a nonstandard #[main] function may change over time, for now a top-level `fn main()` is required (see issue #29634)
+error[E0658]: declaration of a nonstandard #[main] function may change over time, for now a top-level `fn main()` is required
   --> $DIR/feature-gate-main.rs:2:1
    |
 LL | fn foo() {}
    | ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29634
    = help: add #![feature(main)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs
index 2b1b5bba6e1..ea06c775b1a 100644
--- a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs
+++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.rs
@@ -1,7 +1,7 @@
 use std::fmt::{Debug, Display};
 
 #[marker] trait ExplicitMarker {}
-//~^ ERROR marker traits is an experimental feature (see issue #29864)
+//~^ ERROR marker traits is an experimental feature
 
 impl<T: Display> ExplicitMarker for T {}
 impl<T: Debug> ExplicitMarker for T {}
diff --git a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr
index e916df18b66..3ed43b52e56 100644
--- a/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr
+++ b/src/test/ui/feature-gates/feature-gate-marker_trait_attr.stderr
@@ -1,9 +1,10 @@
-error[E0658]: marker traits is an experimental feature (see issue #29864)
+error[E0658]: marker traits is an experimental feature
   --> $DIR/feature-gate-marker_trait_attr.rs:3:1
    |
 LL | #[marker] trait ExplicitMarker {}
    | ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29864
    = help: add #![feature(marker_trait_attr)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-may-dangle.stderr b/src/test/ui/feature-gates/feature-gate-may-dangle.stderr
index 6d21147c9ee..f93be3ed4e7 100644
--- a/src/test/ui/feature-gates/feature-gate-may-dangle.stderr
+++ b/src/test/ui/feature-gates/feature-gate-may-dangle.stderr
@@ -1,9 +1,10 @@
-error[E0658]: may_dangle has unstable semantics and may be removed in the future (see issue #34761)
+error[E0658]: may_dangle has unstable semantics and may be removed in the future
   --> $DIR/feature-gate-may-dangle.rs:6:13
    |
 LL | unsafe impl<#[may_dangle] A> Drop for Pt<A> {
    |             ^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/34761
    = help: add #![feature(dropck_eyepatch)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr
index f6666b40f3e..a1c329df63a 100644
--- a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr
+++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr
@@ -16,20 +16,22 @@ error[E0379]: trait fns cannot be declared const
 LL |     const fn foo() -> u32 { 0 }
    |     ^^^^^ trait fns cannot be const
 
-error[E0658]: const fn is unstable (see issue #57563)
+error[E0658]: const fn is unstable
   --> $DIR/feature-gate-min_const_fn.rs:6:5
    |
 LL |     const fn foo() -> u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57563
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
-error[E0658]: const fn is unstable (see issue #57563)
+error[E0658]: const fn is unstable
   --> $DIR/feature-gate-min_const_fn.rs:8:5
    |
 LL |     const fn bar() -> u32 { 0 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57563
    = help: add #![feature(const_fn)] to the crate attributes to enable
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-naked_functions.stderr b/src/test/ui/feature-gates/feature-gate-naked_functions.stderr
index 2ff5ef101e0..0ba4d551a6d 100644
--- a/src/test/ui/feature-gates/feature-gate-naked_functions.stderr
+++ b/src/test/ui/feature-gates/feature-gate-naked_functions.stderr
@@ -1,17 +1,19 @@
-error[E0658]: the `#[naked]` attribute is an experimental feature (see issue #32408)
+error[E0658]: the `#[naked]` attribute is an experimental feature
   --> $DIR/feature-gate-naked_functions.rs:1:1
    |
 LL | #[naked]
    | ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32408
    = help: add #![feature(naked_functions)] to the crate attributes to enable
 
-error[E0658]: the `#[naked]` attribute is an experimental feature (see issue #32408)
+error[E0658]: the `#[naked]` attribute is an experimental feature
   --> $DIR/feature-gate-naked_functions.rs:5:1
    |
 LL | #[naked]
    | ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32408
    = help: add #![feature(naked_functions)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-never_type.stderr b/src/test/ui/feature-gates/feature-gate-never_type.stderr
index 13166db213e..45a6e6de18b 100644
--- a/src/test/ui/feature-gates/feature-gate-never_type.stderr
+++ b/src/test/ui/feature-gates/feature-gate-never_type.stderr
@@ -1,41 +1,46 @@
-error[E0658]: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:7:17
    |
 LL | type Ma = (u32, !, i32);
    |                 ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/35121
    = help: add #![feature(never_type)] to the crate attributes to enable
 
-error[E0658]: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:8:20
    |
 LL | type Meeshka = Vec<!>;
    |                    ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/35121
    = help: add #![feature(never_type)] to the crate attributes to enable
 
-error[E0658]: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:9:24
    |
 LL | type Mow = &'static fn(!) -> !;
    |                        ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/35121
    = help: add #![feature(never_type)] to the crate attributes to enable
 
-error[E0658]: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:10:27
    |
 LL | type Skwoz = &'static mut !;
    |                           ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/35121
    = help: add #![feature(never_type)] to the crate attributes to enable
 
-error[E0658]: The `!` type is experimental (see issue #35121)
+error[E0658]: The `!` type is experimental
   --> $DIR/feature-gate-never_type.rs:13:16
    |
 LL |     type Wub = !;
    |                ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/35121
    = help: add #![feature(never_type)] to the crate attributes to enable
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-no-debug.stderr b/src/test/ui/feature-gates/feature-gate-no-debug.stderr
index 1ee2ec3c881..a58a75b70c5 100644
--- a/src/test/ui/feature-gates/feature-gate-no-debug.stderr
+++ b/src/test/ui/feature-gates/feature-gate-no-debug.stderr
@@ -1,9 +1,10 @@
-error[E0658]: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand (see issue #29721)
+error[E0658]: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand
   --> $DIR/feature-gate-no-debug.rs:3:1
    |
 LL | #[no_debug]
    | ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29721
    = help: add #![feature(no_debug)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-no_core.stderr b/src/test/ui/feature-gates/feature-gate-no_core.stderr
index 279f2198a80..e2f0fd68a7c 100644
--- a/src/test/ui/feature-gates/feature-gate-no_core.stderr
+++ b/src/test/ui/feature-gates/feature-gate-no_core.stderr
@@ -1,9 +1,10 @@
-error[E0658]: no_core is experimental (see issue #29639)
+error[E0658]: no_core is experimental
   --> $DIR/feature-gate-no_core.rs:3:1
    |
 LL | #![no_core]
    | ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29639
    = help: add #![feature(no_core)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr
index 5e4c4649d01..1d78b87a3e0 100644
--- a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr
+++ b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr
@@ -1,105 +1,118 @@
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:1:22
    |
 LL | extern crate core as bäz;
    |                      ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:3:5
    |
 LL | use föö::bar;
    |     ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:5:5
    |
 LL | mod föö {
    |     ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:9:4
    |
 LL | fn bär(
    |    ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:10:5
    |
 LL |     bäz: isize
    |     ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:12:9
    |
 LL |     let _ö: isize;
    |         ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:15:10
    |
 LL |         (_ä, _) => {}
    |          ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:19:8
    |
 LL | struct Föö {
    |        ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:20:5
    |
 LL |     föö: isize
    |     ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:23:6
    |
 LL | enum Bär {
    |      ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:24:5
    |
 LL |     Bäz {
    |     ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:25:9
    |
 LL |         qüx: isize
    |         ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/feature-gate-non_ascii_idents.rs:30:8
    |
 LL |     fn qüx();
    |        ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
 error: aborting due to 13 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs
index b3e2e3d95f5..aca214d1935 100644
--- a/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs
+++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.rs
@@ -1,6 +1,6 @@
 //#![feature(non_exhaustive)]
 
-#[non_exhaustive] //~ERROR non exhaustive is an experimental feature (see issue #44109)
+#[non_exhaustive] //~ERROR non exhaustive is an experimental feature
 pub enum NonExhaustiveEnum {
     Unit,
     Tuple(u32),
diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr
index 524f77902f6..fdb1ffb0a9b 100644
--- a/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr
+++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive.stderr
@@ -1,9 +1,10 @@
-error[E0658]: non exhaustive is an experimental feature (see issue #44109)
+error[E0658]: non exhaustive is an experimental feature
   --> $DIR/feature-gate-non_exhaustive.rs:3:1
    |
 LL | #[non_exhaustive]
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44109
    = help: add #![feature(non_exhaustive)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr b/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr
index 32bfb20d5ed..044a9a398d6 100644
--- a/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr
+++ b/src/test/ui/feature-gates/feature-gate-on-unimplemented.stderr
@@ -1,9 +1,10 @@
-error[E0658]: the `#[rustc_on_unimplemented]` attribute is an experimental feature (see issue #29628)
+error[E0658]: the `#[rustc_on_unimplemented]` attribute is an experimental feature
   --> $DIR/feature-gate-on-unimplemented.rs:4:1
    |
 LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29628
    = help: add #![feature(on_unimplemented)] to the crate attributes to enable
 
 error: aborting due to previous error
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 e5d0a8681fb..baad1627d9c 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
@@ -1,17 +1,19 @@
-error[E0658]: auto traits are experimental and possibly buggy (see issue #13231)
+error[E0658]: auto traits are experimental and possibly buggy
   --> $DIR/feature-gate-optin-builtin-traits.rs:6:1
    |
 LL | auto trait AutoDummyTrait {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/13231
    = 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 (see issue #13231)
+error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
   --> $DIR/feature-gate-optin-builtin-traits.rs:9:1
    |
 LL | impl !AutoDummyTrait for DummyStruct {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/13231
    = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-plugin.stderr b/src/test/ui/feature-gates/feature-gate-plugin.stderr
index 0feebb6f0e0..5ac41201888 100644
--- a/src/test/ui/feature-gates/feature-gate-plugin.stderr
+++ b/src/test/ui/feature-gates/feature-gate-plugin.stderr
@@ -1,9 +1,10 @@
-error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
+error[E0658]: compiler plugins are experimental and possibly buggy
   --> $DIR/feature-gate-plugin.rs:3:1
    |
 LL | #![plugin(foo)]
    | ^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29597
    = help: add #![feature(plugin)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr b/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr
index 6464d4087be..941a6c49d15 100644
--- a/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr
+++ b/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr
@@ -1,9 +1,10 @@
-error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
+error[E0658]: compiler plugins are experimental and possibly buggy
   --> $DIR/feature-gate-plugin_registrar.rs:6:1
    |
 LL | pub fn registrar() {}
    | ^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29597
    = help: add #![feature(plugin_registrar)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
index c47ce70eaae..056bfdd85d1 100644
--- a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
@@ -1,17 +1,19 @@
-error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy
   --> $DIR/feature-gate-repr-simd.rs:1:1
    |
 LL | #[repr(simd)]
    | ^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(repr_simd)] to the crate attributes to enable
 
-error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy
   --> $DIR/feature-gate-repr-simd.rs:5:1
    |
 LL | #[repr(simd)]
    | ^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(repr_simd)] to the crate attributes to enable
 
 warning[E0566]: conflicting representation hints
diff --git a/src/test/ui/feature-gates/feature-gate-repr128.stderr b/src/test/ui/feature-gates/feature-gate-repr128.stderr
index a2fd6593599..30433447a2b 100644
--- a/src/test/ui/feature-gates/feature-gate-repr128.stderr
+++ b/src/test/ui/feature-gates/feature-gate-repr128.stderr
@@ -1,4 +1,4 @@
-error[E0658]: repr with 128-bit type is unstable (see issue #35118)
+error[E0658]: repr with 128-bit type is unstable
   --> $DIR/feature-gate-repr128.rs:2:1
    |
 LL | / enum A {
@@ -6,6 +6,7 @@ LL | |     A(u64)
 LL | | }
    | |_^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/35118
    = help: add #![feature(repr128)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-repr_align_enum.rs b/src/test/ui/feature-gates/feature-gate-repr_align_enum.rs
index f8e68a9de01..8b68caa6f5b 100644
--- a/src/test/ui/feature-gates/feature-gate-repr_align_enum.rs
+++ b/src/test/ui/feature-gates/feature-gate-repr_align_enum.rs
@@ -1,7 +1,7 @@
 #[repr(align(16))]
 struct Foo(u64);
 
-#[repr(align(8))] //~ ERROR `#[repr(align(x))]` on enums is experimental (see issue #57996)
+#[repr(align(8))] //~ ERROR `#[repr(align(x))]` on enums is experimental
 enum Bar {
     Foo { foo: Foo },
     Baz,
diff --git a/src/test/ui/feature-gates/feature-gate-repr_align_enum.stderr b/src/test/ui/feature-gates/feature-gate-repr_align_enum.stderr
index ae4066ceb80..36924f4c167 100644
--- a/src/test/ui/feature-gates/feature-gate-repr_align_enum.stderr
+++ b/src/test/ui/feature-gates/feature-gate-repr_align_enum.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `#[repr(align(x))]` on enums is experimental (see issue #57996)
+error[E0658]: `#[repr(align(x))]` on enums is experimental
   --> $DIR/feature-gate-repr_align_enum.rs:4:1
    |
 LL | #[repr(align(8))]
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/57996
    = help: add #![feature(repr_align_enum)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
index 73cd28fe749..882feb87f42 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
@@ -1,17 +1,19 @@
-error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
   --> $DIR/feature-gate-rustc-attrs-1.rs:5:1
    |
 LL | #[rustc_variance]
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
-error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
   --> $DIR/feature-gate-rustc-attrs-1.rs:6:1
    |
 LL | #[rustc_error]
    | ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
index 40e6d6d9256..3c823c8d4e2 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
@@ -1,9 +1,10 @@
-error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
   --> $DIR/feature-gate-rustc-attrs.rs:3:3
    |
 LL | #[rustc_foo]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-simd.stderr b/src/test/ui/feature-gates/feature-gate-simd.stderr
index b37f138fbb5..1686a8530fe 100644
--- a/src/test/ui/feature-gates/feature-gate-simd.stderr
+++ b/src/test/ui/feature-gates/feature-gate-simd.stderr
@@ -1,9 +1,10 @@
-error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy
   --> $DIR/feature-gate-simd.rs:3:1
    |
 LL | #[repr(simd)]
    | ^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(repr_simd)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
index 58eb57516eb..fe3c1e0afdd 100644
--- a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
+++ b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
@@ -1,49 +1,55 @@
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized
   --> $DIR/feature-gate-slice-patterns.rs:6:16
    |
 LL |         [1, 2, ..] => {}
    |                ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized
   --> $DIR/feature-gate-slice-patterns.rs:7:13
    |
 LL |         [1, .., 5] => {}
    |             ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized
   --> $DIR/feature-gate-slice-patterns.rs:8:10
    |
 LL |         [.., 4, 5] => {}
    |          ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized
   --> $DIR/feature-gate-slice-patterns.rs:13:11
    |
 LL |         [ xs.., 4, 5 ] => {}
    |           ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized
   --> $DIR/feature-gate-slice-patterns.rs:14:14
    |
 LL |         [ 1, xs.., 5 ] => {}
    |              ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized
   --> $DIR/feature-gate-slice-patterns.rs:15:17
    |
 LL |         [ 1, 2, xs.. ] => {}
    |                 ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
 error: aborting due to 6 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-start.stderr b/src/test/ui/feature-gates/feature-gate-start.stderr
index d39e5f35555..fbe64ea130d 100644
--- a/src/test/ui/feature-gates/feature-gate-start.stderr
+++ b/src/test/ui/feature-gates/feature-gate-start.stderr
@@ -1,9 +1,10 @@
-error[E0658]: a #[start] function is an experimental feature whose signature may change over time (see issue #29633)
+error[E0658]: a #[start] function is an experimental feature whose signature may change over time
   --> $DIR/feature-gate-start.rs:2:1
    |
 LL | fn foo(_: isize, _: *const *const u8) -> isize { 0 }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29633
    = help: add #![feature(start)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
index 2e80275f3f7..7d5ed74abd1 100644
--- a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
@@ -1,9 +1,10 @@
-error[E0658]: kind="static-nobundle" is feature gated (see issue #37403)
+error[E0658]: kind="static-nobundle" is feature gated
   --> $DIR/feature-gate-static-nobundle.rs:1:1
    |
 LL | #[link(name="foo", kind="static-nobundle")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/37403
    = help: add #![feature(static_nobundle)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.rs b/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.rs
index 3e5b6260d74..f213e8933bf 100644
--- a/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.rs
+++ b/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.rs
@@ -1,4 +1,4 @@
 const X: i32 = #[allow(dead_code)] 8;
-//~^ ERROR attributes on expressions are experimental. (see issue #15701)
+//~^ ERROR attributes on expressions are experimental
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr b/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr
index 4318edd9230..bbf0f66ca54 100644
--- a/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr
+++ b/src/test/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr
@@ -1,9 +1,10 @@
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/feature-gate-stmt_expr_attributes.rs:1:16
    |
 LL | const X: i32 = #[allow(dead_code)] 8;
    |                ^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-thread_local.stderr b/src/test/ui/feature-gates/feature-gate-thread_local.stderr
index 38064a6bc94..95334d23d51 100644
--- a/src/test/ui/feature-gates/feature-gate-thread_local.stderr
+++ b/src/test/ui/feature-gates/feature-gate-thread_local.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `#[thread_local]` is an experimental feature, and does not currently handle destructors. (see issue #29594)
+error[E0658]: `#[thread_local]` is an experimental feature, and does not currently handle destructors
   --> $DIR/feature-gate-thread_local.rs:8:1
    |
 LL | #[thread_local]
    | ^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29594
    = help: add #![feature(thread_local)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-trace_macros.stderr b/src/test/ui/feature-gates/feature-gate-trace_macros.stderr
index ee22bd25091..bcce31d873b 100644
--- a/src/test/ui/feature-gates/feature-gate-trace_macros.stderr
+++ b/src/test/ui/feature-gates/feature-gate-trace_macros.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-trace_macros.rs:2:5
    |
 LL |     trace_macros!(true);
    |     ^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add #![feature(trace_macros)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-trait-alias.stderr b/src/test/ui/feature-gates/feature-gate-trait-alias.stderr
index bb833c4e732..1a9718a6ce4 100644
--- a/src/test/ui/feature-gates/feature-gate-trait-alias.stderr
+++ b/src/test/ui/feature-gates/feature-gate-trait-alias.stderr
@@ -1,9 +1,10 @@
-error[E0658]: trait aliases are experimental (see issue #41517)
+error[E0658]: trait aliases are experimental
   --> $DIR/feature-gate-trait-alias.rs:1:1
    |
 LL | trait Foo = Default;
    | ^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/41517
    = help: add #![feature(trait_alias)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-try_blocks.stderr b/src/test/ui/feature-gates/feature-gate-try_blocks.stderr
index 74ad0e70c96..cb72b067333 100644
--- a/src/test/ui/feature-gates/feature-gate-try_blocks.stderr
+++ b/src/test/ui/feature-gates/feature-gate-try_blocks.stderr
@@ -1,4 +1,4 @@
-error[E0658]: `try` expression is experimental (see issue #31436)
+error[E0658]: `try` expression is experimental
   --> $DIR/feature-gate-try_blocks.rs:4:33
    |
 LL |       let try_result: Option<_> = try {
@@ -8,6 +8,7 @@ LL | |         x
 LL | |     };
    | |_____^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/31436
    = help: add #![feature(try_blocks)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-try_reserve.stderr b/src/test/ui/feature-gates/feature-gate-try_reserve.stderr
index 61a3249c2ab..f1d82d94a52 100644
--- a/src/test/ui/feature-gates/feature-gate-try_reserve.stderr
+++ b/src/test/ui/feature-gates/feature-gate-try_reserve.stderr
@@ -1,9 +1,10 @@
-error[E0658]: use of unstable library feature 'try_reserve': new API (see issue #48043)
+error[E0658]: use of unstable library feature 'try_reserve': new API
   --> $DIR/feature-gate-try_reserve.rs:3:7
    |
 LL |     v.try_reserve(10);
    |       ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/48043
    = help: add #![feature(try_reserve)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-type_ascription.stderr b/src/test/ui/feature-gates/feature-gate-type_ascription.stderr
index 13dbb602967..0e4e25882c8 100644
--- a/src/test/ui/feature-gates/feature-gate-type_ascription.stderr
+++ b/src/test/ui/feature-gates/feature-gate-type_ascription.stderr
@@ -1,9 +1,10 @@
-error[E0658]: type ascription is experimental (see issue #23416)
+error[E0658]: type ascription is experimental
   --> $DIR/feature-gate-type_ascription.rs:4:13
    |
 LL |     let a = 10: u8;
    |             ^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/23416
    = help: add #![feature(type_ascription)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
index 865b87e7dd5..5fbaf8dd0ba 100644
--- a/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
@@ -1,41 +1,46 @@
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:11:5
    |
 LL |     extern "rust-call" fn call(self, args: ()) -> () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:17:5
    |
 LL |     extern "rust-call" fn call_once(self, args: ()) -> () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:5
    |
 LL |     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:29:5
    |
 LL |     extern "rust-call" fn call_once(&self, args: ()) -> () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:6
    |
 LL | impl Fn<()> for Foo {
    |      ^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
 error[E0229]: associated type bindings are not allowed here
@@ -44,20 +49,22 @@ error[E0229]: associated type bindings are not allowed here
 LL | impl FnOnce() for Foo1 {
    |            ^^ associated type not allowed here
 
-error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:21:6
    |
 LL | impl FnMut<()> for Bar {
    |      ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:27:6
    |
 LL | impl FnOnce<()> for Baz {
    |      ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
 error: aborting due to 8 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr
index 519f6528323..164368cd8ef 100644
--- a/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr
@@ -1,25 +1,28 @@
-error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits'
   --> $DIR/feature-gate-unboxed-closures-method-calls.rs:4:7
    |
 LL |     f.call(());
    |       ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits'
   --> $DIR/feature-gate-unboxed-closures-method-calls.rs:5:7
    |
 LL |     f.call_mut(());
    |       ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits'
   --> $DIR/feature-gate-unboxed-closures-method-calls.rs:6:7
    |
 LL |     f.call_once(());
    |       ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr
index a49a8b4cdb2..ff2629fe421 100644
--- a/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr
@@ -1,25 +1,28 @@
-error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits'
   --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:4:5
    |
 LL |     Fn::call(&f, ());
    |     ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits'
   --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:5:5
    |
 LL |     FnMut::call_mut(&mut f, ());
    |     ^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'fn_traits' (see issue #29625)
+error[E0658]: use of unstable library feature 'fn_traits'
   --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:6:5
    |
 LL |     FnOnce::call_once(f, ());
    |     ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(fn_traits)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures.rs b/src/test/ui/feature-gates/feature-gate-unboxed-closures.rs
index c3f5c99dcb4..b8d3aa4a141 100644
--- a/src/test/ui/feature-gates/feature-gate-unboxed-closures.rs
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures.rs
@@ -9,7 +9,7 @@ impl FnOnce<(u32, u32)> for Test {
     extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
         a + b
     }
-    //~^^^ ERROR rust-call ABI is subject to change (see issue #29625)
+    //~^^^ ERROR rust-call ABI is subject to change
 }
 
 fn main() {
diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr
index e7b1fc589bb..872a593f3e4 100644
--- a/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr
@@ -1,4 +1,4 @@
-error[E0658]: rust-call ABI is subject to change (see issue #29625)
+error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-unboxed-closures.rs:9:5
    |
 LL | /     extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
@@ -6,14 +6,16 @@ LL | |         a + b
 LL | |     }
    | |_____^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
   --> $DIR/feature-gate-unboxed-closures.rs:5:6
    |
 LL | impl FnOnce<(u32, u32)> for Test {
    |      ^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-underscore_const_names.stderr b/src/test/ui/feature-gates/feature-gate-underscore_const_names.stderr
index ef93bb97ab4..8d925424d8c 100644
--- a/src/test/ui/feature-gates/feature-gate-underscore_const_names.stderr
+++ b/src/test/ui/feature-gates/feature-gate-underscore_const_names.stderr
@@ -1,4 +1,4 @@
-error[E0658]: naming constants with `_` is unstable (see issue #54912)
+error[E0658]: naming constants with `_` is unstable
   --> $DIR/feature-gate-underscore_const_names.rs:6:1
    |
 LL | / const _ : () = {
@@ -10,6 +10,7 @@ LL | |     ()
 LL | | };
    | |__^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54912
    = help: add #![feature(underscore_const_names)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr b/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr
index c2f5df48fed..669e87ceada 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr
@@ -1,9 +1,10 @@
-error[E0658]: unsized tuple coercion is not stable enough for use and is subject to change (see issue #42877)
+error[E0658]: unsized tuple coercion is not stable enough for use and is subject to change
   --> $DIR/feature-gate-unsized_tuple_coercion.rs:2:24
    |
 LL |     let _ : &(Send,) = &((),);
    |                        ^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/42877
    = help: add #![feature(unsized_tuple_coercion)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr
index 6faa0528dc7..5df3a1d699f 100644
--- a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr
+++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr
@@ -1,4 +1,4 @@
-error[E0658]: unions with non-`Copy` fields are unstable (see issue #32836)
+error[E0658]: unions with non-`Copy` fields are unstable
   --> $DIR/feature-gate-untagged_unions.rs:9:1
    |
 LL | / union U3 {
@@ -6,9 +6,10 @@ LL | |     a: String,
 LL | | }
    | |_^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32836
    = help: add #![feature(untagged_unions)] to the crate attributes to enable
 
-error[E0658]: unions with non-`Copy` fields are unstable (see issue #32836)
+error[E0658]: unions with non-`Copy` fields are unstable
   --> $DIR/feature-gate-untagged_unions.rs:13:1
    |
 LL | / union U4<T> {
@@ -16,9 +17,10 @@ LL | |     a: T,
 LL | | }
    | |_^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32836
    = help: add #![feature(untagged_unions)] to the crate attributes to enable
 
-error[E0658]: unions with `Drop` implementations are unstable (see issue #32836)
+error[E0658]: unions with `Drop` implementations are unstable
   --> $DIR/feature-gate-untagged_unions.rs:17:1
    |
 LL | / union U5 {
@@ -26,6 +28,7 @@ LL | |     a: u8,
 LL | | }
    | |_^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32836
    = help: add #![feature(untagged_unions)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr
index 149ce9e4f82..bb55013d638 100644
--- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr
@@ -1,9 +1,10 @@
-error[E0658]: #[unwind] is experimental (see issue #58760)
+error[E0658]: #[unwind] is experimental
   --> $DIR/feature-gate-unwind-attributes.rs:11:5
    |
 LL |     #[unwind(allowed)]
    |     ^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/58760
    = help: add #![feature(unwind_attributes)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr b/src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr
index 83b3017a4cd..0931145a6e2 100644
--- a/src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr
+++ b/src/test/ui/feature-gates/underscore_const_names_feature_gate.stderr
@@ -1,9 +1,10 @@
-error[E0658]: naming constants with `_` is unstable (see issue #54912)
+error[E0658]: naming constants with `_` is unstable
   --> $DIR/underscore_const_names_feature_gate.rs:1:1
    |
 LL | const _: () = ();
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54912
    = help: add #![feature(underscore_const_names)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/fn/fn-compare-mismatch.stderr b/src/test/ui/fn/fn-compare-mismatch.stderr
index 07b93d9aae7..74fb00f8ac3 100644
--- a/src/test/ui/fn/fn-compare-mismatch.stderr
+++ b/src/test/ui/fn/fn-compare-mismatch.stderr
@@ -7,6 +7,14 @@ LL |     let x = f == g;
    |             fn() {main::f}
    |
    = note: an implementation of `std::cmp::PartialEq` might be missing for `fn() {main::f}`
+help: you might have forgotten to call this function
+   |
+LL |     let x = f() == g;
+   |             ^^^
+help: you might have forgotten to call this function
+   |
+LL |     let x = f == g();
+   |                  ^^^
 
 error[E0308]: mismatched types
   --> $DIR/fn-compare-mismatch.rs:4:18
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr
index a26f0cbec72..70d197994f3 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr
+++ b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr
@@ -1,4 +1,4 @@
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/local-modularized-tricky-fail-2.rs:20:32
    |
 LL | exported!();
@@ -7,9 +7,10 @@ LL | exported!();
 LL |                 () => ( struct Б; )
    |                                ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/local-modularized-tricky-fail-2.rs:36:24
    |
 LL |     panic!();
@@ -18,9 +19,10 @@ LL |     panic!();
 LL |         () => ( struct Г; )
    |                        ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/local-modularized-tricky-fail-2.rs:46:24
    |
 LL | include!();
@@ -29,6 +31,7 @@ LL | include!();
 LL |         () => ( struct Д; )
    |                        ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/inference/inference_unstable_forced.stderr b/src/test/ui/inference/inference_unstable_forced.stderr
index 067bf44bda8..83e27aaf2f8 100644
--- a/src/test/ui/inference/inference_unstable_forced.stderr
+++ b/src/test/ui/inference/inference_unstable_forced.stderr
@@ -1,9 +1,10 @@
-error[E0658]: use of unstable library feature 'ipu_flatten' (see issue #99999)
+error[E0658]: use of unstable library feature 'ipu_flatten'
   --> $DIR/inference_unstable_forced.rs:11:20
    |
 LL |     assert_eq!('x'.ipu_flatten(), 0);
    |                    ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/99999
    = help: add #![feature(ipu_flatten)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/issue-59756.fixed b/src/test/ui/issue-59756.fixed
new file mode 100644
index 00000000000..7b55d0f17e6
--- /dev/null
+++ b/src/test/ui/issue-59756.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+struct A;
+struct B;
+
+fn foo() -> Result<A, B> {
+    Ok(A)
+}
+
+fn bar() -> Result<A, B> {
+    foo()
+    //~^ ERROR try expression alternatives have incompatible types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-59756.rs b/src/test/ui/issue-59756.rs
new file mode 100644
index 00000000000..cccae396b72
--- /dev/null
+++ b/src/test/ui/issue-59756.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+struct A;
+struct B;
+
+fn foo() -> Result<A, B> {
+    Ok(A)
+}
+
+fn bar() -> Result<A, B> {
+    foo()?
+    //~^ ERROR try expression alternatives have incompatible types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-59756.stderr b/src/test/ui/issue-59756.stderr
new file mode 100644
index 00000000000..d46232874fd
--- /dev/null
+++ b/src/test/ui/issue-59756.stderr
@@ -0,0 +1,15 @@
+error[E0308]: try expression alternatives have incompatible types
+  --> $DIR/issue-59756.rs:13:5
+   |
+LL |     foo()?
+   |     ^^^^^-
+   |     |    |
+   |     |    help: try removing this `?`
+   |     expected enum `std::result::Result`, found struct `A`
+   |
+   = note: expected type `std::result::Result<A, B>`
+              found type `A`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issue-59764.rs b/src/test/ui/issue-59764.rs
new file mode 100644
index 00000000000..09dee8c2732
--- /dev/null
+++ b/src/test/ui/issue-59764.rs
@@ -0,0 +1,136 @@
+// aux-build:issue-59764.rs
+// compile-flags:--extern issue_59764
+// edition:2018
+
+#![allow(warnings)]
+
+// This tests the suggestion to import macros from the root of a crate. This aims to capture
+// the case where a user attempts to import a macro from the definition location instead of the
+// root of the crate and the macro is annotated with `#![macro_export]`.
+
+// Edge cases..
+
+mod multiple_imports_same_line_at_end {
+    use issue_59764::foo::{baz, makro};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod multiple_imports_multiline_at_end_trailing_comma {
+    use issue_59764::foo::{
+        baz,
+        makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+    };
+}
+
+mod multiple_imports_multiline_at_end {
+    use issue_59764::foo::{
+        baz,
+        makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+    };
+}
+
+mod multiple_imports_same_line_in_middle {
+    use issue_59764::foo::{baz, makro, foobar};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod multiple_imports_multiline_in_middle_trailing_comma {
+    use issue_59764::foo::{
+        baz,
+        makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+        foobar,
+    };
+}
+
+mod multiple_imports_multiline_in_middle {
+    use issue_59764::foo::{
+        baz,
+        makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+        foobar
+    };
+}
+
+mod nested_imports {
+    use issue_59764::{foobaz, foo::makro};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod nested_multiple_imports {
+    use issue_59764::{foobaz, foo::{baz, makro}};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod nested_multiline_multiple_imports_trailing_comma {
+    use issue_59764::{
+        foobaz,
+        foo::{
+            baz,
+            makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+        },
+    };
+}
+
+mod nested_multiline_multiple_imports {
+    use issue_59764::{
+        foobaz,
+        foo::{
+            baz,
+            makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+        }
+    };
+}
+
+mod doubly_nested_multiple_imports {
+    use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod doubly_multiline_nested_multiple_imports {
+    use issue_59764::{
+        foobaz,
+        foo::{
+            baz,
+            makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+            barbaz::{
+                barfoo,
+            }
+        }
+    };
+}
+
+mod renamed_import {
+    use issue_59764::foo::makro as baz;
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod renamed_multiple_imports {
+    use issue_59764::foo::{baz, makro as foobar};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod lots_of_whitespace {
+    use
+        issue_59764::{
+
+            foobaz,
+
+
+            foo::{baz,
+
+                makro as foobar} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+
+        };
+}
+
+// Simple case..
+
+use issue_59764::foo::makro;
+//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+
+makro!(bar);
+//~^ ERROR cannot determine resolution for the macro `makro`
+
+fn main() {
+    bar();
+    //~^ ERROR cannot find function `bar` in this scope [E0425]
+}
diff --git a/src/test/ui/issue-59764.stderr b/src/test/ui/issue-59764.stderr
new file mode 100644
index 00000000000..924e69f5f97
--- /dev/null
+++ b/src/test/ui/issue-59764.stderr
@@ -0,0 +1,241 @@
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:14:33
+   |
+LL |     use issue_59764::foo::{baz, makro};
+   |                                 ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{baz}};
+   |                      ^^^^^^^^^       --^^
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:21:9
+   |
+LL |         makro,
+   |         ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{
+LL |         baz,
+LL |
+LL |     }};
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:28:9
+   |
+LL |         makro
+   |         ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{
+LL |         baz,
+LL |
+LL |     }};
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:33:33
+   |
+LL |     use issue_59764::foo::{baz, makro, foobar};
+   |                                 ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{baz, foobar}};
+   |                      ^^^^^^^^^         --      ^^
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:40:9
+   |
+LL |         makro,
+   |         ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{
+LL |         baz,
+LL |
+LL |         foobar,
+LL |     }};
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:48:9
+   |
+LL |         makro,
+   |         ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{
+LL |         baz,
+LL |
+LL |         foobar
+LL |     }};
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:54:31
+   |
+LL |     use issue_59764::{foobaz, foo::makro};
+   |                               ^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foobaz};
+   |                      ^^^^^^^      --
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:59:42
+   |
+LL |     use issue_59764::{foobaz, foo::{baz, makro}};
+   |                                          ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foobaz, foo::{baz}};
+   |                      ^^^^^^^                 --
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:68:13
+   |
+LL |             makro,
+   |             ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, 
+LL |         foobaz,
+LL |         foo::{
+LL |             baz,
+LL |
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:78:13
+   |
+LL |             makro
+   |             ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, 
+LL |         foobaz,
+LL |         foo::{
+LL |             baz,
+LL |
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:84:42
+   |
+LL |     use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
+   |                                          ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}};
+   |                      ^^^^^^^                   --
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:93:13
+   |
+LL |             makro,
+   |             ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, 
+LL |         foobaz,
+LL |         foo::{
+LL |             baz,
+LL |
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:102:9
+   |
+LL |     use issue_59764::foo::makro as baz;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::makro as baz;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:107:33
+   |
+LL |     use issue_59764::foo::{baz, makro as foobar};
+   |                                 ^^^^^^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro as foobar, foo::{baz}};
+   |                      ^^^^^^^^^^^^^^^^^^^       --^^
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:120:17
+   |
+LL |                 makro as foobar}
+   |                 ^^^^^^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |         issue_59764::{makro as foobar, 
+LL | 
+LL |             foobaz,
+LL | 
+LL | 
+LL |             foo::{baz}
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:127:5
+   |
+LL | use issue_59764::foo::makro;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL | use issue_59764::makro;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: cannot determine resolution for the macro `makro`
+  --> $DIR/issue-59764.rs:130:1
+   |
+LL | makro!(bar);
+   | ^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error[E0425]: cannot find function `bar` in this scope
+  --> $DIR/issue-59764.rs:134:5
+   |
+LL |     bar();
+   |     ^^^ not found in this scope
+
+error: aborting due to 18 previous errors
+
+Some errors occurred: E0425, E0432.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-17458.stderr b/src/test/ui/issues/issue-17458.stderr
index a1a8ed9f0cd..69b6ab71e50 100644
--- a/src/test/ui/issues/issue-17458.stderr
+++ b/src/test/ui/issues/issue-17458.stderr
@@ -1,9 +1,10 @@
-error[E0658]: casting pointers to integers in statics is unstable (see issue #51910)
+error[E0658]: casting pointers to integers in statics is unstable
   --> $DIR/issue-17458.rs:1:28
    |
 LL | static X: usize = unsafe { 0 as *const usize as usize };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51910
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/issues/issue-18294.stderr
index a7d0392f7f0..d10242434b0 100644
--- a/src/test/ui/issues/issue-18294.stderr
+++ b/src/test/ui/issues/issue-18294.stderr
@@ -1,9 +1,10 @@
-error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+error[E0658]: casting pointers to integers in constants is unstable
   --> $DIR/issue-18294.rs:3:31
    |
 LL |     const Y: usize = unsafe { &X as *const u32 as usize };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51910
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-20313.stderr b/src/test/ui/issues/issue-20313.stderr
index 87e2e899d3f..405e717c358 100644
--- a/src/test/ui/issues/issue-20313.stderr
+++ b/src/test/ui/issues/issue-20313.stderr
@@ -1,9 +1,10 @@
-error[E0658]: linking to LLVM intrinsics is experimental (see issue #29602)
+error[E0658]: linking to LLVM intrinsics is experimental
   --> $DIR/issue-20313.rs:3:5
    |
 LL |     fn sqrt(x: f32) -> f32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29602
    = help: add #![feature(link_llvm_intrinsics)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-22933-2.rs b/src/test/ui/issues/issue-22933-2.rs
index 68d9ef2cfa8..98a354b1bd0 100644
--- a/src/test/ui/issues/issue-22933-2.rs
+++ b/src/test/ui/issues/issue-22933-2.rs
@@ -2,7 +2,7 @@ enum Delicious {
     Pie      = 0x1,
     Apple    = 0x2,
     ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
-    //~^ ERROR no variant named `PIE` found for type `Delicious`
+    //~^ ERROR no variant or associated item named `PIE` found for type `Delicious`
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr
index 23b1474bde7..72038ea20a3 100644
--- a/src/test/ui/issues/issue-22933-2.stderr
+++ b/src/test/ui/issues/issue-22933-2.stderr
@@ -1,11 +1,11 @@
-error[E0599]: no variant named `PIE` found for type `Delicious` in the current scope
+error[E0599]: no variant or associated item named `PIE` found for type `Delicious` in the current scope
   --> $DIR/issue-22933-2.rs:4:55
    |
 LL | enum Delicious {
-   | -------------- variant `PIE` not found here
+   | -------------- variant or associated item `PIE` not found here
 ...
 LL |     ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
-   |                                                       ^^^ variant not found in `Delicious`
+   |                                                       ^^^ variant or associated item not found in `Delicious`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr
index a972b36b804..0567dcbec6d 100644
--- a/src/test/ui/issues/issue-23024.stderr
+++ b/src/test/ui/issues/issue-23024.stderr
@@ -1,9 +1,10 @@
-error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
   --> $DIR/issue-23024.rs:9:35
    |
 LL |     println!("{:?}",(vfnfer[0] as Fn)(3));
    |                                   ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
 error[E0107]: wrong number of type arguments: expected 1, found 0
diff --git a/src/test/ui/issues/issue-23173.rs b/src/test/ui/issues/issue-23173.rs
index 2922ebddf4c..7c15598448d 100644
--- a/src/test/ui/issues/issue-23173.rs
+++ b/src/test/ui/issues/issue-23173.rs
@@ -6,12 +6,8 @@ struct Struct {
 fn use_token(token: &Token) { unimplemented!() }
 
 fn main() {
-    use_token(&Token::Homura);
-    //~^ ERROR no variant named `Homura`
-    Struct::method();
-    //~^ ERROR no function or associated item named `method` found for type
-    Struct::method;
-    //~^ ERROR no function or associated item named `method` found for type
-    Struct::Assoc;
-    //~^ ERROR no associated item named `Assoc` found for type `Struct` in
+    use_token(&Token::Homura); //~ ERROR no variant or associated item named `Homura`
+    Struct::method(); //~ ERROR no function or associated item named `method` found for type
+    Struct::method; //~ ERROR no function or associated item named `method` found for type
+    Struct::Assoc; //~ ERROR no associated item named `Assoc` found for type `Struct` in
 }
diff --git a/src/test/ui/issues/issue-23173.stderr b/src/test/ui/issues/issue-23173.stderr
index 75dba883608..699e41156fa 100644
--- a/src/test/ui/issues/issue-23173.stderr
+++ b/src/test/ui/issues/issue-23173.stderr
@@ -1,14 +1,14 @@
-error[E0599]: no variant named `Homura` found for type `Token` in the current scope
+error[E0599]: no variant or associated item named `Homura` found for type `Token` in the current scope
   --> $DIR/issue-23173.rs:9:23
    |
 LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ }
-   | ---------- variant `Homura` not found here
+   | ---------- variant or associated item `Homura` not found here
 ...
 LL |     use_token(&Token::Homura);
-   |                       ^^^^^^ variant not found in `Token`
+   |                       ^^^^^^ variant or associated item not found in `Token`
 
 error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
-  --> $DIR/issue-23173.rs:11:13
+  --> $DIR/issue-23173.rs:10:13
    |
 LL | struct Struct {
    | ------------- function or associated item `method` not found for this
@@ -17,7 +17,7 @@ LL |     Struct::method();
    |             ^^^^^^ function or associated item not found in `Struct`
 
 error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
-  --> $DIR/issue-23173.rs:13:13
+  --> $DIR/issue-23173.rs:11:13
    |
 LL | struct Struct {
    | ------------- function or associated item `method` not found for this
@@ -26,7 +26,7 @@ LL |     Struct::method;
    |             ^^^^^^ function or associated item not found in `Struct`
 
 error[E0599]: no associated item named `Assoc` found for type `Struct` in the current scope
-  --> $DIR/issue-23173.rs:15:13
+  --> $DIR/issue-23173.rs:12:13
    |
 LL | struct Struct {
    | ------------- associated item `Assoc` not found for this
diff --git a/src/test/ui/issues/issue-23217.rs b/src/test/ui/issues/issue-23217.rs
index 11426df6177..157f20d22d8 100644
--- a/src/test/ui/issues/issue-23217.rs
+++ b/src/test/ui/issues/issue-23217.rs
@@ -1,6 +1,5 @@
 pub enum SomeEnum {
-    B = SomeEnum::A,
-    //~^ ERROR no variant named `A` found for type `SomeEnum`
+    B = SomeEnum::A, //~ ERROR no variant or associated item named `A` found for type `SomeEnum`
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr
index 2a982422cab..97100ed3753 100644
--- a/src/test/ui/issues/issue-23217.stderr
+++ b/src/test/ui/issues/issue-23217.stderr
@@ -1,13 +1,13 @@
-error[E0599]: no variant named `A` found for type `SomeEnum` in the current scope
+error[E0599]: no variant or associated item named `A` found for type `SomeEnum` in the current scope
   --> $DIR/issue-23217.rs:2:19
    |
 LL | pub enum SomeEnum {
-   | ----------------- variant `A` not found here
+   | ----------------- variant or associated item `A` not found here
 LL |     B = SomeEnum::A,
    |                   ^
    |                   |
-   |                   variant not found in `SomeEnum`
-   |                   help: did you mean: `B`
+   |                   variant or associated item not found in `SomeEnum`
+   |                   help: there is a variant with a similar name: `B`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr
index 43effc0b3b9..bbdb13a9500 100644
--- a/src/test/ui/issues/issue-23302-1.stderr
+++ b/src/test/ui/issues/issue-23302-1.stderr
@@ -5,7 +5,7 @@ LL |     A = X::A as isize,
    |         ^^^^^^^^^^^^^
    |
    = note: ...which again requires processing `X::A::{{constant}}#0`, completing the cycle
-note: cycle used when const-evaluating `X::A::{{constant}}#0`
+note: cycle used when processing `X::A::{{constant}}#0`
   --> $DIR/issue-23302-1.rs:4:9
    |
 LL |     A = X::A as isize,
diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr
index 707d4fa7ed3..03afd82211a 100644
--- a/src/test/ui/issues/issue-23302-2.stderr
+++ b/src/test/ui/issues/issue-23302-2.stderr
@@ -5,7 +5,7 @@ LL |     A = Y::B as isize,
    |         ^^^^^^^^^^^^^
    |
    = note: ...which again requires processing `Y::A::{{constant}}#0`, completing the cycle
-note: cycle used when const-evaluating `Y::A::{{constant}}#0`
+note: cycle used when processing `Y::A::{{constant}}#0`
   --> $DIR/issue-23302-2.rs:4:9
    |
 LL |     A = Y::B as isize,
diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr
index dc547f7c32c..a800f787e38 100644
--- a/src/test/ui/issues/issue-25826.stderr
+++ b/src/test/ui/issues/issue-25826.stderr
@@ -1,9 +1,10 @@
-error[E0658]: comparing raw pointers inside constant (see issue #53020)
+error[E0658]: comparing raw pointers inside constant
   --> $DIR/issue-25826.rs:3:30
    |
 LL |     const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53020
    = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
 
 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 fcd98b111cf..f3a8019e232 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: did you mean: `bitxor`
+   |                         help: there is a method with a similar name: `bitxor`
 
 error[E0191]: the value of the associated type `Output` (from the 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: did you mean: `bitxor`
+   |                     help: there is a method with a similar name: `bitxor`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-28971.rs b/src/test/ui/issues/issue-28971.rs
index 3f0d2fafb04..6493565d216 100644
--- a/src/test/ui/issues/issue-28971.rs
+++ b/src/test/ui/issues/issue-28971.rs
@@ -1,5 +1,3 @@
-// This should not cause an ICE
-
 enum Foo {
     Bar(u8)
 }
@@ -7,7 +5,7 @@ fn main(){
     foo(|| {
         match Foo::Bar(1) {
             Foo::Baz(..) => (),
-            //~^ ERROR no variant named `Baz` found for type `Foo`
+            //~^ ERROR no variant or associated item named `Baz` found for type `Foo`
             _ => (),
         }
     });
diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr
index 4781f7abe81..7411896443d 100644
--- a/src/test/ui/issues/issue-28971.stderr
+++ b/src/test/ui/issues/issue-28971.stderr
@@ -1,14 +1,14 @@
-error[E0599]: no variant named `Baz` found for type `Foo` in the current scope
-  --> $DIR/issue-28971.rs:9:18
+error[E0599]: no variant or associated item named `Baz` found for type `Foo` in the current scope
+  --> $DIR/issue-28971.rs:7:18
    |
 LL | enum Foo {
-   | -------- variant `Baz` not found here
+   | -------- variant or associated item `Baz` not found here
 ...
 LL |             Foo::Baz(..) => (),
    |                  ^^^
    |                  |
-   |                  variant not found in `Foo`
-   |                  help: did you mean: `Bar`
+   |                  variant or associated item not found in `Foo`
+   |                  help: there is a variant with a similar name: `Bar`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-30560.rs b/src/test/ui/issues/issue-30560.rs
index c848a1c51ca..d8d4ca608f1 100644
--- a/src/test/ui/issues/issue-30560.rs
+++ b/src/test/ui/issues/issue-30560.rs
@@ -1,10 +1,7 @@
 type Alias = ();
-use Alias::*;
-//~^ ERROR unresolved import `Alias` [E0432]
-//~| not a module `Alias`
-use std::io::Result::*;
-//~^ ERROR unresolved import `std::io::Result` [E0432]
-//~| not a module `Result`
+use Alias::*; //~ ERROR unresolved import `Alias` [E0432]
+
+use std::io::Result::*; //~ ERROR unresolved import `std::io::Result` [E0432]
 
 trait T {}
 use T::*; //~ ERROR items in traits are not importable
diff --git a/src/test/ui/issues/issue-30560.stderr b/src/test/ui/issues/issue-30560.stderr
index 5225f190f9e..b74134aaccc 100644
--- a/src/test/ui/issues/issue-30560.stderr
+++ b/src/test/ui/issues/issue-30560.stderr
@@ -1,5 +1,5 @@
 error: items in traits are not importable.
-  --> $DIR/issue-30560.rs:10:5
+  --> $DIR/issue-30560.rs:7:5
    |
 LL | use T::*;
    |     ^^^^
@@ -8,13 +8,13 @@ error[E0432]: unresolved import `Alias`
   --> $DIR/issue-30560.rs:2:5
    |
 LL | use Alias::*;
-   |     ^^^^^ not a module `Alias`
+   |     ^^^^^ `Alias` is a type alias, not a module
 
 error[E0432]: unresolved import `std::io::Result`
-  --> $DIR/issue-30560.rs:5:14
+  --> $DIR/issue-30560.rs:4:14
    |
 LL | use std::io::Result::*;
-   |              ^^^^^^ not a module `Result`
+   |              ^^^^^^ `Result` is a type alias, not a module
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr
index 7b3c8e75beb..3ab934f6ca5 100644
--- a/src/test/ui/issues/issue-32655.stderr
+++ b/src/test/ui/issues/issue-32655.stderr
@@ -1,4 +1,4 @@
-error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/issue-32655.rs:6:11
    |
 LL |         #[derive_Clone]
@@ -7,14 +7,16 @@ LL |         #[derive_Clone]
 LL | foo!();
    | ------- in this macro invocation
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/issue-32655.rs:18:7
    |
 LL |     #[derive_Clone]
    |       ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-32829.stderr b/src/test/ui/issues/issue-32829.stderr
index 037f5416fa5..157c8c85af0 100644
--- a/src/test/ui/issues/issue-32829.stderr
+++ b/src/test/ui/issues/issue-32829.stderr
@@ -1,9 +1,10 @@
-error[E0658]: panicking in statics is unstable (see issue #51999)
+error[E0658]: panicking in statics is unstable
   --> $DIR/issue-32829.rs:1:22
    |
 LL | static S : u64 = { { panic!("foo"); 0 } };
    |                      ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51999
    = help: add #![feature(const_panic)] to the crate attributes to enable
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
diff --git a/src/test/ui/issues/issue-34209.rs b/src/test/ui/issues/issue-34209.rs
index 50095be7740..fc2c3679e13 100644
--- a/src/test/ui/issues/issue-34209.rs
+++ b/src/test/ui/issues/issue-34209.rs
@@ -4,8 +4,7 @@ enum S {
 
 fn bug(l: S) {
     match l {
-        S::B { } => { },
-        //~^ ERROR no variant `B` on enum `S`
+        S::B {} => {}, //~ ERROR no variant `B` in enum `S`
     }
 }
 
diff --git a/src/test/ui/issues/issue-34209.stderr b/src/test/ui/issues/issue-34209.stderr
index 79aba89c148..194bb2bfab8 100644
--- a/src/test/ui/issues/issue-34209.stderr
+++ b/src/test/ui/issues/issue-34209.stderr
@@ -1,8 +1,11 @@
-error: no variant `B` on enum `S`
-  --> $DIR/issue-34209.rs:7:9
+error: no variant `B` in enum `S`
+  --> $DIR/issue-34209.rs:7:12
    |
-LL |         S::B { } => { },
-   |         ^^^^ help: did you mean: `S::A`
+LL | enum S {
+   | ------ variant `B` not found here
+...
+LL |         S::B {} => {},
+   |            ^ help: there is a variant with a similar name: `A`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-36163.stderr b/src/test/ui/issues/issue-36163.stderr
index 4c3f726180d..50e8cf6e88c 100644
--- a/src/test/ui/issues/issue-36163.stderr
+++ b/src/test/ui/issues/issue-36163.stderr
@@ -10,7 +10,7 @@ note: ...which requires processing `A`...
 LL | const A: isize = Foo::B as isize;
    |                  ^^^^^^^^^^^^^^^
    = note: ...which again requires processing `Foo::B::{{constant}}#0`, completing the cycle
-note: cycle used when const-evaluating `Foo::B::{{constant}}#0`
+note: cycle used when processing `Foo::B::{{constant}}#0`
   --> $DIR/issue-36163.rs:4:9
    |
 LL |     B = A,
diff --git a/src/test/ui/issues/issue-37887.stderr b/src/test/ui/issues/issue-37887.stderr
index 24543a5efaf..9cac105bab5 100644
--- a/src/test/ui/issues/issue-37887.stderr
+++ b/src/test/ui/issues/issue-37887.stderr
@@ -4,12 +4,13 @@ error[E0432]: unresolved import `libc`
 LL |     use libc::*;
    |         ^^^^ maybe a missing `extern crate libc;`?
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/issue-37887.rs:2:5
    |
 LL |     extern crate libc;
    |     ^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27812
    = help: add #![feature(rustc_private)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr
index b41d9130f12..29e10f1bf41 100644
--- a/src/test/ui/issues/issue-49074.stderr
+++ b/src/test/ui/issues/issue-49074.stderr
@@ -1,9 +1,10 @@
-error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/issue-49074.rs:3:3
    |
 LL | #[marco_use] // typo
    |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use`
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: cannot find macro `bar!` in this scope
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr
index 96d6814b0fe..333036127ea 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `deref_err` found for type `std::result::Result<_,
   --> $DIR/result-deref-err.rs:4:28
    |
 LL |     let _result = &Err(41).deref_err();
-   |                            ^^^^^^^^^ help: did you mean: `deref_ok`
+   |                            ^^^^^^^^^ help: there is a method with a similar name: `deref_ok`
    |
    = note: the method `deref_err` exists but the following trait bounds were not satisfied:
            `{integer} : std::ops::Deref`
diff --git a/src/test/ui/issues/issue-51279.stderr b/src/test/ui/issues/issue-51279.stderr
index bc33eacac99..9dd4a9f2381 100644
--- a/src/test/ui/issues/issue-51279.stderr
+++ b/src/test/ui/issues/issue-51279.stderr
@@ -46,12 +46,13 @@ error: #[cfg] cannot be applied on a generic parameter
 LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
    |                       ^^^^^^^^^^^^
 
-error[E0658]: The attribute `ignored` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `ignored` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/issue-51279.rs:23:8
    |
 LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
    |        ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to 9 previous errors
diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
index 8f36a3f9618..bf453571479 100644
--- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
+++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
@@ -2,7 +2,10 @@ error[E0308]: try expression alternatives have incompatible types
   --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
    |
 LL |     missing_discourses()?
-   |     ^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found isize
+   |     ^^^^^^^^^^^^^^^^^^^^-
+   |     |                   |
+   |     |                   help: try removing this `?`
+   |     expected enum `std::result::Result`, found isize
    |
    = note: expected type `std::result::Result<isize, ()>`
               found type `isize`
diff --git a/src/test/ui/issues/issue-51714.rs b/src/test/ui/issues/issue-51714.rs
index 4885e4a2db7..0dc588d75c6 100644
--- a/src/test/ui/issues/issue-51714.rs
+++ b/src/test/ui/issues/issue-51714.rs
@@ -10,5 +10,4 @@ fn main() {
 
     [(); return while let Some(n) = Some(0) {}];
     //~^ ERROR return statement outside of function body
-    //~^^ WARN irrefutable while-let pattern
 }
diff --git a/src/test/ui/issues/issue-51714.stderr b/src/test/ui/issues/issue-51714.stderr
index df11f6b7f5a..023d9013ab4 100644
--- a/src/test/ui/issues/issue-51714.stderr
+++ b/src/test/ui/issues/issue-51714.stderr
@@ -22,14 +22,6 @@ error[E0572]: return statement outside of function body
 LL |     [(); return while let Some(n) = Some(0) {}];
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: irrefutable while-let pattern
-  --> $DIR/issue-51714.rs:11:17
-   |
-LL |     [(); return while let Some(n) = Some(0) {}];
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: #[warn(irrefutable_let_patterns)] on by default
-
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0572`.
diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr b/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr
index 60e0792954a..f57697e5892 100644
--- a/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr
+++ b/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr
@@ -1,9 +1,10 @@
-error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
+error[E0658]: casting pointers to integers in constants is unstable
   --> $DIR/issue-52023-array-size-pointer-cast.rs:2:17
    |
 LL |     let _ = [0; (&0 as *const i32) as usize];
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51910
    = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
 
 error[E0080]: it is undefined behavior to use this value
diff --git a/src/test/ui/issues/issue-54974.rs b/src/test/ui/issues/issue-54974.rs
new file mode 100644
index 00000000000..b2624ec92a1
--- /dev/null
+++ b/src/test/ui/issues/issue-54974.rs
@@ -0,0 +1,16 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro, futures_api)]
+
+use std::sync::Arc;
+
+trait SomeTrait: Send + Sync + 'static {
+    fn do_something(&self);
+}
+
+async fn my_task(obj: Arc<SomeTrait>) {
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-55324.rs b/src/test/ui/issues/issue-55324.rs
new file mode 100644
index 00000000000..6160fbabd96
--- /dev/null
+++ b/src/test/ui/issues/issue-55324.rs
@@ -0,0 +1,14 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro, futures_api)]
+
+use std::future::Future;
+
+#[allow(unused)]
+async fn foo<F: Future<Output = i32>>(x: &i32, future: F) -> i32 {
+    let y = await!(future);
+    *x + y
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-58885.rs b/src/test/ui/issues/issue-58885.rs
new file mode 100644
index 00000000000..559899194fb
--- /dev/null
+++ b/src/test/ui/issues/issue-58885.rs
@@ -0,0 +1,21 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro, futures_api)]
+
+struct Xyz {
+    a: u64,
+}
+
+trait Foo {}
+
+impl Xyz {
+    async fn do_sth<'a>(
+        &'a self, foo: &'a dyn Foo
+    ) -> bool
+    {
+        true
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-59001.rs b/src/test/ui/issues/issue-59001.rs
new file mode 100644
index 00000000000..a310653fbce
--- /dev/null
+++ b/src/test/ui/issues/issue-59001.rs
@@ -0,0 +1,17 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro, futures_api)]
+
+use std::future::Future;
+
+#[allow(unused)]
+async fn enter<'a, F, R>(mut callback: F)
+where
+    F: FnMut(&'a mut i32) -> R,
+    R: Future<Output = ()> + 'a,
+{
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-59488.rs b/src/test/ui/issues/issue-59488.rs
new file mode 100644
index 00000000000..27cf16a821f
--- /dev/null
+++ b/src/test/ui/issues/issue-59488.rs
@@ -0,0 +1,26 @@
+// ignore-tidy-linelength
+
+fn foo() -> i32 {
+    42
+}
+
+fn bar(a: i64) -> i64 {
+    43
+}
+
+fn main() {
+    foo > 12;
+    //~^ ERROR 12:9: 12:10: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369]
+    //~| ERROR 12:11: 12:13: mismatched types [E0308]
+
+    bar > 13;
+    //~^ ERROR 16:9: 16:10: binary operation `>` cannot be applied to type `fn(i64) -> i64 {bar}` [E0369]
+    //~| ERROR 16:11: 16:13: mismatched types [E0308]
+
+    foo > foo;
+    //~^ ERROR 20:9: 20:10: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369]
+
+    foo > bar;
+    //~^ ERROR 23:9: 23:10: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369]
+    //~| ERROR 23:11: 23:14: mismatched types [E0308]
+}
diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr
new file mode 100644
index 00000000000..b49f5e35f42
--- /dev/null
+++ b/src/test/ui/issues/issue-59488.stderr
@@ -0,0 +1,81 @@
+error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}`
+  --> $DIR/issue-59488.rs:12:9
+   |
+LL |     foo > 12;
+   |     --- ^ -- {integer}
+   |     |
+   |     fn() -> i32 {foo}
+   |     help: you might have forgotten to call this function: `foo()`
+   |
+   = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() -> i32 {foo}`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-59488.rs:12:11
+   |
+LL |     foo > 12;
+   |           ^^ expected fn item, found integer
+   |
+   = note: expected type `fn() -> i32 {foo}`
+              found type `i32`
+
+error[E0369]: binary operation `>` cannot be applied to type `fn(i64) -> i64 {bar}`
+  --> $DIR/issue-59488.rs:16:9
+   |
+LL |     bar > 13;
+   |     --- ^ -- {integer}
+   |     |
+   |     fn(i64) -> i64 {bar}
+   |     help: you might have forgotten to call this function: `bar( /* arguments */ )`
+   |
+   = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn(i64) -> i64 {bar}`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-59488.rs:16:11
+   |
+LL |     bar > 13;
+   |           ^^ expected fn item, found integer
+   |
+   = note: expected type `fn(i64) -> i64 {bar}`
+              found type `i64`
+
+error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}`
+  --> $DIR/issue-59488.rs:20:9
+   |
+LL |     foo > foo;
+   |     --- ^ --- fn() -> i32 {foo}
+   |     |
+   |     fn() -> i32 {foo}
+   |
+   = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() -> i32 {foo}`
+help: you might have forgotten to call this function
+   |
+LL |     foo() > foo;
+   |     ^^^^^
+help: you might have forgotten to call this function
+   |
+LL |     foo > foo();
+   |           ^^^^^
+
+error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}`
+  --> $DIR/issue-59488.rs:23:9
+   |
+LL |     foo > bar;
+   |     --- ^ --- fn(i64) -> i64 {bar}
+   |     |
+   |     fn() -> i32 {foo}
+   |
+   = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() -> i32 {foo}`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-59488.rs:23:11
+   |
+LL |     foo > bar;
+   |           ^^^ expected fn item, found a different fn item
+   |
+   = note: expected type `fn() -> i32 {foo}`
+              found type `fn(i64) -> i64 {bar}`
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0308, E0369.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/linkage4.stderr b/src/test/ui/linkage4.stderr
index fd86671204e..f2aab164bd7 100644
--- a/src/test/ui/linkage4.stderr
+++ b/src/test/ui/linkage4.stderr
@@ -1,9 +1,10 @@
-error[E0658]: the `linkage` attribute is experimental and not portable across platforms (see issue #29603)
+error[E0658]: the `linkage` attribute is experimental and not portable across platforms
   --> $DIR/linkage4.rs:1:1
    |
 LL | #[linkage = "external"]
    | ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29603
    = help: add #![feature(linkage)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/macros/macro-multiple-matcher-bindings.rs b/src/test/ui/macros/macro-multiple-matcher-bindings.rs
index 23d566780c8..7d39dc0a52f 100644
--- a/src/test/ui/macros/macro-multiple-matcher-bindings.rs
+++ b/src/test/ui/macros/macro-multiple-matcher-bindings.rs
@@ -1,16 +1,11 @@
 // Test that duplicate matcher binding names are caught at declaration time, rather than at macro
 // invocation time.
-//
-// FIXME(mark-i-m): Update this when it becomes a hard error.
-
-// compile-pass
 
 #![allow(unused_macros)]
-#![warn(duplicate_matcher_binding_name)]
 
 macro_rules! foo1 {
-    ($a:ident, $a:ident) => {}; //~WARNING duplicate matcher binding
-    ($a:ident, $a:path) => {};  //~WARNING duplicate matcher binding
+    ($a:ident, $a:ident) => {}; //~ERROR duplicate matcher binding
+    ($a:ident, $a:path) => {};  //~ERROR duplicate matcher binding
 }
 
 macro_rules! foo2 {
@@ -19,8 +14,8 @@ macro_rules! foo2 {
 }
 
 macro_rules! foo3 {
-    ($a:ident, $($a:ident),*) => {}; //~WARNING duplicate matcher binding
-    ($($a:ident)+ # $($($a:path),+);*) => {}; //~WARNING duplicate matcher binding
+    ($a:ident, $($a:ident),*) => {}; //~ERROR duplicate matcher binding
+    ($($a:ident)+ # $($($a:path),+);*) => {}; //~ERROR duplicate matcher binding
 }
 
 fn main() {}
diff --git a/src/test/ui/macros/macro-multiple-matcher-bindings.stderr b/src/test/ui/macros/macro-multiple-matcher-bindings.stderr
index f7970dbd2eb..65362388d7d 100644
--- a/src/test/ui/macros/macro-multiple-matcher-bindings.stderr
+++ b/src/test/ui/macros/macro-multiple-matcher-bindings.stderr
@@ -1,41 +1,50 @@
-warning: duplicate matcher binding
-  --> $DIR/macro-multiple-matcher-bindings.rs:12:6
+error: duplicate matcher binding
+  --> $DIR/macro-multiple-matcher-bindings.rs:7:16
    |
 LL |     ($a:ident, $a:ident) => {};
-   |      ^^^^^^^^  ^^^^^^^^
+   |                ^^^^^^^^
    |
-note: lint level defined here
-  --> $DIR/macro-multiple-matcher-bindings.rs:9:9
+note: previous declaration was here
+  --> $DIR/macro-multiple-matcher-bindings.rs:7:6
    |
-LL | #![warn(duplicate_matcher_binding_name)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57593 <https://github.com/rust-lang/rust/issues/57593>
+LL |     ($a:ident, $a:ident) => {};
+   |      ^^^^^^^^
 
-warning: duplicate matcher binding
-  --> $DIR/macro-multiple-matcher-bindings.rs:13:6
+error: duplicate matcher binding
+  --> $DIR/macro-multiple-matcher-bindings.rs:8:16
    |
 LL |     ($a:ident, $a:path) => {};
-   |      ^^^^^^^^  ^^^^^^^
+   |                ^^^^^^^
+   |
+note: previous declaration was here
+  --> $DIR/macro-multiple-matcher-bindings.rs:8:6
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57593 <https://github.com/rust-lang/rust/issues/57593>
+LL |     ($a:ident, $a:path) => {};
+   |      ^^^^^^^^
 
-warning: duplicate matcher binding
-  --> $DIR/macro-multiple-matcher-bindings.rs:22:6
+error: duplicate matcher binding
+  --> $DIR/macro-multiple-matcher-bindings.rs:17:18
    |
 LL |     ($a:ident, $($a:ident),*) => {};
-   |      ^^^^^^^^    ^^^^^^^^
+   |                  ^^^^^^^^
+   |
+note: previous declaration was here
+  --> $DIR/macro-multiple-matcher-bindings.rs:17:6
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57593 <https://github.com/rust-lang/rust/issues/57593>
+LL |     ($a:ident, $($a:ident),*) => {};
+   |      ^^^^^^^^
 
-warning: duplicate matcher binding
-  --> $DIR/macro-multiple-matcher-bindings.rs:23:8
+error: duplicate matcher binding
+  --> $DIR/macro-multiple-matcher-bindings.rs:18:25
    |
 LL |     ($($a:ident)+ # $($($a:path),+);*) => {};
-   |        ^^^^^^^^         ^^^^^^^
+   |                         ^^^^^^^
+   |
+note: previous declaration was here
+  --> $DIR/macro-multiple-matcher-bindings.rs:18:8
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57593 <https://github.com/rust-lang/rust/issues/57593>
+LL |     ($($a:ident)+ # $($($a:path),+);*) => {};
+   |        ^^^^^^^^
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/macros/macro-path-prelude-fail-1.rs b/src/test/ui/macros/macro-path-prelude-fail-1.rs
index 354c2bf8571..cd695ca916e 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-1.rs
+++ b/src/test/ui/macros/macro-path-prelude-fail-1.rs
@@ -2,8 +2,8 @@
 
 mod m {
     fn check() {
-        Vec::clone!(); //~ ERROR failed to resolve: not a module `Vec`
-        u8::clone!(); //~ ERROR failed to resolve: not a module `u8`
+        Vec::clone!(); //~ ERROR failed to resolve: `Vec` is a struct, not a module
+        u8::clone!(); //~ ERROR failed to resolve: `u8` is a builtin type, not a module
     }
 }
 
diff --git a/src/test/ui/macros/macro-path-prelude-fail-1.stderr b/src/test/ui/macros/macro-path-prelude-fail-1.stderr
index 551d2fe8ce0..b68e89f07f6 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-1.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-1.stderr
@@ -1,14 +1,14 @@
-error[E0433]: failed to resolve: not a module `Vec`
+error[E0433]: failed to resolve: `Vec` is a struct, not a module
   --> $DIR/macro-path-prelude-fail-1.rs:5:9
    |
 LL |         Vec::clone!();
-   |         ^^^ not a module `Vec`
+   |         ^^^ `Vec` is a struct, not a module
 
-error[E0433]: failed to resolve: not a module `u8`
+error[E0433]: failed to resolve: `u8` is a builtin type, not a module
   --> $DIR/macro-path-prelude-fail-1.rs:6:9
    |
 LL |         u8::clone!();
-   |         ^^ not a module `u8`
+   |         ^^ `u8` is a builtin type, not a module
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/macros/macro-reexport-removed.stderr b/src/test/ui/macros/macro-reexport-removed.stderr
index 302952909be..600d5d4cc9a 100644
--- a/src/test/ui/macros/macro-reexport-removed.stderr
+++ b/src/test/ui/macros/macro-reexport-removed.stderr
@@ -10,12 +10,13 @@ note: subsumed by `pub use`
 LL | #![feature(macro_reexport)]
    |            ^^^^^^^^^^^^^^
 
-error[E0658]: The attribute `macro_reexport` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `macro_reexport` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/macro-reexport-removed.rs:5:3
    |
 LL | #[macro_reexport(macro_one)]
    |   ^^^^^^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_export`
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/macros/macros-in-extern.stderr b/src/test/ui/macros/macros-in-extern.stderr
index 1d0c28752bc..ec7c37402d4 100644
--- a/src/test/ui/macros/macros-in-extern.stderr
+++ b/src/test/ui/macros/macros-in-extern.stderr
@@ -1,25 +1,28 @@
-error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental
   --> $DIR/macros-in-extern.rs:26:5
    |
 LL |     returns_isize!(rust_get_test_int);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49476
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental
   --> $DIR/macros-in-extern.rs:28:5
    |
 LL |     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49476
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental
   --> $DIR/macros-in-extern.rs:30:5
    |
 LL |     emits_nothing!();
    |     ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49476
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/missing/missing-alloc_error_handler.rs b/src/test/ui/missing/missing-alloc_error_handler.rs
index 1a9e8688e8a..ae0c067bb5f 100644
--- a/src/test/ui/missing/missing-alloc_error_handler.rs
+++ b/src/test/ui/missing/missing-alloc_error_handler.rs
@@ -3,7 +3,7 @@
 
 #![no_std]
 #![crate_type = "staticlib"]
-#![feature(panic_handler, alloc_error_handler, alloc)]
+#![feature(panic_handler, alloc_error_handler)]
 
 #[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! {
diff --git a/src/test/ui/missing/missing-allocator.rs b/src/test/ui/missing/missing-allocator.rs
index dbb10d1e7b9..6d867e2e8b4 100644
--- a/src/test/ui/missing/missing-allocator.rs
+++ b/src/test/ui/missing/missing-allocator.rs
@@ -3,7 +3,7 @@
 
 #![no_std]
 #![crate_type = "staticlib"]
-#![feature(panic_handler, alloc_error_handler, alloc)]
+#![feature(panic_handler, alloc_error_handler)]
 
 #[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! {
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 46de13dbbbd..20041389b3c 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: DefId(0/1:9 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32))
+               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32)),
            ]
 
 error: lifetime may not live long enough
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
index d47b326f48e..b08ec953931 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: DefId(0/1:9 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32))
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)),
            ]
 
 note: No external requirements
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
index dec4a6b811f..7178b22bb5f 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
@@ -8,7 +8,7 @@ LL |             let mut closure1 = || p = &y;
                i16,
                extern "rust-call" fn(()),
                &'_#1r mut &'_#2r i32,
-               &'_#3r i32
+               &'_#3r i32,
            ]
    = note: number of external vids: 4
    = note: where '_#3r: '_#2r
@@ -27,7 +27,7 @@ LL | |         };
                i16,
                extern "rust-call" fn(()),
                &'_#1r mut &'_#2r i32,
-               &'_#3r i32
+               &'_#3r i32,
            ]
    = note: number of external vids: 4
    = note: where '_#3r: '_#2r
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
index 55ede6ed4aa..d129f945f25 100644
--- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
@@ -8,7 +8,7 @@ LL |         let mut closure = || p = &y;
                i16,
                extern "rust-call" fn(()),
                &'_#1r mut &'_#2r i32,
-               &'_#3r i32
+               &'_#3r i32,
            ]
    = note: number of external vids: 4
    = note: where '_#3r: '_#2r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 7eb4d96fc5f..4db1f040770 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -10,7 +10,7 @@ LL | |         },
    |
    = note: defining type: DefId(0/1:20 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)),
            ]
    = note: late-bound region is '_#4r
    = note: late-bound region is '_#5r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index a1a1024bccd..7dedae715be 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)),
            ]
    = note: late-bound region is '_#3r
    = note: late-bound region is '_#4r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index ad2a5cae62e..b2d7fd8df6d 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -10,7 +10,7 @@ LL | |     })
    |
    = note: defining type: DefId(0/1:12 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]::{{closure}}[0]) with closure substs [
                i32,
-               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>)),
            ]
 
 error[E0521]: borrowed data escapes outside of closure
@@ -48,7 +48,7 @@ LL | |     })
    |
    = note: defining type: DefId(0/1:13 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]::{{closure}}[0]) with closure substs [
                i32,
-               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>)),
            ]
    = note: number of external vids: 2
    = note: where '_#1r: '_#0r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index f5167c2197b..e30e2dfee63 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -12,7 +12,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) u32>))
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) u32>)),
            ]
    = note: late-bound region is '_#2r
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index b4e1b0d2247..ec608590a71 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -12,7 +12,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)),
            ]
    = note: late-bound region is '_#3r
    = note: late-bound region is '_#4r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 6ab2104a51c..223c29f5969 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)),
            ]
    = note: late-bound region is '_#3r
    = note: late-bound region is '_#4r
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index 79f0df9a688..d618b4d06a1 100644
--- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -10,7 +10,7 @@ LL | |         },
    |
    = note: defining type: DefId(0/1:16 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)),
            ]
    = note: late-bound region is '_#3r
    = note: number of external vids: 4
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index f8b6bfa003b..07fb4d0d5e3 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)),
            ]
    = note: late-bound region is '_#2r
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 7e7429405fa..a0744c27db7 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)),
            ]
    = note: late-bound region is '_#3r
    = note: late-bound region is '_#4r
diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
index c2bbd813814..282246f8166 100644
--- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr
@@ -15,7 +15,7 @@ LL | |     });
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((T,))
+               extern "rust-call" fn((T,)),
            ]
    = note: number of external vids: 2
    = note: where T: '_#1r
@@ -34,7 +34,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:6 ~ propagate_from_trait_match[317d]::supply[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index d5bfa3f9894..c5645413c77 100644
--- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -6,7 +6,7 @@ LL |     expect_sig(|a, b| b); // ought to return `a`
    |
    = note: defining type: DefId(0/1:9 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32,
            ]
 
 error: lifetime may not live long enough
diff --git a/src/test/ui/nll/extra-unused-mut.rs b/src/test/ui/nll/extra-unused-mut.rs
index d5f0b0ddf18..6d0d6e16a67 100644
--- a/src/test/ui/nll/extra-unused-mut.rs
+++ b/src/test/ui/nll/extra-unused-mut.rs
@@ -1,6 +1,6 @@
 // extra unused mut lint tests for #51918
 
-// run-pass
+// compile-pass
 
 #![feature(generators, nll)]
 #![deny(unused_mut)]
@@ -53,11 +53,14 @@ fn if_guard(x: Result<i32, i32>) {
     }
 }
 
-fn main() {
-    ref_argument(0);
-    mutable_upvar();
-    generator_mutable_upvar();
-    ref_closure_argument();
-    parse_dot_or_call_expr_with(Vec::new());
-    if_guard(Ok(0));
+// #59620
+fn nested_closures() {
+    let mut i = 0;
+    [].iter().for_each(|_: &i32| {
+        [].iter().for_each(move |_: &i32| {
+            i += 1;
+        });
+    });
 }
+
+fn main() {}
diff --git a/src/test/ui/nll/get_default.nll.stderr b/src/test/ui/nll/get_default.nll.stderr
deleted file mode 100644
index 0f71452805d..00000000000
--- a/src/test/ui/nll/get_default.nll.stderr
+++ /dev/null
@@ -1,84 +0,0 @@
-error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Ast)
-  --> $DIR/get_default.rs:23:17
-   |
-LL |         match map.get() {
-   |               --- immutable borrow occurs here
-...
-LL |                 map.set(String::new()); // Ideally, this would not error.
-   |                 ^^^ mutable borrow occurs here
-...
-LL | }
-   | - immutable borrow ends here
-
-error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Ast)
-  --> $DIR/get_default.rs:35:17
-   |
-LL |         match map.get() {
-   |               --- immutable borrow occurs here
-LL |             Some(v) => {
-LL |                 map.set(String::new()); // Both AST and MIR error here
-   |                 ^^^ mutable borrow occurs here
-...
-LL | }
-   | - immutable borrow ends here
-
-error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Ast)
-  --> $DIR/get_default.rs:41:17
-   |
-LL |         match map.get() {
-   |               --- immutable borrow occurs here
-...
-LL |                 map.set(String::new()); // Ideally, just AST would error here
-   |                 ^^^ mutable borrow occurs here
-...
-LL | }
-   | - immutable borrow ends here
-
-error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
-  --> $DIR/get_default.rs:23:17
-   |
-LL | fn ok(map: &mut Map) -> &String {
-   |            - let's call the lifetime of this reference `'1`
-LL |     loop {
-LL |         match map.get() {
-   |               --- immutable borrow occurs here
-LL |             Some(v) => {
-LL |                 return v;
-   |                        - returning this value requires that `*map` is borrowed for `'1`
-...
-LL |                 map.set(String::new()); // Ideally, this would not error.
-   |                 ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
-
-error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
-  --> $DIR/get_default.rs:35:17
-   |
-LL | fn err(map: &mut Map) -> &String {
-   |             - let's call the lifetime of this reference `'1`
-LL |     loop {
-LL |         match map.get() {
-   |               --- immutable borrow occurs here
-LL |             Some(v) => {
-LL |                 map.set(String::new()); // Both AST and MIR error here
-   |                 ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
-...
-LL |                 return v;
-   |                        - returning this value requires that `*map` is borrowed for `'1`
-
-error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
-  --> $DIR/get_default.rs:41:17
-   |
-LL | fn err(map: &mut Map) -> &String {
-   |             - let's call the lifetime of this reference `'1`
-LL |     loop {
-LL |         match map.get() {
-   |               --- immutable borrow occurs here
-...
-LL |                 return v;
-   |                        - returning this value requires that `*map` is borrowed for `'1`
-...
-LL |                 map.set(String::new()); // Ideally, just AST would error here
-   |                 ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/nll/region-ends-after-if-condition.nll.stderr b/src/test/ui/nll/region-ends-after-if-condition.nll.stderr
deleted file mode 100644
index ab8d96d4e99..00000000000
--- a/src/test/ui/nll/region-ends-after-if-condition.nll.stderr
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0502]: cannot borrow `my_struct.field` as mutable because it is also borrowed as immutable (Ast)
-  --> $DIR/region-ends-after-if-condition.rs:19:9
-   |
-LL |     let value = &my_struct.field;
-   |                  --------------- immutable borrow occurs here
-LL |     if value.is_empty() {
-LL |         my_struct.field.push_str("Hello, world!");
-   |         ^^^^^^^^^^^^^^^ mutable borrow occurs here
-...
-LL | }
-   | - immutable borrow ends here
-
-error[E0502]: cannot borrow `my_struct.field` as mutable because it is also borrowed as immutable (Ast)
-  --> $DIR/region-ends-after-if-condition.rs:29:9
-   |
-LL |     let value = &my_struct.field;
-   |                  --------------- immutable borrow occurs here
-LL |     if value.is_empty() {
-LL |         my_struct.field.push_str("Hello, world!");
-   |         ^^^^^^^^^^^^^^^ mutable borrow occurs here
-...
-LL | }
-   | - immutable borrow ends here
-
-error[E0502]: cannot borrow `my_struct.field` as mutable because it is also borrowed as immutable (Mir)
-  --> $DIR/region-ends-after-if-condition.rs:29:9
-   |
-LL |     let value = &my_struct.field;
-   |                 ---------------- immutable borrow occurs here
-LL |     if value.is_empty() {
-LL |         my_struct.field.push_str("Hello, world!");
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
-...
-LL |     drop(value);
-   |          ----- immutable borrow later used here
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
index a7679aac219..cda1f7d3631 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
@@ -8,7 +8,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>,
            ]
    = note: number of external vids: 3
    = note: where <T as std::iter::Iterator>::Item: '_#2r
@@ -27,7 +27,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:6 ~ projection_no_regions_closure[317d]::no_region[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
@@ -48,7 +48,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>,
            ]
    = note: number of external vids: 3
    = note: where <T as std::iter::Iterator>::Item: '_#2r
@@ -66,7 +66,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:7 ~ projection_no_regions_closure[317d]::correct_region[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 note: External requirements
@@ -80,7 +80,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>,
            ]
    = note: number of external vids: 4
    = note: where <T as std::iter::Iterator>::Item: '_#3r
@@ -100,7 +100,7 @@ LL | | }
    = note: defining type: DefId(0/0:8 ~ projection_no_regions_closure[317d]::wrong_region[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
@@ -122,7 +122,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>,
            ]
    = note: number of external vids: 4
    = note: where <T as std::iter::Iterator>::Item: '_#3r
@@ -142,7 +142,7 @@ LL | | }
    = note: defining type: DefId(0/0:9 ~ projection_no_regions_closure[317d]::outlives_region[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index 7ba7164b35b..9d716006500 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -8,7 +8,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
    = note: late-bound region is '_#3r
    = note: number of external vids: 4
@@ -29,7 +29,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
@@ -62,7 +62,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
    = note: number of external vids: 4
    = note: where T: '_#3r
@@ -83,7 +83,7 @@ LL | | }
    = note: defining type: DefId(0/0:9 ~ projection_one_region_closure[317d]::no_relationships_early[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
@@ -116,7 +116,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
    = note: number of external vids: 4
    = note: where <T as Anything<ReClosureBound('_#2r)>>::AssocType: '_#3r
@@ -136,7 +136,7 @@ LL | | }
    = note: defining type: DefId(0/0:10 ~ projection_one_region_closure[317d]::projection_outlives[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 note: External requirements
@@ -150,7 +150,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
    = note: number of external vids: 4
    = note: where T: '_#3r
@@ -171,7 +171,7 @@ LL | | }
    = note: defining type: DefId(0/0:11 ~ projection_one_region_closure[317d]::elements_outlive[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index 63ead49adfc..0fa4060137a 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -8,7 +8,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
    = note: late-bound region is '_#3r
    = note: number of external vids: 4
@@ -28,7 +28,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 error: lifetime may not live long enough
@@ -53,7 +53,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
    = note: number of external vids: 4
    = note: where '_#2r: '_#3r
@@ -73,7 +73,7 @@ LL | | }
    = note: defining type: DefId(0/0:9 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_early[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 error: lifetime may not live long enough
@@ -98,7 +98,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
    = note: number of external vids: 4
    = note: where <T as Anything<ReClosureBound('_#2r)>>::AssocType: '_#3r
@@ -118,7 +118,7 @@ LL | | }
    = note: defining type: DefId(0/0:10 ~ projection_one_region_trait_bound_closure[317d]::projection_outlives[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 note: External requirements
@@ -132,7 +132,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
    = note: number of external vids: 4
    = note: where '_#2r: '_#3r
@@ -152,7 +152,7 @@ LL | | }
    = note: defining type: DefId(0/0:11 ~ projection_one_region_trait_bound_closure[317d]::elements_outlive[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 note: External requirements
@@ -165,7 +165,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
    = note: number of external vids: 3
    = note: where '_#1r: '_#2r
@@ -184,7 +184,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:12 ~ projection_one_region_trait_bound_closure[317d]::one_region[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
index 61f8132cf49..f616a7feae3 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
@@ -8,7 +8,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
    = note: late-bound region is '_#3r
 
@@ -25,7 +25,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:8 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_late[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 note: No external requirements
@@ -39,7 +39,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
 
 note: No external requirements
@@ -57,7 +57,7 @@ LL | | }
    = note: defining type: DefId(0/0:9 ~ projection_one_region_trait_bound_static_closure[317d]::no_relationships_early[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 note: No external requirements
@@ -71,7 +71,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
 
 note: No external requirements
@@ -89,7 +89,7 @@ LL | | }
    = note: defining type: DefId(0/0:10 ~ projection_one_region_trait_bound_static_closure[317d]::projection_outlives[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 note: No external requirements
@@ -103,7 +103,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
 
 note: No external requirements
@@ -121,7 +121,7 @@ LL | | }
    = note: defining type: DefId(0/0:11 ~ projection_one_region_trait_bound_static_closure[317d]::elements_outlive[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 note: No external requirements
@@ -134,7 +134,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
 
 note: No external requirements
@@ -151,6 +151,6 @@ LL | | }
    |
    = note: defining type: DefId(0/0:12 ~ projection_one_region_trait_bound_static_closure[317d]::one_region[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index f5daae28670..b761b031444 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -9,7 +9,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
    = note: late-bound region is '_#4r
    = note: number of external vids: 5
@@ -30,7 +30,7 @@ LL | | }
    = note: defining type: DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
@@ -53,7 +53,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#3r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
            ]
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
@@ -74,7 +74,7 @@ LL | | }
                '_#1r,
                '_#2r,
                '_#3r,
-               T
+               T,
            ]
 
 error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
@@ -97,7 +97,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#3r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
            ]
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
@@ -118,7 +118,7 @@ LL | | }
                '_#1r,
                '_#2r,
                '_#3r,
-               T
+               T,
            ]
 
 note: External requirements
@@ -133,7 +133,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#3r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
            ]
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
@@ -154,7 +154,7 @@ LL | | }
                '_#1r,
                '_#2r,
                '_#3r,
-               T
+               T,
            ]
 
 note: External requirements
@@ -169,7 +169,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#3r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)),
            ]
    = note: number of external vids: 5
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
@@ -190,7 +190,7 @@ LL | | }
                '_#1r,
                '_#2r,
                '_#3r,
-               T
+               T,
            ]
 
 note: External requirements
@@ -203,7 +203,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
    = note: late-bound region is '_#3r
    = note: number of external vids: 4
@@ -223,7 +223,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 error: lifetime may not live long enough
@@ -248,7 +248,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
    = note: number of external vids: 4
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#2r)>>::AssocType: '_#3r
@@ -268,7 +268,7 @@ LL | | }
    = note: defining type: DefId(0/0:14 ~ projection_two_region_trait_bound_closure[317d]::two_regions_outlive[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 note: External requirements
@@ -281,7 +281,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
    = note: number of external vids: 3
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
@@ -300,7 +300,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:15 ~ projection_two_region_trait_bound_closure[317d]::one_region[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index 41c2916dca3..6f3071becfd 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -7,7 +7,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: defining type: DefId(0/1:14 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]::{{closure}}[0]) with closure substs [
                T,
                i16,
-               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T))
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T)),
            ]
    = note: number of external vids: 2
    = note: where T: '_#1r
@@ -22,7 +22,7 @@ LL | | }
    | |_^
    |
    = note: defining type: DefId(0/0:5 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]) with substs [
-               T
+               T,
            ]
 
 note: External requirements
@@ -34,7 +34,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: defining type: DefId(0/1:17 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [
                T,
                i16,
-               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T))
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T)),
            ]
    = note: late-bound region is '_#2r
    = note: number of external vids: 3
@@ -50,7 +50,7 @@ LL | | }
    | |_^
    |
    = note: defining type: DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]) with substs [
-               T
+               T,
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
index 6a201b8523a..cdb71576203 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -8,7 +8,7 @@ LL |     with_signature(x, |y| y)
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>
+               extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>,
            ]
    = note: number of external vids: 3
    = note: where T: '_#2r
@@ -27,7 +27,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:5 ~ ty_param_closure_outlives_from_return_type[317d]::no_region[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
index 4ddc54717fb..68798a335f9 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -14,7 +14,7 @@ LL | |     })
    = note: defining type: DefId(0/1:16 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]::{{closure}}[0]) with closure substs [
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T)),
            ]
    = note: late-bound region is '_#2r
    = note: number of external vids: 3
@@ -33,7 +33,7 @@ LL | | }
    | |_^
    |
    = note: defining type: DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]) with substs [
-               T
+               T,
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
@@ -68,7 +68,7 @@ LL | |     })
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
    = note: number of external vids: 3
    = note: where T: '_#2r
@@ -87,7 +87,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:7 ~ ty_param_closure_outlives_from_where_clause[317d]::correct_region[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 note: External requirements
@@ -105,7 +105,7 @@ LL | |     })
                '_#1r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)),
            ]
    = note: late-bound region is '_#3r
    = note: number of external vids: 4
@@ -125,7 +125,7 @@ LL | | }
    |
    = note: defining type: DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]) with substs [
                '_#1r,
-               T
+               T,
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
@@ -156,7 +156,7 @@ LL | |     })
                '_#2r,
                T,
                i32,
-               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T))
+               extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)),
            ]
    = note: number of external vids: 4
    = note: where T: '_#3r
@@ -176,7 +176,7 @@ LL | | }
    = note: defining type: DefId(0/0:9 ~ ty_param_closure_outlives_from_where_clause[317d]::outlives_region[0]) with substs [
                '_#1r,
                '_#2r,
-               T
+               T,
            ]
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/panic-runtime/needs-gate.stderr b/src/test/ui/panic-runtime/needs-gate.stderr
index 5b8ff82d1fd..72999a0de89 100644
--- a/src/test/ui/panic-runtime/needs-gate.stderr
+++ b/src/test/ui/panic-runtime/needs-gate.stderr
@@ -1,17 +1,19 @@
-error[E0658]: the `#[panic_runtime]` attribute is an experimental feature (see issue #32837)
+error[E0658]: the `#[panic_runtime]` attribute is an experimental feature
   --> $DIR/needs-gate.rs:4:1
    |
 LL | #![panic_runtime]
    | ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32837
    = help: add #![feature(panic_runtime)] to the crate attributes to enable
 
-error[E0658]: the `#[needs_panic_runtime]` attribute is an experimental feature (see issue #32837)
+error[E0658]: the `#[needs_panic_runtime]` attribute is an experimental feature
   --> $DIR/needs-gate.rs:5:1
    |
 LL | #![needs_panic_runtime]
    | ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/32837
    = help: add #![feature(needs_panic_runtime)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/parser/recover-missing-semi.rs b/src/test/ui/parser/recover-missing-semi.rs
new file mode 100644
index 00000000000..1893dc716be
--- /dev/null
+++ b/src/test/ui/parser/recover-missing-semi.rs
@@ -0,0 +1,13 @@
+fn main() {
+    let _: usize = ()
+    //~^ ERROR mismatched types
+    let _ = 3;
+    //~^ ERROR expected one of
+}
+
+fn foo() -> usize {
+    let _: usize = ()
+    //~^ ERROR mismatched types
+    return 3;
+    //~^ ERROR expected one of
+}
diff --git a/src/test/ui/parser/recover-missing-semi.stderr b/src/test/ui/parser/recover-missing-semi.stderr
new file mode 100644
index 00000000000..99339e4dd50
--- /dev/null
+++ b/src/test/ui/parser/recover-missing-semi.stderr
@@ -0,0 +1,39 @@
+error: expected one of `.`, `;`, `?`, or an operator, found `let`
+  --> $DIR/recover-missing-semi.rs:4:5
+   |
+LL |     let _: usize = ()
+   |                      - help: a semicolon may be missing here
+LL |
+LL |     let _ = 3;
+   |     ^^^
+
+error: expected one of `.`, `;`, `?`, or an operator, found `return`
+  --> $DIR/recover-missing-semi.rs:11:5
+   |
+LL |     let _: usize = ()
+   |                      - help: a semicolon may be missing here
+LL |
+LL |     return 3;
+   |     ^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/recover-missing-semi.rs:2:20
+   |
+LL |     let _: usize = ()
+   |                    ^^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-missing-semi.rs:9:20
+   |
+LL |     let _: usize = ()
+   |                    ^^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/print_type_sizes/multiple_types.stdout b/src/test/ui/print_type_sizes/multiple_types.stdout
index eed9af26987..64118815458 100644
--- a/src/test/ui/print_type_sizes/multiple_types.stdout
+++ b/src/test/ui/print_type_sizes/multiple_types.stdout
@@ -1,9 +1,9 @@
 print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
-print-type-size     variant `Small`: 7 bytes
-print-type-size         field `.0`: 7 bytes
 print-type-size     variant `Large`: 50 bytes
 print-type-size         field `.0`: 50 bytes
+print-type-size     variant `Small`: 7 bytes
+print-type-size         field `.0`: 7 bytes
 print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
 print-type-size     field `.0`: 50 bytes
 print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
diff --git a/src/test/ui/print_type_sizes/niche-filling.stdout b/src/test/ui/print_type_sizes/niche-filling.stdout
index 0789c6d7f34..9cdb2ae4f57 100644
--- a/src/test/ui/print_type_sizes/niche-filling.stdout
+++ b/src/test/ui/print_type_sizes/niche-filling.stdout
@@ -4,15 +4,15 @@ print-type-size     field `.post`: 2 bytes
 print-type-size     field `.pre`: 1 bytes
 print-type-size     end padding: 1 bytes
 print-type-size type: `MyOption<IndirectNonZero>`: 12 bytes, alignment: 4 bytes
-print-type-size     variant `None`: 0 bytes
 print-type-size     variant `Some`: 12 bytes
 print-type-size         field `.0`: 12 bytes
-print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
 print-type-size     variant `None`: 0 bytes
+print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
 print-type-size     variant `Record`: 7 bytes
 print-type-size         field `.val`: 4 bytes
 print-type-size         field `.post`: 2 bytes
 print-type-size         field `.pre`: 1 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size     end padding: 1 bytes
 print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes
 print-type-size     field `.val`: 4 bytes
@@ -20,59 +20,59 @@ print-type-size     field `.post`: 2 bytes
 print-type-size     field `.pre`: 1 bytes
 print-type-size     end padding: 1 bytes
 print-type-size type: `Enum4<(), char, (), ()>`: 4 bytes, alignment: 4 bytes
-print-type-size     variant `One`: 0 bytes
-print-type-size         field `.0`: 0 bytes
 print-type-size     variant `Two`: 4 bytes
 print-type-size         field `.0`: 4 bytes
+print-type-size     variant `One`: 0 bytes
+print-type-size         field `.0`: 0 bytes
 print-type-size     variant `Three`: 0 bytes
 print-type-size         field `.0`: 0 bytes
 print-type-size     variant `Four`: 0 bytes
 print-type-size         field `.0`: 0 bytes
 print-type-size type: `MyOption<char>`: 4 bytes, alignment: 4 bytes
-print-type-size     variant `None`: 0 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
-print-type-size type: `MyOption<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `None`: 0 bytes
+print-type-size type: `MyOption<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes
 print-type-size     field `.0`: 4 bytes
 print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes
+print-type-size     variant `Four`: 2 bytes
+print-type-size         field `.0`: 2 bytes
 print-type-size     variant `One`: 0 bytes
 print-type-size         field `.0`: 0 bytes
 print-type-size     variant `Two`: 0 bytes
 print-type-size         field `.0`: 0 bytes
 print-type-size     variant `Three`: 0 bytes
 print-type-size         field `.0`: 0 bytes
-print-type-size     variant `Four`: 2 bytes
-print-type-size         field `.0`: 2 bytes
 print-type-size type: `MyOption<MyOption<u8>>`: 2 bytes, alignment: 1 bytes
-print-type-size     variant `None`: 0 bytes
 print-type-size     variant `Some`: 2 bytes
 print-type-size         field `.0`: 2 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size type: `MyOption<u8>`: 2 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
-print-type-size     variant `None`: 0 bytes
 print-type-size     variant `Some`: 1 bytes
 print-type-size         field `.0`: 1 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size type: `Enum4<(), (), bool, ()>`: 1 bytes, alignment: 1 bytes
+print-type-size     variant `Three`: 1 bytes
+print-type-size         field `.0`: 1 bytes
 print-type-size     variant `One`: 0 bytes
 print-type-size         field `.0`: 0 bytes
 print-type-size     variant `Two`: 0 bytes
 print-type-size         field `.0`: 0 bytes
-print-type-size     variant `Three`: 1 bytes
-print-type-size         field `.0`: 1 bytes
 print-type-size     variant `Four`: 0 bytes
 print-type-size         field `.0`: 0 bytes
 print-type-size type: `MyOption<bool>`: 1 bytes, alignment: 1 bytes
-print-type-size     variant `None`: 0 bytes
 print-type-size     variant `Some`: 1 bytes
 print-type-size         field `.0`: 1 bytes
-print-type-size type: `MyOption<std::cmp::Ordering>`: 1 bytes, alignment: 1 bytes
 print-type-size     variant `None`: 0 bytes
+print-type-size type: `MyOption<std::cmp::Ordering>`: 1 bytes, alignment: 1 bytes
 print-type-size     variant `Some`: 1 bytes
 print-type-size         field `.0`: 1 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size type: `std::cmp::Ordering`: 1 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Less`: 0 bytes
diff --git a/src/test/ui/print_type_sizes/padding.stdout b/src/test/ui/print_type_sizes/padding.stdout
index 0eaff7118b3..9afdf76245d 100644
--- a/src/test/ui/print_type_sizes/padding.stdout
+++ b/src/test/ui/print_type_sizes/padding.stdout
@@ -1,21 +1,21 @@
 print-type-size type: `E1`: 12 bytes, alignment: 4 bytes
 print-type-size     discriminant: 1 bytes
+print-type-size     variant `B`: 11 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
 print-type-size     variant `A`: 7 bytes
 print-type-size         field `.1`: 1 bytes
 print-type-size         padding: 2 bytes
 print-type-size         field `.0`: 4 bytes, alignment: 4 bytes
+print-type-size type: `E2`: 12 bytes, alignment: 4 bytes
+print-type-size     discriminant: 1 bytes
 print-type-size     variant `B`: 11 bytes
 print-type-size         padding: 3 bytes
 print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
-print-type-size type: `E2`: 12 bytes, alignment: 4 bytes
-print-type-size     discriminant: 1 bytes
 print-type-size     variant `A`: 7 bytes
 print-type-size         field `.0`: 1 bytes
 print-type-size         padding: 2 bytes
 print-type-size         field `.1`: 4 bytes, alignment: 4 bytes
-print-type-size     variant `B`: 11 bytes
-print-type-size         padding: 3 bytes
-print-type-size         field `.0`: 8 bytes, alignment: 4 bytes
 print-type-size type: `S`: 8 bytes, alignment: 4 bytes
 print-type-size     field `.g`: 4 bytes
 print-type-size     field `.a`: 1 bytes
diff --git a/src/test/ui/print_type_sizes/repr-align.stdout b/src/test/ui/print_type_sizes/repr-align.stdout
index 7df12f040b1..33671bd8e14 100644
--- a/src/test/ui/print_type_sizes/repr-align.stdout
+++ b/src/test/ui/print_type_sizes/repr-align.stdout
@@ -1,10 +1,10 @@
 print-type-size type: `E`: 32 bytes, alignment: 16 bytes
 print-type-size     discriminant: 4 bytes
-print-type-size     variant `A`: 4 bytes
-print-type-size         field `.0`: 4 bytes
 print-type-size     variant `B`: 28 bytes
 print-type-size         padding: 12 bytes
 print-type-size         field `.0`: 16 bytes, alignment: 16 bytes
+print-type-size     variant `A`: 4 bytes
+print-type-size         field `.0`: 4 bytes
 print-type-size type: `S`: 32 bytes, alignment: 16 bytes
 print-type-size     field `.c`: 16 bytes
 print-type-size     field `.a`: 4 bytes
diff --git a/src/test/ui/print_type_sizes/variants.stdout b/src/test/ui/print_type_sizes/variants.stdout
index eed9af26987..64118815458 100644
--- a/src/test/ui/print_type_sizes/variants.stdout
+++ b/src/test/ui/print_type_sizes/variants.stdout
@@ -1,9 +1,9 @@
 print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
-print-type-size     variant `Small`: 7 bytes
-print-type-size         field `.0`: 7 bytes
 print-type-size     variant `Large`: 50 bytes
 print-type-size         field `.0`: 50 bytes
+print-type-size     variant `Small`: 7 bytes
+print-type-size         field `.0`: 7 bytes
 print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
 print-type-size     field `.0`: 50 bytes
 print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stderr b/src/test/ui/proc-macro/attr-stmt-expr.stderr
index 34ee012ab31..3928a973eab 100644
--- a/src/test/ui/proc-macro/attr-stmt-expr.stderr
+++ b/src/test/ui/proc-macro/attr-stmt-expr.stderr
@@ -1,17 +1,19 @@
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/attr-stmt-expr.rs:10:5
    |
 LL |     #[expect_print_expr]
    |     ^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/attr-stmt-expr.rs:23:5
    |
 LL |     #[expect_expr]
    |     ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr
index 5f2009b384b..58139353492 100644
--- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr
+++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr
@@ -1,9 +1,10 @@
-error[E0658]: The attribute `my_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `my_attr` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/derive-helper-shadowing.rs:20:15
    |
 LL |             #[my_attr]
    |               ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0659]: `my_attr` is ambiguous (derive helper attribute vs any other name)
diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr
index f7c8960372e..d235343ff16 100644
--- a/src/test/ui/proc-macro/derive-still-gated.stderr
+++ b/src/test/ui/proc-macro/derive-still-gated.stderr
@@ -1,9 +1,10 @@
-error[E0658]: The attribute `derive_A` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `derive_A` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/derive-still-gated.rs:8:3
    |
 LL | #[derive_A]
    |   ^^^^^^^^ help: a built-in attribute with a similar name exists: `derive`
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to previous error
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 09340988c89..618380d7f0b 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
@@ -2,79 +2,79 @@ PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ;
 PROC MACRO INPUT: TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI)
-            }
+                span: #2 bytes(LO..HI),
+            },
         ],
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI)
-    }
+        span: #2 bytes(LO..HI),
+    },
 ]
 ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S);
 ATTRIBUTE INPUT: TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI)
-            }
+                span: #2 bytes(LO..HI),
+            },
         ],
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI)
-    }
+        span: #2 bytes(LO..HI),
+    },
 ]
diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout
index c47b3603f41..454da539430 100644
--- a/src/test/ui/proc-macro/dollar-crate.stdout
+++ b/src/test/ui/proc-macro/dollar-crate.stdout
@@ -2,239 +2,239 @@ PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ;
 PROC MACRO INPUT: TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI)
-            }
+                span: #2 bytes(LO..HI),
+            },
         ],
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI)
-    }
+        span: #2 bytes(LO..HI),
+    },
 ]
 ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S);
 ATTRIBUTE INPUT: TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI)
-            }
+                span: #2 bytes(LO..HI),
+            },
         ],
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI)
-    }
+        span: #2 bytes(LO..HI),
+    },
 ]
 DERIVE INPUT (PRETTY-PRINTED): struct D(crate::S);
 DERIVE INPUT: TokenStream [
     Ident {
         ident: "struct",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Ident {
         ident: "D",
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #2 bytes(LO..HI)
+                span: #2 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #2 bytes(LO..HI)
-            }
+                span: #2 bytes(LO..HI),
+            },
         ],
-        span: #2 bytes(LO..HI)
+        span: #2 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #2 bytes(LO..HI)
-    }
+        span: #2 bytes(LO..HI),
+    },
 ]
 PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ;
 PROC MACRO INPUT: TokenStream [
     Ident {
         ident: "struct",
-        span: #10 bytes(LO..HI)
+        span: #10 bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #10 bytes(LO..HI)
+        span: #10 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #10 bytes(LO..HI)
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #10 bytes(LO..HI)
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #10 bytes(LO..HI)
+                span: #10 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #10 bytes(LO..HI)
-            }
+                span: #10 bytes(LO..HI),
+            },
         ],
-        span: #10 bytes(LO..HI)
+        span: #10 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #10 bytes(LO..HI)
-    }
+        span: #10 bytes(LO..HI),
+    },
 ]
 ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(::dollar_crate_external::S);
 ATTRIBUTE INPUT: TokenStream [
     Ident {
         ident: "struct",
-        span: #10 bytes(LO..HI)
+        span: #10 bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #10 bytes(LO..HI)
+        span: #10 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #10 bytes(LO..HI)
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #10 bytes(LO..HI)
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #10 bytes(LO..HI)
+                span: #10 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #10 bytes(LO..HI)
-            }
+                span: #10 bytes(LO..HI),
+            },
         ],
-        span: #10 bytes(LO..HI)
+        span: #10 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #10 bytes(LO..HI)
-    }
+        span: #10 bytes(LO..HI),
+    },
 ]
 DERIVE INPUT (PRETTY-PRINTED): struct D(::dollar_crate_external::S);
 DERIVE INPUT: TokenStream [
     Ident {
         ident: "struct",
-        span: #10 bytes(LO..HI)
+        span: #10 bytes(LO..HI),
     },
     Ident {
         ident: "D",
-        span: #10 bytes(LO..HI)
+        span: #10 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #10 bytes(LO..HI)
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #10 bytes(LO..HI)
+                span: #10 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #10 bytes(LO..HI)
+                span: #10 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #10 bytes(LO..HI)
-            }
+                span: #10 bytes(LO..HI),
+            },
         ],
-        span: #10 bytes(LO..HI)
+        span: #10 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #10 bytes(LO..HI)
-    }
+        span: #10 bytes(LO..HI),
+    },
 ]
diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.stderr b/src/test/ui/proc-macro/expand-to-unstable-2.stderr
index b322f8e9d56..e2f51dd3d5d 100644
--- a/src/test/ui/proc-macro/expand-to-unstable-2.stderr
+++ b/src/test/ui/proc-macro/expand-to-unstable-2.stderr
@@ -1,9 +1,10 @@
-error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
   --> $DIR/expand-to-unstable-2.rs:8:10
    |
 LL | #[derive(Unstable)]
    |          ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/proc-macro/issue-41211.stderr b/src/test/ui/proc-macro/issue-41211.stderr
index f75481e4829..dfb2f6f63d8 100644
--- a/src/test/ui/proc-macro/issue-41211.stderr
+++ b/src/test/ui/proc-macro/issue-41211.stderr
@@ -1,9 +1,10 @@
-error[E0658]: The attribute `emit_unchanged` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `emit_unchanged` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/issue-41211.rs:8:4
    |
 LL | #![emit_unchanged]
    |    ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: inconsistent resolution for a macro: first custom attribute, then attribute macro
diff --git a/src/test/ui/proc-macro/macros-in-extern.stderr b/src/test/ui/proc-macro/macros-in-extern.stderr
index 8a48656d087..61571650f2f 100644
--- a/src/test/ui/proc-macro/macros-in-extern.stderr
+++ b/src/test/ui/proc-macro/macros-in-extern.stderr
@@ -1,25 +1,28 @@
-error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental
   --> $DIR/macros-in-extern.rs:15:5
    |
 LL |     #[no_output]
    |     ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49476
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental
   --> $DIR/macros-in-extern.rs:19:5
    |
 LL |     #[nop_attr]
    |     ^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49476
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental
   --> $DIR/macros-in-extern.rs:23:5
    |
 LL |     emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/49476
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/proc-macro/more-gates.stderr b/src/test/ui/proc-macro/more-gates.stderr
index c6c2954f939..80985ce7523 100644
--- a/src/test/ui/proc-macro/more-gates.stderr
+++ b/src/test/ui/proc-macro/more-gates.stderr
@@ -1,41 +1,46 @@
-error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+error[E0658]: procedural macros cannot expand to macro definitions
   --> $DIR/more-gates.rs:9:1
    |
 LL | #[attr2mac1]
    | ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+error[E0658]: procedural macros cannot expand to macro definitions
   --> $DIR/more-gates.rs:12:1
    |
 LL | #[attr2mac2]
    | ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+error[E0658]: procedural macros cannot expand to macro definitions
   --> $DIR/more-gates.rs:16:1
    |
 LL | mac2mac1!();
    | ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+error[E0658]: procedural macros cannot expand to macro definitions
   --> $DIR/more-gates.rs:17:1
    |
 LL | mac2mac2!();
    | ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727)
+error[E0658]: procedural macros cannot expand to macro definitions
   --> $DIR/more-gates.rs:19:1
    |
 LL | tricky!();
    | ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr
index f8f1e7cd988..084c7289d04 100644
--- a/src/test/ui/proc-macro/proc-macro-attributes.stderr
+++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr
@@ -1,9 +1,10 @@
-error[E0658]: The attribute `C` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `C` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/proc-macro-attributes.rs:7:3
    |
 LL | #[C]
    |   ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0659]: `B` is ambiguous (derive helper attribute vs any other name)
diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr
index 4ae8e63df72..1bb864b52ea 100644
--- a/src/test/ui/proc-macro/proc-macro-gates.stderr
+++ b/src/test/ui/proc-macro/proc-macro-gates.stderr
@@ -1,33 +1,37 @@
-error[E0658]: non-builtin inner attributes are unstable (see issue #54726)
+error[E0658]: non-builtin inner attributes are unstable
   --> $DIR/proc-macro-gates.rs:11:5
    |
 LL |     #![a]
    |     ^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54726
    = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable
 
-error[E0658]: non-builtin inner attributes are unstable (see issue #54726)
+error[E0658]: non-builtin inner attributes are unstable
   --> $DIR/proc-macro-gates.rs:18:5
    |
 LL |     #![a]
    |     ^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54726
    = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable
 
-error[E0658]: custom attributes cannot be applied to modules (see issue #54727)
+error[E0658]: custom attributes cannot be applied to modules
   --> $DIR/proc-macro-gates.rs:14:1
    |
 LL | #[a]
    | ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: custom attributes cannot be applied to modules (see issue #54727)
+error[E0658]: custom attributes cannot be applied to modules
   --> $DIR/proc-macro-gates.rs:18:5
    |
 LL |     #![a]
    |     ^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
 error: custom attribute invocations must be of the form #[foo] or #[foo(..)], the macro name must only be followed by a delimiter token
@@ -36,100 +40,112 @@ error: custom attribute invocations must be of the form #[foo] or #[foo(..)], th
 LL | #[a = "y"]
    | ^^^^^^^^^^
 
-error[E0658]: custom attributes cannot be applied to statements (see issue #54727)
+error[E0658]: custom attributes cannot be applied to statements
   --> $DIR/proc-macro-gates.rs:31:5
    |
 LL |     #[a]
    |     ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: custom attributes cannot be applied to statements (see issue #54727)
+error[E0658]: custom attributes cannot be applied to statements
   --> $DIR/proc-macro-gates.rs:35:5
    |
 LL |     #[a]
    |     ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: custom attributes cannot be applied to statements (see issue #54727)
+error[E0658]: custom attributes cannot be applied to statements
   --> $DIR/proc-macro-gates.rs:39:5
    |
 LL |     #[a]
    |     ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: custom attributes cannot be applied to expressions (see issue #54727)
+error[E0658]: custom attributes cannot be applied to expressions
   --> $DIR/proc-macro-gates.rs:43:14
    |
 LL |     let _x = #[a] 2;
    |              ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: custom attributes cannot be applied to expressions (see issue #54727)
+error[E0658]: custom attributes cannot be applied to expressions
   --> $DIR/proc-macro-gates.rs:46:15
    |
 LL |     let _x = [#[a] 2];
    |               ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: custom attributes cannot be applied to expressions (see issue #54727)
+error[E0658]: custom attributes cannot be applied to expressions
   --> $DIR/proc-macro-gates.rs:49:14
    |
 LL |     let _x = #[a] println!();
    |              ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot be expanded to types (see issue #54727)
+error[E0658]: procedural macros cannot be expanded to types
   --> $DIR/proc-macro-gates.rs:53:13
    |
 LL |     let _x: m!(u32) = 3;
    |             ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot be expanded to patterns (see issue #54727)
+error[E0658]: procedural macros cannot be expanded to patterns
   --> $DIR/proc-macro-gates.rs:54:12
    |
 LL |     if let m!(Some(_x)) = Some(3) {}
    |            ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot be expanded to statements (see issue #54727)
+error[E0658]: procedural macros cannot be expanded to statements
   --> $DIR/proc-macro-gates.rs:56:5
    |
 LL |     m!(struct S;);
    |     ^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot be expanded to statements (see issue #54727)
+error[E0658]: procedural macros cannot be expanded to statements
   --> $DIR/proc-macro-gates.rs:57:5
    |
 LL |     m!(let _x = 3;);
    |     ^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot be expanded to expressions (see issue #54727)
+error[E0658]: procedural macros cannot be expanded to expressions
   --> $DIR/proc-macro-gates.rs:59:14
    |
 LL |     let _x = m!(3);
    |              ^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
-error[E0658]: procedural macros cannot be expanded to expressions (see issue #54727)
+error[E0658]: procedural macros cannot be expanded to expressions
   --> $DIR/proc-macro-gates.rs:60:15
    |
 LL |     let _x = [m!(3)];
    |               ^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
 
 error: aborting due to 17 previous errors
diff --git a/src/test/ui/proc-macro/proc-macro-gates2.stderr b/src/test/ui/proc-macro/proc-macro-gates2.stderr
index 89ad527a43c..0e8236f460f 100644
--- a/src/test/ui/proc-macro/proc-macro-gates2.stderr
+++ b/src/test/ui/proc-macro/proc-macro-gates2.stderr
@@ -1,17 +1,19 @@
-error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/proc-macro-gates2.rs:13:11
    |
 LL | fn _test6<#[a] T>() {}
    |           ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/proc-macro-gates2.rs:18:9
    |
 LL |         #[a]
    |         ^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr
index 3e082e53ca8..c8738d1ed34 100644
--- a/src/test/ui/reserved/reserved-attr-on-macro.stderr
+++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr
@@ -1,9 +1,10 @@
-error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
   --> $DIR/reserved-attr-on-macro.rs:1:3
    |
 LL | #[rustc_attribute_should_be_reserved]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
 error: cannot determine resolution for the macro `foo`
diff --git a/src/test/ui/resolve/resolve-variant-assoc-item.rs b/src/test/ui/resolve/resolve-variant-assoc-item.rs
index f0f55c0c667..db4fedfb0bd 100644
--- a/src/test/ui/resolve/resolve-variant-assoc-item.rs
+++ b/src/test/ui/resolve/resolve-variant-assoc-item.rs
@@ -2,6 +2,6 @@ enum E { V }
 use E::V;
 
 fn main() {
-    E::V::associated_item; //~ ERROR failed to resolve: not a module `V`
-    V::associated_item; //~ ERROR failed to resolve: not a module `V`
+    E::V::associated_item; //~ ERROR failed to resolve: `V` is a variant, not a module
+    V::associated_item; //~ ERROR failed to resolve: `V` is a variant, not a module
 }
diff --git a/src/test/ui/resolve/resolve-variant-assoc-item.stderr b/src/test/ui/resolve/resolve-variant-assoc-item.stderr
index 173976d707c..4be1019968b 100644
--- a/src/test/ui/resolve/resolve-variant-assoc-item.stderr
+++ b/src/test/ui/resolve/resolve-variant-assoc-item.stderr
@@ -1,14 +1,14 @@
-error[E0433]: failed to resolve: not a module `V`
+error[E0433]: failed to resolve: `V` is a variant, not a module
   --> $DIR/resolve-variant-assoc-item.rs:5:8
    |
 LL |     E::V::associated_item;
-   |        ^ not a module `V`
+   |        ^ `V` is a variant, not a module
 
-error[E0433]: failed to resolve: not a module `V`
+error[E0433]: failed to resolve: `V` is a variant, not a module
   --> $DIR/resolve-variant-assoc-item.rs:6:5
    |
 LL |     V::associated_item;
-   |     ^ not a module `V`
+   |     ^ `V` is a variant, not a module
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve_self_super_hint.rs b/src/test/ui/resolve_self_super_hint.rs
index 91a01cc0fa2..a9423830d90 100644
--- a/src/test/ui/resolve_self_super_hint.rs
+++ b/src/test/ui/resolve_self_super_hint.rs
@@ -1,4 +1,3 @@
-#![feature(alloc)]
 #![allow(unused_extern_crates)]
 
 mod a {
diff --git a/src/test/ui/resolve_self_super_hint.stderr b/src/test/ui/resolve_self_super_hint.stderr
index 03214cad8e4..14cdae97d14 100644
--- a/src/test/ui/resolve_self_super_hint.stderr
+++ b/src/test/ui/resolve_self_super_hint.stderr
@@ -1,17 +1,17 @@
 error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:6:9
+  --> $DIR/resolve_self_super_hint.rs:5:9
    |
 LL |     use alloc::HashMap;
    |         ^^^^^ help: a similar path exists: `self::alloc`
 
 error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:11:13
+  --> $DIR/resolve_self_super_hint.rs:10:13
    |
 LL |         use alloc::HashMap;
    |             ^^^^^ help: a similar path exists: `super::alloc`
 
 error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:16:17
+  --> $DIR/resolve_self_super_hint.rs:15:17
    |
 LL |             use alloc::HashMap;
    |                 ^^^^^
@@ -20,7 +20,7 @@ LL |             use alloc::HashMap;
    |                 help: a similar path exists: `a::alloc`
 
 error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:21:21
+  --> $DIR/resolve_self_super_hint.rs:20:21
    |
 LL |                 use alloc::HashMap;
    |                     ^^^^^
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
index 67f7f80a9e2..f1b73ee115d 100644
--- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
+++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
@@ -64,22 +64,22 @@ fn validate_stderr(stderr: Vec<String>) {
 
         ":28] Point{x: 42, y: 24,} = Point {",
         "    x: 42,",
-        "    y: 24",
+        "    y: 24,",
         "}",
 
         ":29] b = Point {",
         "    x: 42,",
-        "    y: 24",
+        "    y: 24,",
         "}",
 
         ":37]",
 
         ":41] &a = NoCopy(",
-        "    1337",
+        "    1337,",
         ")",
 
         ":41] dbg!(& a) = NoCopy(",
-        "    1337",
+        "    1337,",
         ")",
         ":46] f(&42) = 42",
 
diff --git a/src/test/ui/rfc1445/feature-gate.no_gate.stderr b/src/test/ui/rfc1445/feature-gate.no_gate.stderr
index 370b74b8779..3a2014fab09 100644
--- a/src/test/ui/rfc1445/feature-gate.no_gate.stderr
+++ b/src/test/ui/rfc1445/feature-gate.no_gate.stderr
@@ -1,9 +1,10 @@
-error[E0658]: the semantics of constant patterns is not yet settled (see issue #31434)
+error[E0658]: the semantics of constant patterns is not yet settled
   --> $DIR/feature-gate.rs:13:1
    |
 LL | #[structural_match]
    | ^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/31434
    = help: add #![feature(structural_match)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed
index a977e00c013..17449caf84f 100644
--- a/src/test/ui/rust-2018/remove-extern-crate.fixed
+++ b/src/test/ui/rust-2018/remove-extern-crate.fixed
@@ -4,7 +4,6 @@
 // aux-build:remove-extern-crate.rs
 // compile-flags:--extern remove_extern_crate
 
-#![feature(alloc)]
 #![warn(rust_2018_idioms)]
 
 
diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs
index cafe82d846e..fb2217df000 100644
--- a/src/test/ui/rust-2018/remove-extern-crate.rs
+++ b/src/test/ui/rust-2018/remove-extern-crate.rs
@@ -4,7 +4,6 @@
 // aux-build:remove-extern-crate.rs
 // compile-flags:--extern remove_extern_crate
 
-#![feature(alloc)]
 #![warn(rust_2018_idioms)]
 
 extern crate core;
diff --git a/src/test/ui/rust-2018/remove-extern-crate.stderr b/src/test/ui/rust-2018/remove-extern-crate.stderr
index 4e08b7aa6a0..549693201b7 100644
--- a/src/test/ui/rust-2018/remove-extern-crate.stderr
+++ b/src/test/ui/rust-2018/remove-extern-crate.stderr
@@ -1,24 +1,24 @@
 warning: unused extern crate
-  --> $DIR/remove-extern-crate.rs:10:1
+  --> $DIR/remove-extern-crate.rs:9:1
    |
 LL | extern crate core;
    | ^^^^^^^^^^^^^^^^^^ help: remove it
    |
 note: lint level defined here
-  --> $DIR/remove-extern-crate.rs:8:9
+  --> $DIR/remove-extern-crate.rs:7:9
    |
 LL | #![warn(rust_2018_idioms)]
    |         ^^^^^^^^^^^^^^^^
    = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)]
 
 warning: `extern crate` is not idiomatic in the new edition
-  --> $DIR/remove-extern-crate.rs:11:1
+  --> $DIR/remove-extern-crate.rs:10:1
    |
 LL | extern crate core as another_name;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
 
 warning: `extern crate` is not idiomatic in the new edition
-  --> $DIR/remove-extern-crate.rs:29:5
+  --> $DIR/remove-extern-crate.rs:28:5
    |
 LL |     extern crate core;
    |     ^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr
index a61af699cdc..42daf7c6fb1 100644
--- a/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr
@@ -8,7 +8,7 @@ error[E0432]: unresolved import `rustfmt`
   --> $DIR/prelude-fail.rs:7:5
    |
 LL | use rustfmt::skip as imported_rustfmt_skip;
-   |     ^^^^^^^ not a module `rustfmt`
+   |     ^^^^^^^ `rustfmt` is a tool module, not a module
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
index 1a5ab7a7d56..4e2ab59f822 100644
--- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
@@ -18,7 +18,7 @@ LL | fn test2<F>(f: &F) where F: FnMut() {
 LL |     (*f)();
    |     ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow `*f.f` as mutable, as it is behind a `&` reference
+error[E0596]: cannot borrow `f.f` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5
    |
 LL | fn test4(f: &Test) {
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs
index cfebd6f7003..f246f1118bf 100644
--- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs
@@ -32,7 +32,7 @@ fn test3<F>(f: &mut F) where F: FnMut() {
 
 fn test4(f: &Test) {
     f.f.call_mut(())
-    //~^ ERROR: cannot borrow `Box` content `*f.f` of immutable binding as mutable
+    //~^ ERROR: cannot borrow field `f.f` of immutable binding as mutable
 }
 
 fn test5(f: &mut Test) {
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
index 6c8f477e310..a61ee8334af 100644
--- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
@@ -19,13 +19,13 @@ LL | fn test2<F>(f: &F) where F: FnMut() {
 LL |     (*f)();
    |     ^^^^ cannot borrow as mutable
 
-error[E0596]: cannot borrow `Box` content `*f.f` of immutable binding as mutable
+error[E0596]: cannot borrow field `f.f` of immutable binding as mutable
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5
    |
 LL | fn test4(f: &Test) {
    |             ----- use `&mut Test` here to make mutable
 LL |     f.f.call_mut(())
-   |     ^^^ cannot borrow as mutable
+   |     ^^^ cannot mutably borrow field of immutable binding
 
 error[E0504]: cannot move `f` into closure because it is borrowed
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:56:13
diff --git a/src/test/ui/span/gated-features-attr-spans.stderr b/src/test/ui/span/gated-features-attr-spans.stderr
index 45d14f32f96..938edbe463f 100644
--- a/src/test/ui/span/gated-features-attr-spans.stderr
+++ b/src/test/ui/span/gated-features-attr-spans.stderr
@@ -1,9 +1,10 @@
-error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
+error[E0658]: SIMD types are experimental and possibly buggy
   --> $DIR/gated-features-attr-spans.rs:1:1
    |
 LL | #[repr(simd)]
    | ^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/27731
    = help: add #![feature(repr_simd)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr
index 05b2ca90570..ee479d6c791 100644
--- a/src/test/ui/span/issue-36530.stderr
+++ b/src/test/ui/span/issue-36530.stderr
@@ -1,25 +1,28 @@
-error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/issue-36530.rs:3:3
    |
 LL | #[foo]
    |   ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: non-builtin inner attributes are unstable (see issue #54726)
+error[E0658]: non-builtin inner attributes are unstable
   --> $DIR/issue-36530.rs:5:5
    |
 LL |     #![foo]
    |     ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54726
    = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable
 
-error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/issue-36530.rs:5:8
    |
 LL |     #![foo]
    |        ^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr
index 0b20a19d2e1..b95e62edaaa 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr
@@ -1,4 +1,4 @@
-error[E0658]: specialization is unstable (see issue #31844)
+error[E0658]: specialization is unstable
   --> $DIR/specialization-feature-gate-default.rs:7:1
    |
 LL | / default impl<T> Foo for T {
@@ -6,6 +6,7 @@ LL | |     fn foo(&self) {}
 LL | | }
    | |_^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/31844
    = help: add #![feature(specialization)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/specialization/specialization-feature-gate-default.stderr b/src/test/ui/specialization/specialization-feature-gate-default.stderr
index ad33908eff6..e649f2aa47a 100644
--- a/src/test/ui/specialization/specialization-feature-gate-default.stderr
+++ b/src/test/ui/specialization/specialization-feature-gate-default.stderr
@@ -1,9 +1,10 @@
-error[E0658]: specialization is unstable (see issue #31844)
+error[E0658]: specialization is unstable
   --> $DIR/specialization-feature-gate-default.rs:10:5
    |
 LL |     default fn foo(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/31844
    = help: add #![feature(specialization)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/stability-attribute/stability-attribute-issue.rs b/src/test/ui/stability-attribute/stability-attribute-issue.rs
index fc4a7dab1af..ca4d7cc6a6c 100644
--- a/src/test/ui/stability-attribute/stability-attribute-issue.rs
+++ b/src/test/ui/stability-attribute/stability-attribute-issue.rs
@@ -8,7 +8,7 @@ use stability_attribute_issue::*;
 
 fn main() {
     unstable();
-    //~^ ERROR use of unstable library feature 'unstable_test_feature' (see issue #1)
+    //~^ ERROR use of unstable library feature 'unstable_test_feature'
     unstable_msg();
-    //~^ ERROR use of unstable library feature 'unstable_test_feature': message (see issue #2)
+    //~^ ERROR use of unstable library feature 'unstable_test_feature': message
 }
diff --git a/src/test/ui/stability-attribute/stability-attribute-issue.stderr b/src/test/ui/stability-attribute/stability-attribute-issue.stderr
index 94fdc0db3d9..36e192e583e 100644
--- a/src/test/ui/stability-attribute/stability-attribute-issue.stderr
+++ b/src/test/ui/stability-attribute/stability-attribute-issue.stderr
@@ -1,17 +1,19 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature' (see issue #1)
+error[E0658]: use of unstable library feature 'unstable_test_feature'
   --> $DIR/stability-attribute-issue.rs:10:5
    |
 LL |     unstable();
    |     ^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/1
    = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': message (see issue #2)
+error[E0658]: use of unstable library feature 'unstable_test_feature': message
   --> $DIR/stability-attribute-issue.rs:12:5
    |
 LL |     unstable_msg();
    |     ^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/2
    = help: add #![feature(unstable_test_feature)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/stmt_expr_attrs_no_feature.rs b/src/test/ui/stmt_expr_attrs_no_feature.rs
index 0a71d8d1333..8952175e425 100644
--- a/src/test/ui/stmt_expr_attrs_no_feature.rs
+++ b/src/test/ui/stmt_expr_attrs_no_feature.rs
@@ -91,42 +91,42 @@ item_mac!(e);
 extern {
     #[cfg(unset)]
     fn x(a: [u8; #[attr] 5]);
-    fn y(a: [u8; #[attr] 5]); //~ ERROR 15701
+    fn y(a: [u8; #[attr] 5]); //~ ERROR attributes on expressions are experimental
 }
 
 struct Foo;
 impl Foo {
     #[cfg(unset)]
     const X: u8 = #[attr] 5;
-    const Y: u8 = #[attr] 5; //~ ERROR 15701
+    const Y: u8 = #[attr] 5; //~ ERROR attributes on expressions are experimental
 }
 
 trait Bar {
     #[cfg(unset)]
     const X: [u8; #[attr] 5];
-    const Y: [u8; #[attr] 5]; //~ ERROR 15701
+    const Y: [u8; #[attr] 5]; //~ ERROR attributes on expressions are experimental
 }
 
 struct Joyce {
     #[cfg(unset)]
     field: [u8; #[attr] 5],
-    field2: [u8; #[attr] 5] //~ ERROR 15701
+    field2: [u8; #[attr] 5] //~ ERROR attributes on expressions are experimental
 }
 
 struct Walky(
     #[cfg(unset)] [u8; #[attr] 5],
-    [u8; #[attr] 5] //~ ERROR 15701
+    [u8; #[attr] 5] //~ ERROR attributes on expressions are experimental
 );
 
 enum Mike {
     Happy(
         #[cfg(unset)] [u8; #[attr] 5],
-        [u8; #[attr] 5] //~ ERROR 15701
+        [u8; #[attr] 5] //~ ERROR attributes on expressions are experimental
     ),
     Angry {
         #[cfg(unset)]
         field: [u8; #[attr] 5],
-        field2: [u8; #[attr] 5] //~ ERROR 15701
+        field2: [u8; #[attr] 5] //~ ERROR attributes on expressions are experimental
     }
 }
 
@@ -134,7 +134,7 @@ fn pat() {
     match 5 {
         #[cfg(unset)]
         5 => #[attr] (),
-        6 => #[attr] (), //~ ERROR 15701
+        6 => #[attr] (), //~ ERROR attributes on expressions are experimental
         _ => (),
     }
 }
diff --git a/src/test/ui/stmt_expr_attrs_no_feature.stderr b/src/test/ui/stmt_expr_attrs_no_feature.stderr
index c644126535d..1b5e989af7b 100644
--- a/src/test/ui/stmt_expr_attrs_no_feature.stderr
+++ b/src/test/ui/stmt_expr_attrs_no_feature.stderr
@@ -1,73 +1,82 @@
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/stmt_expr_attrs_no_feature.rs:13:5
    |
 LL |     #[attr]
    |     ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/stmt_expr_attrs_no_feature.rs:94:18
    |
 LL |     fn y(a: [u8; #[attr] 5]);
    |                  ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/stmt_expr_attrs_no_feature.rs:101:19
    |
 LL |     const Y: u8 = #[attr] 5;
    |                   ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/stmt_expr_attrs_no_feature.rs:107:19
    |
 LL |     const Y: [u8; #[attr] 5];
    |                   ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/stmt_expr_attrs_no_feature.rs:113:18
    |
 LL |     field2: [u8; #[attr] 5]
    |                  ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/stmt_expr_attrs_no_feature.rs:118:10
    |
 LL |     [u8; #[attr] 5]
    |          ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/stmt_expr_attrs_no_feature.rs:124:14
    |
 LL |         [u8; #[attr] 5]
    |              ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/stmt_expr_attrs_no_feature.rs:129:22
    |
 LL |         field2: [u8; #[attr] 5]
    |                      ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
-error[E0658]: attributes on expressions are experimental. (see issue #15701)
+error[E0658]: attributes on expressions are experimental
   --> $DIR/stmt_expr_attrs_no_feature.rs:137:14
    |
 LL |         6 => #[attr] (),
    |              ^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/15701
    = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
 
 error: aborting due to 9 previous errors
diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr
index 077c955431a..8367ff20aa4 100644
--- a/src/test/ui/suggestions/attribute-typos.stderr
+++ b/src/test/ui/suggestions/attribute-typos.stderr
@@ -1,25 +1,28 @@
-error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
   --> $DIR/attribute-typos.rs:11:3
    |
 LL | #[rustc_err]
    |   ^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
-error[E0658]: The attribute `tests` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `tests` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/attribute-typos.rs:6:3
    |
 LL | #[tests]
    |   ^^^^^ help: a built-in attribute with a similar name exists: `test`
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error[E0658]: The attribute `deprcated` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+error[E0658]: The attribute `deprcated` is currently unknown to the compiler and may have meaning added to it in the future
   --> $DIR/attribute-typos.rs:1:3
    |
 LL | #[deprcated]
    |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated`
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr
index 09d58575d97..ad4a4deb5a8 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: did you mean: `bar`
+   |       ^^^ help: there is a method with a similar name: `bar`
 
 error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope
   --> $DIR/suggest-methods.rs:21:15
    |
 LL |     let _ = s.is_emtpy();
-   |               ^^^^^^^^ help: did you mean: `is_empty`
+   |               ^^^^^^^^ help: there is a method 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: did you mean: `count_zeros`
+   |                   ^^^^^^^^^ help: there is a method 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/suggestions/suggest-variants.rs b/src/test/ui/suggestions/suggest-variants.rs
index 6d6e280d965..d418834432e 100644
--- a/src/test/ui/suggestions/suggest-variants.rs
+++ b/src/test/ui/suggestions/suggest-variants.rs
@@ -12,4 +12,7 @@ fn main() {
     println!("My shape is {:?}", Shape::Squareee { size: 5});  //~ ERROR no variant `Squareee`
     println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant `Circl`
     println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant `Rombus`
+    Shape::Squareee; //~ ERROR no variant
+    Shape::Circl; //~ ERROR no variant
+    Shape::Rombus; //~ ERROR no variant
 }
diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr
index 08ae68ea713..ef0ba70c340 100644
--- a/src/test/ui/suggestions/suggest-variants.stderr
+++ b/src/test/ui/suggestions/suggest-variants.stderr
@@ -1,20 +1,65 @@
-error: no variant `Squareee` on enum `Shape`
-  --> $DIR/suggest-variants.rs:12:34
+error: no variant `Squareee` in enum `Shape`
+  --> $DIR/suggest-variants.rs:12:41
    |
+LL | enum Shape {
+   | ---------- variant `Squareee` not found here
+...
 LL |     println!("My shape is {:?}", Shape::Squareee { size: 5});
-   |                                  ^^^^^^^^^^^^^^^ help: did you mean: `Shape::Square`
+   |                                         ^^^^^^^^ help: there is a variant with a similar name: `Square`
 
-error: no variant `Circl` on enum `Shape`
-  --> $DIR/suggest-variants.rs:13:34
+error: no variant `Circl` in enum `Shape`
+  --> $DIR/suggest-variants.rs:13:41
    |
+LL | enum Shape {
+   | ---------- variant `Circl` not found here
+...
 LL |     println!("My shape is {:?}", Shape::Circl { size: 5});
-   |                                  ^^^^^^^^^^^^ help: did you mean: `Shape::Circle`
+   |                                         ^^^^^ help: there is a variant with a similar name: `Circle`
 
-error: no variant `Rombus` on enum `Shape`
-  --> $DIR/suggest-variants.rs:14:34
+error: no variant `Rombus` in enum `Shape`
+  --> $DIR/suggest-variants.rs:14:41
    |
+LL | enum Shape {
+   | ---------- variant `Rombus` not found here
+...
 LL |     println!("My shape is {:?}", Shape::Rombus{ size: 5});
-   |                                  ^^^^^^^^^^^^^ unknown variant
+   |                                  -------^^^^^^
+   |                                  |
+   |                                  variant not found in `Shape`
 
-error: aborting due to 3 previous errors
+error[E0599]: no variant or associated item named `Squareee` found for type `Shape` in the current scope
+  --> $DIR/suggest-variants.rs:15:12
+   |
+LL | enum Shape {
+   | ---------- variant or associated item `Squareee` not found here
+...
+LL |     Shape::Squareee;
+   |            ^^^^^^^^
+   |            |
+   |            variant or associated item not found in `Shape`
+   |            help: there is a variant with a similar name: `Square`
+
+error[E0599]: no variant or associated item named `Circl` found for type `Shape` in the current scope
+  --> $DIR/suggest-variants.rs:16:12
+   |
+LL | enum Shape {
+   | ---------- variant or associated item `Circl` not found here
+...
+LL |     Shape::Circl;
+   |            ^^^^^
+   |            |
+   |            variant or associated item not found in `Shape`
+   |            help: there is a variant with a similar name: `Circle`
+
+error[E0599]: no variant or associated item named `Rombus` found for type `Shape` in the current scope
+  --> $DIR/suggest-variants.rs:17:12
+   |
+LL | enum Shape {
+   | ---------- variant or associated item `Rombus` not found here
+...
+LL |     Shape::Rombus;
+   |            ^^^^^^ variant or associated item not found in `Shape`
+
+error: aborting due to 6 previous errors
 
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.stderr b/src/test/ui/syntax-trait-polarity-feature-gate.stderr
index 7b9c3da3712..86b4bc1157b 100644
--- a/src/test/ui/syntax-trait-polarity-feature-gate.stderr
+++ b/src/test/ui/syntax-trait-polarity-feature-gate.stderr
@@ -1,9 +1,10 @@
-error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231)
+error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
   --> $DIR/syntax-trait-polarity-feature-gate.rs:7:1
    |
 LL | impl !Send for TestType {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/13231
    = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr
index 24141d0064f..155298e5062 100644
--- a/src/test/ui/target-feature-gate.stderr
+++ b/src/test/ui/target-feature-gate.stderr
@@ -1,9 +1,10 @@
-error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839)
+error[E0658]: the target feature `avx512bw` is currently unstable
   --> $DIR/target-feature-gate.rs:28:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44839
    = help: add #![feature(avx512_target_feature)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/trace_macros-gate.stderr b/src/test/ui/trace_macros-gate.stderr
index 4d2fd554a06..e0ffcfe295f 100644
--- a/src/test/ui/trace_macros-gate.stderr
+++ b/src/test/ui/trace_macros-gate.stderr
@@ -1,9 +1,10 @@
-error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/trace_macros-gate.rs:4:5
    |
 LL |     trace_macros!();
    |     ^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add #![feature(trace_macros)] to the crate attributes to enable
 
 error: trace_macros! accepts only `true` or `false`
@@ -12,23 +13,25 @@ error: trace_macros! accepts only `true` or `false`
 LL |     trace_macros!();
    |     ^^^^^^^^^^^^^^^^
 
-error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/trace_macros-gate.rs:6:5
    |
 LL |     trace_macros!(true);
    |     ^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add #![feature(trace_macros)] to the crate attributes to enable
 
-error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/trace_macros-gate.rs:7:5
    |
 LL |     trace_macros!(false);
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add #![feature(trace_macros)] to the crate attributes to enable
 
-error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+error[E0658]: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/trace_macros-gate.rs:10:26
    |
 LL |         ($x: ident) => { trace_macros!($x) }
@@ -37,6 +40,7 @@ LL |         ($x: ident) => { trace_macros!($x) }
 LL |     expando!(true);
    |     --------------- in this macro invocation
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add #![feature(trace_macros)] to the crate attributes to enable
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui/traits/trait-alias-ambiguous.rs b/src/test/ui/traits/trait-alias-ambiguous.rs
new file mode 100644
index 00000000000..28409e0c662
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-ambiguous.rs
@@ -0,0 +1,24 @@
+#![feature(trait_alias)]
+
+mod inner {
+    pub trait A { fn foo(&self); }
+    pub trait B { fn foo(&self); }
+
+    impl A for u8 {
+        fn foo(&self) {}
+    }
+    impl B for u8 {
+        fn foo(&self) {}
+    }
+
+    pub trait C = A + B;
+}
+
+use inner::C;
+
+fn main() {
+    let t = 1u8;
+    t.foo(); //~ ERROR E0034
+
+    inner::A::foo(&t); // ok
+}
diff --git a/src/test/ui/traits/trait-alias-ambiguous.stderr b/src/test/ui/traits/trait-alias-ambiguous.stderr
new file mode 100644
index 00000000000..b7443269b88
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-ambiguous.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/trait-alias-ambiguous.rs:21:7
+   |
+LL |     t.foo();
+   |       ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in an impl of the trait `inner::A` for the type `u8`
+  --> $DIR/trait-alias-ambiguous.rs:8:9
+   |
+LL |         fn foo(&self) {}
+   |         ^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `inner::B` for the type `u8`
+  --> $DIR/trait-alias-ambiguous.rs:11:9
+   |
+LL |         fn foo(&self) {}
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr
index 6687bd9d9e1..07e7149793c 100644
--- a/src/test/ui/try-block/try-block-bad-type.stderr
+++ b/src/test/ui/try-block/try-block-bad-type.stderr
@@ -6,9 +6,9 @@ LL |         Err("")?;
    |
    = help: the following implementations were found:
              <i32 as std::convert::From<bool>>
-             <i32 as std::convert::From<core::num::NonZeroI32>>
              <i32 as std::convert::From<i16>>
              <i32 as std::convert::From<i8>>
+             <i32 as std::convert::From<std::num::NonZeroI32>>
            and 2 others
    = note: required by `std::convert::From::from`
 
diff --git a/src/test/ui/try-block/try-block-catch.rs b/src/test/ui/try-block/try-block-catch.rs
new file mode 100644
index 00000000000..d165015611d
--- /dev/null
+++ b/src/test/ui/try-block/try-block-catch.rs
@@ -0,0 +1,10 @@
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn main() {
+    let res: Option<bool> = try {
+        true
+    } catch { };
+    //~^ ERROR keyword `catch` cannot follow a `try` block
+}
diff --git a/src/test/ui/try-block/try-block-catch.stderr b/src/test/ui/try-block/try-block-catch.stderr
new file mode 100644
index 00000000000..39cf943f4d8
--- /dev/null
+++ b/src/test/ui/try-block/try-block-catch.stderr
@@ -0,0 +1,10 @@
+error: keyword `catch` cannot follow a `try` block
+  --> $DIR/try-block-catch.rs:8:7
+   |
+LL |     } catch { };
+   |       ^^^^^
+   |
+   = help: try using `match` on the result of the `try` block instead
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs
index 4efded8b376..82a593ff16c 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.rs
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs
@@ -45,9 +45,9 @@ fn main() {
     <u8 as E::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `E::N`
     <u8 as A::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `A::N`
     let _: <u8 as Tr::Y>::NN; //~ ERROR cannot find associated type `NN` in `Tr::Y`
-    let _: <u8 as E::Y>::NN; //~ ERROR failed to resolve: not a module `Y`
+    let _: <u8 as E::Y>::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module
     <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: not a module `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`
     <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
index 900c7297211..c399a32bc56 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
@@ -1,14 +1,14 @@
-error[E0433]: failed to resolve: not a module `Y`
+error[E0433]: failed to resolve: `Y` is a variant, not a module
   --> $DIR/ufcs-partially-resolved.rs:48:22
    |
 LL |     let _: <u8 as E::Y>::NN;
-   |                      ^ not a module `Y`
+   |                      ^ `Y` is a variant, not a module
 
-error[E0433]: failed to resolve: not a module `Y`
+error[E0433]: failed to resolve: `Y` is a variant, not a module
   --> $DIR/ufcs-partially-resolved.rs:50:15
    |
 LL |     <u8 as E::Y>::NN;
-   |               ^ not a module `Y`
+   |               ^ `Y` is a variant, not a module
 
 error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:19:24
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr b/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr
index 038167ae9d7..1604aa4a0f7 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr
@@ -1,9 +1,10 @@
-error[E0658]: parenthetical notation is only stable when used with `Fn`-family traits (see issue #29625)
+error[E0658]: parenthetical notation is only stable when used with `Fn`-family traits
   --> $DIR/unboxed-closure-feature-gate.rs:13:16
    |
 LL |     let x: Box<Foo(isize)>;
    |                ^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
 error: aborting due to previous error
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr
index 90f04a52d37..0901126a3fe 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr
@@ -1,17 +1,19 @@
-error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
   --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:3:13
    |
 LL | fn bar1(x: &Fn<(), Output=()>) {
    |             ^^^^^^^^^^^^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
-error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead (see issue #29625)
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
   --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:7:28
    |
 LL | fn bar2<T>(x: &T) where T: Fn<()> {
    |                            ^^^^^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29625
    = help: add #![feature(unboxed_closures)] to the crate attributes to enable
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/unnecessary-extern-crate.rs b/src/test/ui/unnecessary-extern-crate.rs
index e25b99bcb61..67eaaf4b6c2 100644
--- a/src/test/ui/unnecessary-extern-crate.rs
+++ b/src/test/ui/unnecessary-extern-crate.rs
@@ -1,7 +1,7 @@
 // edition:2018
 
 #![deny(unused_extern_crates)]
-#![feature(alloc, test, rustc_private, crate_visibility_modifier)]
+#![feature(test, rustc_private, crate_visibility_modifier)]
 
 extern crate libc;
 //~^ ERROR unused extern crate
diff --git a/src/test/ui/use/use-associated-const.rs b/src/test/ui/use/use-associated-const.rs
new file mode 100644
index 00000000000..714fbdabb81
--- /dev/null
+++ b/src/test/ui/use/use-associated-const.rs
@@ -0,0 +1,13 @@
+#![allow(unused_imports)]
+
+pub mod foo {
+    pub struct Foo;
+
+    impl Foo {
+        pub const BAR: i32 = 0;
+    }
+}
+
+use foo::Foo::BAR; //~ ERROR unresolved import `foo::Foo`
+
+fn main() {}
diff --git a/src/test/ui/use/use-associated-const.stderr b/src/test/ui/use/use-associated-const.stderr
new file mode 100644
index 00000000000..4bc0d7e61cb
--- /dev/null
+++ b/src/test/ui/use/use-associated-const.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `foo::Foo`
+  --> $DIR/use-associated-const.rs:11:10
+   |
+LL | use foo::Foo::BAR;
+   |          ^^^ `Foo` is a struct, not a module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/use/use-from-trait-xc.stderr b/src/test/ui/use/use-from-trait-xc.stderr
index 97dc603f9eb..faa4829bfdd 100644
--- a/src/test/ui/use/use-from-trait-xc.stderr
+++ b/src/test/ui/use/use-from-trait-xc.stderr
@@ -20,19 +20,19 @@ error[E0432]: unresolved import `use_from_trait_xc::Foo`
   --> $DIR/use-from-trait-xc.rs:14:24
    |
 LL | use use_from_trait_xc::Foo::new;
-   |                        ^^^ not a module `Foo`
+   |                        ^^^ `Foo` is a struct, not a module
 
 error[E0432]: unresolved import `use_from_trait_xc::Foo`
   --> $DIR/use-from-trait-xc.rs:17:24
    |
 LL | use use_from_trait_xc::Foo::C;
-   |                        ^^^ not a module `Foo`
+   |                        ^^^ `Foo` is a struct, not a module
 
 error[E0432]: unresolved import `use_from_trait_xc::Bar`
   --> $DIR/use-from-trait-xc.rs:20:24
    |
 LL | use use_from_trait_xc::Bar::new as bnew;
-   |                        ^^^ not a module `Bar`
+   |                        ^^^ `Bar` is a struct, not a module
 
 error[E0432]: unresolved import `use_from_trait_xc::Baz::new`
   --> $DIR/use-from-trait-xc.rs:23:5
diff --git a/src/test/ui/use/use-from-trait.rs b/src/test/ui/use/use-from-trait.rs
index fe578723bd3..eab4bb6e3b5 100644
--- a/src/test/ui/use/use-from-trait.rs
+++ b/src/test/ui/use/use-from-trait.rs
@@ -1,17 +1,10 @@
-use Trait::foo;
-//~^ ERROR `foo` is not directly importable
-use Trait::Assoc;
-//~^ ERROR `Assoc` is not directly importable
-use Trait::C;
-//~^ ERROR `C` is not directly importable
+use Trait::foo; //~ ERROR `foo` is not directly importable
+use Trait::Assoc; //~ ERROR `Assoc` is not directly importable
+use Trait::C; //~ ERROR `C` is not directly importable
 
-use Foo::new;
-//~^ ERROR unresolved import `Foo` [E0432]
-//~| not a module `Foo`
+use Foo::new; //~ ERROR unresolved import `Foo` [E0432]
 
-use Foo::C2;
-//~^ ERROR unresolved import `Foo` [E0432]
-//~| not a module `Foo`
+use Foo::C2; //~ ERROR unresolved import `Foo` [E0432]
 
 pub trait Trait {
     fn foo();
diff --git a/src/test/ui/use/use-from-trait.stderr b/src/test/ui/use/use-from-trait.stderr
index 9e138422a2f..af4b3b0c455 100644
--- a/src/test/ui/use/use-from-trait.stderr
+++ b/src/test/ui/use/use-from-trait.stderr
@@ -5,28 +5,28 @@ LL | use Trait::foo;
    |     ^^^^^^^^^^ cannot be imported directly
 
 error[E0253]: `Assoc` is not directly importable
-  --> $DIR/use-from-trait.rs:3:5
+  --> $DIR/use-from-trait.rs:2:5
    |
 LL | use Trait::Assoc;
    |     ^^^^^^^^^^^^ cannot be imported directly
 
 error[E0253]: `C` is not directly importable
-  --> $DIR/use-from-trait.rs:5:5
+  --> $DIR/use-from-trait.rs:3:5
    |
 LL | use Trait::C;
    |     ^^^^^^^^ cannot be imported directly
 
 error[E0432]: unresolved import `Foo`
-  --> $DIR/use-from-trait.rs:8:5
+  --> $DIR/use-from-trait.rs:5:5
    |
 LL | use Foo::new;
-   |     ^^^ not a module `Foo`
+   |     ^^^ `Foo` is a struct, not a module
 
 error[E0432]: unresolved import `Foo`
-  --> $DIR/use-from-trait.rs:12:5
+  --> $DIR/use-from-trait.rs:7:5
    |
 LL | use Foo::C2;
-   |     ^^^ not a module `Foo`
+   |     ^^^ `Foo` is a struct, not a module
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/utf8_idents.stderr b/src/test/ui/utf8_idents.stderr
index 330ba3e0a8c..b65848cc58f 100644
--- a/src/test/ui/utf8_idents.stderr
+++ b/src/test/ui/utf8_idents.stderr
@@ -1,33 +1,37 @@
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/utf8_idents.rs:2:5
    |
 LL |     'β,
    |     ^^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/utf8_idents.rs:3:5
    |
 LL |     γ
    |     ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/utf8_idents.rs:8:5
    |
 LL |     δ: usize
    |     ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
-error[E0658]: non-ascii idents are not fully supported. (see issue #55467)
+error[E0658]: non-ascii idents are not fully supported
   --> $DIR/utf8_idents.rs:12:9
    |
 LL |     let α = 0.00001f64;
    |         ^
    |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55467
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
 warning: type parameter `γ` should have an upper camel case name
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 0611e53d092..61cc78ad807 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -103,7 +103,9 @@ static TARGETS: &[&str] = &[
     "thumbv7em-none-eabi",
     "thumbv7em-none-eabihf",
     "thumbv7m-none-eabi",
+    "thumbv8m.base-none-eabi",
     "thumbv8m.main-none-eabi",
+    "thumbv8m.main-none-eabihf",
     "wasm32-unknown-emscripten",
     "wasm32-unknown-unknown",
     "wasm32-unknown-wasi",
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 63231f438a2b5b84ccf319a5de22343ee031632
+Subproject 6f3e9c367abb497c64f360c3839dab5e74928d5
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject 92612c9de159889f77f05855a77482ee1d895f5
+Subproject abf7f911d88e9209b54cfba2776d7dbca5a440c
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index d735d3351e6..2fe837e99d3 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -303,6 +303,10 @@ pub struct TestProps {
     // For UI tests, allows compiler to generate arbitrary output to stderr
     pub dont_check_compiler_stderr: bool,
     // Don't force a --crate-type=dylib flag on the command line
+    //
+    // Set this for example if you have an auxiliary test file that contains
+    // a proc-macro and needs `#![crate_type = "proc-macro"]`. This ensures
+    // that the aux file is compiled as a `proc-macro` and not as a `dylib`.
     pub no_prefer_dynamic: bool,
     // Run --pretty expanded when running pretty printing tests
     pub pretty_expanded: bool,
@@ -490,7 +494,7 @@ impl TestProps {
             }
 
             if !self.compile_pass {
-                // run-pass implies must_compile_successfully
+                // run-pass implies compile_pass
                 self.compile_pass = config.parse_compile_pass(ln) || self.run_pass;
             }
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 35f8dca79b5..2021dd513aa 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2820,12 +2820,15 @@ impl<'test> TestCx<'test> {
             // don't test rustfix with nll right now
         } else if self.config.rustfix_coverage {
             // Find out which tests have `MachineApplicable` suggestions but are missing
-            // `run-rustfix` or `run-rustfix-only-machine-applicable` headers
+            // `run-rustfix` or `run-rustfix-only-machine-applicable` headers.
+            //
+            // This will return an empty `Vec` in case the executed test file has a
+            // `compile-flags: --error-format=xxxx` header with a value other than `json`.
             let suggestions = get_suggestions_from_json(
                 &proc_res.stderr,
                 &HashSet::new(),
                 Filter::MachineApplicableOnly
-            ).unwrap();
+            ).unwrap_or_default();
             if suggestions.len() > 0
                 && !self.props.run_rustfix
                 && !self.props.rustfix_only_machine_applicable {
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 72b4ee0381decf609204e5548c1f5e79bdfb18b
+Subproject 7c06679f93df53f83bbf61b197f2e5c39f5d763
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 90f7ab070321ebc5ad217dc0d6db163c029dffd
+Subproject b202e14dbf53949d05822e680ee5166b3346885
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index 1aba52bafbb..d51841cd650 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -57,7 +57,7 @@ features = [
 [dependencies]
 curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
 parking_lot = { version = "0.7", features = ['nightly'] }
-rand = { version = "0.5.5", features = ["i128_support"] }
+rand = { version = "0.6.1", features = ["i128_support"] }
 serde = { version = "1.0.82", features = ['derive'] }
 serde_json = { version = "1.0.31", features = ["raw_value"] }
 smallvec = { version = "0.6", features = ['union', 'may_dangle'] }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 30fe327cac4..411961d70bf 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -96,6 +96,7 @@ const WHITELIST: &[Crate<'_>] = &[
     Crate("lock_api"),
     Crate("log"),
     Crate("log_settings"),
+    Crate("measureme"),
     Crate("memchr"),
     Crate("memmap"),
     Crate("memoffset"),
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index cd60f36b1d2..f7e40ce4bae 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -3,13 +3,13 @@ use std::fs;
 use std::path;
 use crate::features::{collect_lang_features, collect_lib_features, Features, Status};
 
-pub const PATH_STR: &str = "doc/unstable-book/src";
+pub const PATH_STR: &str = "doc/unstable-book";
 
-pub const COMPILER_FLAGS_DIR: &str = "compiler-flags";
+pub const COMPILER_FLAGS_DIR: &str = "src/compiler-flags";
 
-pub const LANG_FEATURES_DIR: &str = "language-features";
+pub const LANG_FEATURES_DIR: &str = "src/language-features";
 
-pub const LIB_FEATURES_DIR: &str = "library-features";
+pub const LIB_FEATURES_DIR: &str = "src/library-features";
 
 /// Builds the path to the Unstable Book source directory from the Rust 'src' directory.
 pub fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf {
diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs
index 427014ce7fe..e92d174a4e1 100644
--- a/src/tools/unstable-book-gen/src/main.rs
+++ b/src/tools/unstable-book-gen/src/main.rs
@@ -52,7 +52,7 @@ fn set_to_summary_str(set: &BTreeSet<String>, dir: &str
 
 fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) {
     let compiler_flags = collect_unstable_book_section_file_names(
-        &path.join("compiler-flags"));
+        &path.join("src/compiler-flags"));
 
     let compiler_flags_str = set_to_summary_str(&compiler_flags,
                                                 "compiler-flags");
@@ -61,11 +61,11 @@ fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Featur
     let unstable_lib_features = collect_unstable_feature_names(&lib_features);
 
     let lang_features_str = set_to_summary_str(&unstable_lang_features,
-                                               LANG_FEATURES_DIR);
+                                               "language-features");
     let lib_features_str = set_to_summary_str(&unstable_lib_features,
-                                              LIB_FEATURES_DIR);
+                                              "library-features");
 
-    let mut file = t!(File::create(&path.join("SUMMARY.md")));
+    let mut file = t!(File::create(&path.join("src/SUMMARY.md")));
     t!(file.write_fmt(format_args!(include_str!("SUMMARY.md"),
                                    compiler_flags = compiler_flags_str,
                                    language_features = lang_features_str,
@@ -102,8 +102,8 @@ fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) {
     }
 }
 
-fn copy_recursive(path: &Path, to: &Path) {
-    for entry in t!(fs::read_dir(path)) {
+fn copy_recursive(from: &Path, to: &Path) {
+    for entry in t!(fs::read_dir(from)) {
         let e = t!(entry);
         let t = t!(e.metadata());
         let dest = &to.join(e.file_name());
@@ -120,7 +120,7 @@ fn main() {
     let src_path_str = env::args_os().skip(1).next().expect("source path required");
     let dest_path_str = env::args_os().skip(2).next().expect("destination path required");
     let src_path = Path::new(&src_path_str);
-    let dest_path = Path::new(&dest_path_str).join("src");
+    let dest_path = Path::new(&dest_path_str);
 
     let lang_features = collect_lang_features(src_path, &mut false);
     let lib_features = collect_lib_features(src_path).into_iter().filter(|&(ref name, _)| {